ivl 679
ivl/details/array/impl/specialization/indirect_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 indirect_tools
00029 {
00030         template<class A>
00031         static void shrink(A& a, size_t j) { }
00032 
00033         template<class A_IT, class B>
00034         static size_t cut(A_IT a, const B& b, size_t len) { return 0; }
00035 };
00036 
00037 template<>
00038 struct indirect_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, class B>
00047         static size_t cut(A_IT a, const B& b, size_t len);
00048 };
00049 
00050 template<class A_IT, class B>
00051 size_t indirect_tools<true>::cut(A_IT a, const B& b, size_t len)
00052 {
00053         // len: length of a before cut. different meaning in other specializations.
00054         array<size_t, mem> c(b);
00055         if(c.length() == 0)
00056                 return len;
00057         std::sort(c.begin(), c.end());
00058 
00059         size_t i = 0;
00060         size_t j = 0;
00061 
00062         for(size_t i = 0; i < len && i != c[0]; ++i, ++a) { ++j; }
00063 
00064         array<size_t, mem>::const_iterator cp = c.begin();
00065         array<size_t, mem>::const_iterator cp_e = c.end();
00066 
00067         ++cp;
00068         while(*cp == *(cp - 1) && cp != cp_e)
00069                 ++cp;
00070 
00071         A_IT wa = a;
00072 
00073         for(++i, ++a; i < len; ++i, ++a) {
00074                 if(i != *cp) {
00075                         *wa = *a;
00076                         ++wa;
00077                         ++j;
00078                 }
00079                 else {
00080                         ++cp;
00081                         while(*cp == *(cp - 1) && cp != cp_e) {
00082                                 ++cp;
00083                         }
00084                 }
00085         }
00086 
00087         return j;
00088 }
00089 
00090 } /* namespace array_details */
00091 
00097 template <class T,
00098                  class A,
00099                  class B,
00100                  class DERIVED_INFO
00101              >
00102 class array<T, data::indirect<A, B, DERIVED_INFO> >
00103         :
00104 
00105         public array_common_base<
00106                 array<T, data::indirect<A, B, DERIVED_INFO> > >,
00107 
00108         public data::referer<typename types::derive<
00109                 array<T, data::indirect<A, B, DERIVED_INFO> > >::type>
00110 {
00111 
00112 private:
00113         typedef array_common_base<array<T,
00114                 data::indirect<A, B, DERIVED_INFO> > > common_base_class;
00115 
00116         typedef typename types::is_ref<B>::type prv_b_ref;
00117         typedef typename types::bare_type<B>::type prv_b;
00118         typedef typename types::t_if<prv_b_ref, 
00119                 const typename types::bare_type<B>::type*, 
00120                 internal::relaxed_pointer_face<
00121                         typename types::bare_type<B>::type> >
00122                         ::type prv_b_type;
00123 
00124 
00125         typedef typename types::t_if<typename array::is_writeable,
00126                 typename A::iterator,
00127                 typename A::const_iterator>::type a_best_iterator;
00128 
00129         typedef typename prv_b::const_iterator b_iterator;
00130 
00131         // used to disable some types. TODO: test that not_a_type actually throws an error
00132         // and consider explicitly making the default constructor private.
00133         class not_a_type {};
00134         struct skip_assign { template<class X> void assign_array(X t) const {} };
00135 
00136         typedef typename types::t_if<types::is_const<A>, 
00137                 typename types::remove_const<A>::type, not_a_type>::type prv_second_init_a;
00138 
00139         typedef typename types::t_and_3<
00140                         types::t_not<types::is_const<A> >,
00141                         typename A::is_writeable,
00142                         typename A::is_resizeable>
00143                         ::type is_content_resizeable;
00144 
00145         typedef typename array_details::
00146                 indirect_tools<array::is_content_resizeable::value> indirect_tool;
00147 
00148         A* a;
00149         prv_b_type b;
00150         size_t len; //used to allow cut modify the length.
00151 
00152 protected:
00153         template <class J, class D>
00154         void copy_or_cut_impl(const array<J, D>& o)
00155         {
00156                 if(is_content_resizeable::value && o.begin() == o.end() && len != 0) {
00157 
00158                         indirect_tool::shrink(*a,
00159                                 indirect_tool::cut(a->begin(), *b, a->length()));
00160 
00161                         len = 0;
00162 
00163                 } else {
00164                         // for non-const: do not do nothing!
00165                         types::r_if<typename this_type::is_writeable>(
00166                                 static_cast<common_base_class&>(*this), skip_assign()).assign_array(o);
00167                 }
00168         }
00169         template <class J, class D>
00170         void copy_or_cut(const array<J, D>& o)
00171         {
00172                 copy_or_cut_impl(o);
00173         }
00174         template <class J, class P2, class D>
00175         void copy_or_cut(const array<J, data::indirect<A, P2, D> >& o)
00176         {
00177                 if(!a)
00178                         this->init(o.get_ref_1(), o.get_ref_2());
00179                 else
00180                         copy_or_cut_impl(o);
00181         }
00182         template <class J, class P2, class D>
00183         void copy_or_cut(const array<J, data::indirect<
00184                 prv_second_init_a, P2, D> >& o)
00185         {
00186                 if(!a)
00187                         this->init(o.get_ref_1(), o.get_ref_2());
00188                 else
00189                         copy_or_cut_impl(o);
00190         }
00191 
00192 
00193 public:
00194         typedef array this_type;
00195 
00196         typedef this_type this_array_type;
00197 
00198         typedef this_type array_type;
00199 
00200         typedef T elem_type;
00201 
00202         typedef typename common_base_class::derived_type derived_type;
00203 
00204         typedef typename common_base_class::base_class base_class;
00205 
00207         typedef size_t size_type;
00208 
00209         using base_class::derived;
00210 
00212         typedef is_content_resizeable is_cuttable;
00213 
00214         // special to this type
00215         typedef tuple<A&, const prv_b&> data_init_arg;
00216         //typedef tuple<A&, B> data_init_arg;
00217 
00218 
00219         template <bool CONST>
00220         class iterator_type
00221         : public data::data_details::
00222                 rnd_iter_operator_expander<iterator_type<CONST>, T, CONST,
00223                         typename types::remove_const<
00224                                 typename a_best_iterator::reference>::type>
00225         {
00226         private:
00227                 template <bool C> friend class iterator_type;
00228 
00229                 template <class X, class Y, bool C, class Z>
00230                 friend class data::data_details::rnd_iter_operator_expander;
00231 
00232                 template <class X, class Y, bool C, class Z>
00233                 friend class data::data_details::iter_operator_expander;
00234 
00235                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00236                         ::type best_value_type;
00237 
00238                 typedef typename types::apply_const<
00239                         typename a_best_iterator::reference, types::t_expr<CONST> >
00240                         ::type best_ref_type;
00241 
00242                 // this class is used to disable specific specialization members
00243                 class not_a_type { };
00244 
00245                 typedef typename types::t_if<types::t_expr<CONST>, not_a_type,
00246                         types::code_word<> >::type invalid_if_const;
00247 
00248                 typedef typename types::t_if<types::t_expr<CONST>,
00249                         typename A::const_iterator, a_best_iterator>::type a_iterator;
00250 
00251                 a_iterator a;
00252                 b_iterator b;
00253 
00254         protected:
00255                 inline typename types::apply_const<best_ref_type>::type base(
00256                         types::code_word<> ok = types::code_word<>()) const
00257                         { return (a[*b]); }
00258 //TODO!!!! make it random access only if b is random access
00259 // otherwise make it non-random access.
00260 // make it complain if a is non-random access.
00261                 inline best_ref_type base(
00262                         invalid_if_const disable = invalid_if_const())
00263                         { return (a[*b]); }
00264 
00265                 inline typename types::apply_const<best_ref_type>::type base(size_t j,
00266                         types::code_word<> ok = types::code_word<>()) const
00267                         { return (a[*(b + j)]); }
00268 
00269                 inline best_ref_type base(size_t j,
00270                         invalid_if_const disable = invalid_if_const())
00271                         { return (a[*(b + j)]); }
00272 
00273         public:
00274                 typedef iterator_type<CONST> this_type;
00275 
00276                 // iterator_traits
00277                 typedef std::random_access_iterator_tag iterator_category;
00278                 typedef T value_type;
00279                 typedef ptrdiff_t difference_type;
00280                 typedef best_value_type* pointer;
00281                 typedef best_ref_type reference;
00282 
00283                 // constructors
00284                 iterator_type() { }
00285                 iterator_type(const this_type& it)
00286                 : a(it.a), b(it.b) { }
00287                 template <bool C>
00288                 iterator_type(const iterator_type<C>& it)
00289                 : a(it.a), b(it.b) { }
00290                 iterator_type(const a_iterator& a, const b_iterator& b)
00291                         : a(a), b(b) { }
00292 
00293                 // members
00294 
00295                 // increment-decrement
00296                 this_type& operator++() { ++b; return *this; }
00297                 this_type& operator--() { --b; return *this; }
00298 
00299                 this_type operator++(int) { this_type t(*this); ++(*this); return t; }
00300                 this_type operator--(int) { this_type t(*this); --(*this); return t; }
00301 
00302                 // random access.
00303 
00304                 // X can be either size_t or B::iter_bound_mover
00305                 template<class X>
00306                 this_type& operator +=(X j) { b += j; return *this; }
00307 
00308                 template<class X>
00309                 this_type& operator -=(X j) { b -= j; return *this; }
00310 
00311                 template<class X>
00312                 inline this_type operator +(X j) const
00313                 {
00314                         this_type tmp(*this);
00315                         tmp += j;
00316                         return tmp;
00317                 }
00318                 template<class X>
00319                 inline this_type operator -(size_t j) const // TODO: @@@ cant i X? wrap iter has prob in 'code'.
00320                 {
00321                         this_type tmp(*this);
00322                         tmp -= j;
00323                         return tmp;
00324                 }
00325 
00326                 // difference.
00327                 ptrdiff_t operator-(const this_type& it) const
00328                 {
00329                         return b - it.b;
00330                 }
00331 
00332                 //copy same type iterator
00333                 this_type& operator=(const this_type& it)
00334                 {
00335                         a = it.a; b = it.b;
00336                         return *this;
00337                 }
00338                 //copy relevant type iterator
00339                 template<bool C>
00340                 this_type& operator=(const iterator_type<C>& it)
00341                 {
00342                         a = it.a; b = it.b;
00343                         return *this;
00344                 }
00345 
00346                 bool operator==(const this_type& it) const { return (b == it.b); }
00347                 bool operator!=(const this_type& it) const { return (b != it.b); }
00348                 bool operator<(const this_type& it) const { return (b < it.b); }
00349                 bool operator<=(const this_type& it) const { return (b <= it.b); }
00350                 bool operator>(const this_type& it) const { return (b > it.b); }
00351                 bool operator>=(const this_type& it) const { return (b >= it.b); }
00352 
00353         };
00354 
00355         // typedefs for class iterators
00356         typedef typename types::t_if<typename array::is_writeable,
00357                 iterator_type<false>, not_a_type>::type iterator;
00358 
00359         typedef iterator_type<true> const_iterator;
00360 
00361         typedef typename types::t_if<types::t_eq<iterator, not_a_type>,
00362                 const_iterator, iterator>::type best_iterator;
00363 
00364         typedef typename best_iterator::reference best_reference;
00365         typedef best_reference reference;
00366         typedef typename const_iterator::reference const_reference;
00367 
00368         typedef std::reverse_iterator<iterator> reverse_iterator;
00369 
00370         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00371 
00372         typedef ptrdiff_t iter_border_walker;
00373 
00374         best_iterator begin()
00375                 { if(is_cuttable::value && len == 0)
00376                                 return best_iterator(a->begin(), b->end());
00377                         else return best_iterator(a->begin(), b->begin()); }
00378 
00379         best_iterator end()
00380                 { return best_iterator(a->begin(), b->end()); }
00381 
00382         const_iterator begin() const
00383                 { if(is_cuttable::value && len == 0)
00384                                 return const_iterator(a->begin(), b->end());
00385                         else return const_iterator(a->begin(), b->begin()); }
00386 
00387         const_iterator end() const
00388                 { return const_iterator(a->begin(), b->end()); }
00389 
00390         // reverse iterator defs
00391         reverse_iterator rbegin() { return reverse_iterator(end()); }
00392 
00393         reverse_iterator rend() { return reverse_iterator(begin()); }
00394 
00395         const_reverse_iterator rbegin() const
00396                 { return const_reverse_iterator(end()); }
00397 
00398         const_reverse_iterator rend() const
00399                 { return const_reverse_iterator(begin()); }
00400 
00401 
00402         using common_base_class::operator[];
00403 
00404         // todo: resolve when b has no random access
00405         typename best_iterator::reference operator[](size_t j)
00406         {
00407                 return (*a)[(*b)[j]];
00408         }
00409         typename const_iterator::reference operator[](size_t j) const
00410         {
00411                 return (*a)[(*b)[j]];
00412         }
00413 
00416         //TODO: explain this better.
00418         size_t length() const { return len; }
00420         size_type size() const { return length(); }
00422         size_t numel() const { return length(); }
00425         void resize(size_t l) { CHECK(length() == l, ecomp); }
00426 
00427         iter_border_walker first_to_last() { return b.length() - 1; }
00428         iter_border_walker begin_to_end() { return b.length(); }
00429 
00430 
00431         /*
00432         void init(A& a0, const B& b0)
00433         {
00434                 a = &a0;
00435                 b = &b0;
00436                 len = b0.length();
00437         }
00438         */
00439         template<class I>
00440         void init(A& a0, const I& b0)
00441         {
00442                 a = &a0;
00443                 b = &b0;
00444                 len = b0.length();
00445         }
00446 
00447         void init(size_t sz, data_init_arg d)
00448         {
00449                 a = &d.v1;
00450                 b = &d.v2;
00451                 len = d.v2.length();
00452         }
00453 
00454         void init(const array& o)
00455         {
00456                 a = o.a;
00457                 b = o.b;
00458                 len = o.len;
00459         }
00460 
00461         template <class J, class P2, class D>
00462         void init(const array<J, data::indirect<A, P2, D> >& o)
00463         {
00464                 a = &o.get_ref_1();
00465                 b = &o.get_ref_1();
00466                 len = o.length();
00467         }
00468 
00469         template <class J, class P2, class D>
00470         void init(const array<J, data::indirect<prv_second_init_a, P2, D> >& o)
00471         {
00472                 a = &o.get_ref_1();
00473                 b = &o.get_ref_1();
00474                 len = o.length();
00475         }
00476 
00477 
00478 
00481         array() { a = NULL; }
00482 
00484         array(A& a) : a(&a), b(rng(0, a.length()-1)), len(a.length()) { }
00485         
00487         array(A& a, const prv_b& b) : a(&a), b(&b), len(b.length()) { }
00488 
00489         //The same with data init arg
00490         array(size_t sz, data_init_arg d) : a(&d.v1), b(&d.v2), len(d.v2.length()) { }
00491         
00492         //The same constructor with template
00493         template<class I>
00494         array(A& a, const I& b) : a(&a), b(&b), len(b.length()) { }
00495 
00497         array(const this_type& o) : a(o.a), b(o.b), len(o.len) {}
00498 
00499         // Constructor from another indirect array
00500         template <class J, class P2, class D>
00501         array(const array<J, data::indirect<A, P2, D> >& o)
00502                 : a(&o.get_ref_1()), b(&o.get_ref_2()), len(o.length()) { }
00503 
00504         template <class J, class P2, class D>
00505         array(const array<J, data::indirect<prv_second_init_a, P2, D> >& o)
00506                 : a(&o.get_ref_1()), b(&o.get_ref_2()), len(o.length()) { }
00507 
00510 
00511         ~array() { }
00512 
00515         // exclusive to indirect array
00516         A& get_ref_1() const { return *a; }
00517         const prv_b& get_ref_2() const { return *b; }
00518         //TODO: may be better or just possible is several cases as elem func.
00519         //return value could also be templated.
00520         template <class J, class P>
00521         size_array merge_idx(const array<J, P>& idx) const
00522         {
00523                 size_array sz(idx.length());
00524                 for(size_t i=0;i<sz.length();i++)
00525                         sz[i] = (*b)[idx[i]];
00526                 return sz;
00527         }
00528         //
00529 
00530         template <class D>
00531         bool overlap(const D& d) const
00532         {
00533                 return a->overlap(d);
00534         }
00535 
00536         template <class D>
00537         bool self_overlap(const D& d) const
00538         {
00539                 return d.overlap(*a) || d.overlap(*b);
00540         }
00541 
00542         /*
00543         TODO: wipe this completely. Cannot detect anything here anyway.
00544         template <class J, class P>
00545         derived_type& assign_array(const array<J, data::empty<P> >& o)
00546         {
00547                 copy_or_cut(o); // will always fallback to cut
00548                 return this->derived();
00549         }
00550         */
00551 
00552         template<class D>
00553         derived_type& assign_array(const D& o)
00554         {
00555                 copy_or_cut(o);
00556                 return this->derived();
00557         }
00564         //using common_base_class::operator=;
00565         template<class K>
00566         derived_type& operator=(const K& o)
00567         {
00568                 // avoid the safety check when we just need to assign
00569                 // TODO: check about this all, espec. const K&. and what happens
00570                 // when we derive to higher class, e.g. image, what is called. 
00571                 // (esp. for subarray).
00572                 if(!a) 
00573                         this->assign(o);
00574                 else 
00575                         common_base_class::operator=(o);
00576                 return this->derived();
00577         }
00578 
00579         this_type& operator=(const this_type& o) // copy operator
00580         {
00581                 copy_or_cut(o);
00582                 return *this;
00583         }
00584 
00587         //todo: either make this (rvalue) a rule or not at all
00588         //this_type& rvalue() const { return *const_cast<this_type*>(this); }
00589 
00590 
00591 };
00592 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations