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 00026 00027 template <class T, 00028 template <typename, typename, typename> class F, 00029 class A1, class A2, bool SWAP_ARGS, 00030 class DERIVED_INFO 00031 > 00032 class array_nd<T, 00033 data::binary_elem_func_ptr<F, A1, A2, SWAP_ARGS, DERIVED_INFO> > : 00034 00035 public 00036 array_common_base<array_nd<T, 00037 data::binary_elem_func_ptr<F, A1, A2, SWAP_ARGS, DERIVED_INFO> > >, 00038 00039 public 00040 array_nd_details::basic_iterator_nd_interface<array_nd<T, 00041 data::binary_elem_func_ptr<F, A1, A2, SWAP_ARGS, DERIVED_INFO > > > 00042 { 00043 private: 00044 typedef array_nd prv_this_type; 00045 typedef typename prv_this_type::common_base_class common_base_class; 00046 typedef typename prv_this_type::iter_nd_interface_class iter_nd_interface; 00047 00048 class not_a_type {}; 00049 00050 protected: 00051 typedef typename common_base_class::tool1 tool1; 00052 typedef typename common_base_class::tool2 tool2; 00053 00054 typedef typename common_base_class::in1_s in1_s; 00055 typedef typename common_base_class::in2_s in2_s; 00056 00057 typedef typename common_base_class::ptr_t ptr_t; 00058 00059 public: 00060 typedef array_nd this_type; 00061 00062 typedef this_type this_array_nd_type; 00063 00064 typedef typename common_base_class::derived_type derived_type; 00065 00066 typedef typename common_base_class::base_class base_class; 00067 00068 typedef this_type array_type; 00069 00071 typedef array<size_t, tiny> size_type; 00072 00074 typedef typename A1::size_nd_ref_type size_nd_ref_type; 00075 00077 typedef typename A1::stride_ref_type stride_ref_type; 00078 //typedef typename tool::template 00079 // meta_nd<A1>::stride_ref_type stride_ref_type; 00080 00081 #if 0 00082 // unstable feature 00084 typedef typename types::t_and< 00085 typename A1::has_1d_parenthesis, 00086 typename A2::has_1d_parenthesis 00087 >::type has_1d_parenthesis; 00088 00089 typedef typename types::t_and< 00090 typename A1::has_2d_parenthesis, 00091 typename A2::has_2d_parenthesis 00092 >::type has_2d_parenthesis; 00093 00094 typedef typename types::t_and< 00095 typename A1::has_3d_parenthesis, 00096 typename A2::has_3d_parenthesis 00097 >::type has_3d_parenthesis; 00098 00099 typedef typename types::t_and< 00100 typename A1::has_nd_parenthesis, 00101 typename A2::has_nd_parenthesis 00102 >::type has_nd_parenthesis; 00103 #endif 00104 00105 template<bool PAST_END_CAPABLE = true> 00106 struct const_iterator_nd_class 00107 { 00108 private: 00109 typedef typename types::t_if<types::t_expr<PAST_END_CAPABLE>, 00110 typename A1::const_iterator_nd, 00111 typename A1::_fast_const_iterator_nd>::type iter_nd_1; 00112 00113 typedef typename types::t_if<types::t_expr<PAST_END_CAPABLE>, 00114 typename A2::const_iterator_nd, 00115 typename A2::_fast_const_iterator_nd>::type iter_nd_2; 00116 00117 //typedef typename A1::const_iterator_nd iter_nd_1; 00118 //typedef typename A2::const_iterator_nd iter_nd_2; 00119 00120 ptr_t ptr1; 00121 iter_nd_1 i1; 00122 iter_nd_2 i2; 00123 00124 public: 00125 00126 // TODO: check others types iterator_traits for nd. 00127 // probably wrong or missing. 00128 // esspecially the default iterator nd which 00129 // for some reason (??) questions random access. 00130 // iterator_traits 00131 00132 typedef std::random_access_iterator_tag iterator_category; 00133 typedef T value_type; 00134 typedef ptrdiff_t difference_type; 00135 //typedef const T* pointer; 00136 //typedef const T reference; 00137 typedef internal::pointer_face<const T> pointer; 00138 // using this to comply with std:: iterators. if it is not optimized-out 00139 // by the compiler, consider using 00140 // `const internal::reference_face<const T, types::skip>' 00141 typedef const internal::reference_face<const T, const_iterator_nd_class> 00142 reference; 00143 00144 00145 typedef const_iterator_nd_class this_type; 00146 00147 typedef types::t_false has_base_iterator; 00148 00149 struct iter_nd_border_walker 00150 { 00151 typedef typename iter_nd_1::iter_nd_border_walker iw_t_1; 00152 typedef typename iter_nd_2::iter_nd_border_walker iw_t_2; 00153 iw_t_1 iw1; 00154 iw_t_2 iw2; 00155 00156 iter_nd_border_walker() {} 00157 iter_nd_border_walker(ptrdiff_t x) : iw1(x), iw2(x) { } 00158 iter_nd_border_walker(const iw_t_1& iw1, const iw_t_2& iw2) 00159 : iw1(iw1), iw2(iw2) { } 00160 }; 00161 00162 struct iter_nd_dir_type 00163 { 00164 typedef typename iter_nd_1::iter_nd_dir_type id_t_1; 00165 typedef typename iter_nd_1::iter_nd_dir_type id_t_2; 00166 id_t_1 id1; 00167 id_t_2 id2; 00168 iter_nd_dir_type(const id_t_1& id1, const id_t_2& id2) 00169 : id1(id1), id2(id2) { } 00170 }; 00171 00172 // constructors 00173 const_iterator_nd_class() { } 00174 const_iterator_nd_class(ptr_t p1, const iter_nd_1& i1, const iter_nd_2& i2) 00175 : ptr1(p1), i1(i1), i2(i2) { } 00176 const_iterator_nd_class(const const_iterator_nd_class& o) 00177 : ptr1(o.ptr1), i1(o.i1), i2(o.i2) { } 00178 00179 // members 00180 pointer operator ->() const 00181 { 00182 return pointer(*this, array_details::elem_func_swap_op<SWAP_ARGS, 00183 T, F<T, typename iter_nd_1::value_type, 00184 typename iter_nd_2::value_type>, in1_s, in2_s>:: 00185 from(ptr1, *i1, *i2)); 00186 } 00187 00188 reference operator *() const 00189 { 00190 return reference(array_details::elem_func_swap_op<SWAP_ARGS, 00191 T, F<T, typename iter_nd_1::value_type, 00192 typename iter_nd_2::value_type>, in1_s, in2_s>:: 00193 from(ptr1, *i1, *i2), *this); 00194 } 00195 00196 reference operator [] (ptrdiff_t j) const 00197 { 00198 return reference(array_details::elem_func_swap_op<SWAP_ARGS, 00199 T, F<T, typename iter_nd_1::value_type, 00200 typename iter_nd_2::value_type>, in1_s, in2_s>:: 00201 from(ptr1, i1[j], i2[j]), 00202 // hope that the below line will be optimized-out when using T. 00203 const_iterator_nd_class(ptr1, i1 + j, i2 + j)); 00204 } 00205 00206 // increment-decrement 00207 this_type& operator++() { ++i1; ++i2; return *this; } 00208 this_type& operator--() { --i1; --i2; return *this; } 00209 00210 this_type operator++(int) 00211 { this_type tmp(*this); ++i1; ++i2; return tmp; } 00212 00213 this_type operator--(int) 00214 { this_type tmp(*this); --i1; --i2; return tmp; } 00215 00216 // random access 00217 this_type operator +(const ptrdiff_t j) const 00218 { this_type tmp(i1 + j, i2 + j); return tmp; } 00219 00220 this_type operator -(const ptrdiff_t j) const 00221 { this_type tmp(i1 - j, i2 - j); return tmp; } 00222 00223 this_type& operator +=(const size_t j) 00224 { i1 += j; i2 += j; return *this; } 00225 00226 this_type& operator -=(const size_t j) 00227 { i1 -= j; i2 -= j; return *this; } 00228 00229 // border walker 00230 this_type operator +(const iter_nd_border_walker& z) 00231 { this_type tmp(z.ptr1, i1 + z.iw1, i2 + z.iw2); return tmp; } 00232 00233 this_type operator -(const iter_nd_border_walker& z) 00234 { this_type tmp(z.ptr1, i1 - z.iw1, i2 - z.iw2); return tmp; } 00235 00236 this_type& operator +=(const iter_nd_border_walker& z) 00237 { i1 += z.iw1; i2 += z.iw2; return *this; } 00238 00239 this_type& operator -=(const iter_nd_border_walker& z) 00240 { i1 -= z.iw1; i2 -= z.iw2; return *this; } 00241 00242 00243 iter_nd_dir_type dir() const 00244 { return iter_nd_dir_type(i1.dir(), i2.dir()); } 00245 00246 iter_nd_dir_type dir(ptrdiff_t x) const 00247 { return iter_nd_dir_type(i1.dir(x), i2.dir(x)); } 00248 00249 void inc_along_other_dim_at_begin(const this_type& y) 00250 { i1 += y.i1.dir(); i2 += y.i2.dir(); } 00251 00252 void dec_along_other_dim_at_begin(const this_type& y) 00253 { i1 -= y.i1.dir(); i2 -= y.i2.dir(); } 00254 00255 void move_along(const this_type& y, ptrdiff_t x) 00256 { i1 += y.i1.dir(x); i2 += y.i2.dir(x); } 00257 00258 // difference 00259 ptrdiff_t operator -(const this_type& a) const 00260 { return i1 - a.i1; } 00261 00262 }; 00263 00264 typedef const_iterator_nd_class<true> const_iterator_nd; 00265 typedef const_iterator_nd_class<false> _fast_const_iterator_nd; 00266 00267 typedef std::reverse_iterator<const_iterator_nd> 00268 const_reverse_iterator_nd; 00269 00270 //YOU ARE HERE 00271 00272 00273 using base_class::derived; 00274 00276 base_class& base() { return *this; } 00277 const base_class& base() const { return *this; } 00278 00283 #if 0 //enable them when you make the has_?d_parenthesis feature 00284 const T& operator()(size_t s1) const; 00285 const T& operator()(size_t s1, size_t s2) const; 00286 const T& operator()(size_t s1, size_t s2, size_t s3) const; 00287 const T& operator()(size_t s1, size_t s2, size_t s3, size_t s4) const; 00288 const T& operator()(size_t s1, size_t s2, size_t s3, size_t s4, size_t s5) const; 00289 const T& operator()(size_t s1, size_t s2, size_t s3, size_t s4, size_t s5, size_t s6) const; 00290 #endif 00291 00292 00293 template<class S> 00294 T operator()(const array<size_t, S>& indx) const 00295 { 00296 return array_details::elem_func_swap_op<SWAP_ARGS, 00297 T, F<T, typename A1::elem_type, typename A2::elem_type>, 00298 in1_s, in2_s>:: 00299 from((this->in1->derived())(indx), (this->in2->derived())(indx)); 00300 } 00302 00303 00304 // TODO: place properly 00305 void init(ptr_t p1, const A1& a1, const A2& a2) { this->setref(p1, a1, a2); } 00306 00307 void init(const array_nd& a) { base().init(a); } 00308 00309 00312 00313 array_nd() { } 00314 00316 array_nd(ptr_t p1, const A1& a1, const A2& a2) { this->setref(p1, a1, a2); } 00317 00319 array_nd(const array_nd& a) : common_base_class(a) { } 00320 00326 // Construct by defining an element count. 00327 explicit array_nd(size_t count) { } 00328 00329 // Construct by defining an element count and a sigle default value 00330 array_nd(size_t count, const T& s) { } 00331 00332 // Construct by defining an element count and a pointer to data. 00333 array_nd(size_t count, const T *data) { } 00334 00335 // Construct from a size_array containing the dimension sizes 00336 template<class S> 00337 array_nd(const array<size_t, S>& sz) { } 00338 00339 // construct from a size_array containing the dimension sizes and scalar 00340 template<class S> 00341 array_nd(const array<size_t, S>& sz, const T& s) { } 00342 00343 //Construct from a size_array and pointer 00344 template<class S> 00345 array_nd(const array<size_t, S>& sz, const T* ptr) { } 00346 00347 //Construct from a size_array and an array with the values. 00348 template<class S, class J, class D> 00349 array_nd(const array<size_t, S>& sz, const array<J, D>& a) { } 00350 00351 // Constructor using another form of array_nd 00352 template<class J, class S> 00353 array_nd(const array_nd<J, S>& a) { } 00354 00360 00361 size_nd_ref_type size_nd() const { return this->in1->size_nd(); } 00362 00364 size_t size_nd(size_t d) const { return this->in1->size_nd(d); } 00365 00366 // todo fix this and use a tool::stride 00368 stride_ref_type stride() const 00369 { return this->in1->stride(); } 00370 00372 size_t stride(size_t dim) const 00373 { return this->in1->stride(dim); } 00374 00376 size_t size(size_t d) const { return this->in1->size(d); } 00377 00379 size_type size() const { return this->in1->size(); } 00380 00382 size_t ndims() const { return this->in1->ndims(); } 00386 }; 00387 00388