ivl 679
ivl/details/array/impl/specialization/slice_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 namespace array_details {
00026 
00027 template<bool IS_CONTENT_RESIZEABLE>
00028 struct slice_tools
00029 {
00030         template<class A>
00031         static void shrink(A& a, size_t j) { }
00032 
00033         template<class A_IT>
00034         static size_t cut(A_IT a, size_t, ptrdiff_t, size_t) { return 0; }
00035 };
00036 
00037 template<>
00038 struct slice_tools<true>
00039 {
00040         template<class A>
00041         static void shrink(A& a, size_t j)
00042         {
00043                  a.resize(j);
00044         }
00045 
00046         template<class A_IT>
00047         static size_t cut(A_IT a, size_t first, ptrdiff_t step, size_t len);
00048 };
00049 
00050 template<class A_IT>
00051 size_t slice_tools<true>::cut(A_IT a, size_t first, ptrdiff_t step, size_t len)
00052 {
00053         // len:length after cut. these specs are not same across specializations.
00054         size_t i = 0;
00055         size_t j = 0;
00056 
00057         for(size_t i = 0; j < len && i != first; ++i, ++a) { ++j; }
00058         first += step;
00059 
00060         A_IT wa = a;
00061 
00062         for(++i, ++a; j < len; ++i, ++a) {
00063                 if(i != first) {
00064                         *wa = *a;
00065                         ++wa;
00066                         ++j;
00067                 }
00068                 else {
00069                         first += step;
00070                 }
00071         }
00072 
00073         return len;
00074 }
00075 
00076 } /* namespace array_details */
00077 
00083 template <class T,
00084                  class A,
00085                  class DERIVED_INFO
00086              >
00087 class array<T, data::slice<A, DERIVED_INFO> >
00088         :
00089         public array_common_base<array<T,
00090                 data::slice<A, DERIVED_INFO> > >,
00091 
00092         public data::referer<typename types::derive<
00093                 array<T, data::slice<A, DERIVED_INFO> > >::type>
00094 {
00095 
00096 private:
00097         typedef array_common_base<array<T,
00098                 data::slice<A, DERIVED_INFO> > > common_base_class;
00099 
00100         typedef typename types::t_if<typename array::is_writeable,
00101                 typename A::iterator,
00102                 typename A::const_iterator>::type a_best_iterator;
00103 
00104         // used to disable some types. TODO: test that not_a_type actually throws an error and
00105         // consider explicitly making the default constructor private.
00106         class not_a_type { };
00107 
00108         typedef typename types::t_and_3<
00109                         types::t_not<types::is_const<A> >,
00110                         typename A::is_writeable,
00111                         typename A::is_resizeable>
00112                         ::type is_content_resizeable;
00113 
00114         typedef typename array_details::
00115                 slice_tools<array::is_content_resizeable::value> slice_tool;
00116 
00117         A* a;
00118         ivl::slice b;
00119         size_t end_el;
00120 
00121 protected:
00122         template <class J, class D>
00123         void copy_or_cut(const array<J, D>& o)
00124         {
00125                 if(is_content_resizeable::value &&
00126                         o.begin() == o.end() && b.length > 0) {
00127 
00128                         size_t newlen_a;
00129 
00130                         if(b.stride < 0)
00131                                 newlen_a = slice_tool::cut(a->begin(),
00132                                         end_el, -b.stride, a->length() - b.length);
00133                         else
00134                                 newlen_a = slice_tool::cut(a->begin(),
00135                                         b.start, b.stride, a->length() - b.length);
00136 
00137                         slice_tool::shrink(*a, newlen_a);
00138 
00139                         b.length = 0;
00140                         end_el = b.start;
00141 
00142                 } else {
00143                         static_cast<common_base_class&>(*this).assign_array(o);
00144                 }
00145         }
00146 public:
00147         typedef array this_type;
00148 
00149         typedef this_type this_array_type;
00150 
00151         typedef this_type array_type;
00152 
00153         typedef T elem_type;
00154 
00155         typedef typename a_best_iterator::reference reference;
00156         typedef typename A::const_reference const_reference;
00157 
00158         typedef typename common_base_class::derived_type derived_type;
00159 
00160         typedef typename common_base_class::base_class base_class;
00161 
00163         typedef size_t size_type;
00164 
00165         using base_class::derived;
00166 
00168         typename types::t_and_3<
00169                 types::t_not<types::is_const<A> >,
00170                 typename A::is_writeable,
00171                 typename A::is_resizeable>
00172                 ::type is_cuttable;
00173 
00174 
00175         template <bool CONST>
00176         class iterator_type
00177         : public data::data_details::
00178                 rnd_iter_operator_expander<iterator_type<CONST>, T, CONST,
00179                         typename types::remove_const<
00180                                 typename a_best_iterator::reference>::type>
00181         {
00182         private:
00183                 template <bool C> friend class iterator_type;
00184 
00185                 template <class X, class Y, bool C, class Z>
00186                 friend class data::data_details::rnd_iter_operator_expander;
00187 
00188                 template <class X, class Y, bool C, class Z>
00189                 friend class data::data_details::iter_operator_expander;
00190 
00191 
00192                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00193                         ::type best_value_type;
00194 
00195                 typedef typename types::apply_const<
00196                         typename a_best_iterator::reference, types::t_expr<CONST> >
00197                         ::type best_ref_type;
00198 
00199                 // this class is used to disable specific specialization members
00200                 class not_a_type { };
00201 
00202                 typedef typename types::t_if<types::t_expr<CONST>, not_a_type,
00203                         types::code_word<> >::type invalid_if_const;
00204 
00205                 typedef typename types::t_if<types::t_expr<CONST>,
00206                         typename A::const_iterator, typename A::iterator>::type a_iterator;
00207 
00208                 a_iterator a;
00209                 ptrdiff_t step;
00210 
00211         protected:
00212                 inline typename types::apply_const<best_ref_type>::type base(
00213                         types::code_word<> ok = types::code_word<>()) const
00214                         { return (*a); }
00215 //TODO!!!! make it random access only if b is random access
00216 // otherwise make it non-random access.
00217 // make it complain if a is non-random access.
00218                 inline best_ref_type base(
00219                         invalid_if_const disable = invalid_if_const())
00220                         { return (*a); }
00221 
00222                 inline typename types::apply_const<best_ref_type>::type base(size_t j,
00223                         types::code_word<> ok = types::code_word<>()) const
00224                         { return (a[j * step]); }
00225 
00226                 inline best_ref_type base(size_t j,
00227                         invalid_if_const disable = invalid_if_const())
00228                         { return (a[j * step]); }
00229 
00230         public:
00231                 typedef iterator_type<CONST> this_type;
00232 
00233                 // iterator_traits
00234                 typedef std::random_access_iterator_tag iterator_category;
00235                 typedef T value_type;
00236                 typedef ptrdiff_t difference_type;
00237                 typedef best_value_type* pointer;
00238                 typedef best_ref_type reference;
00239 
00240                 // constructors
00241                 iterator_type() { }
00242                 iterator_type(const this_type& it)
00243                 : a(it.a), step(it.step) { }
00244                 template <bool C>
00245                 iterator_type(const iterator_type<C>& it)
00246                 : a(it.a), step(it.step) { }
00247                 iterator_type(const a_iterator& a, ptrdiff_t step)
00248                         : a(a), step(step) { }
00249 
00250                 // members
00251 
00252                 // increment-decrement
00253                 this_type& operator++() { a += step; return *this; }
00254                 this_type& operator--() { a -= step; return *this; }
00255 
00256                 this_type operator++(int) { this_type t(*this); ++(*this); return t; }
00257                 this_type operator--(int) { this_type t(*this); --(*this); return t; }
00258 
00259                 // random access.
00260 
00261                 // X can be either size_t or B::iter_bound_mover
00262                 template<class X>
00263                 this_type& operator +=(X j) { a += j * step; return *this; }
00264 
00265                 template<class X>
00266                 this_type& operator -=(X j) { a -= j * step; return *this; }
00267 
00268                 template<class X>
00269                 inline this_type operator +(X j) const
00270                 {
00271                         this_type tmp(*this);
00272                         tmp += j;
00273                         return tmp;
00274                 }
00275                 template<class X>
00276                 inline this_type operator -(X j) const
00277                 {
00278                         this_type tmp(*this);
00279                         tmp -= j;
00280                         return tmp;
00281                 }
00282 
00283                 // difference.
00284                 ptrdiff_t operator-(const this_type& it)
00285                 {
00286                         return (a - it.a) / step;
00287                 }
00288 
00289                 //copy same type iterator
00290                 this_type& operator=(const this_type& it)
00291                 {
00292                         a = it.a; step = it.step;
00293                         return *this;
00294                 }
00295                 //copy relevant type iterator
00296                 template<bool C>
00297                 this_type& operator=(const iterator_type<C>& it)
00298                 {
00299                         a = it.a; step = it.step;
00300                         return *this;
00301                 }
00302 
00303                 bool operator==(const this_type& it) const { return (a == it.a); }
00304                 bool operator!=(const this_type& it) const { return (a != it.a); }
00305                 bool operator<(const this_type& it) const { return (a < it.a); }
00306                 bool operator<=(const this_type& it) const { return (a <= it.a); }
00307                 bool operator>(const this_type& it) const { return (a > it.a); }
00308                 bool operator>=(const this_type& it) const { return (a >= it.a); }
00309 
00310         };
00311 
00312         // typedefs for class iterators
00313         typedef typename types::t_if<typename array::is_writeable,
00314                 iterator_type<false>, not_a_type>::type iterator;
00315 
00316         typedef iterator_type<true> const_iterator;
00317 
00318         typedef typename types::t_if<types::t_eq<iterator, not_a_type>,
00319                 const_iterator, iterator>::type best_iterator;
00320 
00321         typedef std::reverse_iterator<iterator> reverse_iterator;
00322 
00323         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00324 
00325         typedef ptrdiff_t iter_border_walker;
00326 
00327         iterator begin()
00328                 { return best_iterator(a->begin() + b.start, b.stride); }
00329 
00330         iterator end()
00331                 { return best_iterator(a->begin() + end_el, b.stride); }
00332 
00333         const_iterator begin() const
00334                 { return const_iterator(a->begin() + b.start, b.stride); }
00335 
00336         const_iterator end() const
00337                 { return const_iterator(a->begin() + end_el, b.stride); }
00338 
00339         // reverse iterator defs
00340         reverse_iterator rbegin() { return reverse_iterator(end()); }
00341 
00342         reverse_iterator rend() { return reverse_iterator(begin()); }
00343 
00344         const_reverse_iterator rbegin() const
00345                 { return const_reverse_iterator(end()); }
00346 
00347         const_reverse_iterator rend() const
00348                 { return const_reverse_iterator(begin()); }
00349 
00350 
00351         using common_base_class::operator[];
00352 
00353         // todo: resolve when b has no random access
00354         typename best_iterator::reference operator[](size_t j)
00355         {
00356                 return (*a)[b.start + j * b.stride];
00357         }
00358         typename const_iterator::reference operator[](size_t j) const
00359         {
00360                 return (*a)[b.start + j * b.stride];
00361         }
00362 
00365         //TODO: explain this better.
00367         size_t length() const { return b.length; }
00369         size_type size() const { return length(); }
00371         size_t numel() const { return length(); }
00374         iter_border_walker first_to_last() { return b.length - 1; }
00375         iter_border_walker begin_to_end() { return b.length; }
00376 
00377         void init(A& a0, const slice& b0)
00378         {
00379                 a = &a0;
00380                 b = b0;
00381                 end_el = b0.start + b0.stride * b0.length;
00382         }
00383 
00384         void init(const array& o)
00385         {
00386                 a = o.a;
00387                 b = o.b;
00388                 end_el = o.end_el;
00389         }
00390 
00393 
00394         array(A& a, const ivl::slice& b)
00395                 : a(&a), b(b), end_el(b.start + b.stride * b.length) { }
00396 
00398         array(const this_type& o) : a(o.a), b(o.b), end_el(o.end_el) {}
00399 
00402 
00403         ~array() { }
00404 
00405 
00409         template <class J, class P>
00410         derived_type& assign_array(const array<J, data::empty<P> >& o)
00411         {
00412                 copy_or_cut(o); // will always fallback to cut
00413                 return this->derived();
00414         }
00415 
00416         template<class D>
00417         derived_type& assign_array(const D& o)
00418         {
00419                 copy_or_cut(o);
00420                 return this->derived();
00421         }
00422 
00423         template <class D>
00424         bool overlap(const D& d) const
00425         {
00426                 return a->overlap(d);
00427         }
00428 
00429         template <class D>
00430         bool self_overlap(const D& d) const
00431         {
00432                 return d.overlap(*a);
00433         }
00434 
00441         using common_base_class::operator=;
00442 
00443         this_type& operator=(const this_type& o) // copy operator
00444         {
00445                 copy_or_cut(o);
00446                 return *this;
00447         }
00448 
00451 };
00452 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations