00001
00002
00008 #if !defined(__ArrayIndexingBase_h__)
00009 #define __ArrayIndexingBase_h__
00010
00011
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
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
00053
00054
00055
00056 index_type _extents;
00057
00058 range_type _ranges;
00059
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
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