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