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