ivl 679
|
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>. 00002 A C++ template library extending syntax towards mathematical notation. 00003 00004 Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr> 00005 Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr> 00006 00007 ivl is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU Lesser General Public License 00009 version 3 as published by the Free Software Foundation. 00010 00011 Alternatively, you can redistribute it and/or modify it under the terms 00012 of the GNU General Public License version 2 as published by the Free 00013 Software Foundation. 00014 00015 ivl is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 See the GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 and a copy of the GNU Lesser General Public License along 00022 with ivl. If not, see <http://www.gnu.org/licenses/>. */ 00023 00024 #ifndef IVL_ARRAY_DETAILS_INDEX_ARRAY_HPP 00025 #define IVL_ARRAY_DETAILS_INDEX_ARRAY_HPP 00026 00027 namespace ivl { 00028 00029 struct index_array_all_type 00030 { 00031 }; 00032 00035 class index_array 00036 : public array<size_t, data::stack<4, true> > 00037 , public size_range 00038 { 00039 protected: 00040 00041 public: 00042 typedef array<size_t, data::stack<4, true> > size_array; 00043 00044 using size_array::operator[]; 00045 using size_array::operator=; 00046 00047 enum index_array_type { 00048 ARRAY, 00049 RANGE, 00050 ALL 00051 }; 00052 00053 index_array_type indtype; 00054 00055 // Constructors 00056 index_array() : size_array(1,(size_t)(0)), indtype(ALL) { } 00057 00058 index_array(const size_array& sa) : size_array(sa), indtype(ARRAY) { } 00059 00060 template <class S> 00061 index_array(const array<size_t, S>& sa) : size_array(sa), indtype(ARRAY) { } 00062 00063 index_array(size_t s) : size_array(1,s), indtype(ARRAY) { } 00064 00065 index_array(const size_range& sr) : size_range(sr), indtype(RANGE) { } 00066 00067 index_array(const range<int>& sr) : size_range(sr), indtype(RANGE) { } 00068 00069 index_array(const index_array_all_type& sa) : indtype(ALL) { } 00070 00071 index_array(const index_array& ia) 00072 : size_array(ia), size_range(ia), indtype(ia.indtype) { } 00073 00074 00075 // Operator= 00076 index_array& operator= (const size_array& sa) 00077 { 00078 size_array::operator=(sa); 00079 indtype = ARRAY; 00080 return *this; 00081 } 00082 00083 template <class S> 00084 index_array& operator= (const array<size_t, S>& sa) 00085 { 00086 size_array::operator=(sa); 00087 indtype = ARRAY; 00088 return *this; 00089 } 00090 00091 template <class S> 00092 index_array& operator= (size_t s) 00093 { 00094 size_array::resize(1, s); 00095 indtype = ARRAY; 00096 return *this; 00097 } 00098 00099 index_array& operator =(const size_range &a) 00100 { 00101 size_range::operator=(a); 00102 indtype = RANGE; 00103 return *this; 00104 } 00105 index_array& operator =(const range<int> &a) 00106 { 00107 size_range::operator=(a); 00108 indtype = RANGE; 00109 return *this; 00110 } 00111 00112 index_array& operator =(const index_array_all_type& sa) 00113 { 00114 indtype = ALL; 00115 return *this; 00116 } 00117 00118 index_array& operator =(const index_array &a) 00119 { 00120 const size_array &tmp = a; 00121 size_array::operator=(tmp); 00122 size_range::operator=(a); 00123 indtype = a.indtype; 00124 return *this; 00125 } 00126 00127 00128 00129 inline bool is_all() const; 00130 inline bool is_array() const; 00131 inline bool is_range() const; 00132 inline size_t length() const; 00133 inline size_t length(const size_array& sizes, size_t dim = 0) const; 00134 inline size_t starts() const; 00135 inline size_t ends() const; 00136 inline size_t steps() const; 00137 inline size_array cast() const; 00138 00139 inline size_array& as_array() 00140 { 00141 return static_cast<size_array&>(*this); 00142 } 00143 inline const size_array& as_array() const 00144 { 00145 return static_cast<const size_array&>(*this); 00146 } 00147 inline size_range& as_range() 00148 { 00149 return static_cast<size_range&>(*this); 00150 } 00151 inline const size_range& as_range() const 00152 { 00153 return static_cast<const size_range&>(*this); 00154 } 00155 }; 00156 00157 inline 00158 size_t index_array::length() const 00159 { 00160 switch (indtype) { 00161 case ARRAY: 00162 return size_array::length(); 00163 case RANGE: 00164 return size_range::length(); 00165 default: 00166 // In case we have ALL, the length is not known. 00167 // We need the array this index is applied to to compute it. 00168 return 0; 00169 } 00170 } 00171 00172 inline 00173 size_t index_array::length(const size_array& sizes, size_t dim) const 00174 { 00175 switch (indtype) { 00176 case ARRAY: 00177 return size_array::length(); 00178 case RANGE: 00179 return size_range::length(); 00180 case ALL: 00181 return sizes[dim]; 00182 default: 00183 return 0; 00184 } 00185 } 00186 00187 inline 00188 size_t index_array::starts() const 00189 { 00190 switch (indtype) { 00191 case ARRAY: 00192 return size_array::operator[](0); 00193 case RANGE: 00194 return size_range::first; 00195 case ALL: 00196 default: 00197 return 0; 00198 } 00199 } 00200 00201 inline 00202 size_t index_array::ends() const 00203 { 00204 switch (indtype) { 00205 case ARRAY: 00206 return size_array::operator[](length() - 1); 00207 case RANGE: 00208 return size_range::last; 00209 case ALL: 00210 default: 00211 return 0; 00212 } 00213 } 00214 00215 inline 00216 size_t index_array::steps() const 00217 { 00218 switch (indtype) { 00219 case RANGE: 00220 return size_range::step; 00221 case ALL: 00222 return 1; 00223 case ARRAY: 00224 return 1; // steps() is meaningless in case of array. 00225 // however the minimum step is 1 and has to be returned 00226 // because it is used in subarray. 00227 default: 00228 return 0; 00229 } 00230 } 00231 00232 inline 00233 index_array::size_array index_array::cast() const 00234 { 00235 size_array a; 00236 const size_array& myself = *this; 00237 00238 switch (indtype) { 00239 case RANGE: 00240 a = size_array(size_range::length()); 00241 for (size_t i = 0; i < a.length(); i++) 00242 a[i] = first + i * step; 00243 return a; 00244 case ALL: 00245 return size_array(0); 00246 case ARRAY: 00247 return myself; 00248 default: 00249 return size_array(0); 00250 } 00251 } 00252 00253 /* 00254 inline index_array::type index_array::index_type() const 00255 { 00256 return indtype; 00257 } 00258 */ 00259 00260 inline 00261 bool index_array::is_all() const 00262 { 00263 return (indtype == ALL); 00264 } 00265 00266 inline 00267 bool index_array::is_array() const 00268 { 00269 return (indtype == ARRAY); 00270 } 00271 00272 inline 00273 bool index_array::is_range() const 00274 { 00275 return (indtype == RANGE); 00276 } 00277 00279 inline 00280 std::ostream& operator<<(std::ostream& os, const index_array& a) 00281 { 00282 if (a.is_all()) 00283 os << ":"; 00284 else if(a.is_range()) 00285 os << a.as_range(); 00286 else if(a.is_array()) 00287 os << a.as_array(); 00288 00289 return os; 00290 } 00291 00292 // index_array NON_MEMBER FUNCTIONS 00293 00294 inline 00295 index_array_all_type all() 00296 { 00297 return index_array_all_type(); 00298 } 00299 00300 } // namespace ivl 00301 00302 #endif // IVL_ARRAY_DETAILS_INDEX_ARRAY_HPP