ivl 679
ivl/details/array/impl/specialization/subarray_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                  class A,
00032                  class I,
00033                  class DERIVED_INFO
00034              >
00035 class array<T, data::subarray<A, I, DERIVED_INFO> >
00036         :
00037         public array_common_base<array<T,
00038                 data::subarray<A, I, DERIVED_INFO> > >,
00039 
00040         public data::referer<typename types::derive<
00041                 array<T, data::subarray<A, I, DERIVED_INFO> > >::type>
00042 {
00043 private:
00044         typedef array_common_base<array<T,
00045                 data::subarray<A, I, DERIVED_INFO> > > common_base_class;
00046 
00047 protected:
00048 //--------------------------------------------------------------------------
00049 // types
00050 
00051         // validates that I is random access.
00052         // if there is a compile error here, you are probably trying to create
00053         // a subarray with an index_array that has no random access.
00054         types::validate_class<typename I::has_random_access, types::t_true>
00055                 index_array_is_valid;
00056 
00057         // I is stored or referenced? :
00058         typedef typename types::is_ref<I>::type prv_i_ref;
00059         typedef typename types::bare_type<I>::type prv_i;
00060         typedef typename types::t_if<prv_i_ref, 
00061                 const typename types::bare_type<I>::type*, 
00062                 internal::relaxed_pointer_face<
00063                         typename types::bare_type<I>::type> >
00064                         ::type prv_i_type;
00065 
00066         // reference_iterator_is_nd:
00067         // define true if the underlying array will be accessed using an
00068         // iterator_nd. otherwise it will be accessed using an iterator.
00069         // the two options differ a lot and have seperate implementations.
00070         typedef typename types::t_if<
00071                 types::t_and<
00072                         types::t_eq<
00073                                 typename A::optimal_access_tag, data::seq_optimal_tag>,
00074                         typename A::has_random_access
00075                 >, types::t_false, types::t_true>::type reference_iterator_is_nd;
00076 
00077         // best_reference_iterator:
00078         // defines which is the best possible iterator to be used for the
00079         // underlying array, meaning the most powerful, between the const_
00080         // and non-const_ ones. const_ is used if the array is read only.
00081         typedef typename types::t_if<reference_iterator_is_nd,
00082                 typename
00083                         types::best_iterator_nd<A>::type
00084                         /*types::t_if<typename A::is_writeable,
00085                                 typename A::iterator_nd,
00086                                 typename A::const_iterator_nd>::type,*/,
00087 
00088                 typename
00089                         types::best_iterator<A>::type/*
00090                         types::t_if<typename A::is_writeable,
00091                                 typename A::iterator,
00092                                 typename A::const_iterator>::type todo:wipe*/
00093 
00094                 >::type best_reference_iterator;
00095 
00096         // const_reference_iterator:
00097         // defines which is the const_iterator to be used for the
00098         // underlying array.
00099         typedef typename types::t_if<reference_iterator_is_nd,
00100                 typename A::const_iterator_nd,
00101                 typename A::const_iterator
00102 
00103                 >::type const_reference_iterator;
00104 
00105         typedef best_reference_iterator best_ref_iter;
00106         typedef const_reference_iterator const_ref_iter;
00107 
00108         // tool:
00109         // the correct specialization of the class subarray_tools that implements
00110         // functionality of the reference iterator depending of the type.
00111         typedef array_details::subarray_tools<
00112                 reference_iterator_is_nd, best_ref_iter> tool;
00113 
00114         // some helper structs
00115         typedef array_details::subarray_common_tools ctool;
00116 
00117         // used to disable some types. TODO: test that not_a_type actually throws an error and
00118         // consider explicitly making the default constructor private.
00119         class not_a_type { };
00120         struct skip_assign { template<class X> void assign_array(X t) const {} };
00121 
00122         typedef typename types::t_if<types::is_const<A>, 
00123         typename types::remove_const<A>::type, not_a_type>::type prv_second_init_a;
00124 
00125 
00126 //--------------------------------------------------------------------------
00127 // members
00128         A* in;
00129         prv_i_type idx;
00130 
00131 
00132         // helper data that is computed on the construction of the subarray
00133         // object, needed to improve speed.
00134 
00135         array<size_t, tiny> all_sizes; // the subarray sizes
00136         size_t all_len; // the subarray total length
00137         int itspec1; // the inner iterator specialization
00138         int itspec2; // the second inner iterator specialization
00139 
00140         // arrays with size equal to the total of non singleton dimensions
00141         array<array<ptrdiff_t, tiny>, stack<5> > diffs_ar;
00142         array<ptrdiff_t*, stack<5> > diffs;
00143         array<size_t, stack<5> > sizes;
00144         array<ptrdiff_t, stack<5> > steps;
00145         array<best_reference_iterator> iters;
00146         const best_reference_iterator* iter;
00147         array<ptrdiff_t, tiny> back_diffs;
00148         array<ptrdiff_t, tiny> begin_to_ends;
00149         array<ptrdiff_t, tiny> first_to_lasts;
00150 
00151         // maps from one type of ordering to another
00152         array<size_t, tiny> nonsing_map;
00153         array<size_t, tiny> nonsing_rmap;
00154         array<size_t, tiny> idx_ar_map;
00155         array<ptrdiff_t, tiny> idx_ar_rmap;
00156 
00157 
00158 
00159 
00160 //--------------------------------------------------------------------------
00161 // functions
00162 
00163 
00164         array<size_t, tiny> starts_vec()
00165         {
00166                 size_t i;
00167                 size_t ndim = idx->length();
00168                 array<size_t, tiny> ar(in->ndims());
00169                 for(i = 0; i < ndim; i++)
00170                         ar[i] = (*idx)[i].starts();
00171                 for(; i < ar.length(); i++)
00172                         ar[i] = 0;
00173                 return ar;
00174         }
00175 
00176         array<size_t, tiny> ends_vec()
00177         {
00178                 size_t i;
00179                 size_t ndim = idx->length();
00180                 array<size_t, tiny> ar(in->ndims());
00181                 for(i = 0; i < ndim; i++) {
00182                         if((*idx)[i].is_all())
00183                                 ar[i] = in->size_nd(i) - 1;
00184                         else
00185                                 ar[i] = (*idx)[i].ends();
00186                 }
00187                 for(; i < ar.length(); i++)
00188                         ar[i] = 0;
00189                 return ar;
00190         }
00191 
00192         const best_reference_iterator& get_iter(size_t d) const
00193         {
00194                 return types::r_if<reference_iterator_is_nd> (iter[d], iter[-3]);
00195         }
00196 
00197         template <class J, class D>
00198         void copy_or_cut_impl(const array<J, D>& o)
00199         {
00200                 //if(is_content_resizeable::value && o.begin() == o.end() && len != 0) {
00201                         /*
00202 
00203                         cut!
00204 
00205                         indirect_tool::shrink(*a,
00206                                 indirect_tool::cut(a->begin(), *b, a->length()));
00207 
00208                         len = 0;
00209                         */
00210 
00211                 //} else 
00212                 {
00213                         // for non-const: do not do nothing!
00214                         types::r_if<typename this_type::is_writeable>(
00215                                 static_cast<common_base_class&>(*this), skip_assign()).assign_array(o);
00216                 }
00217         }
00218         template <class J, class D>
00219         void copy_or_cut_impl(const array_nd<J, D>& o)
00220         {
00221                 //if(is_content_resizeable::value && o.begin() == o.end() && len != 0) {
00222                         /*
00223 
00224                         cut!
00225 
00226                         indirect_tool::shrink(*a,
00227                                 indirect_tool::cut(a->begin(), *b, a->length()));
00228 
00229                         len = 0;
00230                         */
00231 
00232                 //} else 
00233                 {
00234                         types::r_if<typename this_type::is_writeable>(
00235                                 static_cast<common_base_class&>(*this), skip_assign()).assign_array(o);
00236                 }
00237         }
00238         template <class J, class D>
00239         void copy_or_cut(const array<J, D>& o)
00240         {
00241                 copy_or_cut_impl(o);
00242         }
00243         template <class J, class D>
00244         void copy_or_cut(const array_nd<J, D>& o)
00245         {
00246                 copy_or_cut_impl(o);
00247         }
00248         template <class J, class P2, class D>
00249         void copy_or_cut(const array_nd<J, data::subarray<A, P2, D> >& o)
00250         {
00251                 if(!in)
00252                         this->init(o.get_ref_1(), o.get_ref_2());
00253                 else
00254                         copy_or_cut_impl(o);
00255         }
00256         template <class J, class P2, class D>
00257         void copy_or_cut(const array_nd<J, data::subarray<
00258                 prv_second_init_a, P2, D> >& o)
00259         {
00260                 if(!in)
00261                         this->init(o.get_ref_1(), o.get_ref_2());
00262                 else
00263                         copy_or_cut_impl(o);
00264         }
00265 
00266 public:
00267         void init(A& a, const prv_i& idx);
00268 
00269         void init(const array& o);
00270 
00271         typedef array this_type;
00272 
00273         typedef this_type this_array_type;
00274 
00275         typedef this_type array_type;
00276 
00277         typedef T elem_type;
00278 
00279         typedef typename best_reference_iterator::reference reference;
00280         typedef typename best_reference_iterator::reference best_reference;
00281         typedef typename const_reference_iterator::reference const_reference;
00282 
00283         typedef typename common_base_class::derived_type derived_type;
00284 
00285         typedef typename common_base_class::base_class base_class;
00286 
00288         typedef size_t size_type;
00289 
00290         using base_class::derived;
00291 
00292         typename types::t_and_3<
00293                 types::t_not<types::is_const<A> >,
00294                 typename A::is_writeable,
00295                 typename A::is_resizeable>
00296                 ::type is_cuttable;
00297 
00298 
00299 
00300         // typedefs for class iterators
00301         typedef typename types::t_if<types::t_and<typename array::is_writeable,
00302                 types::t_not<types::is_const<A> > >,
00303                 data::subarray_iterator_type<T, best_reference_iterator,
00304                         best_reference_iterator,
00305                         reference_iterator_is_nd::value, false>,
00306                 not_a_type>::type iterator;
00307 
00308         typedef data::subarray_iterator_type<T, const_reference_iterator,
00309                 best_reference_iterator,
00310                 reference_iterator_is_nd::value, true> const_iterator;
00311 
00312         typedef typename types::t_if<types::t_eq<iterator, not_a_type>,
00313                 const_iterator, iterator>::type best_iterator;
00314 
00315         typedef std::reverse_iterator<iterator> reverse_iterator;
00316 
00317         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00318 
00319         typedef typename const_iterator::iter_border_walker iter_border_walker;
00320 
00321         template<int SPC>
00322         struct s_iterator
00323         {
00324                 typedef data::subarray_iterator_type<T, best_reference_iterator,
00325                         best_reference_iterator,
00326                         reference_iterator_is_nd::value, false, SPC> type;
00327         };
00328         template<int SPC>
00329         struct const_s_iterator
00330         {
00331                 typedef data::subarray_iterator_type<T, best_reference_iterator,
00332                         best_reference_iterator,
00333                         reference_iterator_is_nd::value, true, SPC> type;
00334         };
00335         template<int SPC>
00336         struct reverse_s_iterator
00337         {
00338                 typedef std::reverse_iterator<s_iterator<SPC> > type;
00339         };
00340         template<int SPC>
00341         struct const_reverse_s_iterator
00342         {
00343                 typedef std::reverse_iterator<const_s_iterator<SPC> > type;
00344         };
00345         int iter_specialization() const
00346         {
00347                 return itspec1;
00348         }
00349 
00350         iterator begin()
00351         {
00352                 return iterator(iter[-3], iter, nonsing_map.length(),
00353                         sizes.c_ptr(), diffs.c_ptr(), steps.c_ptr(),
00354                         back_diffs.c_ptr(), false, 1);
00355         }
00356 
00357         iterator end()
00358         {
00359                 return iterator(iter[-1], iter, nonsing_map.length(),
00360                         sizes, diffs, steps, back_diffs, false, 2);
00361         }
00362 
00363         const_iterator begin() const
00364         {
00365                 return const_iterator(iter[-3], iter, nonsing_map.length(),
00366                         sizes.c_ptr(), diffs.c_ptr(), steps.c_ptr(),
00367                         back_diffs.c_ptr(), false, 1);
00368         }
00369 
00370         const_iterator end() const
00371         {
00372                 return const_iterator(iter[-1], iter, nonsing_map.length(),
00373                         sizes.c_ptr(), diffs.c_ptr(), steps.c_ptr(),
00374                         back_diffs.c_ptr(), false, 2);
00375         }
00376 
00377         // reverse iterator defs
00378         reverse_iterator rbegin() { return reverse_iterator(end()); }
00379 
00380         reverse_iterator rend() { return reverse_iterator(begin()); }
00381 
00382         const_reverse_iterator rbegin() const
00383                 { return const_reverse_iterator(end()); }
00384 
00385         const_reverse_iterator rend() const
00386                 { return const_reverse_iterator(begin()); }
00387 
00388 
00389         iter_border_walker first_to_last()
00390         {
00391                 return iter_border_walker(1,
00392                         types::r_if<reference_iterator_is_nd>(0, iter[-2] - iter[-3]));
00393         }
00394 
00395         iter_border_walker begin_to_end()
00396         {
00397                 return iter_border_walker(2,
00398                         types::r_if<reference_iterator_is_nd>(0, iter[-1] - iter[-3]));
00399         }
00400 
00401         typename types::best_iterator<array>::type::reference operator[](size_t j)
00402         {
00403                 //TODO: Note: method should be removed
00404                 int r = j % derived().size_nd(0);
00405                 j /= derived().size_nd(0);
00406                 int c = j % derived().size_nd(1);
00407                 int d = j / derived().size_nd(1);
00408                 array<size_t, data::mem<> > idd(3);
00409                 idd[0]=r; idd[1]=c; idd[2]=d;
00410                 return derived()(idd);  
00411         }
00412 
00413         typename const_iterator::reference operator[](size_t j) const
00414         {
00415                 //TODO: Note: method should be removed
00416                 int r = j % derived().size_nd(0);
00417                 j /= derived().size_nd(0);
00418                 int c = j % derived().size_nd(1);
00419                 int d = j / derived().size_nd(1);
00420                 array<size_t, data::mem<> > idd(3);
00421                 idd[0]=r; idd[1]=c; idd[2]=d;
00422                 return derived()(idd);  
00423         }
00424 
00425 
00428         //TODO: explain this better.
00430         size_t length() const
00431         {
00432                 return all_len;
00433         }
00434 
00436         size_type size() const { return length(); }
00437 
00439         size_t numel() const { return length(); }
00447         array() { in = NULL; }
00448 
00449         array(const array& o) { init(o); }
00450 
00451         array(A& a, const prv_i& idxn)
00452         {
00453                 init(a, idxn);
00454         }
00455         template<class J>
00456         array(A& a, const J& idxn)
00457         {
00458                 init(a, idxn);
00459         }
00460 
00461 
00462         void setref(A& a, const prv_i& idxn)
00463         {
00464                 init(a, idxn);
00465         }
00466         template<class J>
00467         void setref(A& a, const J& idxn)
00468         {
00469                 init(a, idxn);
00470         }
00471 
00472         template <class D>
00473         bool overlap(const D& d) const
00474         {
00475                 return in->overlap(d);
00476         }
00477 
00478         template <class D>
00479         bool self_overlap(const D& d) const
00480         {
00481                 return d.overlap(*in) || d.overlap(*idx);
00482         }
00483 
00484 
00485 
00487         ~array() { 
00488         }
00489 
00490         //using common_base_class::operator=;
00491         template<class K>
00492         derived_type& operator=(const K& o)
00493         {
00494                 // avoid the safety check when we just need to assign
00495                 // TODO: check about this all, espec. const K&. and what happens
00496                 // when we derive to higher class, e.g. image, what is called. 
00497                 // (esp. for subarray).
00498                 if(!in) 
00499                         this->assign(o);
00500                 else 
00501                         common_base_class::operator=(o);
00502                 return this->derived();
00503         }
00504 
00505         this_type& operator=(const array& o)
00506         { 
00507                 //TODO:check
00508                 if(!in) 
00509                         init(o);
00510                 else
00511                         common_base_class::operator=(o); return *this; 
00512         }
00513 
00514         template<class D>
00515         derived_type& assign_array(const D& o)
00516         {
00517                 copy_or_cut(o);
00518                 return this->derived();
00519         }
00520 
00521         A& get_ref_1() const { return *in; }
00522         const prv_i& get_ref_2() const { return *idx; }
00523 
00524 };
00525 
00526 
00527 template <class T,
00528                  class A,
00529                  class I,
00530                  class DERIVED_INFO
00531              >
00532 void array<T, data::subarray<A, I, DERIVED_INFO> >
00533         ::init(const array& o)
00534 {
00535         in = o.in;
00536         if(!in) return;
00537         idx = o.idx;
00538 
00539         all_sizes = o.all_sizes;
00540         all_len = o.all_len;
00541 
00542         itspec1 = o.itspec1;
00543         itspec2 = o.itspec2;
00544 
00545         diffs_ar = o.diffs_ar;
00546         sizes = o.sizes;
00547         steps = o.steps;
00548         iters = o.iters;
00549         iter = iters.c_ptr() + 4;
00550         back_diffs = o.back_diffs;
00551         begin_to_ends = o.begin_to_ends;
00552         first_to_lasts = o.first_to_lasts;
00553 
00554         nonsing_map = o.nonsing_map;
00555         nonsing_rmap = o.nonsing_rmap;
00556         idx_ar_map = o.idx_ar_map;
00557         idx_ar_rmap = o.idx_ar_rmap;
00558 
00559         //diffs refers to local pointers so it has to be re-initialized.
00560         size_t jmin = nonsing_map.length();
00561         diffs.resize(jmin + 2, NULL);
00562 
00563         size_t ia = idx_ar_map.length();
00564         for(size_t a = 0; a < ia; a++)
00565         {
00566                 size_t k = idx_ar_map[a];
00567                 size_t i = nonsing_rmap[k];
00568                 diffs[i] = diffs_ar[a].c_ptr() + 1;
00569         }
00570 
00571         if(!reference_iterator_is_nd::value) {
00572                 diffs[jmin] = diffs_ar[ia].c_ptr();
00573         }
00574 
00575         diffs[jmin + 1] = diffs_ar[ia + 1].c_ptr() + 1;
00576 }
00577 
00578 template <class T,
00579                  class A,
00580                  class I,
00581                  class DERIVED_INFO
00582              >
00583 void array<T, data::subarray<A, I, DERIVED_INFO> >
00584 ::init(A& a, const 
00585            typename array<T, data::subarray<A, I, DERIVED_INFO> >::prv_i& idx)
00586 {
00587         using namespace ivl::types;
00588 
00589         in = &a;
00590         this->idx = &idx;
00591         //todo: check no sizes==0!!
00592 
00593         size_t ndims = idx.length(); //a.ndims();
00594 
00595         //std::cout << "SUBARRAY " << idx << "OF:" << a << ":O (" <<ndims << ")"<<std::endl;
00596         CHECK(ndims != 0, ecomp);
00597 //@@@@todo:redo CHECK(idx.length() == ndims, ecomp);
00598 
00599         size_t j = 0;
00600         size_t ia = 0;
00601 
00602         all_sizes.resize(ndims);
00603         all_len = 1;
00604         itspec1 = 0;
00605         itspec2 = 0;
00606 
00607         for(size_t i = 0; i < ndims; i++) {
00608 
00609                 if(idx[i].is_all())
00610                         all_sizes[i] = a.size_nd(i);
00611                 else
00612                         all_sizes[i] = idx[i].length();
00613 
00614                 if(all_sizes[i] > 1) {
00615                         if(idx[i].is_array()) ia++;
00616                         j++;
00617                 }
00618 
00619                 //@@@@@
00620                 if(ndims < idx.length() && i == ndims - 1) {
00621                         for(size_t p = i + 1; p < idx.length(); p++) {
00622                                 all_sizes[i] *= a.size_nd(p);
00623                         }
00624                 }
00625 
00626                 all_len *= all_sizes[i];
00627         }
00628 
00629         bool j0 = (j == 0);
00630         size_t jmin = (j <= 1 ? 2 : j);
00631                 // in case we have only 1 dimension, we have to make it 2 dimensions
00632                 // with outer having size = 1, to comply with the loops.
00633 
00634         nonsing_map.resize(jmin);
00635         //first_to_last.resize(jmin);todo:wipe
00636         diffs.resize(jmin + 2); // 1 for an extra helper dim which moves to end
00637                                                  // and 1 to use for all singleton dims
00638         back_diffs.resize(jmin + 2);
00639         begin_to_ends.resize(jmin + 2);
00640         first_to_lasts.resize(jmin + 2);
00641         sizes.resize(jmin + 2);
00642         steps.resize(jmin + 2);
00643         iters.resize(4 + r_if<reference_iterator_is_nd>(jmin + 2, 0));
00644                 // same as above for nd_reference, but also 4 iterators in front
00645                 // which are: begin-1, begin, end-1, end
00646         iter = iters.c_ptr() + 4;
00647 
00648 
00649         nonsing_rmap.resize(ndims);
00650         nonsing_map[1] = -1;
00651 
00652         for(size_t i = 0, k = 0; i < ndims; i++)
00653                 if(all_sizes[i] == 1) {
00654                         nonsing_rmap[i] = jmin + 1;
00655                         // singleton location
00656                 } else {
00657                         nonsing_map[k] = i;
00658                         nonsing_rmap[i] = k;
00659                         k++;
00660                 }
00661 
00662         if(j0) {
00663                 // single element subarray
00664                 nonsing_map[0] = 0;
00665                 nonsing_rmap[0] = 0;
00666         }
00667 
00668         // inner iterator specializations
00669         size_t inner = nonsing_map[0];
00670         if(idx[inner].is_array()) itspec1 = 2; else itspec1 = 1;
00671         if(j > 1) {
00672                 if(idx[nonsing_map[1]].is_array()) itspec2 = 2; else itspec2 = 1;
00673         }
00674 
00675         // store the 4 important reference iterators
00676         if(all_len == 0) { //todo: check if this is actually necessary and why
00677                 //iters[0] = tool::end(a, inner); //todo: also use something faster here.
00678                 iters[1] = tool::end(a, inner);
00679                 iters[2] = tool::end(a, inner);
00680                 iters[3] = tool::end(a, inner);
00681         } else {
00682                 //iters[0] = tool::rend_base(a, inner);
00683                 iters[1] = tool::begin(a, inner, starts_vec());
00684                 iters[2] = tool::begin(a, inner, ends_vec()); //rbegin_base
00685                 iters[3] = tool::end(a, inner);
00686         }
00687 
00688         if(reference_iterator_is_nd::value) {
00689                 // one iterator for each non-singleton dimension.
00690                 for(size_t i = 0; i < j; i++) {
00691                         iters[4 + i] = tool::iter(a, nonsing_map[i], iters[1]);
00692                 }
00693 
00694                 // [jmin + 5] for all singleton dimensions. [jmin + 4] is padding.
00695                 iters[jmin + 5] = iters[1];
00696 
00697                 // if dims = 1, iter[4 + 1] must have a value but it won't be used.
00698                 if(jmin > j) iters[5] = iters[1];
00699         }
00700 
00701         //sizes
00702         sizes[1] = 1;
00703         for(size_t i = 0; i < j; i++)
00704                 sizes[i] = all_sizes[nonsing_map[i]];
00705 
00706         sizes[jmin] = 3;
00707         sizes[jmin + 1] = 1;
00708 
00709         //steps
00710         for(size_t i = 0; i < j; i++) {
00711                 size_t k = nonsing_map[i];
00712                 steps[i] = idx[k].steps();
00713 
00714                 if(!reference_iterator_is_nd::value)
00715                         steps[i] *= tool::stride(a, k);
00716         }
00717         steps[jmin] = 1;
00718         steps[jmin + 1] = 1;
00719 
00720 
00721         //diffs resize
00722         diffs_ar.resize(ia + 2);
00723         idx_ar_map.resize(ia);
00724         idx_ar_rmap.resize(ndims, -1);
00725 
00726         //diffs
00727         for(size_t i = 0, a = 0; i < j; i++) {
00728                 size_t k = nonsing_map[i];
00729                 if(!idx[k].is_array())
00730                         diffs[i] = NULL;
00731                 else {
00732                         idx_ar_map[a] = k;
00733                         idx_ar_rmap[k] = a;
00734 
00735                         array<ptrdiff_t, tiny>& diff = diffs_ar[a];
00736                         typedef typename I::elem_type::size_array idx_sz_t;
00737                         const idx_sz_t& idc = idx[k];
00738                         diff.resize(idc.length() + 1);
00739 
00740                         for(size_t p = 0, l = idc.length() -1; p < l; p++)
00741                                 diff[p + 1] = (idc[p + 1] - idc[p]) *
00742                                         r_if<reference_iterator_is_nd>(1, steps[i]);
00743 
00744                         diff[0] = (idc[0] + 1) *
00745                                 r_if<reference_iterator_is_nd>(1, steps[i]);
00746 
00747                         *diff.rbegin() = (ptrdiff_t(in->size_nd(k)) - ptrdiff_t(*idc.rbegin())) *
00748                                 r_if<reference_iterator_is_nd>(1, steps[i]);
00749 
00750                         diffs[i] = diff.c_ptr() + 1;
00751 
00752                         a++;
00753                 }
00754         }
00755 
00756         if(!reference_iterator_is_nd::value) {
00757                 diffs_ar[ia].resize(2);
00758                 diffs[jmin] = diffs_ar[ia].c_ptr();
00759                 //diffs[jmin][0] = 0; // we dont need begin to begin-1!!!
00760                         //r_if<reference_iterator_is_nd>(0, iters[1]) -
00761                         //r_if<reference_iterator_is_nd>(0, iters[0]);//maybe 2 to 0 if back is considered.
00762 
00763                 diffs[jmin][1] =
00764                         r_if<reference_iterator_is_nd>(0, iters[3]) -
00765                         r_if<reference_iterator_is_nd>(0, iters[1]);
00766         }
00767 
00768         diffs_ar[ia + 1].resize(2);
00769         diffs[jmin + 1] = diffs_ar[ia + 1].c_ptr() + 1;
00770         diffs[jmin + 1][-1] = 1;
00771         diffs[jmin + 1][0] = 1;
00772 
00773 
00774 
00775         //back_diffs, begin_to_ends and first_to_lasts
00776         for(size_t i = 0, a = 0; i < j; i++) {
00777                 size_t k = nonsing_map[i];
00778                 if(idx[k].is_array()) {
00779                         back_diffs[i] = - steps[i] *
00780                         (*(idx[k].as_array().rbegin()) -
00781                         *(idx[k].as_array().begin()));
00782 
00783                         first_to_lasts[i] = -back_diffs[i];
00784             begin_to_ends[i] = -back_diffs[i] + *diffs_ar[a].rbegin();
00785 
00786             a++;
00787 
00788                 } else {
00789                         back_diffs[i] = - ptrdiff_t(sizes[i] - 1) * steps[i];
00790 
00791                         first_to_lasts[i] = -back_diffs[i];
00792             begin_to_ends[i] = -back_diffs[i] + steps[i];
00793                 }
00794 
00795 
00796                 if(i > 0 && !reference_iterator_is_nd::value)
00797                         back_diffs[i] += back_diffs[i - 1];
00798         }
00799 
00800         if(!reference_iterator_is_nd::value) {
00801                 for(size_t i = 0; i < j - 1; i++) {
00802                         if(!idx[nonsing_map[i + 1]].is_array())
00803                                 back_diffs[i] += steps[i + 1];
00804                 }
00805         }
00806 
00807         if(jmin > j)
00808                 back_diffs[1] =
00809                         (reference_iterator_is_nd::value ? 0 : back_diffs[0]);
00810 
00811         back_diffs[jmin] = 0;
00812         back_diffs[jmin + 1] = 0;
00813 
00814     begin_to_ends[jmin + 1] = 1;
00815     first_to_lasts[jmin + 1] = 0;
00816 /*
00817 for(size_t i=0;i<iters.length();i++)
00818 std::cout << "itr:["<<i<<"]=" << &*iters[i] << std::endl;
00819 std::cout << "su:" << diffs_ar << " of sz: " << all_sizes << std::endl;
00820 std::cout << idx[idx.length()-1].length() << std::endl;*/
00821 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations