2d.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef METALIC_ARRAY_2D_HH
00029 # define METALIC_ARRAY_2D_HH
00030 
00031 # include <mlc/array/objs.hh>
00032 # include <mlc/contract.hh>
00033 # include <mlc/cmp.hh>
00034 # include <ntg/basics.hh>
00035 
00036 # include <iostream>
00037 
00038 // impl
00039 # include <mlc/array/2d.hxx>
00040 
00041 namespace mlc
00042 {
00043 
00044   template<class Info_, class T_>
00045   struct array2d
00046   {
00047     typedef array2d self;
00048     typedef T_ T;
00049     typedef Info_ Info;
00050 
00051     //
00052     // Constructors
00053     //
00054 
00055     array2d()
00056     {
00057     }
00058 
00059     array2d(T* ptr)
00060     {
00061       less< 0, Info_::nrows >::ensure();
00062       less< 0, Info_::ncols >::ensure();
00063       less< Info_::card, internal::max_card_ >::ensure();
00064       for (unsigned i = 0; i < Info_::card; ++i)
00065         buffer_[i] = *ptr++;
00066     }
00067 
00068     // Copy
00069 
00070     array2d(const self& rhs)
00071     {
00072       for (unsigned i = 0; i < Info_::card; ++i)
00073         buffer_[i] = rhs[i];
00074     }
00075     self& operator=(const self& rhs)
00076     {
00077       for (unsigned i = 0; i < Info_::card; ++i)
00078         buffer_[i] = rhs[i];
00079       return *this;
00080     }
00081 
00082 
00083     // Name
00084 
00085     static std::string
00086     name()
00087     {
00088       return std::string("array2d< Info, ") + ntg_name(T) + " >";
00089     }
00090 
00091 
00092 
00093     //
00094     // Operations on array
00095     //
00096 
00097 
00098     // Normalize (absolute values -> relative values)
00099 
00100     array2d<Info_, ntg::float_s>
00101     normalize()
00102     {
00103       array2d<Info_, ntg::float_s> tmp;
00104       ntg::float_s sum = 0.f;
00105       const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be global
00106       unsigned i;
00107       for (i = 0; i < Info_::card; ++i)
00108         sum += this->buffer_[i];
00109       for (i = 0; i < Info_::card; ++i)
00110         tmp[i] = this->buffer_[i] / sum;
00111       // security
00112       sum = 0.f;
00113       for (i = 0; i < Info_::card; ++i)
00114         sum += tmp[i];
00115       postcondition(std::abs(sum - 1) <= epsilon);
00116       return tmp;
00117     }
00118 
00119     // Central symmetry
00120 
00121     array2d<array2d_info<Info_::nrows,
00122                          Info_::ncols,
00123                          Info_::card - Info_::center - 1,
00124                          Info_::i>, T>
00125     operator-() const
00126     {
00127       enum { new_center =  Info_::card - Info_::center - 1 };
00128       array2d<array2d_info< Info_::nrows, Info_::ncols, new_center, Info_::i>,T> tmp;
00129 
00130       for (unsigned i = 0; i < Info_::card; ++i)
00131         tmp[Info_::card - i - 1] = this->operator[](i);
00132       return tmp;
00133     }
00134 
00135 
00136     // Transpose
00137 
00138     typedef array2d<array2d_info<
00139       Info_::ncols,
00140       Info_::nrows,
00141       (Info_::center * Info_::nrows + Info_::center / Info_::ncols) % Info_::card,
00142       Info_::i
00143       >, T> transposed_array_t;
00144 
00145     transposed_array_t transpose() const
00146     {
00147       transposed_array_t tmp;
00148       for (int i = 0; i < Info::card; ++i)
00149         tmp[i] = this->operator[]((i * Info_::ncols + i / Info_::nrows) % Info_::card);
00150       return tmp;
00151     }
00152 
00153     // Operators
00154 
00155     // FIXME: This code should be factorized between 1d, 2d and 3d.
00156     // Think of a mechanism similar to apply() and apply2().
00157 
00158     template <class U>
00159     array2d< Info, ntg_return_type(times, T, U) >
00160     operator*(U w)
00161     {
00162       array2d< Info, ntg_return_type(times, T, U) > tmp;
00163       for (unsigned i = 0; i < Info::card; ++i)
00164         tmp[i] = this->buffer_[i] * w;
00165       return tmp;
00166     }
00167 
00168     template <class U>
00169     array2d< Info, ntg_return_type(div, T, U) >
00170     operator/(U w)
00171     {
00172       array2d< Info, ntg_return_type(div, T, U) > tmp;
00173       for (unsigned i = 0; i < Info::card; ++i)
00174         tmp[i] = this->buffer_[i] / w;
00175       return tmp;
00176     }
00177 
00178     self operator+(const self& rhs) const
00179     {
00180       self tmp;
00181       for (unsigned i = 0; i < Info::card; ++i)
00182         tmp[i] = this->buffer_[i] + rhs.buffer_[i];
00183       return tmp;
00184     }
00185     self& operator+=(const self& rhs)
00186     {
00187       for (unsigned i = 0; i < Info::card; ++i)
00188         this->buffer_[i] += rhs.buffer_[i];
00189       return *this;
00190     }
00191 
00192     self operator-(const self& rhs) const
00193     {
00194       self tmp;
00195       for (unsigned i = 0; i < Info::card; ++i)
00196         tmp[i] = this->buffer_[i] - rhs.buffer_[i];
00197       return tmp;
00198     }
00199     self& operator-=(const self& rhs)
00200     {
00201       for (unsigned i = 0; i < Info::card; ++i)
00202         this->buffer_[i] -= rhs.buffer_[i];
00203       return *this;
00204     }
00205 
00206 
00207     //
00208     // Accessors
00209     //
00210 
00211     unsigned size() const
00212     {
00213       return Info_::card;
00214     }
00215 
00216     const T* buffer() const
00217     {
00218       return buffer_;
00219     }
00220 
00221     // dynamic accessors:
00222 
00223     T operator[](unsigned i) const      // Absolute position
00224     {
00225       precondition(i < Info_::card);
00226       return *(buffer_ + i);
00227     }
00228     T& operator[](unsigned i)
00229     {
00230       precondition(i < Info_::card);
00231       return *(buffer_ + i);
00232     }
00233 
00234 
00235     T operator()(int row, int col) const                // Relative position
00236     {
00237       precondition(-Info_::center_row <= row);
00238       precondition(row <= Info_::nrows - Info_::center_row - 1);
00239       precondition(-Info_::center_col <= col);
00240       precondition(col <= Info_::ncols - Info_::center_col - 1);
00241 
00242       return *(buffer_ + Info_::center + (row * Info_::ncols) + col);
00243     }
00244     T& operator()(int row, int col)
00245     {
00246       precondition(-Info_::center_row <= row);
00247       precondition(row <= Info_::nrows - Info_::center_row - 1);
00248       precondition(-Info_::center_col <= col);
00249       precondition(col <= Info_::ncols - Info_::center_col - 1);
00250 
00251       return *(buffer_ + Info_::center + (row * Info_::ncols) + col);
00252     }
00253 
00254 
00255     // do not use these methods...
00256 
00257     template<unsigned i>
00258     T get_at_() const {
00259       lesseq<i, Info_::card>::ensure();
00260       return *(buffer_ + i);
00261     }
00262 
00263     template<int nrow, int ncol>
00264     T get_() const {
00265       lesseq< -Info_::center_row, nrow >::ensure();
00266       lesseq< nrow, Info_::nrows - Info_::center_row - 1 >::ensure();
00267       lesseq< -Info_::center_col, ncol >::ensure();
00268       lesseq< ncol, Info_::ncols - Info_::center_col - 1 >::ensure();
00269       return *(buffer_ + Info_::center + (nrow * Info_::ncols) + ncol);
00270     }
00271 
00272 
00273   protected:
00274 
00275     T buffer_[internal::max_card_];
00276   };
00277 
00278 
00279   // ...but these static accessors:
00280 
00281   template<unsigned i, class Info, class T> inline
00282   T get_at(const array2d<Info, T>& arr)
00283   {
00284     return arr.template get_at_<i>();
00285   }
00286 
00287   template<int row, int col, class Info, class T> inline
00288   T get(const array2d<Info, T>& arr)
00289   {
00290     return arr.template get_<row, col>();
00291   }
00292 
00293   // starter objects
00294 
00295   // FIXME: what about other types? Replace this by a function
00296   // returning a starter.
00297 
00298 # define array2d_starter(T) \
00299   static internal::array2d_start_<T >   T##s_2d   = internal::array2d_start_<T >()
00300 
00301   array2d_starter(int);         // ints_2d
00302   array2d_starter(float);       // floats_2d
00303 
00304 
00305   // print
00306 
00307   template<class Info, class T>
00308   std::ostream& operator<<(std::ostream& ostr, const array2d<Info, T>& rhs)
00309   {
00310     for (int i = 0; i < Info::card; ++i)
00311       {
00312         if (i == Info::center)
00313           ostr << "<" << rhs[i] << ">";
00314         else
00315           ostr << rhs[i];
00316 
00317         ostr << ((i + 1) %  Info::ncols == 0 ? "\n" : "\t");
00318       }
00319     ostr << std::flush;
00320     return ostr;
00321   }
00322 
00323 } // end of mlc
00324 
00325 
00326 #endif // ! METALIC_ARRAY_2D_HH

Generated on Thu Apr 15 20:13:04 2004 for Olena by doxygen 1.3.6-20040222