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 00025 namespace array_details { 00026 00027 template<bool IS_CONTENT_RESIZEABLE> 00028 struct indirect_tools 00029 { 00030 template<class A> 00031 static void shrink(A& a, size_t j) { } 00032 00033 template<class A_IT, class B> 00034 static size_t cut(A_IT a, const B& b, size_t len) { return 0; } 00035 }; 00036 00037 template<> 00038 struct indirect_tools<true> 00039 { 00040 template<class A> 00041 static void shrink(A& a, size_t j) 00042 { 00043 a.resize(j); 00044 } 00045 00046 template<class A_IT, class B> 00047 static size_t cut(A_IT a, const B& b, size_t len); 00048 }; 00049 00050 template<class A_IT, class B> 00051 size_t indirect_tools<true>::cut(A_IT a, const B& b, size_t len) 00052 { 00053 // len: length of a before cut. different meaning in other specializations. 00054 array<size_t, mem> c(b); 00055 if(c.length() == 0) 00056 return len; 00057 std::sort(c.begin(), c.end()); 00058 00059 size_t i = 0; 00060 size_t j = 0; 00061 00062 for(size_t i = 0; i < len && i != c[0]; ++i, ++a) { ++j; } 00063 00064 array<size_t, mem>::const_iterator cp = c.begin(); 00065 array<size_t, mem>::const_iterator cp_e = c.end(); 00066 00067 ++cp; 00068 while(*cp == *(cp - 1) && cp != cp_e) 00069 ++cp; 00070 00071 A_IT wa = a; 00072 00073 for(++i, ++a; i < len; ++i, ++a) { 00074 if(i != *cp) { 00075 *wa = *a; 00076 ++wa; 00077 ++j; 00078 } 00079 else { 00080 ++cp; 00081 while(*cp == *(cp - 1) && cp != cp_e) { 00082 ++cp; 00083 } 00084 } 00085 } 00086 00087 return j; 00088 } 00089 00090 } /* namespace array_details */ 00091 00097 template <class T, 00098 class A, 00099 class B, 00100 class DERIVED_INFO 00101 > 00102 class array<T, data::indirect<A, B, DERIVED_INFO> > 00103 : 00104 00105 public array_common_base< 00106 array<T, data::indirect<A, B, DERIVED_INFO> > >, 00107 00108 public data::referer<typename types::derive< 00109 array<T, data::indirect<A, B, DERIVED_INFO> > >::type> 00110 { 00111 00112 private: 00113 typedef array_common_base<array<T, 00114 data::indirect<A, B, DERIVED_INFO> > > common_base_class; 00115 00116 typedef typename types::is_ref<B>::type prv_b_ref; 00117 typedef typename types::bare_type<B>::type prv_b; 00118 typedef typename types::t_if<prv_b_ref, 00119 const typename types::bare_type<B>::type*, 00120 internal::relaxed_pointer_face< 00121 typename types::bare_type<B>::type> > 00122 ::type prv_b_type; 00123 00124 00125 typedef typename types::t_if<typename array::is_writeable, 00126 typename A::iterator, 00127 typename A::const_iterator>::type a_best_iterator; 00128 00129 typedef typename prv_b::const_iterator b_iterator; 00130 00131 // used to disable some types. TODO: test that not_a_type actually throws an error 00132 // and consider explicitly making the default constructor private. 00133 class not_a_type {}; 00134 struct skip_assign { template<class X> void assign_array(X t) const {} }; 00135 00136 typedef typename types::t_if<types::is_const<A>, 00137 typename types::remove_const<A>::type, not_a_type>::type prv_second_init_a; 00138 00139 typedef typename types::t_and_3< 00140 types::t_not<types::is_const<A> >, 00141 typename A::is_writeable, 00142 typename A::is_resizeable> 00143 ::type is_content_resizeable; 00144 00145 typedef typename array_details:: 00146 indirect_tools<array::is_content_resizeable::value> indirect_tool; 00147 00148 A* a; 00149 prv_b_type b; 00150 size_t len; //used to allow cut modify the length. 00151 00152 protected: 00153 template <class J, class D> 00154 void copy_or_cut_impl(const array<J, D>& o) 00155 { 00156 if(is_content_resizeable::value && o.begin() == o.end() && len != 0) { 00157 00158 indirect_tool::shrink(*a, 00159 indirect_tool::cut(a->begin(), *b, a->length())); 00160 00161 len = 0; 00162 00163 } else { 00164 // for non-const: do not do nothing! 00165 types::r_if<typename this_type::is_writeable>( 00166 static_cast<common_base_class&>(*this), skip_assign()).assign_array(o); 00167 } 00168 } 00169 template <class J, class D> 00170 void copy_or_cut(const array<J, D>& o) 00171 { 00172 copy_or_cut_impl(o); 00173 } 00174 template <class J, class P2, class D> 00175 void copy_or_cut(const array<J, data::indirect<A, P2, D> >& o) 00176 { 00177 if(!a) 00178 this->init(o.get_ref_1(), o.get_ref_2()); 00179 else 00180 copy_or_cut_impl(o); 00181 } 00182 template <class J, class P2, class D> 00183 void copy_or_cut(const array<J, data::indirect< 00184 prv_second_init_a, P2, D> >& o) 00185 { 00186 if(!a) 00187 this->init(o.get_ref_1(), o.get_ref_2()); 00188 else 00189 copy_or_cut_impl(o); 00190 } 00191 00192 00193 public: 00194 typedef array this_type; 00195 00196 typedef this_type this_array_type; 00197 00198 typedef this_type array_type; 00199 00200 typedef T elem_type; 00201 00202 typedef typename common_base_class::derived_type derived_type; 00203 00204 typedef typename common_base_class::base_class base_class; 00205 00207 typedef size_t size_type; 00208 00209 using base_class::derived; 00210 00212 typedef is_content_resizeable is_cuttable; 00213 00214 // special to this type 00215 typedef tuple<A&, const prv_b&> data_init_arg; 00216 //typedef tuple<A&, B> data_init_arg; 00217 00218 00219 template <bool CONST> 00220 class iterator_type 00221 : public data::data_details:: 00222 rnd_iter_operator_expander<iterator_type<CONST>, T, CONST, 00223 typename types::remove_const< 00224 typename a_best_iterator::reference>::type> 00225 { 00226 private: 00227 template <bool C> friend class iterator_type; 00228 00229 template <class X, class Y, bool C, class Z> 00230 friend class data::data_details::rnd_iter_operator_expander; 00231 00232 template <class X, class Y, bool C, class Z> 00233 friend class data::data_details::iter_operator_expander; 00234 00235 typedef typename types::apply_const<T, types::t_expr<CONST> > 00236 ::type best_value_type; 00237 00238 typedef typename types::apply_const< 00239 typename a_best_iterator::reference, types::t_expr<CONST> > 00240 ::type best_ref_type; 00241 00242 // this class is used to disable specific specialization members 00243 class not_a_type { }; 00244 00245 typedef typename types::t_if<types::t_expr<CONST>, not_a_type, 00246 types::code_word<> >::type invalid_if_const; 00247 00248 typedef typename types::t_if<types::t_expr<CONST>, 00249 typename A::const_iterator, a_best_iterator>::type a_iterator; 00250 00251 a_iterator a; 00252 b_iterator b; 00253 00254 protected: 00255 inline typename types::apply_const<best_ref_type>::type base( 00256 types::code_word<> ok = types::code_word<>()) const 00257 { return (a[*b]); } 00258 //TODO!!!! make it random access only if b is random access 00259 // otherwise make it non-random access. 00260 // make it complain if a is non-random access. 00261 inline best_ref_type base( 00262 invalid_if_const disable = invalid_if_const()) 00263 { return (a[*b]); } 00264 00265 inline typename types::apply_const<best_ref_type>::type base(size_t j, 00266 types::code_word<> ok = types::code_word<>()) const 00267 { return (a[*(b + j)]); } 00268 00269 inline best_ref_type base(size_t j, 00270 invalid_if_const disable = invalid_if_const()) 00271 { return (a[*(b + j)]); } 00272 00273 public: 00274 typedef iterator_type<CONST> this_type; 00275 00276 // iterator_traits 00277 typedef std::random_access_iterator_tag iterator_category; 00278 typedef T value_type; 00279 typedef ptrdiff_t difference_type; 00280 typedef best_value_type* pointer; 00281 typedef best_ref_type reference; 00282 00283 // constructors 00284 iterator_type() { } 00285 iterator_type(const this_type& it) 00286 : a(it.a), b(it.b) { } 00287 template <bool C> 00288 iterator_type(const iterator_type<C>& it) 00289 : a(it.a), b(it.b) { } 00290 iterator_type(const a_iterator& a, const b_iterator& b) 00291 : a(a), b(b) { } 00292 00293 // members 00294 00295 // increment-decrement 00296 this_type& operator++() { ++b; return *this; } 00297 this_type& operator--() { --b; return *this; } 00298 00299 this_type operator++(int) { this_type t(*this); ++(*this); return t; } 00300 this_type operator--(int) { this_type t(*this); --(*this); return t; } 00301 00302 // random access. 00303 00304 // X can be either size_t or B::iter_bound_mover 00305 template<class X> 00306 this_type& operator +=(X j) { b += j; return *this; } 00307 00308 template<class X> 00309 this_type& operator -=(X j) { b -= j; return *this; } 00310 00311 template<class X> 00312 inline this_type operator +(X j) const 00313 { 00314 this_type tmp(*this); 00315 tmp += j; 00316 return tmp; 00317 } 00318 template<class X> 00319 inline this_type operator -(size_t j) const // TODO: @@@ cant i X? wrap iter has prob in 'code'. 00320 { 00321 this_type tmp(*this); 00322 tmp -= j; 00323 return tmp; 00324 } 00325 00326 // difference. 00327 ptrdiff_t operator-(const this_type& it) const 00328 { 00329 return b - it.b; 00330 } 00331 00332 //copy same type iterator 00333 this_type& operator=(const this_type& it) 00334 { 00335 a = it.a; b = it.b; 00336 return *this; 00337 } 00338 //copy relevant type iterator 00339 template<bool C> 00340 this_type& operator=(const iterator_type<C>& it) 00341 { 00342 a = it.a; b = it.b; 00343 return *this; 00344 } 00345 00346 bool operator==(const this_type& it) const { return (b == it.b); } 00347 bool operator!=(const this_type& it) const { return (b != it.b); } 00348 bool operator<(const this_type& it) const { return (b < it.b); } 00349 bool operator<=(const this_type& it) const { return (b <= it.b); } 00350 bool operator>(const this_type& it) const { return (b > it.b); } 00351 bool operator>=(const this_type& it) const { return (b >= it.b); } 00352 00353 }; 00354 00355 // typedefs for class iterators 00356 typedef typename types::t_if<typename array::is_writeable, 00357 iterator_type<false>, not_a_type>::type iterator; 00358 00359 typedef iterator_type<true> const_iterator; 00360 00361 typedef typename types::t_if<types::t_eq<iterator, not_a_type>, 00362 const_iterator, iterator>::type best_iterator; 00363 00364 typedef typename best_iterator::reference best_reference; 00365 typedef best_reference reference; 00366 typedef typename const_iterator::reference const_reference; 00367 00368 typedef std::reverse_iterator<iterator> reverse_iterator; 00369 00370 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00371 00372 typedef ptrdiff_t iter_border_walker; 00373 00374 best_iterator begin() 00375 { if(is_cuttable::value && len == 0) 00376 return best_iterator(a->begin(), b->end()); 00377 else return best_iterator(a->begin(), b->begin()); } 00378 00379 best_iterator end() 00380 { return best_iterator(a->begin(), b->end()); } 00381 00382 const_iterator begin() const 00383 { if(is_cuttable::value && len == 0) 00384 return const_iterator(a->begin(), b->end()); 00385 else return const_iterator(a->begin(), b->begin()); } 00386 00387 const_iterator end() const 00388 { return const_iterator(a->begin(), b->end()); } 00389 00390 // reverse iterator defs 00391 reverse_iterator rbegin() { return reverse_iterator(end()); } 00392 00393 reverse_iterator rend() { return reverse_iterator(begin()); } 00394 00395 const_reverse_iterator rbegin() const 00396 { return const_reverse_iterator(end()); } 00397 00398 const_reverse_iterator rend() const 00399 { return const_reverse_iterator(begin()); } 00400 00401 00402 using common_base_class::operator[]; 00403 00404 // todo: resolve when b has no random access 00405 typename best_iterator::reference operator[](size_t j) 00406 { 00407 return (*a)[(*b)[j]]; 00408 } 00409 typename const_iterator::reference operator[](size_t j) const 00410 { 00411 return (*a)[(*b)[j]]; 00412 } 00413 00416 //TODO: explain this better. 00418 size_t length() const { return len; } 00420 size_type size() const { return length(); } 00422 size_t numel() const { return length(); } 00425 void resize(size_t l) { CHECK(length() == l, ecomp); } 00426 00427 iter_border_walker first_to_last() { return b.length() - 1; } 00428 iter_border_walker begin_to_end() { return b.length(); } 00429 00430 00431 /* 00432 void init(A& a0, const B& b0) 00433 { 00434 a = &a0; 00435 b = &b0; 00436 len = b0.length(); 00437 } 00438 */ 00439 template<class I> 00440 void init(A& a0, const I& b0) 00441 { 00442 a = &a0; 00443 b = &b0; 00444 len = b0.length(); 00445 } 00446 00447 void init(size_t sz, data_init_arg d) 00448 { 00449 a = &d.v1; 00450 b = &d.v2; 00451 len = d.v2.length(); 00452 } 00453 00454 void init(const array& o) 00455 { 00456 a = o.a; 00457 b = o.b; 00458 len = o.len; 00459 } 00460 00461 template <class J, class P2, class D> 00462 void init(const array<J, data::indirect<A, P2, D> >& o) 00463 { 00464 a = &o.get_ref_1(); 00465 b = &o.get_ref_1(); 00466 len = o.length(); 00467 } 00468 00469 template <class J, class P2, class D> 00470 void init(const array<J, data::indirect<prv_second_init_a, P2, D> >& o) 00471 { 00472 a = &o.get_ref_1(); 00473 b = &o.get_ref_1(); 00474 len = o.length(); 00475 } 00476 00477 00478 00481 array() { a = NULL; } 00482 00484 array(A& a) : a(&a), b(rng(0, a.length()-1)), len(a.length()) { } 00485 00487 array(A& a, const prv_b& b) : a(&a), b(&b), len(b.length()) { } 00488 00489 //The same with data init arg 00490 array(size_t sz, data_init_arg d) : a(&d.v1), b(&d.v2), len(d.v2.length()) { } 00491 00492 //The same constructor with template 00493 template<class I> 00494 array(A& a, const I& b) : a(&a), b(&b), len(b.length()) { } 00495 00497 array(const this_type& o) : a(o.a), b(o.b), len(o.len) {} 00498 00499 // Constructor from another indirect array 00500 template <class J, class P2, class D> 00501 array(const array<J, data::indirect<A, P2, D> >& o) 00502 : a(&o.get_ref_1()), b(&o.get_ref_2()), len(o.length()) { } 00503 00504 template <class J, class P2, class D> 00505 array(const array<J, data::indirect<prv_second_init_a, P2, D> >& o) 00506 : a(&o.get_ref_1()), b(&o.get_ref_2()), len(o.length()) { } 00507 00510 00511 ~array() { } 00512 00515 // exclusive to indirect array 00516 A& get_ref_1() const { return *a; } 00517 const prv_b& get_ref_2() const { return *b; } 00518 //TODO: may be better or just possible is several cases as elem func. 00519 //return value could also be templated. 00520 template <class J, class P> 00521 size_array merge_idx(const array<J, P>& idx) const 00522 { 00523 size_array sz(idx.length()); 00524 for(size_t i=0;i<sz.length();i++) 00525 sz[i] = (*b)[idx[i]]; 00526 return sz; 00527 } 00528 // 00529 00530 template <class D> 00531 bool overlap(const D& d) const 00532 { 00533 return a->overlap(d); 00534 } 00535 00536 template <class D> 00537 bool self_overlap(const D& d) const 00538 { 00539 return d.overlap(*a) || d.overlap(*b); 00540 } 00541 00542 /* 00543 TODO: wipe this completely. Cannot detect anything here anyway. 00544 template <class J, class P> 00545 derived_type& assign_array(const array<J, data::empty<P> >& o) 00546 { 00547 copy_or_cut(o); // will always fallback to cut 00548 return this->derived(); 00549 } 00550 */ 00551 00552 template<class D> 00553 derived_type& assign_array(const D& o) 00554 { 00555 copy_or_cut(o); 00556 return this->derived(); 00557 } 00564 //using common_base_class::operator=; 00565 template<class K> 00566 derived_type& operator=(const K& o) 00567 { 00568 // avoid the safety check when we just need to assign 00569 // TODO: check about this all, espec. const K&. and what happens 00570 // when we derive to higher class, e.g. image, what is called. 00571 // (esp. for subarray). 00572 if(!a) 00573 this->assign(o); 00574 else 00575 common_base_class::operator=(o); 00576 return this->derived(); 00577 } 00578 00579 this_type& operator=(const this_type& o) // copy operator 00580 { 00581 copy_or_cut(o); 00582 return *this; 00583 } 00584 00587 //todo: either make this (rvalue) a rule or not at all 00588 //this_type& rvalue() const { return *const_cast<this_type*>(this); } 00589 00590 00591 }; 00592