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