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_SPECIALIZATION_DETAILS_SUBARRAY_ITERATOR_HPP 00025 #define IVL_ARRAY_SPECIALIZATION_DETAILS_SUBARRAY_ITERATOR_HPP 00026 00027 namespace ivl { 00028 00029 namespace data { 00030 00031 00032 template <class T, class IT, class BEST_IT, 00033 bool REF_IS_ND, bool CONST, int SPECIALIZED = 0> 00034 class subarray_iterator_type 00035 { 00036 }; 00037 00038 template <class T, class IT, class BEST_IT, bool CONST, int SPECIALIZED> 00039 class subarray_iterator_type<T, IT, BEST_IT, false, CONST, SPECIALIZED> 00040 : public data::data_details:: 00041 iter_operator_expander< 00042 subarray_iterator_type<T, IT, BEST_IT, false, CONST, SPECIALIZED>, 00043 T, CONST, typename IT::reference> 00044 { 00045 private: 00046 typedef IT reference_iterator; 00047 typedef BEST_IT best_reference_iterator; 00048 00049 template <class J, class Y, class Z, bool R, bool C, int S> 00050 friend class subarray_iterator_type; 00051 00052 typedef array_details::subarray_common_tools ctool; 00053 00054 /* 00055 A little notice: 00056 This code was intended to be here: 00057 friend class data::data_details::iter_operator_expander 00058 <subarray_iterator_type, T, CONST, typename IT::reference>; 00059 however MSVC does not like it, so instead of making portability hacks 00060 I will rather generalize the declaration. I've also done this in other places. 00061 */ 00062 template <class X, class Y, bool C, class Z> 00063 friend class data::data_details::iter_operator_expander; 00064 00065 typedef typename types::apply_const<T, types::t_expr<CONST> > 00066 ::type best_value_type; 00067 00068 typedef typename types::apply_const<typename IT::reference, 00069 types::t_expr<CONST> >::type best_ref_type; 00070 00071 // this class is used to disable specific specialization members 00072 class not_a_type { }; 00073 00074 typedef typename types::t_if<types::t_expr<CONST>, not_a_type, 00075 types::code_word<> >::type invalid_if_const; 00076 00077 protected: 00078 reference_iterator ir; 00079 const size_t* sizes; 00080 size_t size0; 00081 const ptrdiff_t* const* diffs; 00082 const ptrdiff_t* diff0; 00083 ptrdiff_t step0; 00084 const ptrdiff_t* back; 00085 internal::little_arrayling<ptrdiff_t> pos; 00086 size_t pos0; 00087 00088 inline size_t get_pos1() const { return pos[1]; } 00089 00090 inline typename types::apply_const<typename IT::reference>::type base( 00091 types::code_word<> ok = types::code_word<>()) const 00092 { return (*ir); } 00093 00094 inline best_ref_type base( 00095 invalid_if_const disable = invalid_if_const()) 00096 { return (*ir); } 00097 00098 public: 00099 typedef subarray_iterator_type this_type; 00100 00101 // iterator_traits 00102 typedef std::bidirectional_iterator_tag iterator_category; 00103 typedef T value_type; 00104 typedef ptrdiff_t difference_type; 00105 typedef best_value_type* pointer; 00106 typedef best_ref_type reference; 00107 00108 struct iter_border_walker 00109 { 00110 char type; // 0: stay. 1: first_to_last. 2: begin_to_end 00111 ptrdiff_t step; 00112 iter_border_walker(ptrdiff_t x) : type(0), step(0) { } 00113 iter_border_walker(ptrdiff_t x, char t) : type(t), step(x) { } 00114 }; 00115 00116 // constructors 00117 subarray_iterator_type() { } 00118 subarray_iterator_type(const this_type& it) 00119 : ir(it.ir), sizes(it.sizes), size0(it.size0), diffs(it.diffs), 00120 diff0(it.diff0), step0(it.step0), back(it.back), 00121 pos(it.pos), pos0(it.pos0) { } 00122 00123 template <class Y, bool C, int S> 00124 subarray_iterator_type( 00125 const subarray_iterator_type<T, Y, BEST_IT, false, C, S>& it) 00126 : ir(it.ir), sizes(it.sizes), size0(it.size0), diffs(it.diffs), 00127 diff0(it.diff0), step0(it.step0), back(it.back), 00128 pos(it.pos), pos0(it.pos0) { } 00129 00130 template <class Y> 00131 subarray_iterator_type( 00132 const Y& ir, 00133 const best_reference_iterator* iter, 00134 size_t ndims, 00135 const size_t* sizes, 00136 const ptrdiff_t* const* diffs, 00137 const ptrdiff_t* steps, 00138 const ptrdiff_t* back, 00139 bool ending, 00140 ptrdiff_t outer_pos) : 00141 ir(ir), 00142 sizes(sizes), 00143 diffs(diffs), 00144 step0(steps[0]), 00145 back(back), 00146 pos(ndims + 1) 00147 { 00148 diff0 = diffs[0]; 00149 size0 = sizes[0]; 00150 00151 if(!ending) { 00152 for(size_t j = 0; j <= ndims; j++) 00153 pos[j] = 0; 00154 00155 } else { 00156 00157 for(size_t j = 0; j < ndims; j++) 00158 pos[j] = sizes[j] - 1; 00159 } 00160 00161 pos[ndims] = outer_pos; 00162 pos0 = pos[0]; 00163 } 00164 00165 //copy same type iterator 00166 this_type& operator=(const this_type& it) 00167 { 00168 ir = it.ir; 00169 sizes = it.sizes; 00170 size0 = it.size0; 00171 diffs = it.diffs; 00172 diff0 = it.diff0; 00173 step0 = it.step0; 00174 back = it.back; 00175 pos = it.pos; 00176 pos0 = it.pos0; 00177 00178 return *this; 00179 } 00180 00181 //copy relevant type iterator 00182 template<class Y, bool C, int S> 00183 this_type& operator=(const subarray_iterator_type<T, Y, 00184 BEST_IT, true, C, S>& it) 00185 { 00186 ir = it.ir; 00187 sizes = it.sizes; 00188 size0 = it.size0; 00189 diffs = it.diffs; 00190 diff0 = it.diff0; 00191 step0 = it.step0; 00192 pos = it.pos; 00193 pos0 = it.pos0; 00194 back = it.back; 00195 00196 return *this; 00197 } 00198 00199 // members 00200 00201 // increment-decrement 00202 inline this_type& operator++() 00203 { 00204 if(++pos0 >= size0) { 00205 pos0 = 0; 00206 00207 size_t i = 1; 00208 while(/*i < pos.length() &&*/ ++pos[i] >= ptrdiff_t(sizes[i])) { 00209 pos[i++] = 0; 00210 } 00211 00212 ir += back[i - 1]; 00213 if(diffs[i]) 00214 ir += diffs[i][pos[i] - 1]; 00215 00216 } 00217 else { 00218 ctool::inner_dim_adder<SPECIALIZED>::template 00219 operate<ctool::add_op>(ir, diff0, pos0 - 1, step0); 00220 } 00221 return *this; 00222 } 00223 00224 inline this_type& operator--() 00225 { 00226 if(--pos0 < 0) { 00227 pos0 = size0 - 1; 00228 00229 size_t i = 1; 00230 while(/*i < pos.length() &&*/ --pos[i] < 0) { 00231 pos[i] = sizes[i] - 1; 00232 i++; 00233 } 00234 ir -= back[i - 1]; 00235 if(diffs[i]) 00236 ir -= diffs[i][pos[i]]; 00237 } 00238 else { 00239 ctool::inner_dim_adder<SPECIALIZED>::template 00240 operate<ctool::sub_op>(ir, diff0, pos0, step0); 00241 } 00242 return *this; 00243 } 00244 00245 this_type operator++(int) { this_type tmp(*this); ++(*this); return tmp; } 00246 this_type operator--(int) { this_type tmp(*this); --(*this); return tmp; } 00247 00249 this_type& operator +=(size_t j) 00250 { 00251 CHECK(j == 1, ecomp); 00252 ++(*this); 00253 return *this; 00254 } 00256 this_type& operator -=(size_t j) 00257 { 00258 CHECK(j == 1, ecomp); 00259 --(*this); 00260 return *this; 00261 } 00262 inline this_type operator +(size_t j) const 00263 { 00264 CHECK(j == 1, ecomp); 00265 this_type tmp(*this); 00266 ++(*this); 00267 return tmp; 00268 } 00269 inline this_type operator -(size_t j) const 00270 { 00271 CHECK(j == 1, ecomp); 00272 this_type tmp(*this); 00273 --(*this); 00274 return tmp; 00275 } 00276 00277 this_type& operator +=(const iter_border_walker& b) 00278 { 00279 ir += b.step; 00280 00281 size_t p = pos.length() - 1; 00282 00283 if(b.type == 1 || (b.type && pos[p] != 1)) { 00284 // first to last or begin to end, added from begin-1 00285 00286 for(size_t i = 1; i < p; i++) 00287 pos[i] = sizes[i] - 1; 00288 00289 pos[p] = 1; 00290 00291 pos0 = size0 - 1; 00292 00293 } else if(b.type == 2) { // begin to end, added from begin 00294 00295 pos[p] = 2; // end 00296 00297 } 00298 return *this; 00299 } 00300 00301 this_type& operator -=(const iter_border_walker& b) 00302 { 00303 ir += b.step; 00304 00305 size_t p = pos.length() - 1; 00306 00307 if(b.type == 1 || (b.type && pos[p] != 1)) { 00308 // first to last or begin to end, subtracted from end 00309 00310 for(size_t i = 1; i < p; i++) 00311 pos[i] = 0; 00312 00313 pos[p] = 1; 00314 00315 pos0 = 0; 00316 00317 } else if(b.type == 2) { // begin to end, subtracted from end-1 00318 00319 pos[p] = 0; // begin-1 00320 00321 } 00322 return *this; 00323 } 00324 00325 00326 inline this_type operator +(const iter_border_walker& b) const 00327 { 00328 this_type tmp(*this); 00329 tmp += b; 00330 return tmp; 00331 } 00332 inline this_type operator -(const iter_border_walker& b) const 00333 { 00334 this_type tmp(*this); 00335 tmp -= b; 00336 return tmp; 00337 } 00338 00339 // difference is not implemented. 00340 // this is a non-random_access iterator. 00341 00342 00343 bool operator==(const this_type& it) const { return (ir == it.ir); } 00344 bool operator!=(const this_type& it) const { return (ir != it.ir); } 00345 00346 }; 00347 00348 template <class T, class IT, class BEST_IT, 00349 bool CONST, int SPECIALIZED> 00350 class subarray_iterator_type<T, IT, BEST_IT, true, CONST, SPECIALIZED> 00351 : public data::data_details:: 00352 iter_operator_expander< 00353 subarray_iterator_type<T, IT, BEST_IT, true, CONST, SPECIALIZED>, T, CONST, 00354 typename IT::reference> 00355 { 00356 private: 00357 typedef IT reference_iterator; 00358 typedef BEST_IT best_reference_iterator; 00359 00360 template <class J, class Y, class Z, bool R, bool C, int S> 00361 friend class subarray_iterator_type; 00362 00363 typedef array_details::subarray_common_tools ctool; 00364 00365 template <class X, class Y, bool C, class Z> 00366 friend class data::data_details::iter_operator_expander; 00367 00368 typedef typename types::apply_const<T, types::t_expr<CONST> > 00369 ::type best_value_type; 00370 00371 typedef typename types::apply_const<typename IT::reference, 00372 types::t_expr<CONST> >::type best_ref_type; 00373 00374 // this class is used to disable specific specialization members 00375 class not_a_type { }; 00376 00377 typedef typename types::t_if<types::t_expr<CONST>, not_a_type, 00378 types::code_word<> >::type invalid_if_const; 00379 00380 00381 protected: 00382 00383 00384 00385 reference_iterator ir; 00386 const best_reference_iterator* iter; 00387 reference_iterator it1; 00388 const size_t* sizes; 00389 size_t size0; 00390 size_t size1; 00391 const ptrdiff_t* const* diffs; 00392 const ptrdiff_t* diff0; 00393 const ptrdiff_t* diff1; 00394 const ptrdiff_t* steps; 00395 size_t step0; 00396 size_t step1; 00397 const ptrdiff_t* back; 00398 ptrdiff_t back0; 00399 ptrdiff_t back1; 00400 internal::little_arrayling<size_t> pos; 00401 size_t pos0; 00402 size_t pos1; 00403 00404 inline size_t get_pos1() const { return pos1; } 00405 00406 inline typename IT::reference base( 00407 types::code_word<> ok = types::code_word<>()) const 00408 { return (*ir); } 00409 00410 inline best_ref_type base( 00411 invalid_if_const disable = invalid_if_const()) 00412 { return (*ir); } 00413 00414 public: 00415 typedef subarray_iterator_type this_type; 00416 00417 // iterator_traits 00418 typedef std::bidirectional_iterator_tag iterator_category; 00419 typedef T value_type; 00420 typedef ptrdiff_t difference_type; 00421 typedef best_value_type* pointer; 00422 typedef best_ref_type reference; 00423 00424 struct iter_border_walker 00425 { 00426 char type; // 0: stay. 1: first_to_last. 2: begin_to_end 00427 iter_border_walker(ptrdiff_t x) : type(0) { } 00428 iter_border_walker(ptrdiff_t x, char t) : type(t) { } 00429 }; 00430 00431 00432 // constructors 00433 subarray_iterator_type() { } 00434 subarray_iterator_type(const this_type& it) 00435 : ir(it.ir), iter(it.iter), it1(it.it1), sizes(it.sizes), 00436 size0(it.size0), size1(it.size1), diffs(it.diffs), diff0(it.diff0), 00437 diff1(it.diff1), steps(it.steps), step0(it.step0), step1(it.step1), 00438 back(it.back), back0(it.back0), back1(it.back1), pos(it.pos), 00439 pos0(it.pos0), pos1(it.pos1) { } 00440 00441 template <class Y, bool C, int S> 00442 subarray_iterator_type( 00443 const subarray_iterator_type<T, Y, BEST_IT, false, C, S>& it) 00444 : ir(it.ir), iter(it.iter), it1(it.it1), sizes(it.sizes), 00445 size0(it.size0), size1(it.size1), diffs(it.diffs), diff0(it.diff0), 00446 diff1(it.diff1), steps(it.steps), step0(it.step0), step1(it.step1), 00447 back(it.back), back0(it.back0), back1(it.back1), pos(it.pos), 00448 pos0(it.pos0), pos1(it.pos1) { } 00449 00450 template <class Y> 00451 subarray_iterator_type( 00452 const Y& ir, 00453 const best_reference_iterator* iter, 00454 size_t ndims, 00455 const size_t* sizes, 00456 const ptrdiff_t* const* diffs, 00457 const ptrdiff_t* steps, 00458 const ptrdiff_t* back, 00459 bool ending, 00460 ptrdiff_t outer_pos) : 00461 ir(ir), 00462 iter(iter), 00463 sizes(sizes), 00464 diffs(diffs), 00465 steps(steps), 00466 back(back), 00467 pos(ndims + 1) 00468 { 00469 diff0 = diffs[0]; 00470 diff1 = diffs[1]; 00471 size0 = sizes[0]; 00472 size1 = sizes[1]; 00473 step0 = steps[0]; 00474 step1 = steps[1]; 00475 back0 = back[0]; 00476 back1 = back[1]; 00477 00478 if(ndims > 1) 00479 it1 = iter[1]; 00480 00481 if(!ending) { 00482 00483 for(size_t j = 0; j <= ndims; j++) 00484 pos[j] = 0; 00485 00486 } else { 00487 00488 for(size_t j = 0; j < ndims; j++) 00489 pos[j] = sizes[j] - 1; 00490 } 00491 00492 pos[ndims] = outer_pos; 00493 pos0 = pos[0]; 00494 pos1 = ndims <= 1 ? 0 : pos[1]; 00495 } 00496 00497 // members 00498 00499 // increment-decrement 00500 00501 inline this_type& operator++() 00502 { 00503 int i; 00504 00505 if(++pos0 >= size0) { 00506 pos0 = 0; 00507 00508 ir -= back0; 00509 if(++pos1 < size1) { 00510 ctool::inc_along(ir, it1, diff1, pos1 - 1, step1); 00511 00512 } else { 00513 // TODO: ensure in the case of ndim == 1 to have: 00514 // first_to_last1 = 0 00515 // pos = minimum 3, instead of 1+1 = 2. 00516 // pos1 = 0, pos[1] = 0 00517 // sizes[1]=size1 =0 in that case. so sizes = minimum 2. 00518 // size1 = 0 is adequate for all the above line. 00519 pos1 = 0; 00520 ir.move_along(it1, -back1); 00521 i = 2; 00522 /*if(pos[pos.length() - 1] == 0) { // begin-1 to begin 00523 ir = iter[-3]; 00524 for(; i < pos.length(); i++) 00525 pos[i] = 0; 00526 pos[i] = 1; 00527 i++; // to disable both while and if below 00528 }*/ 00529 while(i < pos.length() && ++pos[i] >= sizes[i]) { 00530 pos[i] = 0; 00531 ir.move_along(iter[i], -back[i]); 00532 i++; 00533 } 00534 if(i == pos.length()) { // end-1 to end 00535 pos[i] = 2; 00536 ir = iter[-1]; 00537 } else { 00538 ctool::inc_along(ir, iter[i], 00539 diffs[i], pos[i] - 1, steps[i]); 00540 } 00541 } 00542 } 00543 else { 00544 ctool::inner_dim_adder<SPECIALIZED>::template 00545 operate<ctool::add_op>(ir, diff0, pos0 - 1, step0); 00546 } 00547 return *this; 00548 } 00549 00550 inline this_type& operator--() 00551 { 00552 int i; 00553 00554 if(--pos0 < 0) { 00555 pos0 = size0 - 1; 00556 00557 ir += back0; 00558 if(--pos1 >= 0) { 00559 ctool::dec_along(ir, it1, diff1, pos1, step0); 00560 00561 } else { 00562 00563 pos1 = size1 - 1; 00564 ir.move_along(it1, back1); 00565 i = 2; 00566 if(pos[pos.length() - 1] == 2) { // end to end-1 00567 ir = iter[-2]; 00568 for(; i < pos.length(); i++) 00569 pos[i] = sizes[i] - 1; 00570 pos[i] = 1; 00571 i++; 00572 } 00573 while(i < pos.length() && --pos[i] < 0) { 00574 pos[i] = sizes[i] - 1; 00575 ir.move_along(iter[i], back[i]); 00576 i++; 00577 } 00578 /*if(i == pos.length()) { // begin to begin-1 00579 pos[i] = 0; 00580 ir = iter[-4]; 00581 } else */{ 00582 ctool::dec_along(ir, iter[i], diffs[i], pos[i], steps[i]); 00583 } 00584 } 00585 } 00586 else { 00587 ctool::inner_dim_adder<SPECIALIZED>::template 00588 operate<ctool::sub_op>(ir, diff0, pos0, step0); 00589 } 00590 return *this; 00591 } 00592 00593 this_type operator++(int) { this_type tmp(*this); ++(*this); return tmp; } 00594 this_type operator--(int) { this_type tmp(*this); --(*this); return tmp; } 00595 00597 this_type& operator +=(size_t j) 00598 { 00599 CHECK(j == 1, ecomp); 00600 ++(*this); 00601 return *this; 00602 } 00604 this_type& operator -=(size_t j) 00605 { 00606 CHECK(j == 1, ecomp); 00607 --(*this); 00608 return *this; 00609 } 00610 inline this_type operator +(size_t j) const 00611 { 00612 CHECK(j == 1, ecomp); 00613 this_type tmp(*this); 00614 ++(*this); 00615 return tmp; 00616 } 00617 inline this_type operator -(size_t j) const 00618 { 00619 CHECK(j == 1, ecomp); 00620 this_type tmp(*this); 00621 --(*this); 00622 return tmp; 00623 } 00624 00625 00626 this_type& operator +=(const iter_border_walker& b) 00627 { 00628 size_t p = pos.length() - 1; 00629 00630 if(b.type == 1 /*|| (b.type && pos[p] != 1)*/) { 00631 // first to last [[or begin to end, added from begin-1]] 00632 00633 for(size_t i = 2; i < p; i++) 00634 pos[i] = sizes[i] - 1; 00635 00636 pos[p] = 1; 00637 00638 pos0 = size0 - 1; 00639 pos1 = size1 - 1; 00640 00641 ir = iter[-2]; 00642 00643 } else if(b.type == 2) { // begin to end, added from begin 00644 00645 pos[p] = 2; // end 00646 00647 ir = iter[-1]; 00648 00649 } 00650 return *this; 00651 } 00652 00653 this_type& operator -=(const iter_border_walker& b) 00654 { 00655 size_t p = pos.length() - 1; 00656 00657 //if(b.type == 1 || (b.type && pos[p] != 1)) { 00658 // first to last or begin to end, subtracted from end 00659 00660 for(size_t i = 2; i < p; i++) 00661 pos[i] = 0; 00662 00663 pos[p] = 1; 00664 00665 pos0 = 0; 00666 pos1 = 0; 00667 00668 ir = iter[-3]; 00669 00670 /*} else if(b.type == 2) { // begin to end, subtracted from end-1 00671 00672 pos[p] = 0; // begin-1 00673 00674 ir = iter[-1]; 00675 00676 }*/ 00677 return *this; 00678 } 00679 00680 inline this_type operator +(const iter_border_walker& b) const 00681 { 00682 this_type tmp(*this); 00683 tmp += b; 00684 return tmp; 00685 } 00686 inline this_type operator -(const iter_border_walker& b) const 00687 { 00688 this_type tmp(*this); 00689 tmp -= b; 00690 return tmp; 00691 } 00692 00693 // difference is not implemented. 00694 // this is a non-random_access iterator. 00695 00696 //copy same type iterator 00697 this_type& operator=(const this_type& it) 00698 { 00699 ir = it.ir; 00700 iter = it.iter; 00701 it1 = it.it1; 00702 sizes = it.sizes; 00703 size0 = it.size0; 00704 size1 = it.size1; 00705 diffs = it.diffs; 00706 diff0 = it.diff0; 00707 diff1 = it.diff1; 00708 steps = it.steps; 00709 step0 = it.step0; 00710 step1 = it.step1; 00711 back = it.back; 00712 back0 = it.back0; 00713 back1 = it.back1; 00714 pos = it.pos; 00715 pos0 = it.pos0; 00716 pos1 = it.pos1; 00717 00718 return *this; 00719 } 00720 //copy relevant type iterator 00721 template<class J, bool C, int S> 00722 this_type& operator=(const subarray_iterator_type<T, J, 00723 BEST_IT, true, C, S>& it) 00724 { 00725 ir = it.ir; 00726 iter = it.iter; 00727 it1 = it.it1; 00728 sizes = it.sizes; 00729 size0 = it.size0; 00730 size1 = it.size1; 00731 diffs = it.diffs; 00732 diff0 = it.diff0; 00733 diff1 = it.diff1; 00734 steps = it.steps; 00735 step0 = it.step0; 00736 step1 = it.step1; 00737 back = it.back; 00738 back0 = it.back0; 00739 back1 = it.back1; 00740 pos = it.pos; 00741 pos0 = it.pos0; 00742 pos1 = it.pos1; 00743 00744 return *this; 00745 } 00746 00747 bool operator==(const this_type& it) const { return (ir == it.ir); } 00748 bool operator!=(const this_type& it) const { return (ir != it.ir); } 00749 bool operator<(const this_type& it) const 00750 { 00751 size_t p = pos.length() - 1; 00752 // we will also consider the last pos in the < operator 00753 // which is not a pos in a valid dimension but rather 00754 // a 'pseudo pos' indicating if we are after the array data. (end). 00755 for(; p > 0; p--) if(pos[p] < it.pos[p]) return true; 00756 return pos0 < it.pos0; 00757 } 00758 bool operator>(const this_type& it) const 00759 { 00760 // same as above 00761 size_t p = pos.length() - 1; 00762 for(; p > 0; p--) if(pos[p] > it.pos[p]) return true; 00763 return pos0 > it.pos0; 00764 } 00765 bool operator<=(const this_type& it) const 00766 { return this_type::operator<(it) || this_type::operator==(it); } 00767 bool operator>=(const this_type& it) const 00768 { return this_type::operator>(it) || this_type::operator==(it); } 00769 00770 }; 00771 00772 00773 }; /*namespace data */ 00774 00775 }; /*namespace ivl*/ 00776 00777 #endif // IVL_ARRAY_SPECIALIZATION_DETAILS_SUBARRAY_ITERATOR_HPP