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