ivl 679
ivl/details/array_nd/impl/specialization/binary_elem_func_nd_class.hpp
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations