00001 #ifndef GRAL_GB_SEQUENCE_INDEXMAP_ND_H 00002 #define GRAL_GB_SEQUENCE_INDEXMAP_ND_H 00003 00004 00005 /* ------------------------------------------------------------ 00006 00007 Copyright (C) 1997 - 2009 Guntram Berti 00008 00009 This file is part of the Grid Algorithms Library (GrAL), 00010 available at http://gral.berti-cmm.de 00011 00012 GrAL is distributed under the MIT license, 00013 see the file LICENSE or http://gral.berti-cmm.de/license 00014 00015 --------------------------------------------------------------- */ 00016 00017 00018 #include "Container/tuple.h" 00019 #include "Container/tuple-point-traits.h" 00020 #include "Utility/pre-post-conditions.h" 00021 00022 00023 namespace GrAL { 00024 00039 template<unsigned N> 00040 class index_map_nd { 00041 public: 00042 00043 typedef tuple<int,N> index_type; 00044 private: 00045 index_type low; 00046 index_type n; 00047 index_type prod; // prod[k] = n[k+1]* ... *n[N-1] 00048 00049 public: 00051 index_map_nd() : low(0), n(0) { init(); } 00052 00059 index_map_nd(index_type const& nn) : low(0), n(nn) { init();} 00068 index_map_nd(index_type const& low_, 00069 index_type const& beyond_) : low(low_), n(beyond_-low_) {init();} 00070 private: 00071 void init() 00072 { 00073 prod[N-1] = 1; 00074 for(int k = (int)N-2; k >= 0; --k) { 00075 // sort out degenerate cases: 00076 // n[k+1] <= 0 means empty range: nk1 = 0,=> prod[0] = 0 00077 int nk1 = (n[k+1] > 0 ? n[k+1] : 0); 00078 prod[k] = prod[k+1]*nk1; 00079 } 00080 } 00081 00082 public: 00083 // the next two operators could probably be made more 00084 // efficient by using template metaprogramming 00097 int operator()(index_type const& p) const 00098 { 00099 c(p); 00100 int res = 0; 00101 index_type pp = p - min_tuple(); 00102 for(int k = N-1; k >= 0; --k) { 00103 res += prod[k]*pp[k]; 00104 } 00105 return res; 00106 } 00109 index_type operator()(int i) const 00110 { 00111 c(i); 00112 index_type res; 00113 int remainder = i; 00114 for(unsigned k = 0; k < N; ++k) { 00115 if(n[k] == 1) // 'flat' dimension: skip 00116 res[k] = 0; 00117 else 00118 res[k] = remainder / prod[k]; 00119 remainder -= prod[k]*res[k]; 00120 // prod[N-1] = 1 => remainder = 0 for k = N-1 00121 } 00122 return res + min_tuple(); 00123 } 00128 00130 bool valid(index_type const& p) const { 00131 bool res = true; 00132 for(unsigned k = 0; k < N; ++k) 00133 res = res && ( low[k] <= p[k] && p[k] < low[k]+n[k]); 00134 return res; 00135 } 00137 bool valid(int i) const { 00138 return (0 <= i && i <= max_flat_index()); 00139 } 00145 00148 index_type max_tuple() const { 00149 index_type mx; 00150 for(unsigned k = 0; k < N; ++k) 00151 mx[k] = low[k]+n[k]-1; 00152 return mx; 00153 } 00155 index_type min_tuple() const { return low;} 00157 index_type beyond_tuple() const { return low + n;} 00163 index_type size() const { return n;} 00164 00166 int min_flat_index() const { return 0;} 00168 int max_flat_index() const { return n[0]*prod[0] -1;} 00170 unsigned flat_size() const { return 1+ max_flat_index() - min_flat_index();} 00173 private: 00174 void c(index_type const& p) const { REQUIRE(valid(p), "p = " << p 00175 << " min=" << min_tuple() 00176 << " max=" << max_tuple(), 1); 00177 } 00178 void c(int i) const { REQUIRE(valid(i), "i = " << i 00179 << " min=" << min_flat_index() 00180 << " max=" << max_flat_index(), 1); 00181 } 00182 }; 00183 00184 } // namespace GrAL 00185 00186 00187 #endif 00188 00189 00190 00191 00192 00193
1.5.8