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 namespace array_details { 00025 00026 template <class RESIZEABLE> 00027 struct wrap_array_resize_details { }; 00028 00029 template <class HAS_C_PTR, class T> 00030 struct wrap_array_ptr_details { }; 00031 00032 template <class D, class IS_FORCE> 00033 struct wrap_array_overlap_impl { }; 00034 00035 template <class A> 00036 struct wrap_ices_iterator : public A 00037 { 00038 A& base() { return static_cast<A&>(*this); } 00039 const A& base() const { return static_cast<const A&>(*this); } 00040 typedef typename A::value_type prv_vt; 00041 typedef ivl::scalar<prv_vt> value_type; 00042 typedef ivl::scalar<prv_vt> reference; 00043 value_type operator*() const { return A::operator*(); } 00044 template<class I> 00045 value_type operator[](I i) const { return A::operator[](i); } 00046 wrap_ices_iterator() {} 00047 template <class O> 00048 wrap_ices_iterator(const O& a) : A(a) { } 00049 wrap_ices_iterator(const wrap_ices_iterator& a) : A(a) { } 00050 00051 using A::operator -; 00052 ptrdiff_t operator-(const wrap_ices_iterator&o) 00053 { 00054 return base() - o.base(); 00055 } 00056 00057 00058 wrap_ices_iterator& operator=(const wrap_ices_iterator& o) 00059 { A::operator=(o.base()); return *this; } 00060 template<class K> 00061 wrap_ices_iterator& operator=(const K& o) 00062 { 00063 A::operator=(o); 00064 return *this; 00065 } 00066 //using A::operator=; 00067 }; 00068 00069 template <class ICES, class A> 00070 struct wrap_ices_it 00071 { 00072 typedef A type; 00073 }; 00074 template<class A> 00075 struct wrap_ices_it<types::t_true, A> 00076 { 00077 typedef wrap_ices_iterator<A> type; 00078 }; 00079 00080 } /* namespace array_details */ 00081 00092 template <class T, 00093 class A, 00094 class ATTR, 00095 class DERIVED_INFO 00096 > 00097 class array<T, data::wrap_array<A, ATTR, DERIVED_INFO> > 00098 : 00099 public array_common_base< 00100 array<T, data::wrap_array<A, ATTR, DERIVED_INFO> > >, 00101 00102 public data::referer<typename types::derive< 00103 array<T, data::wrap_array<A, ATTR, DERIVED_INFO> > >::type>, 00104 00105 public array_details::wrap_array_overlap_impl< 00106 array<T, data::wrap_array<A, ATTR, DERIVED_INFO> >, 00107 typename types::t_eq<ATTR, data::force_wrap_array_attr>::type>, 00108 00109 public data::wrap_identifier<ATTR> 00110 { 00111 00112 private: 00113 typedef array_common_base<array<T, 00114 data::wrap_array<A, ATTR, DERIVED_INFO> > > common_base_class; 00115 00116 typedef typename 00117 types::is_base<data::ice_wrap_array_attr_base_identifier, ATTR> 00118 ::type prv_is_ice; 00119 typedef typename types::t_or< 00120 //types::t_eq<ATTR, data::ices_wrap_array_attr>, 00121 prv_is_ice, // @@@ test 00122 types::t_eq<ATTR, data::icers_wrap_array_attr<T> > 00123 > 00124 ::type prv_is_ices; 00125 typedef typename types::t_not<prv_is_ice>::type prv_is_nice; 00126 00127 typedef typename types::t_if<typename array::is_writeable, 00128 typename types::best_iterator<A>::type, 00129 typename A::const_iterator>::type ref_a_best_iterator; 00130 00131 typedef typename types::t_if<typename array::is_writeable, 00132 typename types::best_reverse_iterator<A>::type, 00133 typename A::const_reverse_iterator> 00134 ::type ref_a_best_reverse_iterator; 00135 00136 typedef typename array_details:: 00137 wrap_ices_it<prv_is_ices, ref_a_best_iterator> 00138 ::type a_best_iterator; 00139 typedef typename array_details:: 00140 wrap_ices_it<prv_is_ices, ref_a_best_reverse_iterator> 00141 ::type a_best_reverse_iterator; 00142 typedef typename array_details:: 00143 wrap_ices_it<prv_is_ices, typename A::const_iterator> 00144 ::type a_const_iterator; 00145 typedef typename array_details:: 00146 wrap_ices_it<prv_is_ices, 00147 typename A::const_reverse_iterator>::type a_const_reverse_iterator; 00148 00149 typedef typename A::this_array_type a_t; 00150 00151 protected: 00152 typedef typename array::has_random_access prv_has_random_access; 00153 00154 typedef array_details::elem_func_tools<T, 00155 prv_has_random_access::value> tool; 00156 00157 typedef typename types::t_if<prv_is_ice, 00158 internal::relinit_pointer_face<A>, A*> 00159 ::type prv_a_store_t; 00160 00161 friend class tool::not_a_type; // allow disabled types only in our class 00162 00163 typedef typename types::t_if<prv_is_ice, typename tool::not_a_type, array> 00164 ::type nice_this_type; 00165 typedef typename types::t_if<prv_is_ice, array, typename tool::not_a_type> 00166 ::type ice_this_type; 00167 typedef typename types::t_if<types::t_and<prv_is_ice, types::t_not<types::is_const<A> > >, const A&, 00168 typename tool::not_a_type>::type prv_const_ice_a; 00169 00170 prv_a_store_t a_ptr; 00171 a_best_iterator a_begin; 00172 size_t len; 00173 00174 public: 00175 typedef array this_type; 00176 00177 typedef this_type this_array_type; 00178 00179 typedef this_type array_type; 00180 00181 typedef T elem_type; 00182 00183 typedef typename common_base_class::derived_type derived_type; 00184 00185 typedef typename common_base_class::base_class base_class; 00186 00188 typedef size_t size_type; 00189 00191 typedef ptrdiff_t diff_type; 00192 00193 using base_class::derived; 00194 00195 template <class O> 00196 void assign(const O& o) 00197 { 00198 a_ptr->assign(o); 00199 } 00200 template <class O> 00201 void assign_array(const O& o) 00202 { 00203 a_ptr->assign_array(o); 00204 } 00205 template <class O> 00206 void assign_element(const O& o) 00207 { 00208 a_ptr->assign_element(o); 00209 } 00210 00211 void resize(size_t len) 00212 { 00213 if(array_details:: 00214 wrap_array_resize_details<typename array::is_resizeable> 00215 ::resize(a_ptr, len)) { 00216 a_begin = a_ptr->begin(); 00217 len = a_ptr->length(); 00218 } 00219 } 00220 00221 void resize(size_t len, const T& s) // with padding 00222 { 00223 if(array_details:: 00224 wrap_array_resize_details<typename array::is_resizeable> 00225 ::resize(static_cast<a_t*>(a_ptr), len, s)) { 00226 a_begin = a_ptr->begin(); 00227 len = a_ptr->length(); 00228 } 00229 } 00230 00232 void reshape(size_t len) { resize(len); } 00233 void reshape(size_t len, const T& s) { resize(len, s); } 00234 00235 void clear() { resize(0); } 00236 00237 typedef typename types::t_if<typename array::is_writeable, 00238 a_best_iterator, types::not_a_type>::type iterator; 00239 00240 typedef a_const_iterator const_iterator; 00241 00242 typedef typename types::t_if<typename array::is_writeable, 00243 a_best_reverse_iterator, 00244 types::not_a_type>::type reverse_iterator; 00245 00246 typedef a_const_reverse_iterator const_reverse_iterator; 00247 00248 typedef typename A::iter_border_walker iter_border_walker; 00249 00250 typedef a_best_iterator best_iterator; 00251 typedef typename std::iterator_traits<best_iterator>:: 00252 reference best_reference; 00253 typedef typename std::iterator_traits<const_iterator>:: 00254 reference const_reference; 00255 typedef best_reference reference; 00256 00257 best_iterator begin() { return a_begin; } 00258 best_iterator end() { return a_ptr->end(); } 00259 const_iterator begin() const { return const_iterator(a_begin); } 00260 const_iterator end() const { return a_ptr->end(); } 00261 00262 a_best_reverse_iterator rbegin() { return a_ptr->rbegin(); } 00263 a_best_reverse_iterator rend() { return a_ptr->rend(); } 00264 const_reverse_iterator rbegin() const { return a_ptr->rbegin(); } 00265 const_reverse_iterator rend() const { return a_ptr->rend(); } 00266 00267 typename types::apply_const<T, types::is_const<A> >::type c_ptr() 00268 { 00269 return array_details:: 00270 wrap_array_ptr_details<typename array::has_c_ptr, T> 00271 ::c_ptr(a_ptr); 00272 } 00273 00274 const T* c_ptr() const 00275 { 00276 return array_details:: 00277 wrap_array_ptr_details<typename array::has_c_ptr, T> 00278 ::const_c_ptr(a_ptr); 00279 } 00280 00283 //TODO: explain this better. 00285 size_t length() const { return len; } 00287 size_type size() const { return length(); } 00289 size_t numel() const { return length(); } 00292 iter_border_walker first_to_last() const { return a_ptr->first_to_last(); } 00293 iter_border_walker begin_to_end() const { return a_ptr->begin_to_end(); } 00294 00300 00301 best_reference operator[] 00302 (typename tool::brackets_arg i) 00303 { 00304 CHECK(i >= 0 && i < length(), erange); 00305 typedef typename tool::template brackets_c<best_reference> toolf; 00306 return toolf::f(a_begin, i); 00307 } 00308 00310 const_reference operator[] 00311 (typename tool::brackets_arg i) const 00312 { 00313 CHECK(i >= 0 && i < length(), erange); 00314 typedef typename tool::template brackets_c<best_reference> toolf; 00315 return toolf::f(a_begin, i); 00316 } 00321 void setref(A& a) 00322 { 00323 a_ptr = &a; 00324 //a_begin = a.begin(); 00325 a_begin = a_ptr->begin(); 00326 len = a.length(); 00327 } 00328 A& getref() { return *a_ptr; } 00329 00330 void init(A& a) 00331 { 00332 setref(a); 00333 } 00334 void init(const array& o) 00335 { 00336 a_ptr = o.a_ptr; 00337 //a_begin = o.a_begin; 00338 a_begin = a_ptr->begin(); 00339 len = o.len; 00340 } 00341 template<class J> 00342 void init(J& a) // TODO: const weirdness in ice requires this 00343 { 00344 a_ptr = &a; 00345 //a_begin = a.begin(); 00346 a_begin = a_ptr->begin(); 00347 len = a.length(); 00348 } 00349 00350 00351 template <class X, class Y> 00352 friend struct array_details::wrap_array_overlap_impl; 00353 00354 using array_details::wrap_array_overlap_impl< 00355 this_type, 00356 typename types::t_eq<ATTR, data::force_wrap_array_attr>::type>::overlap; 00357 00358 operator A&() { return *a_ptr; } 00359 operator typename types::apply_const<A>::type&() const { return *a_ptr; } 00364 00365 array() { types::r_if<prv_is_nice>(a_ptr, types::skip()) = 0; len = 0; } 00366 00368 array(A& a) : a_ptr(&a) { 00369 a_begin = a_ptr->begin(); 00370 len = a.length(); 00371 } 00372 00373 // construction from const reference arrays for ice 00374 array(prv_const_ice_a a) : a_ptr(&a) { 00375 a_begin = a_ptr->begin(); 00376 len = a.length(); 00377 } 00378 00380 array(const array& o) 00381 : a_ptr(o.a_ptr) { a_begin = a_ptr->begin(); len = o.len; } 00387 00388 array(size_t) {} 00389 00391 template <class J, class D> 00392 array(size_t, const array<J, D>&) {} 00393 00395 array(size_t, const T*) {} 00396 00398 template<class J, class S> 00399 array(const array<J, S>& a) { init(a.derived()); } 00401 template<class J, class S> 00402 array(array<J, S>& a) { init(a.derived()); } 00403 00416 using base_class::operator=; 00417 00418 this_type& operator=(const nice_this_type& a) 00419 { 00420 common_base_class::operator=(a); 00421 return *this; 00422 } 00423 this_type& operator=(const ice_this_type& a) 00424 { 00425 init(a); 00426 return *this; 00427 } 00428 00431 00432 ~array() { } 00433 00434 }; 00435 00436 namespace array_details { 00437 00438 template <> 00439 struct wrap_array_resize_details<types::t_false> 00440 { 00441 template <class A, class S> 00442 static inline 00443 bool resize(A* a, const S& l) { return false; } 00444 00445 template <class A, class S, class T> 00446 static inline 00447 bool resize(A* a, const S& l, const T& t) { return false; } 00448 }; 00449 00450 template <> 00451 struct wrap_array_resize_details<types::t_true> 00452 { 00453 template <class A, class S> 00454 static inline 00455 bool resize(A* a, const S& l) { a->resize(l); return true; } 00456 00457 template <class A, class S, class T> 00458 static inline 00459 bool resize(A* a, const S& l, const T& t) { a->resize(l, t); return true; } 00460 }; 00461 00462 template <class T> 00463 struct wrap_array_ptr_details <types::t_false, T> 00464 { 00465 template <class A> 00466 static inline T* c_ptr(A* a) { return 0; } 00467 template <class A> 00468 static inline const T* c_ptr(const A* a) { return 0; } 00469 }; 00470 00471 template <class T> 00472 struct wrap_array_ptr_details <types::t_true, T> 00473 { 00474 template <class A> 00475 static inline T* c_ptr(A* a) { return a->c_ptr(); } 00476 template <class A> 00477 static inline const T* c_ptr(const A* a) { return a->c_ptr(); } 00478 }; 00479 00480 template <class D> 00481 struct wrap_array_overlap_impl<D, types::t_true> 00482 { 00483 template <class A> 00484 bool overlap(const A& a) const { return false; } 00485 template <class A> 00486 bool self_overlap(const A& a) const { return false; } 00487 00488 }; 00489 00490 template <class D> 00491 struct wrap_array_overlap_impl<D, types::t_false> 00492 { 00493 private: 00494 const D& d() const { return static_cast<const D&>(*this); } 00495 public: 00496 template <class A> 00497 bool overlap(const A& a) const { return d().a_ptr->overlap(a); } 00498 template <class A> 00499 bool self_overlap(const A& a) const { return d().a_ptr->overlap(a); } //TODO: @@@@!!! check! 00500 }; 00501 00502 } /* namespace array_details */