3d.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_3D_HH
00029 # define METALIC_ARRAY_3D_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/3d.hxx>
00040 
00041 namespace mlc
00042 {
00043 
00044   class not_implemented_yet{}; // FIXME
00045 
00046   template<class Info_, class T_>
00047   struct array3d
00048   {
00049     typedef array3d self;
00050     typedef T_ T;
00051     typedef Info_ Info;
00052 
00053     //
00054     // Constructors
00055     //
00056 
00057     array3d()
00058     {
00059     }
00060 
00061     array3d(T* ptr)
00062     {
00063       less< 0, Info_::nplanes >::ensure();
00064       less< 0, Info_::nrows >::ensure();
00065       less< 0, Info_::ncols >::ensure();
00066       less< Info_::card, internal::max_card_ >::ensure();
00067       for (unsigned i = 0; i < Info_::card; ++i)
00068         buffer_[i] = *ptr++;
00069     }
00070 
00071     // Copy
00072 
00073     array3d(const self& rhs)
00074     {
00075       for (unsigned i = 0; i < Info_::card; ++i)
00076         buffer_[i] = rhs[i];
00077     }
00078     self& operator=(const self& rhs)
00079     {
00080       for (unsigned i = 0; i < Info_::card; ++i)
00081         buffer_[i] = rhs[i];
00082       return *this;
00083     }
00084 
00085 
00086     // Name
00087 
00088     static std::string
00089     name()
00090     {
00091       return std::string("array3d< Info, ") + ntg_name(T) + " >";
00092     }
00093 
00094 
00095 
00096     //
00097     // Operations on array
00098     //
00099 
00100     // Normalize (absolute values -> relative values)
00101 
00102     array3d<Info_, ntg::float_s>
00103     normalize()
00104     {
00105       array3d<Info_, ntg::float_s> tmp;
00106       ntg::float_s sum = 0.f;
00107       const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be global
00108       unsigned i;
00109       for (i = 0; i < Info_::card; ++i)
00110         sum += this->buffer_[i];
00111       for (i = 0; i < Info_::card; ++i)
00112         tmp[i] = this->buffer_[i] / sum;
00113       // security
00114       sum = 0.f;
00115       for (i = 0; i < Info_::card; ++i)
00116         sum += tmp[i];
00117       postcondition(std::abs(sum - 1) <= epsilon);
00118       return tmp;
00119     }
00120 
00121     // Central symmetry
00122 
00123     array3d<array3d_info<Info_::nplanes,
00124                          Info_::nrows,
00125                          Info_::ncols,
00126                          Info_::card - Info_::center - 1,
00127                          Info_::i>, T>
00128     operator-() const
00129     {
00130       enum { new_center =  Info_::card - Info_::center - 1 };
00131       array3d<array3d_info< Info_::nplanes, Info_::nrows, Info_::ncols, new_center, Info_::i>,T> tmp;
00132 
00133       for (unsigned i = 0; i < Info_::card; ++i)
00134         tmp[Info_::card - i - 1] = this->operator[](i);
00135       return tmp;
00136     }
00137 
00138 
00139     // Transpose
00140 
00141     array3d<Info, T> transpose() const // FIXME
00142     {
00143       std::cerr << "===> 3D transposition not implemented yet. <===" << std::endl;
00144       throw not_implemented_yet();
00145     }
00146 
00147 
00148     // Operators
00149 
00150     // FIXME: This code should be factorized between 1d, 2d and 3d.
00151     // Think of a mechanism similar to apply() and apply2().
00152 
00153     template <class U>
00154     array3d< Info, ntg_return_type(times, T, U) >
00155     operator*(U w)
00156     {
00157       array3d< Info, ntg_return_type(times, T, U) > tmp;
00158       for (unsigned i = 0; i < Info::card; ++i)
00159         tmp[i] = this->buffer_[i] * w;
00160       return tmp;
00161     }
00162 
00163     template <class U>
00164     array3d< Info, ntg_return_type(div, T, U) >
00165     operator/(U w)
00166     {
00167       array3d< Info, ntg_return_type(div, T, U) > tmp;
00168       for (unsigned i = 0; i < Info::card; ++i)
00169         tmp[i] = this->buffer_[i] / w;
00170       return tmp;
00171     }
00172 
00173     self operator+(const self& rhs) const
00174     {
00175       self tmp;
00176       for (unsigned i = 0; i < Info::card; ++i)
00177         tmp[i] = this->buffer_[i] + rhs.buffer_[i];
00178       return tmp;
00179     }
00180     self& operator+=(const self& rhs)
00181     {
00182       for (unsigned i = 0; i < Info::card; ++i)
00183         this->buffer_[i] += rhs.buffer_[i];
00184       return *this;
00185     }
00186 
00187     self operator-(const self& rhs) const
00188     {
00189       self tmp;
00190       for (unsigned i = 0; i < Info::card; ++i)
00191         tmp[i] = this->buffer_[i] - rhs.buffer_[i];
00192       return tmp;
00193     }
00194     self& operator-=(const self& rhs)
00195     {
00196       for (unsigned i = 0; i < Info::card; ++i)
00197         this->buffer_[i] -= rhs.buffer_[i];
00198       return *this;
00199     }
00200 
00201 
00202 
00203     //      template<class U> int operator,(U); // FIXME: why this?
00204 
00205     //
00206     // Accessors
00207     //
00208 
00209     unsigned size() const
00210     {
00211       return Info_::card;
00212     }
00213 
00214     const T* buffer() const
00215     {
00216       return buffer_;
00217     }
00218 
00219     // dynamic accessors:
00220 
00221     T operator[](unsigned i) const      // Absolute position
00222     {
00223       precondition(i < Info_::card);
00224       return *(buffer_ + i);
00225     }
00226     T& operator[](unsigned i)
00227     {
00228       precondition(i < Info_::card);
00229       return *(buffer_ + i);
00230     }
00231 
00232 
00233     T operator()(int plane, int row, int col) const             // Relative position
00234     {
00235       precondition(-Info_::center_plane <= plane);
00236       precondition(plane <= Info::nplanes - Info_::center_plane - 1);
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 + (plane * Info::nrows * Info::ncols) + (row * Info::ncols) + col);
00243     }
00244 
00245     T& operator()(int plane, int row, int col)
00246     {
00247       precondition(-Info_::center_plane <= plane);
00248       precondition(plane <= Info::nplanes - Info_::center_plane - 1);
00249       precondition(-Info_::center_row <= row);
00250       precondition(row <= Info_::nrows - Info_::center_row - 1);
00251       precondition(-Info_::center_col <= col);
00252       precondition(col <= Info_::ncols - Info_::center_col - 1);
00253 
00254       return *(buffer_ + Info_::center + (plane * Info::nrows * Info::ncols) + (row * Info::ncols) + col);
00255     }
00256 
00257 
00258     // do not use these methods...
00259 
00260     template<unsigned i>
00261     T get_at_() const {
00262       lesseq<i, Info_::card>::ensure();
00263       return *(buffer_ + i);
00264     }
00265 
00266     template<int nplane, int nrow, int ncol>
00267     T get_() const {
00268       lesseq< -Info_::center_plane, nplane >::ensure();
00269       lesseq< nplane, Info::nplanes - Info_::center_plane - 1 >::ensure();
00270       lesseq< -Info_::center_row, nrow >::ensure();
00271       lesseq< nrow, Info_::nrows - Info_::center_row - 1 >::ensure();
00272       lesseq< -Info_::center_col, ncol >::ensure();
00273       lesseq< ncol, Info_::ncols - Info_::center_col - 1 >::ensure();
00274       return *(buffer_ + Info_::center + (nplane * Info::nrows * Info::ncols) + (nrow * Info::ncols) + ncol);
00275     }
00276 
00277 
00278   protected:
00279 
00280     T buffer_[internal::max_card_];
00281   };
00282 
00283 
00284   // ...but these static accessors:
00285 
00286   template<unsigned i, class Info, class T> inline
00287   T get_at(const array3d<Info, T>& arr)
00288   {
00289     return arr.template get_at_<i>();
00290   }
00291 
00292   template<int plane, int row, int col, class Info, class T> inline
00293   T get(const array3d<Info, T>& arr)
00294   {
00295     return arr.template get_<plane, row, col>();
00296   }
00297 
00298   // starter objects
00299 
00300   // FIXME: what about other types? Replace this by a function
00301   // returning a starter.
00302 
00303 # define array3d_starter(T) \
00304   static internal::array3d_start_<T >   T##s_3d   = internal::array3d_start_<T >()
00305 
00306   array3d_starter(int);         // ints_3d
00307   array3d_starter(float);       // floats_3d
00308 
00309 
00310   // print
00311 
00312   template<class Info, class T>
00313   std::ostream& operator<<(std::ostream& ostr, const array3d<Info, T>& rhs)
00314   {
00315     for (int i = 0; i < Info::card; ++i)
00316       {
00317         if (i == Info::center)
00318           ostr << "<" << rhs[i] << "> ";
00319         else
00320           ostr << rhs[i] << " ";
00321 
00322         ostr << ((i + 1) % Info::ncols == 0 ? "\n" : "\t");
00323         ostr << ((i + 1) % (Info::ncols * Info::nrows) == 0 ? "\n" : "");
00324       }
00325     ostr << std::flush;
00326 
00327     return ostr;
00328   }
00329 
00330 
00331 } // end of mlc
00332 
00333 #endif // ! METALIC_ARRAY_3D_HH

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