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<F, A1, A2, SWAP_ARGS, DERIVED_INFO> > : 00037 00038 public array_common_base<array<T, data:: 00039 binary_elem_func<F, A1, A2, SWAP_ARGS, DERIVED_INFO> > > 00040 00041 { 00042 00043 private: 00044 typedef array_common_base<array<T, data::binary_elem_func< 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 in1_t in1; 00091 in2_t in2; 00092 00093 // template arguments for the elem_func_swap_op tool, 00094 typedef typename types::t_if<in1_is_scalar, in1_t, types::term>::type in1_s; 00095 typedef typename types::t_if<in2_is_scalar, in2_t, types::term>::type in2_s; 00096 00097 // allows swapping the arguments that are given in direct order 00098 template<class X, class Y> 00099 static inline 00100 const A1& ref1(const X& q1, const Y& q2) 00101 { return types::r_if<types::t_expr<SWAP_ARGS> >(q2, q1); } 00102 00103 template<class X, class Y> 00104 static inline 00105 const A2& ref2(const X& q1, const Y& q2) 00106 { return types::r_if<types::t_expr<SWAP_ARGS> >(q1, q2); } 00107 00108 00109 00110 public: 00111 typedef array this_type; 00112 00113 typedef this_type this_array_type; 00114 00115 typedef this_type array_type; 00116 00117 typedef T elem_type; 00118 00119 typedef typename common_base_class::base_class base_class; 00120 00122 typedef size_t size_type; 00123 00125 typedef ptrdiff_t diff_type; 00126 00127 using base_class::derived; 00128 00129 typedef typename array::has_random_access has_random_access; 00130 00131 00132 class const_iterator 00133 { 00134 private: 00135 typedef typename A1::const_iterator iter_1; 00136 typedef typename A2::const_iterator iter_2; 00137 00138 iter_1 i1; 00139 iter_2 i2; 00140 00141 typedef typename tool1::template 00142 rnd_it<const_iterator>::type rnd_iter; 00143 00144 public: 00145 00146 // iterator_traits 00147 typedef typename types::t_if<has_random_access, 00148 std::random_access_iterator_tag, 00149 std::bidirectional_iterator_tag>::type iterator_category; 00150 00151 typedef T value_type; 00152 typedef ptrdiff_t difference_type; 00153 typedef internal::pointer_face<const T> pointer; 00154 // using this to comply with std:: iterators. if it is not optimized-out 00155 // by the compiler, consider using 00156 // `const internal::reference_face<const T, types::skip>' 00157 typedef const internal::reference_face<const T, const_iterator> 00158 reference; 00159 00160 // constructors 00161 const_iterator() { } 00162 00163 const_iterator(const iter_1& i1, const iter_2& i2) : i1(i1), i2(i2) { } 00164 00165 const_iterator(const const_iterator& it) : i1(it.i1), i2(it.i2) { } 00166 00167 // pointer 00168 pointer operator ->() const 00169 { 00170 return pointer(*this, array_details::elem_func_swap_op<SWAP_ARGS, 00171 T, F<T, typename std::iterator_traits<iter_1>::value_type, 00172 typename std::iterator_traits<iter_2>::value_type>, 00173 in1_s, in2_s>:: 00174 from(*i1, *i2)); 00175 } 00176 00177 // members 00178 reference operator *() const 00179 { 00180 return reference(array_details::elem_func_swap_op<SWAP_ARGS, 00181 T, F<T, typename std::iterator_traits<iter_1>::value_type, 00182 typename std::iterator_traits<iter_2>::value_type>, 00183 in1_s, in2_s>:: 00184 from(*i1, *i2), *this); 00185 } 00186 00187 // optional random access in iterator 00188 //typename tool::brackets_ret_type 00189 00190 reference operator[] 00191 (typename tool1::brackets_arg j) const 00192 { 00193 return reference(array_details::elem_func_swap_op<SWAP_ARGS, 00194 T, F<T, typename std::iterator_traits<iter_1>::value_type, 00195 typename std::iterator_traits<iter_2>::value_type>, 00196 in1_s, in2_s>:: 00197 from(tool1::brackets(i1, j), 00198 tool2::brackets(i2, j)), 00199 // hope that the below line will be optimized-out when using T. 00200 rnd_iter(tool1::add_op(i1, j), tool2::add_op(i2, j))); 00201 } 00202 00203 // increment-decrement 00204 const_iterator& operator++() 00205 { 00206 ++i1; 00207 ++i2; 00208 return *this; 00209 } 00210 const_iterator& operator--() 00211 { 00212 --i1; 00213 --i2; 00214 return *this; 00215 } 00216 00217 const_iterator operator++(int) 00218 { const_iterator tmp(*this); ++(*this); return tmp; } 00219 00220 const_iterator operator--(int) 00221 { const_iterator tmp(*this); --(*this); return tmp; } 00222 00223 // random access. enabled only if 'has_random_access' 00224 const_iterator& operator +=(typename tool1::brackets_arg j) 00225 { 00226 tool1::add_asgn(i1, j); 00227 tool2::add_asgn(i2, j); 00228 return *this; 00229 } 00230 const_iterator& operator -=(typename tool1::brackets_arg j) 00231 { 00232 tool1::sub_asgn(i1, j); 00233 tool2::sub_asgn(i2, j); 00234 return *this; 00235 } 00236 inline rnd_iter operator +(typename tool1::brackets_arg j) const 00237 { 00238 return rnd_iter(tool1::add_op(i1, j), tool2::add_op(i2, j)); 00239 } 00240 inline rnd_iter operator -(typename tool1::brackets_arg j) const 00241 { 00242 return rnd_iter(tool1::sub_op(i1, j), tool2::sub_op(i2, j)); 00243 } 00244 00245 // difference 00246 difference_type operator -(const rnd_iter& a) const 00247 { 00248 return tool1::dif_op(i1, a.i1); 00249 } 00250 00251 //copy same type iterator 00252 const_iterator& operator=(const const_iterator& o) 00253 { 00254 i1 = o.i1; 00255 i2 = o.i2; 00256 return *this; 00257 } 00258 00259 bool operator==(const const_iterator& o) const { return (i1 == o.i1); } 00260 bool operator!=(const const_iterator& o) const { return (i1 != o.i1); } 00261 bool operator<(const const_iterator& o) const { return (i1 < o.i1); } 00262 bool operator<=(const const_iterator& o) const { return (i1 <= o.i1); } 00263 bool operator>(const const_iterator& o) const { return (i1 > o.i1); } 00264 bool operator>=(const const_iterator& o) const { return (i1 >= o.i1); } 00265 }; 00266 00267 typedef typename const_iterator::reference const_reference; 00268 typedef const_iterator best_iterator; 00269 typedef const_reference best_reference; 00270 00271 00272 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00273 00274 typedef ptrdiff_t iter_border_walker; 00275 00276 const_iterator begin() const 00277 { return const_iterator(in1->begin(), in2->begin()); } 00278 const_iterator end() const 00279 { return const_iterator(in1->end(), in2->end()); } 00280 00281 const_reverse_iterator rbegin() const 00282 { return const_reverse_iterator(in1->rbegin(), in2->rbegin()); } 00283 const_reverse_iterator rend() const 00284 { return const_reverse_iterator(in1->rend(), in2->rend()); } 00285 00288 00289 00290 size_t length() const 00291 { 00292 return in1->derived().length(); 00293 } 00294 00296 size_type size() const { return length(); } 00298 size_t numel() const { return length(); } 00301 iter_border_walker first_to_last() { return this->length() - 1; } 00302 iter_border_walker begin_to_end() { return this->length(); } 00303 00304 00305 using common_base_class::operator []; 00306 00312 00313 00314 /* 00315 T operator[]( 00316 typename tool1::brackets_arg i) const 00317 { 00318 CHECK(i >= 0 && i < length(), erange); 00319 00320 return array_details::elem_func_swap_op<SWAP_ARGS, 00321 T, F<T, typename A1::elem_type, typename A2::elem_type>, 00322 in1_s, in2_s>:: 00323 from(tool1::brackets(in1->derived(), i), 00324 tool2::brackets(in2->derived(), i)); 00325 }*/ 00326 const_reference operator[]( 00327 typename tool1::brackets_arg i) const 00328 { 00329 CHECK(i >= 0 && i < length(), erange); 00330 00331 return (begin()[i]); 00332 } 00333 00334 00343 00344 void validate() 00345 { 00346 CHECK(in1->length() == in2->length(), eshape); 00347 } 00348 00352 void setref(const A1& a1, const A2& a2) 00353 { 00354 in1 = &a1; 00355 in2 = &a2; 00356 validate(); 00357 } 00358 00359 template <class A> 00360 bool self_overlap(const A& a) const 00361 { 00362 return a.overlap(*in1) || a.overlap(*in2); 00363 } 00366 // TODO: proper place 00367 void init(const A1& a1, const A2& a2) { setref(a1, a2); } 00368 00369 void init(const array& o) { setref(*o.in1, *o.in2); } 00370 00371 00374 00375 array() {} 00376 00378 array(const A1& a1, const A2& a2) { setref(a1, a2); } 00379 00381 array(const array& o) { setref(*o.in1, *o.in2); } 00382 00387 00388 array(size_t) {} 00389 00391 array(size_t, const T&) {} 00392 00394 template <class J, class S> 00395 array(size_t, const array<J, S>&) {} 00396 00398 array(size_t, const T*) {} 00399 00401 template<class J, class S> 00402 array(const array<J, S>& a) {} 00403 00406 00407 ~array() { } 00408 00409 }; 00410