ivl 679
ivl/details/array/impl/specialization/catarray_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 #if 1
00025 
00030 template <class T,
00031                  class A1,
00032                  class A2,
00033                  int CATDIM,
00034                  class DERIVED_INFO
00035              >
00036 class array<T, data::catarray<A1, A2, CATDIM, DERIVED_INFO> >
00037         :
00038         public array_common_base<array<T,
00039                 data::catarray<A1, A2, CATDIM, DERIVED_INFO> > >,
00040 
00041         public data::referer<typename types::derive<
00042                 array<T, data::catarray<A1, A2, CATDIM,
00043                         DERIVED_INFO> > >::type>
00044 {
00045 private:
00046         typedef array_common_base<array<T,
00047                 data::catarray<A1, A2, CATDIM,
00048                         DERIVED_INFO> > > common_base_class;
00049 
00050 protected:
00051 //--------------------------------------------------------------------------
00052 // types
00053 
00054         // best_reference_iterator:
00055         // defines which is the best possible iterator to be used for the
00056         // underlying array, meaning the most powerful, between the const_
00057         // and non-const_ ones. const_ is used if the array is read only.
00058         typedef typename types::best_iterator<A1>::type best_reference_iterator1;
00059         typedef typename types::best_iterator<A2>::type best_reference_iterator2;
00060 
00061         // const_reference_iterator:
00062         // defines which is the const_iterator to be used for the
00063         // underlying array.
00064         typedef typename A1::const_iterator const_reference_iterator1;
00065         typedef typename A2::const_iterator const_reference_iterator2;
00066 
00067 
00068         typedef best_reference_iterator1 best_ref_iter1;
00069         typedef const_reference_iterator1 const_ref_iter1;
00070         typedef best_reference_iterator2 best_ref_iter2;
00071         typedef const_reference_iterator2 const_ref_iter2;
00072 
00073 #if 0
00074         // tool:
00075         // the correct specialization of the class catarray_tools that implements
00076         // functionality of the reference iterator depending of the type.
00077         typedef array_details::catarray_tools<
00078                 reference_iterator_is_nd, best_ref_iter> tool;
00079 
00080 
00081         // some helper structs
00082         typedef array_details::catarray_common_tools ctool;
00083 
00084 #endif
00085         // used to disable some types. TODO: test that not_a_type actually throws an error and
00086         // consider explicitly making the default constructor private.
00087         class not_a_type { };
00088 
00089         typedef typename types::t_if<types::t_expr<(CATDIM == -1)>,
00090                 ivl::scalar<int>, ivl::fixed_scalar<int, CATDIM> >::type catdim_t;
00091 
00092 
00093 //--------------------------------------------------------------------------
00094 // members
00095         A1* in1;
00096         A2* in2;
00097         catdim_t cdim;
00098         size_t catstride, catstride1, catstride2;
00099         size_t all_len;
00100 
00101 
00102         // helper data that is computed on the construction of the catarray
00103         // object, needed to improve speed.
00104 
00105 
00106 
00107 
00108 //--------------------------------------------------------------------------
00109 // functions
00110 
00111 public:
00112         void init(A1& a1, A2& a2, catdim_t cdim = -1);
00113         void init(const array& o);
00114 
00115         typedef array this_type;
00116 
00117         typedef this_type this_array_type;
00118 
00119         typedef this_type array_type;
00120 
00121         typedef T elem_type;
00122 
00123         typedef typename best_reference_iterator1::reference reference;
00124         typedef typename best_reference_iterator1::reference best_reference;
00125         typedef typename const_reference_iterator1::reference const_reference;
00126 
00127         typedef typename common_base_class::derived_type derived_type;
00128 
00129         typedef typename common_base_class::base_class base_class;
00130 
00132         typedef size_t size_type;
00133 
00134         using base_class::derived;
00135 
00136 
00137 
00138         struct iter_border_walker
00139         {
00140                 typedef typename A1::iter_border_walker t1;
00141                 typedef typename A2::iter_border_walker t2;
00142                 t1 s1;
00143                 t2 s2;
00144                 ptrdiff_t sp;
00145 
00146                 iter_border_walker() {}
00147                 iter_border_walker(const t1& s1, const t2& s2, ptrdiff_t sp)
00148                 : s1(s1), s2(s2), sp(sp) { }
00149         };
00150 
00151         template<bool CONST, int SPEC = 0>
00152         class iterator_type
00153         : public types::t_if<typename array::has_random_access,
00154         data::data_details::
00155                 rnd_iter_operator_expander<iterator_type<CONST, SPEC>, T, CONST,
00156                         typename types::remove_const<reference>::type>,
00157         data::data_details::
00158                 iter_operator_expander<iterator_type<CONST, SPEC>, T, CONST,
00159                         typename types::remove_const<reference>::type >
00160         >::type,
00161         public types::border_walker_iterator_identifier
00162         {
00163         private:
00164                 template <bool C, int S> friend class iterator_type;
00165                 friend class array;
00166 
00167                 friend class iter_border_walker;
00168 
00169                 friend class data::data_details::iter_operator_expander
00170                         <iterator_type<CONST, SPEC>, T, CONST>;
00171                 friend class data::data_details::rnd_iter_operator_expander
00172                         <iterator_type<CONST, SPEC>, T, CONST>;
00173 
00174                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00175                         ::type best_value_type;
00176 
00177                 // this class is used to disable specific specialization members
00178                 class not_a_type { };
00179 
00180                 typedef typename types::t_if<types::t_expr<CONST>, not_a_type,
00181                         types::code_word<> >::type invalid_if_const;
00182 
00183                 typedef typename types::t_if<types::t_expr<CONST>,
00184                         typename A1::const_iterator,
00185                         typename A1::best_iterator>::type iterator1;
00186 
00187                 typedef typename types::t_if<types::t_expr<CONST>,
00188                         typename A2::const_iterator,
00189                         typename A2::best_iterator>::type iterator2;
00190 
00191                 typedef typename iterator1::reference prv_reference;
00192                 typedef prv_reference best_ref_type;
00193 
00194                 iterator1 ir1;
00195                 iterator2 ir2;
00196                 ptrdiff_t p;
00197                 size_t stride1, stride2, stride;
00198 
00199         protected:
00200                 inline const_reference base(
00201                         types::code_word<> ok = types::code_word<>()) const
00202                         { return p < stride1 ? (*ir1) : (*ir2); }
00203 
00204                 inline prv_reference base(
00205                         invalid_if_const disable = invalid_if_const())
00206                         { return p < stride1 ? (*ir1) : (*ir2); }
00207 
00208                 inline typename types::apply_const<best_ref_type>::type base(size_t j,
00209                         types::code_word<> ok = types::code_word<>()) const
00210                 {
00211                         ptrdiff_t soffs = (p + j) / stride;
00212                         ptrdiff_t offs = (p + j) % stride;
00213                         ptrdiff_t d;
00214                         if(offs >= stride1) {
00215                                 d = soffs * stride2 +
00216                                         (p >= stride1 ? offs - p : offs);
00217                                 return ir2[d]; // TODO: rnd_add
00218                         } else {
00219                                 d = soffs * stride1 +
00220                                         (p < stride1 ?  offs - p : offs - stride1);
00221                                 return ir1[d];
00222                         }
00223                 }
00224 
00225                 inline best_ref_type base(size_t j,
00226                         invalid_if_const disable = invalid_if_const())
00227                 {
00228                         ptrdiff_t soffs = (p + j) / stride;
00229                         ptrdiff_t offs = (p + j) % stride;
00230                         ptrdiff_t d;
00231                         if(offs >= stride1) {
00232                                 d = soffs * stride2 +
00233                                         (p >= stride1 ? offs - p : offs);
00234                                 return ir2[d];
00235                         } else {
00236                                 d = soffs * stride1 +
00237                                         (p < stride1 ?  offs - p : offs - stride1);
00238                                 return ir1[d];
00239                         }
00240                 }
00241 
00242         public:
00243                 typedef iterator_type<CONST, 0> this_type;
00244 
00245                 // iterator_traits
00246                 typedef typename types::t_if<typename array::has_random_access,
00247                         std::random_access_iterator_tag,
00248                         std::bidirectional_iterator_tag>::type iterator_category;
00249                 typedef T value_type;
00250                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00251                         ::type access_value_type;
00252                 typedef ptrdiff_t difference_type;
00253                 typedef access_value_type* pointer;
00254                 typedef prv_reference reference;
00255 
00256                 // border walker
00257                 typedef typename array::iter_border_walker iter_border_walker;
00258 
00259                 // constructors
00260                 iterator_type() { }
00261 
00262                 iterator_type(const this_type& it)
00263                 : ir1(it.ir1), ir2(it.ir2), p(it.p),
00264                         stride1(it.stride1), stride2(it.stride2), stride(it.stride)
00265                  { }
00266 
00267                 template <bool C, int S>
00268                 iterator_type(const iterator_type<C, S>& it)
00269                 : ir1(it.ir1), ir2(it.ir2), p(it.p),
00270                         stride1(it.stride1), stride2(it.stride2), stride(it.stride)
00271                  { }
00272 
00273                 iterator_type(const iterator1& i1, const iterator2& i2,
00274                         size_t p, size_t stride1, size_t stride2, size_t stride)
00275                         : ir1(i1), ir2(i2), p(p),
00276                                 stride1(stride1), stride2(stride2), stride(stride) {}
00277 
00278 
00279                 // members
00280 
00281                 // increment-decrement
00282                 this_type& operator++()
00283                 {
00284                         if(p++ < stride1)
00285                                 ++ir1;
00286                         else
00287                         {
00288                                 ++ir2;
00289                                 if(p >= stride)
00290                                         p = 0;
00291                         }
00292                         return *this;
00293                 }
00294                 this_type& operator--()
00295                 {
00296                         if(--p >= stride1)
00297                                 --ir2;
00298                         else
00299                         {
00300                                 --ir1;
00301                                 if(p < 0)
00302                                         p = stride;
00303                         }
00304                         return *this;
00305                 }
00306 
00307                 this_type operator++(int) { this_type t(*this); ++(*this); return t; }
00308                 this_type operator--(int) { this_type t(*this); --(*this); return t; }
00309 
00310                 this_type& operator +=(ptrdiff_t j)
00311                 {
00312                         ptrdiff_t soffs = (p + j) / stride;
00313                         ptrdiff_t offs = (p + j) % stride;
00314                         ptrdiff_t d;
00315 
00316                         if(offs >= stride1) {
00317                                 d = soffs * stride2 +
00318                                         (p >= stride1 ? offs - p : offs);
00319                                 ir2 += d; // TODO: rnd_add
00320                                 ir1 += soffs * stride1 + (p >= stride1 ? 0 : stride1 - p);
00321                         } else {
00322                                 d = soffs * stride1 +
00323                                         (p < stride1 ?  offs - p : offs - stride1);
00324                                 ir1 += d;
00325                                 ir2 += soffs * stride2 + (p < stride1 ? 0 : stride1 - p);
00326                         }
00327                         p = offs;
00328 
00329                         return *this;
00330                 }
00331                 this_type& operator -=(ptrdiff_t j)
00332                 {
00333                         return (*this) += (-j);
00334                 }
00335                 inline this_type operator +(ptrdiff_t j) const
00336                 {
00337                         this_type tmp(*this);
00338                         tmp += j;
00339                         return tmp;
00340                 }
00341                 inline this_type operator -(ptrdiff_t j) const
00342                 {
00343                         this_type tmp(*this);
00344                         tmp -= j;
00345                         return tmp;
00346                 }
00347 
00348                 this_type& operator +=(iter_border_walker ib)
00349                 {
00350                         ir1 += ib.s1;
00351                         ir2 += ib.s2;
00352                         p += ib.sp;
00353                         return *this;
00354                 }
00355                 this_type& operator -=(iter_border_walker ib)
00356                 {
00357                         ir1 -= ib.s1;
00358                         ir2 -= ib.s2;
00359                         p -= ib.sp;
00360                         return *this;
00361                 }
00362                 inline this_type operator +(iter_border_walker j) const
00363                 {
00364                         this_type tmp(*this);
00365                         tmp += j;
00366                         return tmp;
00367                 }
00368                 inline this_type operator -(iter_border_walker j) const
00369                 {
00370                         this_type tmp(*this);
00371                         tmp -= j;
00372                         return tmp;
00373                 }
00374 
00375                 // difference
00376                 ptrdiff_t operator-(const this_type& o) const
00377                 {
00378                         ptrdiff_t d1;
00379                         d1 = (ir1 - o.ir1)
00380                                 + (p < stride1) ? -p : 0 + (o.p < stride1) ? o.p : 0;
00381                         return (d1 / stride1) * stride + p - o.p;
00382                 }
00383 
00384 
00385                 //copy same type iterator
00386                 this_type& operator=(const this_type& it)
00387                 {
00388                         ir1 = it.ir1; ir2 = it.ir2; p = it.p;
00389                         stride1 = it.stride1; stride2 = it.stride2; stride = it.stride;
00390                         return *this;
00391                 }
00392                 //copy relevant type iterator
00393                 template<bool C, int S>
00394                 this_type& operator=(const iterator_type<C, S>& it)
00395                 {
00396                         ir1 = it.ir1; ir2 = it.ir2; p = it.p;
00397                         stride1 = it.stride1; stride2 = it.stride2; stride = it.stride;
00398                         return *this;
00399                 }
00400 
00401                 bool operator==(const this_type& it) const
00402                         { return (p == it.p && ir1 == it.ir1); }
00403                 bool operator!=(const this_type& it) const
00404                         { return (p != it.p || ir1 != it.ir1); }
00405                 bool operator<(const this_type& it) const
00406                         { return (ir1 < it.ir1 || (ir1 == it.ir1 && p < it.p)); }
00407                 bool operator<=(const this_type& it) const
00408                         { return (ir1 < it.ir1 || (ir1 == it.ir1 && p <= it.p)); }
00409                 bool operator>(const this_type& it) const
00410                         { return (ir1 > it.ir1 || (ir1 == it.ir1 && p > it.p)); }
00411                 bool operator>=(const this_type& it) const
00412                         { return (ir1 > it.ir1 || (ir1 == it.ir1 && p >= it.p)); }
00413 
00414         };
00415 
00416         // typedefs for class iterators
00417         typedef typename types::t_if<typename array::is_writeable,
00418                 iterator_type<false, 0>,
00419                 not_a_type>::type iterator;
00420 
00421         typedef iterator_type<true, 0> const_iterator;
00422 
00423         typedef typename types::t_if<types::t_eq<iterator, not_a_type>,
00424                 const_iterator, iterator>::type best_iterator;
00425 
00426         typedef std::reverse_iterator<iterator> reverse_iterator;
00427 
00428         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00429 
00430 #if 0
00431         template<int SPC>
00432         struct s_iterator
00433         {
00434                 typedef data::catarray_iterator_type<T, best_reference_iterator,
00435                         best_reference_iterator,
00436                         reference_iterator_is_nd::value, false, SPC> type;
00437         };
00438         template<int SPC>
00439         struct const_s_iterator
00440         {
00441                 typedef data::catarray_iterator_type<T, best_reference_iterator,
00442                         best_reference_iterator,
00443                         reference_iterator_is_nd::value, true, SPC> type;
00444         };
00445         template<int SPC>
00446         struct reverse_s_iterator
00447         {
00448                 typedef std::reverse_iterator<s_iterator<SPC> > type;
00449         };
00450         template<int SPC>
00451         struct const_reverse_s_iterator
00452         {
00453                 typedef std::reverse_iterator<const_s_iterator<SPC> > type;
00454         };
00455         int iter_specialization() const
00456         {
00457                 return itspec1;
00458         }
00459 #endif
00460 
00461         iterator begin()
00462         {
00463                 return iterator(in1->begin(), in2->begin(), 0,
00464                         catstride1, catstride2, catstride);
00465         }
00466 
00467         iterator end()
00468         {
00469                 return iterator(in1->end(), in2->end(), 0,
00470                         catstride1, catstride2, catstride);
00471         }
00472 
00473         const_iterator begin() const
00474         {
00475                 return const_iterator(in1->begin(), in2->begin(), 0,
00476                         catstride1, catstride2, catstride);
00477         }
00478 
00479         const_iterator end() const
00480         {
00481                 return const_iterator(in1->end(), in2->end(), 0,
00482                         catstride1, catstride2, catstride);
00483         }
00484 
00485         // reverse iterator defs
00486         reverse_iterator rbegin() { return reverse_iterator(end()); }
00487 
00488         reverse_iterator rend() { return reverse_iterator(begin()); }
00489 
00490         const_reverse_iterator rbegin() const
00491                 { return const_reverse_iterator(end()); }
00492 
00493         const_reverse_iterator rend() const
00494                 { return const_reverse_iterator(begin()); }
00495 
00496 
00497         iter_border_walker first_to_last()
00498         {
00499                 return iter_border_walker(in1->first_to_last(),
00500                         in2->first_to_last(), catstride - 1);
00501         }
00502 
00503         iter_border_walker begin_to_end()
00504         {
00505                 return iter_border_walker(in1->begin_to_end(),
00506                         in2->begin_to_end(), catstride);
00507         }
00508 
00509 
00510         using common_base_class::operator[];
00511 
00512         // todo: resolve when b has no random access
00513         // todo: create a special reference class
00514         // and specialize for writing
00515         typename best_iterator::reference operator[](size_t j)
00516         {
00517                 size_t so = j / catstride;
00518                 size_t o = j % catstride;
00519                 if(o < catstride1)
00520                         return (*in1)[so * catstride1 + o];
00521                 else
00522                         return (*in2)[so * catstride2 + (o - catstride1)];
00523         }
00524         typename const_iterator::reference operator[](size_t j) const
00525         {
00526                 size_t so = j / catstride;
00527                 size_t o = j % catstride;
00528                 if(o < catstride1)
00529                         return (*in1)[so * catstride1 + o];
00530                 else
00531                         return (*in2)[so * catstride2 + (o - catstride1)];
00532         }
00533 
00534 
00537         //TODO: explain this better.
00539         size_t length() const
00540         {
00541                 return all_len;
00542         }
00543 
00545         size_type size() const { return length(); }
00546 
00548         size_t numel() const { return length(); }
00556         array() { in1 = NULL; }
00557 
00558         array(const array& o) { init(o); }
00559 
00560         // Filler constructor
00561         array(const size_t) { in1 = NULL; }
00562 
00563         array(A1& a1, A2& a2, catdim_t cd = -1)
00564         {
00565                 init(a1, a2, cd);
00566         }
00567 
00568 
00569         void setref(A1& a1, A2& a2, catdim_t cd = -1)
00570         {
00571                 init(a1, a2, cd);
00572         }
00573 
00574         template <class D>
00575         bool overlap(const D& d) const
00576         {
00577                 return in1->overlap(d) || in2->overlap(d);
00578         }
00579 
00580         template <class D>
00581         bool self_overlap(const D& d) const
00582         {
00583                 return d.overlap(*in1) || d.overlap(*in2);
00584         }
00585 
00586 
00587 
00589         ~array() { }
00590 
00591         using common_base_class::operator=;
00592 
00593         this_type& operator=(const array& o)
00594         { common_base_class::operator=(o); return *this; }
00595 
00596         template <class J, class P>
00597         derived_type& assign_array(const array<J, data::empty<P> >& o)
00598         {
00599                 *in1 = o;
00600                 *in2 = o;
00601                 //copy_or_cut(o); // will always fallback to cut // todo
00602                 return this->derived();
00603         }
00604 
00605         template<class D>
00606         derived_type& assign_array(const D& o)
00607         {
00608                 //copy_or_cut(o); TODO
00609                 static_cast<common_base_class&>(*this).assign_array(o);
00610                 return this->derived();
00611         }
00612 
00613 
00614 };
00615 
00616 
00617 template <class T,
00618                  class A1,
00619                  class A2,
00620                  int CD,
00621                  class DERIVED_INFO
00622              >
00623 void array<T, data::catarray<A1, A2, CD, DERIVED_INFO> >
00624         ::init(const array& o)
00625 {
00626         in1 = o.in1;
00627         in2 = o.in2;
00628         cdim = o.cdim;
00629         catstride = o.catstride;
00630         catstride1 = o.catstride1;
00631         catstride2 = o.catstride2;
00632         all_len = o.all_len;
00633 }
00634 
00635 template <class T,
00636                  class A1,
00637                  class A2,
00638                  int CD,
00639                  class DERIVED_INFO
00640              >
00641 void array<T, data::catarray<A1, A2, CD, DERIVED_INFO> >
00642         ::init(A1& a1, A2& a2, catdim_t cd)
00643 {
00644         in1 = &a1;
00645         in2 = &a2;
00646         cdim = cd;
00647         //notice: limits dimensions to 32 bit or native bit int
00648         catstride1 = (cdim == int(a1.ndims()) - 1) ?
00649                 a1.length() : a1.stride(int(cdim) + 1);
00650         catstride2 = (cdim == int(a2.ndims()) - 1) ?
00651                 a2.length() : a2.stride(int(cdim) + 1);
00652 
00653         catstride = catstride1 + catstride2;
00654 
00655         all_len = a1.length() + a2.length();
00656 }
00657 
00658 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations