2d.hxx

00001 // Copyright (C) 2001, 2002, 2003  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_HXX
00029 # define METALIC_ARRAY_2D_HXX
00030 
00031 # include <mlc/array/nd.hh>
00032 
00033 namespace mlc
00034 {
00035 
00036     //
00037     //  mlc::array2d_info
00038     //
00040     
00041 
00042     // nrows_   -> total number of rows (1-indexed)
00043     // ncols_   -> total number of columns (1-indexed)
00044 
00045     // center_  -> position of the central element (0-indexed)
00046     //             domain : [ 0, card [
00047 
00048     // i_       -> number of elements that have been eaten yet (0-indexed)
00049     //             domain : [ 0, card ] -> watch out !!
00050 
00051 
00052 
00053     // Center is user-defined
00054 
00055     template < unsigned nrows_, 
00056                unsigned ncols_,
00057                unsigned center_ = ncols_ * (nrows_ / 2) + (ncols_ / 2),
00058                unsigned i_ = nrows_ * ncols_>
00059     struct array2d_info
00060     {
00061       enum {
00062         nrows = nrows_,
00063         ncols = ncols_,
00064         center = center_,
00065         center_row = center_ / ncols_,
00066         center_col = center_ % ncols_,
00067         card = nrows_ * ncols_,
00068         i = i_,
00069         well_formed = ((i_ % ncols_) == 0),
00070         get_real_center = center_
00071       };
00072 
00073       typedef array2d_info< nrows_, ncols_, center_, i + 1 > next_elt;
00074 
00075     };
00076     
00077     // Center is defined automatically, if nrows and ncols are both odd
00078 
00079     template < unsigned nrows_, unsigned ncols_, unsigned i_ >
00080     struct array2d_info <nrows_, ncols_, internal::unknown_, i_ >
00081     {
00082       enum {
00083         nrows = nrows_,
00084         ncols = ncols_,
00085         center = internal::unknown_,
00086         i = i_,
00087         card = nrows_ * ncols_,
00088         well_formed = ((i_ % ncols_) == 0),
00089         get_real_center = i_ / 2
00090       };
00091 
00092       typedef array2d_info< nrows_, ncols_, internal::unknown_, i + 1 > next_elt;
00093 
00094     };
00095 
00096     // fwd decl
00097     template<class, class> struct array2d;
00098 
00099 
00100     namespace internal 
00101     {
00102 
00103       // fwd decl
00104 
00105       template<class T, class Info>
00106       struct array2d_elt_;
00107 
00108       // for error messages
00109 
00110       template<class U>
00111       struct here_a_value_is_not_of_type_;
00112 
00113 
00114       //
00115       //  mlc::internal::array2d_start_ decl
00116       //
00118 
00119       template<class T>
00120       struct array2d_start_ {
00121 
00122         array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > > 
00123         operator=(T val);
00124         
00125         array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > > 
00126         operator=(x_<T> val);
00127         
00128         array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > > 
00129         operator=(x_<void> val);
00130 
00131         T ptr[max_card_]; // could be static
00132       };
00133 
00134 
00135       //
00136       //  mlc::internal::array2d_elt_
00137       //
00139 
00140       template<class T, class Info>
00141       struct array2d_elt_
00142       {
00143         typedef array2d_elt_< T, typename Info::next_elt >
00144         next_elt_t_;
00145 
00146         typedef array2d_elt_< T, array2d_info< Info::nrows, Info::ncols, Info::i, Info::i + 1> >
00147         eat_center_t_;
00148 
00149         typedef array2d_elt_< T, array2d_info< Info::nrows, Info::i, Info::center, Info::i > >
00150         eat_lbrk_t_;
00151 
00152         typedef array2d< array2d_info< Info::i / Info::ncols, Info::ncols, Info::get_real_center, Info::i > , T>
00153         array2d_t_;
00154 
00155       public:
00156         
00157         // Constructor
00158 
00159         array2d_elt_(T* ptr, array2d_start_<T>* arr) : ptr(ptr), arr(arr)
00160         {
00161         }
00162 
00163 
00164         //
00165         // Overloading "operator,"
00166         //
00167 
00168 
00169         // elt, elt
00170 
00171         next_elt_t_ operator,(T val)
00172         {
00173           is_true<Info::nrows == unknown_>::ensure();
00174           *ptr = val;
00175           return next_elt_t_(ptr + 1, arr);
00176         }
00177 
00178 
00179         // elt, x(elt)          -> center
00180 
00181         eat_center_t_ operator,(x_<T> val)
00182         {
00183           is_true<Info::center == unknown_>::ensure();
00184           *ptr = val.ue; // FIXME : give a *name* to this variable !!
00185           return eat_center_t_(ptr + 1, arr);
00186         }
00187 
00188 
00189         // elt, x()             -> center
00190 
00191         eat_center_t_ operator,(x_<void>)
00192         {
00193           is_true<Info::center == unknown_>::ensure();
00194           *ptr = T(0);
00195           return eat_center_t_(ptr + 1, arr);
00196         }
00197 
00198 
00199         // elt, lbrk
00200 
00201         eat_lbrk_t_ operator,(lbrk_)
00202         {
00203           is_true<Info::ncols == unknown_>::ensure();
00204           is_true<Info::ncols != 0>::ensure();
00205           return eat_lbrk_t_(ptr, arr);
00206         }
00207 
00208 
00209         // elt, end
00210         
00211         array2d_t_ operator,(end_type)
00212         {
00213           enum { nrows = Info::i / Info::ncols };
00214           
00215           // array is well-formed :
00216           is_true<Info::well_formed == true>::ensure();
00217           // centering is automatic or user-defined :
00218           
00219           is_true<Info::ncols != unknown_>::ensure();
00220 
00221 
00222           // both nrows and ncols must be odd 
00223           // or the center must be user-defined
00224 
00225           is_true<       
00226             ((Info::ncols % 2 == 1) && (nrows % 2 == 1)) 
00227             || (Info::center != unknown_)
00228           >::ensure();
00229           
00230           return array2d_t_(arr->ptr);
00231         }
00232         
00233 
00234         // else -> error
00235 
00236         template<class U>
00237         void operator,(array2d< Info, U >);
00238 
00239         template<class U>
00240         here_a_value_is_not_of_type_<T> operator,(U u) const;
00241 
00242         T* ptr;
00243         array2d_start_<T>* arr;
00244       };
00245 
00246 
00247 
00248       //
00249       //  mlc::internal::array2d_start_  impl
00250       //
00252 
00253       template<class T> inline 
00254       array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > >
00255       array2d_start_<T>::operator=(T val)
00256       {
00257         ptr[0] = val;
00258         return array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > >(ptr+1,this);
00259       }
00260 
00261       template<class T> inline 
00262       array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >
00263       array2d_start_<T>::operator=(x_<T> val)
00264       {
00265         ptr[0] = val.ue;
00266         // center <- 0
00267         return array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >(ptr+1,this);
00268       }
00269 
00270       template<class T> inline 
00271       array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >
00272       array2d_start_<T>::operator=(x_<void> val)
00273       {
00274         ptr[0] = T(0);
00275         // center <- 0
00276         return array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >(ptr+1,this);
00277       }
00278 
00279     } // end of internal
00280 
00281 } // end of mlc
00282 
00283 #endif // ! METALIC_ARRAY_2D_HXX

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