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_CORE_DETAILS_ITERATOR_SUBARRAY_ND_ITERATOR_HPP 00025 #define IVL_CORE_DETAILS_ITERATOR_SUBARRAY_ND_ITERATOR_HPP 00026 00027 00028 namespace ivl { 00029 00030 namespace data { 00031 /* 00032 template <class T, class IT, bool REF_IS_ND, bool CONST, int SPECIALIZED = 0> 00033 class subarray_nd_iterator 00034 { 00035 }; 00036 */ 00037 00038 template <class T, class IT, class CONST_IT, 00039 bool REF_IS_ND, bool CONST, int SPECIALIZED = 0, 00040 bool PAST_END_CAPABLE = true> 00041 class subarray_nd_iterator 00042 : public data::data_details:: 00043 iter_operator_expander< 00044 subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, CONST, SPECIALIZED, 00045 PAST_END_CAPABLE>, 00046 T, CONST, 00047 typename types::remove_const<typename IT::reference>::type> 00048 { 00049 private: 00050 template <class J, class Y, class V, bool R, bool C, int S, bool P> 00051 friend class subarray_nd_iterator; 00052 00053 friend class array_nd_details:: 00054 subarray_tools<typename types::t_expr<REF_IS_ND>::type>; 00055 00056 typedef array_nd_details::subarray_common_tools ctool; 00057 00058 typedef array_nd_details:: 00059 subarray_tools<typename types::t_expr<REF_IS_ND>::type> tool; 00060 00061 template <class X, class Y, bool C, class Z> 00062 friend class data::data_details::iter_operator_expander; 00063 00064 typedef typename types::apply_const<T, types::t_expr<CONST> > 00065 ::type best_value_type; 00066 00067 typedef typename types::apply_const<typename IT::reference, 00068 types::t_expr<CONST> >::type best_ref_type; 00069 00070 // this class is used to disable specific specialization members 00071 // this class is used to disable non-const operator [] for const_operators 00072 class not_a_type { operator size_t() { return 0; } }; 00073 00074 typedef typename types::t_if<types::t_expr<CONST>, not_a_type, 00075 types::code_word<> >::type invalid_if_const; 00076 00077 typedef array_nd_details::subarray_common_tools::sub_type sub_type; 00078 00079 protected: 00080 /* typedef typename types::t_if<types::t_expr< 00081 (!REF_IS_ND && PAST_END_CAPABLE && 00082 !data::iterator_extended_traits<IT>::is_past_end_capable::value)>, 00083 data::past_end_capable_iterator<IT>, IT>::type ref_iter_type; 00084 */ 00085 typedef iterator_nd_details::it_wrapper<typename IT::value_type, IT, 00086 PAST_END_CAPABLE && !REF_IS_ND, types::is_ptr<IT>::value> ref_iter_type; 00087 /* 00088 typename types::t_if<types::t_expr<REF_IS_ND && PAST_END_CAPABLE && 00089 !data::iterator_extended_traits<IT>::is_past_end_capable::value)>, 00090 data::past_end_capable_iterator<IT>, IT>::type ref_iter_type; 00091 */ 00092 ref_iter_type ptr; 00093 size_t step; 00094 ptrdiff_t posit; 00095 const size_t* idx; 00096 ptrdiff_t* diff; 00097 ptrdiff_t cur_pos; // -1 means either no array or singleton array 00098 sub_type type_deprecated; 00099 ivl::array<size_t, tiny> pos; 00100 00101 inline typename types::apply_const<best_ref_type>::type base( 00102 types::code_word<> ok = types::code_word<>()) const 00103 { return (*ptr); } 00104 00105 inline best_ref_type base( 00106 invalid_if_const disable = invalid_if_const()) 00107 { return (*ptr); } 00108 00109 00110 public: 00111 typedef subarray_nd_iterator this_type; 00112 00113 // iterator_traits 00114 typedef std::random_access_iterator_tag iterator_category; 00115 typedef T value_type; 00116 typedef ptrdiff_t difference_type; 00117 typedef best_value_type* pointer; 00118 typedef best_ref_type reference; 00119 00120 typedef types::t_false has_base_iterator; 00121 00122 typedef IT reference_iterator; 00123 00124 struct iter_nd_dir_type 00125 { 00126 IT ptr; 00127 }; 00128 00129 //todo: basically i need to put dir_type instead of iterator in the definition 00130 // of border_walker(in tool), though the problem is i have not created such a 00131 // type for array. that would be useful for many reasons. used also in the 00132 // iterator, in array, instead of iters, for moving around. and hold only 00133 // the 4 iterators begin end rbegin rend in the iters array. (though that'd 00134 // make 2 pointers/iter overhead). 00135 00136 /*typedef typename tool::template 00137 iter_nd_border_walker<subarray_nd_iterator<T, CONST_IT, CONST_IT, 00138 REF_IS_ND, true, 0> > iter_nd_border_walker;*/ 00139 typedef typename tool::template 00140 iter_nd_border_walker<CONST_IT> iter_nd_border_walker; 00141 00142 // constructors 00143 subarray_nd_iterator() { } 00144 template<class S> 00145 subarray_nd_iterator( 00146 const IT& ptr, 00147 size_t step, 00148 ptrdiff_t posit, 00149 const size_t* idx, 00150 ptrdiff_t* diff, 00151 ptrdiff_t cur_pos, 00152 sub_type type, 00153 const array<size_t, S>& pos) : 00154 ptr(types::code_word<>(), ptr), step(step), posit(posit), idx(idx), diff(diff), 00155 cur_pos(cur_pos), type_deprecated(type), pos(pos) 00156 { } 00157 00158 subarray_nd_iterator( 00159 const IT& ptr, 00160 size_t step, 00161 ptrdiff_t posit, 00162 const size_t* idx, 00163 ptrdiff_t* diff, 00164 ptrdiff_t cur_pos, 00165 sub_type type, 00166 size_t pos_size, size_t pos_dim, size_t pos_val 00167 ) : 00168 ptr(types::code_word<>(), ptr), step(step), posit(posit), idx(idx), diff(diff), 00169 cur_pos(cur_pos), type_deprecated(type) 00170 { pos.resize(pos_size, 0); pos[pos_dim] = pos_val; } 00171 00172 00173 subarray_nd_iterator( 00174 const IT& ptr, 00175 size_t step, 00176 ptrdiff_t posit, 00177 const size_t* idx, 00178 ptrdiff_t* diff, 00179 ptrdiff_t cur_pos, 00180 sub_type type, 00181 size_t pos_size 00182 ) : 00183 ptr(types::code_word<>(), ptr), step(step), posit(posit), idx(idx), diff(diff), 00184 cur_pos(cur_pos), type_deprecated(type), pos(pos_size, size_t(0)) 00185 { } 00186 00187 template<class S> 00188 subarray_nd_iterator( 00189 const IT& ptr, 00190 size_t step, 00191 ptrdiff_t posit, 00192 const size_t* idx, 00193 ptrdiff_t* diff, 00194 ptrdiff_t cur_pos, 00195 sub_type type, 00196 array<size_t, S> pos, size_t pos_dim, size_t pos_val 00197 ) : 00198 ptr(types::code_word<>(), ptr), step(step), posit(posit), idx(idx), diff(diff), 00199 cur_pos(cur_pos), type_deprecated(type), pos(pos) 00200 { pos[pos_dim] = pos_val; } 00201 00202 subarray_nd_iterator(const this_type& it) : 00203 ptr(it.ptr), step(it.step), posit(it.posit), idx(it.idx), diff(it.diff), 00204 cur_pos(it.cur_pos), type_deprecated(it.type_deprecated), pos(it.pos) { } 00205 00206 00207 00208 template <bool C, int S> 00209 subarray_nd_iterator( 00210 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00211 PAST_END_CAPABLE>& it) 00212 : 00213 ptr(types::code_word<>(), it.ptr), step(it.step), posit(it.posit), idx(it.idx), diff(it.diff), 00214 cur_pos(it.cur_pos), type_deprecated(it.type_deprecated), pos(it.pos) { } 00215 00216 00217 00218 //copy same type iterator 00219 this_type& operator=(const this_type& it) 00220 { 00221 ptr = it.ptr; 00222 step = it.step; 00223 posit = it.posit; 00224 idx = it.idx; 00225 diff = it.diff; 00226 cur_pos = it.cur_pos; 00227 type_deprecated = it.type_deprecated; 00228 pos = it.pos; 00229 return *this; 00230 } 00231 00232 //copy relevant type iterator 00233 template <bool C, int S> 00234 this_type& operator=( 00235 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00236 PAST_END_CAPABLE>& it) 00237 { 00238 using namespace types; 00239 00240 ptr = it.ptr; 00241 step = it.step; 00242 00243 // skip these assignments 00244 r_if<t_expr<S != 1> >(posit, types::skip()) = it.posit; 00245 r_if<t_expr<S != 1> >(idx, types::skip()) = it.idx; 00246 r_if<t_expr<S != 1> >(diff, types::skip()) = it.diff; 00247 //r_if<t_expr<S != 1> >(cur_pos, types::skip()) = it.cur_pos; 00248 cur_pos = r_if<t_expr<S != 1> >(it.cur_pos, -1); 00249 00250 type_deprecated = it.type_deprecated; 00251 pos = it.pos; 00252 return *this; 00253 } 00254 00255 00256 // members 00257 00258 // increment-decrement 00259 inline this_type& operator++() 00260 { 00261 //TODO: create the specialized versions: 00262 // 1: for step 00263 // 2: for array 00264 // 0: for the following with if: 00265 if(cur_pos >= 0) { 00266 ptr += *(diff++); 00267 posit++; 00268 00269 } else { 00270 ptr += step; 00271 } 00272 return *this; 00273 } 00274 00275 inline this_type& operator--() 00276 { 00277 if(cur_pos >= 0) { 00278 ptr -= *(--diff); 00279 posit--; 00280 00281 } else { 00282 ptr -= step; 00283 } 00284 return *this; 00285 } 00286 00287 this_type operator++(int) { this_type tmp(*this); ++(*this); return tmp; } 00288 this_type operator--(int) { this_type tmp(*this); --(*this); return tmp; } 00289 00291 this_type& operator +=(ptrdiff_t j) 00292 { 00293 //TODO: create the specialized versions: 00294 // 1: for step 00295 // 2: for array 00296 // 0: for the following with if: 00297 if(cur_pos >= 0) { 00298 00299 size_t last = idx[posit]; 00300 posit += j; 00301 diff += j; 00302 ptr += step * (idx[posit] - last); 00303 00304 } else { 00305 ptr += step * j; 00306 } 00307 return *this; 00308 } 00309 00310 this_type& operator -=(ptrdiff_t j) 00311 { 00312 //TODO: create the specialized versions: 00313 // 1: for step 00314 // 2: for array 00315 // 0: for the following with if: 00316 if(cur_pos >= 0) { 00317 00318 size_t last = idx[posit]; 00319 posit -= j; 00320 diff -= j; 00321 ptr += step * (idx[posit] - last); 00322 00323 } else { 00324 ptr -= step * j; 00325 } 00326 return *this; 00327 } 00328 00330 this_type& operator +=(const iter_nd_border_walker& b) 00331 { 00332 //TODO: create the specialized versions: 00333 // 1: for step, which excludes posit 00334 // 2: for array, and 0: same as below 00335 // TODO: ensure non-array has invalid curpos!! 00336 if(b.cur_pos >= 0) { // b is for an array dimension 00337 if(cur_pos == b.cur_pos) { 00338 posit += b.len; 00339 diff += b.len; 00340 } else { 00341 pos[b.cur_pos] += b.len; 00342 } 00343 } 00344 00345 tool::move_ref_along(this->ptr, b.it, b.step, 1); 00346 00347 return *this; 00348 } 00349 00350 this_type& operator -=(const iter_nd_border_walker& b) 00351 { 00352 //TODO: create the specialized versions: 00353 // 1: for step, which excludes posit 00354 // 2: for array, and 0: same as below 00355 if(b.cur_pos >= 0) { // b is for an array dimension 00356 if(cur_pos == b.cur_pos) { 00357 posit -= b.len; 00358 diff -= b.len; 00359 } else { 00360 pos[b.cur_pos] -= b.len; 00361 } 00362 } 00363 00364 tool::move_ref_along(this->ptr, b.it, -b.step, 1); 00365 00366 00367 return *this; 00368 } 00369 00370 template <bool C, int S, bool P> 00371 void inc_along_other_dim_at_begin(const subarray_nd_iterator<T, IT, CONST_IT, 00372 REF_IS_ND, C, S, P>& it) 00373 // 1. other it must be at begin 00374 // 2. must be of different direction 00375 { 00376 //TODO: create specialized by SP x S versions of inc along 00377 //if(it.type == ctool::array_it) { 00378 if(it.cur_pos >= 0) { 00379 00380 tool::move_ref_along(this->ptr, it.ptr, 00381 *(it.diff + (pos[it.cur_pos]++)), 1); 00382 00383 } else { 00384 00385 tool::inc_along(*this, it); 00386 } 00387 } 00388 00389 template <bool C, int S, bool P> 00390 void dec_along_other_dim_at_begin(const subarray_nd_iterator<T, IT, CONST_IT, 00391 REF_IS_ND, C, S, P>& it) 00392 // 1. other it must be at begin 00393 // 2. must be of different direction 00394 { 00395 //TODO: create specialized by SP x S versions of inc along 00396 //if(it.type == ctool::array_it) { 00397 if(it.cur_pos >= 0) { 00398 00399 tool::move_ref_along(this->ptr, it.ptr, 00400 -*(it.diff + (--pos[it.cur_pos])), 1); 00401 00402 } else { 00403 00404 tool::dec_along(*this, it); 00405 } 00406 } 00407 00408 template <bool C, int S, bool P> 00409 void move_along(const subarray_nd_iterator<T, IT, CONST_IT, 00410 REF_IS_ND, C, S, P>& it, 00411 ptrdiff_t j) 00412 // none of these holds! 00413 // 1. other it must be at begin 00414 // 2. must be of different direction 00415 { 00416 //TODO: create specialized by SP x S versions of inc along 00417 //if(it.type == ctool::array_it) { 00418 if(it.cur_pos >= 0) { 00419 00420 if(cur_pos == it.cur_pos) { 00421 00422 size_t last = idx[posit]; 00423 posit += j; 00424 diff += j; 00425 ptr += step * (idx[posit] - last); 00426 00427 } else { 00428 00429 size_t& p(pos[it.cur_pos]); 00430 ptrdiff_t last = it.idx[p]; 00431 p += j; 00432 tool::move_along(*this, it, it.idx[p] - last); 00433 00434 } 00435 } else { 00436 00437 // TODO: ensure this calls the correct offset displacement 00438 // for singleton-dim arrays, and if not try to set step 00439 // accordingly, to make so. 00440 tool::move_along(*this, it, j); 00441 } 00442 } 00443 00444 template <class J> 00445 inline this_type operator +(const J& j) const 00446 { 00447 this_type tmp(*this); 00448 tmp += j; 00449 return tmp; 00450 } 00451 00452 template <class J> 00453 inline this_type operator -(const J& j) const 00454 { 00455 this_type tmp(*this); 00456 tmp -= j; 00457 return tmp; 00458 } 00459 00461 template<bool C, int S, bool P> 00462 ptrdiff_t operator -( 00463 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, P>& it) 00464 { 00465 // note: only for itertors of the same dim. 00466 //TODO: create the specialized versions: 00467 // 1: for step 00468 // 2: for array 00469 // 0: for the following with if: 00470 if(cur_pos >= 0) { 00471 return posit - it.posit; 00472 00473 } else { 00474 00475 return (ptr - it.ptr) / step; 00476 } 00477 } 00478 00480 template<bool C, int S> 00481 bool operator==( 00482 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00483 PAST_END_CAPABLE>& it) const 00484 { 00485 return (ptr == it.ptr); 00486 } 00487 00488 template<bool C, int S> 00489 bool operator!=( 00490 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00491 PAST_END_CAPABLE>& it) const 00492 { 00493 return (ptr != it.ptr); 00494 } 00495 00496 template<bool C, int S> 00497 bool operator<( 00498 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00499 PAST_END_CAPABLE>& it) const 00500 { 00501 //TODO: specializations 00502 if(cur_pos >= 0) { 00503 return posit < it.posit; 00504 00505 } else { 00506 return (step > 0) ? (ptr < it.ptr) : (it.ptr < ptr); 00507 } 00508 } 00509 00510 template<bool C, int S> 00511 bool operator<=( 00512 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00513 PAST_END_CAPABLE>& it) const 00514 { 00515 return (*this == it || *this < it); 00516 } 00517 00518 template<bool C, int S> 00519 bool operator>( 00520 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00521 PAST_END_CAPABLE>& it) const 00522 { 00523 return (!(*this == it) && !(*this < it)); 00524 } 00525 00526 template<bool C, int S> 00527 bool operator>=( 00528 const subarray_nd_iterator<T, IT, CONST_IT, REF_IS_ND, C, S, 00529 PAST_END_CAPABLE>& it) const 00530 { 00531 return (!(*this < it)); 00532 } 00533 00534 }; 00535 00536 00537 00538 } /*namespace data */ 00539 00540 namespace subarray_iter_create { 00541 00542 template <class IT, class A> 00543 IT _begin(A& a, size_t d) 00544 { 00545 size_t j = a.nonsing_rmap[d]; 00546 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00547 00548 return IT(a.get_iter(j), a.steps[j], 0, (*a.idx)[d].c_ptr(), a.diffs[j], 00549 k, a.type_from_indtype((*a.idx)[d].indtype), 00550 a.idx_ar_map.length()); 00551 } 00552 00553 template <class IT, class A> 00554 IT _begin(A& a, size_t d, const IT& it) 00555 { 00556 size_t j = a.nonsing_rmap[d]; 00557 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00558 00559 return IT(it.ptr, a.steps[j], it.pos[k < 0 ? 0 : k], (*a.idx)[d].c_ptr(), 00560 a.diffs[j], k, a.type_from_indtype((*a.idx)[d].indtype), it.pos); 00561 } 00562 00563 template <class IT, class ITS, class A> 00564 IT _iter(A& a, size_t d, const ITS& it) 00565 { 00566 size_t j = a.nonsing_rmap[d]; 00567 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00568 00569 return iterator_nd(it.ir, a.steps[j], it.pos0, (*a.idx)[d].c_ptr(), 00570 a.diffs[j], k, a.type_from_indtype((*a.idx)[d].indtype), it.pos, 00571 1, it.get_pos1()); 00572 00573 /*return _begin(d, it);*/ 00574 } 00575 00576 template <class IT, class S, class A> 00577 IT _iter(A& a, size_t d, const array<size_t, S>& ind) 00578 { 00579 typename IT::reference_iterator it = a.iter[-3]; 00580 00581 array<size_t, tiny> pos(a.idx_ar_map.length()); 00582 for(size_t i = 0; i < ind.length(); i++) { 00583 size_t q = a.idx_ar_rmap[i]; 00584 size_t n = a.nonsing_rmap[i]; 00585 if(q < 0) { 00586 A::tool::move_along(it, a.iter[n], a.steps[n], ind[i]); 00587 } else { 00588 A::tool::move_along(it, a.iter[n], a.steps[n], (*a.idx)[i][ind[i]]); 00589 pos[q] = ind[i]; 00590 } 00591 } 00592 size_t j = a.nonsing_rmap[d]; 00593 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00594 00595 return IT(it, a.steps[j], ind[d], (*a.idx)[d].c_ptr(), a.diffs[j], 00596 k, a.type_from_indtype((*a.idx)[d].indtype), pos); 00597 } 00598 00599 template <class IT, class A> 00600 IT _next(A& a, size_t d, const IT& it) 00601 { 00602 typename IT::reference_iterator itp = it.ptr; 00603 00604 size_t j = a.nonsing_rmap[d]; 00605 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00606 00607 A::tool::move_along(itp, a.iter[j], 1, a.begin_to_end[j]); 00608 00609 if(k < 0) // maybe could also be discriminated from indtype 00610 return IT(itp, a.steps[j], a.sizes[j], (*a.idx)[d].c_ptr(), a.diffs[j], 00611 k, a.type_from_indtype((*a.idx)[d].indtype), it.pos); 00612 else 00613 return IT(itp, a.steps[j], a.sizes[j], (*a.idx)[d].c_ptr(), a.diffs[j], 00614 k, a.type_from_indtype((*a.idx)[d].indtype), it.pos, 00615 k, a.sizes[j]); 00616 } 00617 00618 template <class IT, class A> 00619 IT _end(A& a, size_t d) 00620 { 00621 size_t j = a.nonsing_rmap[d]; 00622 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00623 00624 typename IT::reference_iterator it = a.get_iter(j); 00625 00626 it += a.begin_to_ends[j]; 00627 00628 if(k < 0) 00629 return IT(it, a.steps[j], a.sizes[j], (*a.idx)[d].c_ptr(), a.diffs[j], 00630 k, a.type_from_indtype((*a.idx)[d].indtype), 00631 a.idx_ar_map.length()); 00632 else 00633 return IT(it, a.steps[j], a.sizes[j], (*a.idx)[d].c_ptr(), a.diffs[j], 00634 k, a.type_from_indtype((*a.idx)[d].indtype), 00635 a.idx_ar_map.length(), k, a.sizes[j]); 00636 } 00637 00638 template <class IT, class A> 00639 IT _last(A& a, size_t d) 00640 { 00641 size_t j = a.nonsing_rmap[d]; 00642 ptrdiff_t k = a.idx_ar_rmap[d]; // cur_pos 00643 00644 typename IT::reference_iterator it = a.get_iter(j); 00645 00646 it += a.first_to_lasts[j]; 00647 00648 if(k < 0) 00649 return IT(it, a.steps[j], a.sizes[j] - 1, 00650 (*a.idx)[d].c_ptr(), a.diffs[j], 00651 k, a.type_from_indtype((*a.idx)[d].indtype), 00652 a.idx_ar_map.length()); 00653 else 00654 return IT(it, a.steps[j], a.sizes[j] - 1, 00655 (*a.idx)[d].c_ptr(), a.diffs[j], 00656 k, a.type_from_indtype((*a.idx)[d].indtype), 00657 a.idx_ar_map.length(), k, a.sizes[j]); 00658 } 00659 00660 }; // namespace subarray_iter_create 00661 00662 } /*namespace ivl */ 00663 00664 #endif // IVL_CORE_DETAILS_ITERATOR_SUBARRAY_ND_ITERATOR_HPP