vtf-logo

ArrayIndexingBase.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00008 #if !defined(__ArrayIndexingBase_h__)
00009 #define __ArrayIndexingBase_h__
00010 
00011 // If we are debugging the whole ads package.
00012 #if defined(DEBUG_ads) && !defined(DEBUG_ArrayIndexingBase)
00013 #define DEBUG_ArrayIndexingBase
00014 #endif
00015 
00016 #include "FixedArray.h"
00017 #include "IndexRange.h"
00018 
00019 #include <iostream>
00020 
00021 BEGIN_NAMESPACE_ADS
00022 
00024 
00027 template <int N>
00028 class ArrayIndexingBase {
00029   //
00030   // Public types.
00031   //
00032 
00033 public:
00034 
00036 
00042   typedef int size_type;
00043 
00045   typedef FixedArray<N,int> index_type;
00047   typedef IndexRange<N,int> range_type;
00048 
00049 private:
00050 
00051   //
00052   // Member data.
00053   //
00054 
00055   // Extents (lengths) in each dimension.
00056   index_type _extents;
00057   // The index ranges.
00058   range_type _ranges;
00059   // Strides between elements in each dimension.
00060   index_type _strides;
00061 
00062 protected:
00063 
00064   //--------------------------------------------------------------------------
00066   // @{
00067 
00069   ArrayIndexingBase() :
00070     _extents(0),
00071     _ranges(),
00072     _strides(0)
00073   {}
00074 
00076   ArrayIndexingBase(const ArrayIndexingBase& x) :
00077     _extents(x._extents),
00078     _ranges(x._ranges),
00079     _strides(x._strides)
00080   {}
00081 
00083   ArrayIndexingBase& 
00084   operator=(const ArrayIndexingBase& x) {
00085     if (&x != this) {
00086       _extents = x._extents;
00087       _ranges = x._ranges;
00088       _strides = x._strides;
00089     }
00090     return *this;
00091   }
00092 
00094   explicit
00095   ArrayIndexingBase(const index_type& extents) :
00096     _extents(extents),
00097     _ranges(extents),
00098     _strides() {
00099     compute_strides();
00100   }
00101 
00103   void
00104   rebuild(const index_type& extents) {
00105     _extents = extents;
00106     _ranges.set_lbounds(index_type(0));
00107     _ranges.set_ubounds(extents);
00108     compute_strides();
00109   }
00110 
00112   explicit
00113   ArrayIndexingBase(const range_type& ranges) :
00114     _extents(ranges.extents()),
00115     _ranges(ranges),
00116     _strides() {
00117     compute_strides();
00118   }
00119 
00121   void
00122   rebuild(const range_type& ranges) {
00123     _extents = ranges.extents();
00124     _ranges = ranges;
00125     compute_strides();
00126   }
00127 
00129   void
00130   swap(ArrayIndexingBase& x) {
00131     _extents.swap(x._extents);
00132     _ranges.swap(x._ranges);
00133     _strides.swap(x._strides);
00134   }
00135 
00137   ~ArrayIndexingBase()
00138   {}
00139 
00140   // @}
00141 
00142 public:
00143 
00144   //--------------------------------------------------------------------------
00146   // @{
00147 
00149   static
00150   int
00151   rank() {
00152     return N;
00153   }
00154 
00155   // @}
00156   //--------------------------------------------------------------------------
00158   // @{
00159 
00161   const index_type&
00162   extents() const { 
00163     return _extents; 
00164   }
00165 
00167   size_type 
00168   extent(const int i) const { 
00169     return _extents[i]; 
00170   }
00171 
00173   const range_type&
00174   ranges() const { 
00175     return _ranges; 
00176   }
00177 
00179   const index_type&
00180   lbounds() const { 
00181     return _ranges.lbounds();
00182   }
00183 
00185   const index_type&
00186   ubounds() const { 
00187     return _ranges.ubounds();
00188   }
00189 
00191   int
00192   lbound(const int i) const { 
00193     return _ranges.lbound(i);
00194   }
00195 
00197   int
00198   ubound(const int i) const { 
00199     return _ranges.ubound(i);
00200   }
00201 
00203   const index_type& 
00204   strides() const {
00205     return _strides;
00206   }
00207 
00208   // @}
00209   //--------------------------------------------------------------------------
00211   // @{
00212 
00214   int
00215   index(const index_type& mi) const {
00216     static index_type translated_indices;
00217 #ifdef DEBUG_ArrayIndexing
00218     assert(_ranges.is_in(mi));
00219 #endif
00220     translated_indices = mi;
00221     translated_indices -= _ranges.lbounds();
00222     return internal::dot(translated_indices, _strides);
00223   }
00224 
00226 
00229   int
00230   index(const int i0, const int i1) const { 
00231     LOKI_STATIC_CHECK(N == 2, Dimension_must_be_2); 
00232 #ifdef DEBUG_ArrayIndexing
00233     assert(_ranges.is_in(i0, i1));
00234 #endif
00235     return (i0 - _ranges.lbound(0)) * _strides[0] + 
00236       (i1 - _ranges.lbound(1)) * _strides[1];
00237   }
00238 
00240 
00243   int
00244   index(const int i0, const int i1, const int i2) const { 
00245     LOKI_STATIC_CHECK(N == 3, Dimension_must_be_3); 
00246 #ifdef DEBUG_ArrayIndexing
00247     assert(_ranges.is_in(i0, i1, i2));
00248 #endif
00249     return (i0 - _ranges.lbound(0)) * _strides[0] + 
00250       (i1 - _ranges.lbound(1)) * _strides[1] + 
00251       (i2 - _ranges.lbound(2)) * _strides[2];
00252   }
00253 
00255 
00258   void 
00259   index_to_indices(const int index, int& i, int& j) const {
00260     LOKI_STATIC_CHECK(N == 2, Dimension_must_be_2);
00261 #ifdef DEBUG_ArrayIndexing
00262     assert(_strides[0] == 1);
00263 #endif
00264     j = index / _strides[1] + _ranges.lbound(1);
00265     i = index % _strides[1] + _ranges.lbound(0);
00266 #ifdef DEBUG_ArrayIndexing
00267     assert(_ranges.is_in(i, j));
00268 #endif
00269   }
00270 
00272 
00275   void 
00276   index_to_indices(int index, int& i, int& j, int& k) const {
00277     LOKI_STATIC_CHECK(N == 3, Dimension_must_be_3);
00278 #ifdef DEBUG_ArrayIndexing
00279     assert(_strides[0] == 1);
00280 #endif
00281     k = index / _strides[2] + _ranges.lbound(2);
00282     index %= _strides[2];
00283     j = index / _strides[1] + _ranges.lbound(1);
00284     i = index % _strides[1] + _ranges.lbound(0);
00285 #ifdef DEBUG_ArrayIndexing
00286     assert(_ranges.is_in(i, j, k));
00287 #endif
00288   }
00289 
00291 
00294   void 
00295   index_to_indices(const int index, ads::FixedArray<2,int>& multi_index) const
00296   {
00297     index_to_indices(index, multi_index[0], multi_index[1]);
00298   }
00299 
00301 
00304   void 
00305   index_to_indices(const int index, ads::FixedArray<3,int>& multi_index) const
00306   {
00307     index_to_indices(index, multi_index[0], multi_index[1], multi_index[2]);
00308   }
00309 
00310   // @}
00311   //--------------------------------------------------------------------------
00313   // @{
00314 
00316   void
00317   put(std::ostream& out) const {
00318     out << ranges() << '\n';
00319   }
00320 
00322   void
00323   write(std::ostream& out) const {
00324     out.write(reinterpret_cast<const char*>(& _ranges), 
00325                sizeof(range_type));
00326   }
00327 
00328   // @}
00329   //--------------------------------------------------------------------------
00331   // @{
00332   
00334   bool
00335   operator==(const ArrayIndexingBase<N>& x) const {
00336     return ranges() == x.ranges();
00337   }
00338 
00339   // @}
00340 
00341 protected:
00342 
00343   //
00344   // Protected member functions.
00345   //
00346 
00348   void
00349   compute_strides() {
00350     _strides[0] = 1;
00351     for (int i = 1; i != N; ++i) {
00352       _strides[i] = _strides[i-1] * _extents[i-1];
00353     }
00354   }
00355 
00357   int
00358   root_offset(const index_type& mi) const {
00359 #ifdef DEBUG_ArrayIndexing
00360     assert(_ranges.is_in(mi));
00361 #endif
00362     return internal::dot(mi, _strides);
00363   }
00364 
00366   int
00367   root_offset(const int i0, const int i1) const { 
00368     LOKI_STATIC_CHECK(N == 2, Dimension_must_be_2); 
00369 #ifdef DEBUG_ArrayIndexing
00370     assert(_ranges.is_in(i0, i1));
00371 #endif
00372     return i0 * _strides[0] + i1 * _strides[1];
00373   }
00374 
00376   int
00377   root_offset(const int i0, const int i1, const int i2) const { 
00378     LOKI_STATIC_CHECK(N == 3, Dimension_must_be_3); 
00379 #ifdef DEBUG_ArrayIndexing
00380     assert(_ranges.is_in(i0, i1, i2));
00381 #endif
00382     return i0 * _strides[0] + i1 * _strides[1] + i2 * _strides[2];
00383   }
00384 
00385 };
00386 
00387 END_NAMESPACE_ADS
00388 
00389 #define __ArrayIndexingBase1_h__
00390 #include "ArrayIndexingBase1.h"
00391 #undef __ArrayIndexingBase1_h__
00392 
00393 #endif

Generated on Fri Aug 24 12:55:22 2007 for Algorithms and Data Structures Package by  doxygen 1.4.7