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 #if 1 00025 00030 template <class T, 00031 class A1, 00032 class A2, 00033 int CATDIM, 00034 class DERIVED_INFO 00035 > 00036 class array<T, data::catarray<A1, A2, CATDIM, DERIVED_INFO> > 00037 : 00038 public array_common_base<array<T, 00039 data::catarray<A1, A2, CATDIM, DERIVED_INFO> > >, 00040 00041 public data::referer<typename types::derive< 00042 array<T, data::catarray<A1, A2, CATDIM, 00043 DERIVED_INFO> > >::type> 00044 { 00045 private: 00046 typedef array_common_base<array<T, 00047 data::catarray<A1, A2, CATDIM, 00048 DERIVED_INFO> > > common_base_class; 00049 00050 protected: 00051 //-------------------------------------------------------------------------- 00052 // types 00053 00054 // best_reference_iterator: 00055 // defines which is the best possible iterator to be used for the 00056 // underlying array, meaning the most powerful, between the const_ 00057 // and non-const_ ones. const_ is used if the array is read only. 00058 typedef typename types::best_iterator<A1>::type best_reference_iterator1; 00059 typedef typename types::best_iterator<A2>::type best_reference_iterator2; 00060 00061 // const_reference_iterator: 00062 // defines which is the const_iterator to be used for the 00063 // underlying array. 00064 typedef typename A1::const_iterator const_reference_iterator1; 00065 typedef typename A2::const_iterator const_reference_iterator2; 00066 00067 00068 typedef best_reference_iterator1 best_ref_iter1; 00069 typedef const_reference_iterator1 const_ref_iter1; 00070 typedef best_reference_iterator2 best_ref_iter2; 00071 typedef const_reference_iterator2 const_ref_iter2; 00072 00073 #if 0 00074 // tool: 00075 // the correct specialization of the class catarray_tools that implements 00076 // functionality of the reference iterator depending of the type. 00077 typedef array_details::catarray_tools< 00078 reference_iterator_is_nd, best_ref_iter> tool; 00079 00080 00081 // some helper structs 00082 typedef array_details::catarray_common_tools ctool; 00083 00084 #endif 00085 // used to disable some types. TODO: test that not_a_type actually throws an error and 00086 // consider explicitly making the default constructor private. 00087 class not_a_type { }; 00088 00089 typedef typename types::t_if<types::t_expr<(CATDIM == -1)>, 00090 ivl::scalar<int>, ivl::fixed_scalar<int, CATDIM> >::type catdim_t; 00091 00092 00093 //-------------------------------------------------------------------------- 00094 // members 00095 A1* in1; 00096 A2* in2; 00097 catdim_t cdim; 00098 size_t catstride, catstride1, catstride2; 00099 size_t all_len; 00100 00101 00102 // helper data that is computed on the construction of the catarray 00103 // object, needed to improve speed. 00104 00105 00106 00107 00108 //-------------------------------------------------------------------------- 00109 // functions 00110 00111 public: 00112 void init(A1& a1, A2& a2, catdim_t cdim = -1); 00113 void init(const array& o); 00114 00115 typedef array this_type; 00116 00117 typedef this_type this_array_type; 00118 00119 typedef this_type array_type; 00120 00121 typedef T elem_type; 00122 00123 typedef typename best_reference_iterator1::reference reference; 00124 typedef typename best_reference_iterator1::reference best_reference; 00125 typedef typename const_reference_iterator1::reference const_reference; 00126 00127 typedef typename common_base_class::derived_type derived_type; 00128 00129 typedef typename common_base_class::base_class base_class; 00130 00132 typedef size_t size_type; 00133 00134 using base_class::derived; 00135 00136 00137 00138 struct iter_border_walker 00139 { 00140 typedef typename A1::iter_border_walker t1; 00141 typedef typename A2::iter_border_walker t2; 00142 t1 s1; 00143 t2 s2; 00144 ptrdiff_t sp; 00145 00146 iter_border_walker() {} 00147 iter_border_walker(const t1& s1, const t2& s2, ptrdiff_t sp) 00148 : s1(s1), s2(s2), sp(sp) { } 00149 }; 00150 00151 template<bool CONST, int SPEC = 0> 00152 class iterator_type 00153 : public types::t_if<typename array::has_random_access, 00154 data::data_details:: 00155 rnd_iter_operator_expander<iterator_type<CONST, SPEC>, T, CONST, 00156 typename types::remove_const<reference>::type>, 00157 data::data_details:: 00158 iter_operator_expander<iterator_type<CONST, SPEC>, T, CONST, 00159 typename types::remove_const<reference>::type > 00160 >::type, 00161 public types::border_walker_iterator_identifier 00162 { 00163 private: 00164 template <bool C, int S> friend class iterator_type; 00165 friend class array; 00166 00167 friend class iter_border_walker; 00168 00169 friend class data::data_details::iter_operator_expander 00170 <iterator_type<CONST, SPEC>, T, CONST>; 00171 friend class data::data_details::rnd_iter_operator_expander 00172 <iterator_type<CONST, SPEC>, T, CONST>; 00173 00174 typedef typename types::apply_const<T, types::t_expr<CONST> > 00175 ::type best_value_type; 00176 00177 // this class is used to disable specific specialization members 00178 class not_a_type { }; 00179 00180 typedef typename types::t_if<types::t_expr<CONST>, not_a_type, 00181 types::code_word<> >::type invalid_if_const; 00182 00183 typedef typename types::t_if<types::t_expr<CONST>, 00184 typename A1::const_iterator, 00185 typename A1::best_iterator>::type iterator1; 00186 00187 typedef typename types::t_if<types::t_expr<CONST>, 00188 typename A2::const_iterator, 00189 typename A2::best_iterator>::type iterator2; 00190 00191 typedef typename iterator1::reference prv_reference; 00192 typedef prv_reference best_ref_type; 00193 00194 iterator1 ir1; 00195 iterator2 ir2; 00196 ptrdiff_t p; 00197 size_t stride1, stride2, stride; 00198 00199 protected: 00200 inline const_reference base( 00201 types::code_word<> ok = types::code_word<>()) const 00202 { return p < stride1 ? (*ir1) : (*ir2); } 00203 00204 inline prv_reference base( 00205 invalid_if_const disable = invalid_if_const()) 00206 { return p < stride1 ? (*ir1) : (*ir2); } 00207 00208 inline typename types::apply_const<best_ref_type>::type base(size_t j, 00209 types::code_word<> ok = types::code_word<>()) const 00210 { 00211 ptrdiff_t soffs = (p + j) / stride; 00212 ptrdiff_t offs = (p + j) % stride; 00213 ptrdiff_t d; 00214 if(offs >= stride1) { 00215 d = soffs * stride2 + 00216 (p >= stride1 ? offs - p : offs); 00217 return ir2[d]; // TODO: rnd_add 00218 } else { 00219 d = soffs * stride1 + 00220 (p < stride1 ? offs - p : offs - stride1); 00221 return ir1[d]; 00222 } 00223 } 00224 00225 inline best_ref_type base(size_t j, 00226 invalid_if_const disable = invalid_if_const()) 00227 { 00228 ptrdiff_t soffs = (p + j) / stride; 00229 ptrdiff_t offs = (p + j) % stride; 00230 ptrdiff_t d; 00231 if(offs >= stride1) { 00232 d = soffs * stride2 + 00233 (p >= stride1 ? offs - p : offs); 00234 return ir2[d]; 00235 } else { 00236 d = soffs * stride1 + 00237 (p < stride1 ? offs - p : offs - stride1); 00238 return ir1[d]; 00239 } 00240 } 00241 00242 public: 00243 typedef iterator_type<CONST, 0> this_type; 00244 00245 // iterator_traits 00246 typedef typename types::t_if<typename array::has_random_access, 00247 std::random_access_iterator_tag, 00248 std::bidirectional_iterator_tag>::type iterator_category; 00249 typedef T value_type; 00250 typedef typename types::apply_const<T, types::t_expr<CONST> > 00251 ::type access_value_type; 00252 typedef ptrdiff_t difference_type; 00253 typedef access_value_type* pointer; 00254 typedef prv_reference reference; 00255 00256 // border walker 00257 typedef typename array::iter_border_walker iter_border_walker; 00258 00259 // constructors 00260 iterator_type() { } 00261 00262 iterator_type(const this_type& it) 00263 : ir1(it.ir1), ir2(it.ir2), p(it.p), 00264 stride1(it.stride1), stride2(it.stride2), stride(it.stride) 00265 { } 00266 00267 template <bool C, int S> 00268 iterator_type(const iterator_type<C, S>& it) 00269 : ir1(it.ir1), ir2(it.ir2), p(it.p), 00270 stride1(it.stride1), stride2(it.stride2), stride(it.stride) 00271 { } 00272 00273 iterator_type(const iterator1& i1, const iterator2& i2, 00274 size_t p, size_t stride1, size_t stride2, size_t stride) 00275 : ir1(i1), ir2(i2), p(p), 00276 stride1(stride1), stride2(stride2), stride(stride) {} 00277 00278 00279 // members 00280 00281 // increment-decrement 00282 this_type& operator++() 00283 { 00284 if(p++ < stride1) 00285 ++ir1; 00286 else 00287 { 00288 ++ir2; 00289 if(p >= stride) 00290 p = 0; 00291 } 00292 return *this; 00293 } 00294 this_type& operator--() 00295 { 00296 if(--p >= stride1) 00297 --ir2; 00298 else 00299 { 00300 --ir1; 00301 if(p < 0) 00302 p = stride; 00303 } 00304 return *this; 00305 } 00306 00307 this_type operator++(int) { this_type t(*this); ++(*this); return t; } 00308 this_type operator--(int) { this_type t(*this); --(*this); return t; } 00309 00310 this_type& operator +=(ptrdiff_t j) 00311 { 00312 ptrdiff_t soffs = (p + j) / stride; 00313 ptrdiff_t offs = (p + j) % stride; 00314 ptrdiff_t d; 00315 00316 if(offs >= stride1) { 00317 d = soffs * stride2 + 00318 (p >= stride1 ? offs - p : offs); 00319 ir2 += d; // TODO: rnd_add 00320 ir1 += soffs * stride1 + (p >= stride1 ? 0 : stride1 - p); 00321 } else { 00322 d = soffs * stride1 + 00323 (p < stride1 ? offs - p : offs - stride1); 00324 ir1 += d; 00325 ir2 += soffs * stride2 + (p < stride1 ? 0 : stride1 - p); 00326 } 00327 p = offs; 00328 00329 return *this; 00330 } 00331 this_type& operator -=(ptrdiff_t j) 00332 { 00333 return (*this) += (-j); 00334 } 00335 inline this_type operator +(ptrdiff_t j) const 00336 { 00337 this_type tmp(*this); 00338 tmp += j; 00339 return tmp; 00340 } 00341 inline this_type operator -(ptrdiff_t j) const 00342 { 00343 this_type tmp(*this); 00344 tmp -= j; 00345 return tmp; 00346 } 00347 00348 this_type& operator +=(iter_border_walker ib) 00349 { 00350 ir1 += ib.s1; 00351 ir2 += ib.s2; 00352 p += ib.sp; 00353 return *this; 00354 } 00355 this_type& operator -=(iter_border_walker ib) 00356 { 00357 ir1 -= ib.s1; 00358 ir2 -= ib.s2; 00359 p -= ib.sp; 00360 return *this; 00361 } 00362 inline this_type operator +(iter_border_walker j) const 00363 { 00364 this_type tmp(*this); 00365 tmp += j; 00366 return tmp; 00367 } 00368 inline this_type operator -(iter_border_walker j) const 00369 { 00370 this_type tmp(*this); 00371 tmp -= j; 00372 return tmp; 00373 } 00374 00375 // difference 00376 ptrdiff_t operator-(const this_type& o) const 00377 { 00378 ptrdiff_t d1; 00379 d1 = (ir1 - o.ir1) 00380 + (p < stride1) ? -p : 0 + (o.p < stride1) ? o.p : 0; 00381 return (d1 / stride1) * stride + p - o.p; 00382 } 00383 00384 00385 //copy same type iterator 00386 this_type& operator=(const this_type& it) 00387 { 00388 ir1 = it.ir1; ir2 = it.ir2; p = it.p; 00389 stride1 = it.stride1; stride2 = it.stride2; stride = it.stride; 00390 return *this; 00391 } 00392 //copy relevant type iterator 00393 template<bool C, int S> 00394 this_type& operator=(const iterator_type<C, S>& it) 00395 { 00396 ir1 = it.ir1; ir2 = it.ir2; p = it.p; 00397 stride1 = it.stride1; stride2 = it.stride2; stride = it.stride; 00398 return *this; 00399 } 00400 00401 bool operator==(const this_type& it) const 00402 { return (p == it.p && ir1 == it.ir1); } 00403 bool operator!=(const this_type& it) const 00404 { return (p != it.p || ir1 != it.ir1); } 00405 bool operator<(const this_type& it) const 00406 { return (ir1 < it.ir1 || (ir1 == it.ir1 && p < it.p)); } 00407 bool operator<=(const this_type& it) const 00408 { return (ir1 < it.ir1 || (ir1 == it.ir1 && p <= it.p)); } 00409 bool operator>(const this_type& it) const 00410 { return (ir1 > it.ir1 || (ir1 == it.ir1 && p > it.p)); } 00411 bool operator>=(const this_type& it) const 00412 { return (ir1 > it.ir1 || (ir1 == it.ir1 && p >= it.p)); } 00413 00414 }; 00415 00416 // typedefs for class iterators 00417 typedef typename types::t_if<typename array::is_writeable, 00418 iterator_type<false, 0>, 00419 not_a_type>::type iterator; 00420 00421 typedef iterator_type<true, 0> const_iterator; 00422 00423 typedef typename types::t_if<types::t_eq<iterator, not_a_type>, 00424 const_iterator, iterator>::type best_iterator; 00425 00426 typedef std::reverse_iterator<iterator> reverse_iterator; 00427 00428 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00429 00430 #if 0 00431 template<int SPC> 00432 struct s_iterator 00433 { 00434 typedef data::catarray_iterator_type<T, best_reference_iterator, 00435 best_reference_iterator, 00436 reference_iterator_is_nd::value, false, SPC> type; 00437 }; 00438 template<int SPC> 00439 struct const_s_iterator 00440 { 00441 typedef data::catarray_iterator_type<T, best_reference_iterator, 00442 best_reference_iterator, 00443 reference_iterator_is_nd::value, true, SPC> type; 00444 }; 00445 template<int SPC> 00446 struct reverse_s_iterator 00447 { 00448 typedef std::reverse_iterator<s_iterator<SPC> > type; 00449 }; 00450 template<int SPC> 00451 struct const_reverse_s_iterator 00452 { 00453 typedef std::reverse_iterator<const_s_iterator<SPC> > type; 00454 }; 00455 int iter_specialization() const 00456 { 00457 return itspec1; 00458 } 00459 #endif 00460 00461 iterator begin() 00462 { 00463 return iterator(in1->begin(), in2->begin(), 0, 00464 catstride1, catstride2, catstride); 00465 } 00466 00467 iterator end() 00468 { 00469 return iterator(in1->end(), in2->end(), 0, 00470 catstride1, catstride2, catstride); 00471 } 00472 00473 const_iterator begin() const 00474 { 00475 return const_iterator(in1->begin(), in2->begin(), 0, 00476 catstride1, catstride2, catstride); 00477 } 00478 00479 const_iterator end() const 00480 { 00481 return const_iterator(in1->end(), in2->end(), 0, 00482 catstride1, catstride2, catstride); 00483 } 00484 00485 // reverse iterator defs 00486 reverse_iterator rbegin() { return reverse_iterator(end()); } 00487 00488 reverse_iterator rend() { return reverse_iterator(begin()); } 00489 00490 const_reverse_iterator rbegin() const 00491 { return const_reverse_iterator(end()); } 00492 00493 const_reverse_iterator rend() const 00494 { return const_reverse_iterator(begin()); } 00495 00496 00497 iter_border_walker first_to_last() 00498 { 00499 return iter_border_walker(in1->first_to_last(), 00500 in2->first_to_last(), catstride - 1); 00501 } 00502 00503 iter_border_walker begin_to_end() 00504 { 00505 return iter_border_walker(in1->begin_to_end(), 00506 in2->begin_to_end(), catstride); 00507 } 00508 00509 00510 using common_base_class::operator[]; 00511 00512 // todo: resolve when b has no random access 00513 // todo: create a special reference class 00514 // and specialize for writing 00515 typename best_iterator::reference operator[](size_t j) 00516 { 00517 size_t so = j / catstride; 00518 size_t o = j % catstride; 00519 if(o < catstride1) 00520 return (*in1)[so * catstride1 + o]; 00521 else 00522 return (*in2)[so * catstride2 + (o - catstride1)]; 00523 } 00524 typename const_iterator::reference operator[](size_t j) const 00525 { 00526 size_t so = j / catstride; 00527 size_t o = j % catstride; 00528 if(o < catstride1) 00529 return (*in1)[so * catstride1 + o]; 00530 else 00531 return (*in2)[so * catstride2 + (o - catstride1)]; 00532 } 00533 00534 00537 //TODO: explain this better. 00539 size_t length() const 00540 { 00541 return all_len; 00542 } 00543 00545 size_type size() const { return length(); } 00546 00548 size_t numel() const { return length(); } 00556 array() { in1 = NULL; } 00557 00558 array(const array& o) { init(o); } 00559 00560 // Filler constructor 00561 array(const size_t) { in1 = NULL; } 00562 00563 array(A1& a1, A2& a2, catdim_t cd = -1) 00564 { 00565 init(a1, a2, cd); 00566 } 00567 00568 00569 void setref(A1& a1, A2& a2, catdim_t cd = -1) 00570 { 00571 init(a1, a2, cd); 00572 } 00573 00574 template <class D> 00575 bool overlap(const D& d) const 00576 { 00577 return in1->overlap(d) || in2->overlap(d); 00578 } 00579 00580 template <class D> 00581 bool self_overlap(const D& d) const 00582 { 00583 return d.overlap(*in1) || d.overlap(*in2); 00584 } 00585 00586 00587 00589 ~array() { } 00590 00591 using common_base_class::operator=; 00592 00593 this_type& operator=(const array& o) 00594 { common_base_class::operator=(o); return *this; } 00595 00596 template <class J, class P> 00597 derived_type& assign_array(const array<J, data::empty<P> >& o) 00598 { 00599 *in1 = o; 00600 *in2 = o; 00601 //copy_or_cut(o); // will always fallback to cut // todo 00602 return this->derived(); 00603 } 00604 00605 template<class D> 00606 derived_type& assign_array(const D& o) 00607 { 00608 //copy_or_cut(o); TODO 00609 static_cast<common_base_class&>(*this).assign_array(o); 00610 return this->derived(); 00611 } 00612 00613 00614 }; 00615 00616 00617 template <class T, 00618 class A1, 00619 class A2, 00620 int CD, 00621 class DERIVED_INFO 00622 > 00623 void array<T, data::catarray<A1, A2, CD, DERIVED_INFO> > 00624 ::init(const array& o) 00625 { 00626 in1 = o.in1; 00627 in2 = o.in2; 00628 cdim = o.cdim; 00629 catstride = o.catstride; 00630 catstride1 = o.catstride1; 00631 catstride2 = o.catstride2; 00632 all_len = o.all_len; 00633 } 00634 00635 template <class T, 00636 class A1, 00637 class A2, 00638 int CD, 00639 class DERIVED_INFO 00640 > 00641 void array<T, data::catarray<A1, A2, CD, DERIVED_INFO> > 00642 ::init(A1& a1, A2& a2, catdim_t cd) 00643 { 00644 in1 = &a1; 00645 in2 = &a2; 00646 cdim = cd; 00647 //notice: limits dimensions to 32 bit or native bit int 00648 catstride1 = (cdim == int(a1.ndims()) - 1) ? 00649 a1.length() : a1.stride(int(cdim) + 1); 00650 catstride2 = (cdim == int(a2.ndims()) - 1) ? 00651 a2.length() : a2.stride(int(cdim) + 1); 00652 00653 catstride = catstride1 + catstride2; 00654 00655 all_len = a1.length() + a2.length(); 00656 } 00657 00658 #endif