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 00030 template <class T, 00031 template <typename, typename, typename> class F, 00032 class A1, class A2, bool SWAP_ARGS, 00033 class DERIVED_INFO 00034 > 00035 class array<T, 00036 data::binary_elem_func_ptr<F, A1, A2, SWAP_ARGS, DERIVED_INFO> > : 00037 00038 public array_common_base<array<T, data:: 00039 binary_elem_func_ptr<F, A1, A2, SWAP_ARGS, DERIVED_INFO> > > 00040 00041 { 00042 00043 private: 00044 typedef array_common_base<array<T, data::binary_elem_func_ptr< 00045 F, A1, A2, SWAP_ARGS, DERIVED_INFO> > > common_base_class; 00046 00047 protected: 00048 typedef typename array::has_random_access prv_has_random_access; 00049 00050 typedef typename array_details::elem_func_tools<typename A1::elem_type, 00051 prv_has_random_access::value> tool1; 00052 typedef typename array_details::elem_func_tools<typename A2::elem_type, 00053 prv_has_random_access::value> tool2; 00054 00055 friend class tool1::not_a_type; // allow disabled types only in our class 00056 friend class tool2::not_a_type; // allow disabled types only in our class 00057 00058 typedef typename types::t_or_3< 00059 types::t_eq<typename A1::data_type, val_repeat>, 00060 types::t_eq<typename A1::data_type, ref_val_repeat>, 00061 types::is_base<data::ice_wrap_array_attr_base_identifier, 00062 typename A1::data_type> 00063 //types::is_base<data::member_identifier, typename A1::data_type> 00064 >::type 00065 in1_is_scalar; 00066 00067 typedef typename types::t_or_3< 00068 types::t_eq<typename A2::data_type, val_repeat>, 00069 types::t_eq<typename A2::data_type, ref_val_repeat>, 00070 types::is_base<data::ice_wrap_array_attr_base_identifier, 00071 typename A2::data_type> 00072 //types::is_base<data::member_identifier, typename A2::data_type> 00073 >::type 00074 in2_is_scalar; 00075 00076 // we have to mask the val_repeat and ref_val_repeat types with a 00077 // "pointer_face" class and keep them stored in the binary_elem_func_class 00078 // instead of referencing them (copy), because they might be created at the 00079 // constructor of the binary_elem_func class and thus they may be 00080 // destroyed before the expression is evaluated. 00081 // Practically this means that when one operand of the binary elem func 00082 // array is a single element then it is copied rather than referenced. 00083 // (a pseudo array with this element is also created). 00084 typedef typename types::t_if<in1_is_scalar, 00085 internal::pointer_face<A1>, const A1*>::type in1_t; 00086 00087 typedef typename types::t_if<in2_is_scalar, 00088 internal::pointer_face<A2>, const A2*>::type in2_t; 00089 00090 typedef typename F<types::term, types::term, types::term>::ptr_t ptr_t; 00091 00092 in1_t in1; 00093 in2_t in2; 00094 ptr_t ptr1;//binary_elem_func_ptr addition 00095 00096 // template arguments for the elem_func_swap_op tool, 00097 typedef typename types::t_if<in1_is_scalar, in1_t, types::term>::type in1_s; 00098 typedef typename types::t_if<in2_is_scalar, in2_t, types::term>::type in2_s; 00099 00100 // allows swapping the arguments that are given in direct order 00101 template<class X, class Y> 00102 static inline 00103 const A1& ref1(const X& q1, const Y& q2) 00104 { return types::r_if<types::t_expr<SWAP_ARGS> >(q2, q1); } 00105 00106 template<class X, class Y> 00107 static inline 00108 const A2& ref2(const X& q1, const Y& q2) 00109 { return types::r_if<types::t_expr<SWAP_ARGS> >(q1, q2); } 00110 00111 00112 00113 public: 00114 typedef array this_type; 00115 00116 typedef this_type this_array_type; 00117 00118 typedef this_type array_type; 00119 00120 typedef T elem_type; 00121 00122 typedef typename common_base_class::base_class base_class; 00123 00125 typedef size_t size_type; 00126 00128 typedef ptrdiff_t diff_type; 00129 00130 using base_class::derived; 00131 00132 typedef typename array::has_random_access has_random_access; 00133 00134 00135 class const_iterator 00136 { 00137 private: 00138 typedef typename A1::const_iterator iter_1; 00139 typedef typename A2::const_iterator iter_2; 00140 00141 iter_1 i1; 00142 iter_2 i2; 00143 ptr_t ptr1;//binary_elem_func_ptr addition 00144 00145 typedef typename tool1::template 00146 rnd_it<const_iterator>::type rnd_iter; 00147 00148 public: 00149 00150 // iterator_traits 00151 typedef typename types::t_if<has_random_access, 00152 std::random_access_iterator_tag, 00153 std::bidirectional_iterator_tag>::type iterator_category; 00154 00155 typedef T value_type; 00156 typedef ptrdiff_t difference_type; 00157 typedef internal::pointer_face<const T> pointer; 00158 // using this to comply with std:: iterators. if it is not optimized-out 00159 // by the compiler, consider using 00160 // `const internal::reference_face<const T, types::skip>' 00161 typedef const internal::reference_face<const T, const_iterator> 00162 reference; 00163 00164 // constructors 00165 const_iterator() { } 00166 00167 const_iterator(ptr_t ptr1, const iter_1& i1, const iter_2& i2) : ptr1(ptr1), i1(i1), i2(i2) { } 00168 00169 const_iterator(const const_iterator& it) : ptr1(it.ptr1), i1(it.i1), i2(it.i2) { } 00170 00171 // pointer 00172 pointer operator ->() const 00173 { 00174 return pointer(*this, array_details::elem_func_swap_op<SWAP_ARGS, 00175 T, F<T, typename std::iterator_traits<iter_1>::value_type, 00176 typename std::iterator_traits<iter_2>::value_type>, 00177 in1_s, in2_s>:: 00178 from(ptr1, *i1, *i2)); 00179 } 00180 00181 // members 00182 reference operator *() const 00183 { 00184 return reference(array_details::elem_func_swap_op<SWAP_ARGS, 00185 T, F<T, typename std::iterator_traits<iter_1>::value_type, 00186 typename std::iterator_traits<iter_2>::value_type>, 00187 in1_s, in2_s>:: 00188 from(ptr1, *i1, *i2), *this); 00189 } 00190 00191 // optional random access in iterator 00192 //typename tool::brackets_ret_type 00193 00194 reference operator[] 00195 (typename tool1::brackets_arg j) const 00196 { 00197 return reference(array_details::elem_func_swap_op<SWAP_ARGS, 00198 T, F<T, typename std::iterator_traits<iter_1>::value_type, 00199 typename std::iterator_traits<iter_2>::value_type>, 00200 in1_s, in2_s>:: 00201 from(ptr1, tool1::brackets(i1, j), 00202 tool2::brackets(i2, j)), 00203 // hope that the below line will be optimized-out when using T. 00204 rnd_iter(ptr1, tool1::add_op(i1, j), tool2::add_op(i2, j))); 00205 } 00206 00207 // increment-decrement 00208 const_iterator& operator++() 00209 { 00210 ++i1; 00211 ++i2; 00212 return *this; 00213 } 00214 const_iterator& operator--() 00215 { 00216 --i1; 00217 --i2; 00218 return *this; 00219 } 00220 00221 const_iterator operator++(int) 00222 { const_iterator tmp(*this); ++(*this); return tmp; } 00223 00224 const_iterator operator--(int) 00225 { const_iterator tmp(*this); --(*this); return tmp; } 00226 00227 // random access. enabled only if 'has_random_access' 00228 const_iterator& operator +=(typename tool1::brackets_arg j) 00229 { 00230 tool1::add_asgn(i1, j); 00231 tool2::add_asgn(i2, j); 00232 return *this; 00233 } 00234 const_iterator& operator -=(typename tool1::brackets_arg j) 00235 { 00236 tool1::sub_asgn(i1, j); 00237 tool2::sub_asgn(i2, j); 00238 return *this; 00239 } 00240 inline rnd_iter operator +(typename tool1::brackets_arg j) const 00241 { 00242 return rnd_iter(ptr1, tool1::add_op(i1, j), tool2::add_op(i2, j)); 00243 } 00244 inline rnd_iter operator -(typename tool1::brackets_arg j) const 00245 { 00246 return rnd_iter(ptr1, tool1::sub_op(i1, j), tool2::sub_op(i2, j)); 00247 } 00248 00249 // difference 00250 difference_type operator -(const rnd_iter& a) const 00251 { 00252 return tool1::dif_op(i1, a.i1); 00253 } 00254 00255 //copy same type iterator 00256 const_iterator& operator=(const const_iterator& o) 00257 { 00258 ptr1 = o.ptr1; 00259 i1 = o.i1; 00260 i2 = o.i2; 00261 return *this; 00262 } 00263 00264 bool operator==(const const_iterator& o) const { return (i1 == o.i1); } 00265 bool operator!=(const const_iterator& o) const { return (i1 != o.i1); } 00266 bool operator<(const const_iterator& o) const { return (i1 < o.i1); } 00267 bool operator<=(const const_iterator& o) const { return (i1 <= o.i1); } 00268 bool operator>(const const_iterator& o) const { return (i1 > o.i1); } 00269 bool operator>=(const const_iterator& o) const { return (i1 >= o.i1); } 00270 }; 00271 00272 typedef typename const_iterator::reference const_reference; 00273 typedef const_iterator best_iterator; 00274 typedef const_reference best_reference; 00275 00276 00277 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00278 00279 typedef ptrdiff_t iter_border_walker; 00280 00281 const_iterator begin() const 00282 { return const_iterator(ptr1, in1->begin(), in2->begin()); } 00283 const_iterator end() const 00284 { return const_iterator(ptr1, in1->end(), in2->end()); } 00285 00286 const_reverse_iterator rbegin() const 00287 { return const_reverse_iterator(ptr1, in1->rbegin(), in2->rbegin()); } 00288 const_reverse_iterator rend() const 00289 { return const_reverse_iterator(ptr1, in1->rend(), in2->rend()); } 00290 00293 00294 00295 size_t length() const 00296 { 00297 return in1->derived().length(); 00298 } 00299 00301 size_type size() const { return length(); } 00303 size_t numel() const { return length(); } 00306 iter_border_walker first_to_last() { return this->length() - 1; } 00307 iter_border_walker begin_to_end() { return this->length(); } 00308 00309 00310 using common_base_class::operator []; 00311 00317 00318 00319 const_reference operator[]( 00320 typename tool1::brackets_arg i) const 00321 { 00322 CHECK(i >= 0 && i < length(), erange); 00323 00324 return (begin()[i]); 00325 } 00334 00335 void validate() 00336 { 00337 CHECK(in1->length() == in2->length(), eshape); 00338 } 00339 00343 void setref(ptr_t p1, const A1& a1, const A2& a2) 00344 { 00345 ptr1 = p1; 00346 in1 = &a1; 00347 in2 = &a2; 00348 validate(); 00349 } 00350 00351 template <class A> 00352 bool self_overlap(const A& a) const 00353 { 00354 return a.overlap(*in1) || a.overlap(*in2); 00355 } 00358 // TODO: proper place 00359 void init(ptr_t p1, const A1& a1, const A2& a2) { setref(p1, a1, a2); } 00360 00361 void init(const array& o) { setref(o.ptr1, *o.in1, *o.in2); } 00362 00363 00366 00367 array() {} 00368 00370 array(ptr_t p1, const A1& a1, const A2& a2) { setref(p1, a1, a2); } 00371 00373 array(const array& o) { setref(o.ptr1, *o.in1, *o.in2); } 00374 00379 00380 array(size_t) {} 00381 00383 array(size_t, const T&) {} 00384 00386 template <class J, class S> 00387 array(size_t, const array<J, S>&) {} 00388 00390 array(size_t, const T*) {} 00391 00393 template<class J, class S> 00394 array(const array<J, S>& a) {} 00395 00398 00399 ~array() { } 00400 00401 }; 00402