ivl 679
|
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 }