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 00025 00048 template <class T, class OPTS = mem> 00049 class array_nd: 00050 public 00051 array_common_base<array_nd<T, OPTS> >, 00052 00053 public 00054 array_nd_details:: 00055 basic_iterator_nd_interface<array_nd<T, OPTS> > 00056 { 00057 private: 00058 typedef array_nd prv_this_type; 00059 typedef typename prv_this_type::common_base_class common_base_class; 00060 typedef typename prv_this_type::iter_nd_interface_class iter_nd_interface; 00061 00063 size_t ndim; 00065 array<size_t, tiny> sizes; 00067 array<size_t, tiny> strides; 00068 00069 public: 00070 /* 00071 TODO: wipe these? 00072 operator common_base_class&() { return *this; } 00073 operator const common_base_class&() const { return *this; } 00074 operator common_base_class() { return *this; } 00075 operator const common_base_class() const { return *this; } 00076 */ 00077 00078 typedef array_nd this_type; 00079 00080 typedef this_type this_array_nd_type; 00081 00082 typedef typename common_base_class::derived_type derived_type; 00083 00084 typedef typename common_base_class::base_class base_class; 00085 00086 typedef this_type array_type; 00087 00089 typedef array<size_t, tiny> size_type; 00090 00092 typedef const array<size_t, tiny>& size_nd_ref_type; 00093 00095 typedef const array<size_t, tiny>& stride_ref_type; 00096 00098 typedef types::t_true has_1d_parenthesis; 00099 typedef types::t_true has_2d_parenthesis; 00100 typedef types::t_true has_3d_parenthesis; 00101 typedef types::t_true has_nd_parenthesis; 00102 00103 typedef typename this_type::best_reference best_reference; 00104 typedef typename this_type::const_reference const_reference; 00105 00106 // use _arg_base instead of _arg to solve weird msvc2005 bug 00107 typedef typename this_type::all_init_arg_base all_init_arg; 00108 typedef typename this_type::data_init_arg_base data_init_arg; 00109 00110 using base_class::derived; 00111 00113 base_class& base() { return *this; } 00114 const base_class& base() const { return *this; } 00115 00122 using base_class::operator[]; 00123 using base_class::length; 00124 using base_class::numel; 00125 00126 using common_base_class::operator(); 00127 00134 best_reference operator()(size_t s1) 00135 { return (*this)[s1]; } 00136 best_reference operator()(size_t s1, size_t s2) 00137 { return (*this)[s1 + s2 * strides[1]]; } 00138 best_reference operator()(size_t s1, size_t s2, size_t s3) 00139 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2]]; } 00140 best_reference operator()(size_t s1, size_t s2, size_t s3, size_t s4) 00141 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00142 s4 * strides[3]]; } 00143 best_reference operator()(size_t s1, size_t s2, size_t s3, size_t s4, 00144 size_t s5) 00145 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00146 s4 * strides[3] + s5 * strides[4]]; } 00147 best_reference operator()(size_t s1, size_t s2, size_t s3, size_t s4, 00148 size_t s5, size_t s6) 00149 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00150 s4 * strides[3] + s5 * strides[4] + s6 * strides[5]]; } 00153 template<class S> 00154 best_reference operator()(const array<size_t, S>& indx) 00155 { return derived()[sub2ind(derived(), indx)]; } 00156 00157 const_reference operator()(size_t s1) const 00158 { return (*this)[s1]; } 00159 const_reference operator()(size_t s1, size_t s2) const 00160 { return (*this)[s1 + s2 * strides[1]]; } 00161 const_reference operator()(size_t s1, size_t s2, size_t s3) const 00162 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2]]; } 00163 const_reference operator()(size_t s1, size_t s2, size_t s3, 00164 size_t s4) const 00165 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00166 s4 * strides[3]]; } 00167 const_reference operator()(size_t s1, size_t s2, size_t s3, size_t s4, 00168 size_t s5) const 00169 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00170 s4 * strides[3] + s5 * strides[4]]; } 00171 const_reference operator()(size_t s1, size_t s2, size_t s3, size_t s4, 00172 size_t s5, size_t s6) const 00173 { return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00174 s4 * strides[3] + s5 * strides[4] + s6 * strides[5]]; } 00177 template<class S> 00178 const_reference operator()(const array<size_t, S>& indx) const 00179 { return derived()[sub2ind(derived(), indx)]; } 00181 00182 00183 00186 00187 array_nd() : ndim(0), sizes(0), strides(0) { } 00188 00190 explicit array_nd(size_t count) 00191 : common_base_class(count), ndim(1), 00192 sizes(size_array(1, count)), strides(size_array(1,1)) { }; 00193 00196 array_nd(size_t count, const T& s) : 00197 common_base_class(count, s), ndim(1), 00198 sizes(size_array(1, count)), strides(size_array(1,1)) { }; 00199 00202 template <class J, class D> 00203 array_nd(size_t count, const array<J, D>& s) : 00204 common_base_class(count, s), ndim(1), 00205 sizes(size_array(1, count)), strides(size_array(1,1)) { }; 00206 00215 array_nd(size_t count, const T *data) : 00216 common_base_class(count, data), ndim(1), 00217 sizes(size_array(1,count)), strides(size_array(1,1)) { }; 00218 00221 template<class S> 00222 array_nd(size_t count, const data_init_arg& y) : 00223 common_base_class(count, y), ndim(1), 00224 sizes(size_array(1,count)), strides(size_array(1,1)) { }; 00225 00230 00231 template<class S> 00232 array_nd(const array<size_t, S>& sz) : 00233 common_base_class(size_t(prod(sz))), ndim(sz.length()), 00234 sizes(sz), strides(cumprod(shift(sz, 1, size_t(1)))) { }; 00235 00238 template<class S> 00239 array_nd(const array<size_t, S>& sz, const T& s) : 00240 common_base_class(prod(sz), s), ndim(sz.length()), sizes(sz), 00241 strides(cumprod(shift(sz, 1, size_t(1)))) { }; 00242 00245 template<class S> 00246 array_nd(const array<size_t, S>& sz, const T* ptr) : 00247 common_base_class(prod(sz), ptr), ndim(sz.length()), 00248 sizes(sz), strides(cumprod(shift(sz, 1, size_t(1)))) { }; 00249 00252 template<class S> 00253 array_nd(const array<size_t, S>& sz, const data_init_arg& y) : 00254 common_base_class(prod(sz), y), ndim(sz.length()), 00255 sizes(sz), strides(cumprod(shift(sz, 1, size_t(1)))) { }; 00256 00259 template<class S, class J, class D> 00260 array_nd(const array<size_t, S>& sz, const array<J, D>& a) : 00261 common_base_class(prod(sz), a), 00262 ndim(sz.length()), sizes(sz), 00263 strides(cumprod(shift(sz, 1, size_t(1)))) { }; 00264 00265 // specific for the case that we have ref iterator and we need non-const 00266 // array 00269 template<class S, class J, class D> 00270 array_nd(const array<size_t, S>& sz, array<J, D>& a) : 00271 common_base_class(prod(sz), a), 00272 ndim(sz.length()), sizes(sz), 00273 strides(cumprod(shift(sz, 1, size_t(1)))) { }; 00274 00276 array_nd(const this_type& a) : 00277 common_base_class(a), 00278 ndim(a.ndims()), sizes(a.size_nd()), strides(a.stride()) { }; 00279 00281 template<class J, class S> 00282 array_nd(const array_nd<J, S>& a) : 00283 common_base_class(a), 00284 ndim(a.ndims()), sizes(a.size_nd()), 00285 strides(a.stride()) { }; 00286 00288 template<class J, class S> 00289 array_nd(array_nd<J, S>& a) : 00290 common_base_class(a), 00291 ndim(a.ndims()), sizes(a.size_nd()), 00292 strides(a.stride()) { }; 00293 00294 #ifdef IVL_MATLAB 00295 00304 array_nd(const mxArray* mx); 00305 #endif 00306 00307 00315 00316 size_nd_ref_type size_nd() const { return sizes; } 00317 00319 size_t size_nd(size_t d) const { return sizes[d]; } 00320 00322 stride_ref_type stride() const { return strides; } 00323 00325 size_t stride(size_t dim) const { return strides[dim]; } 00326 00328 size_type size() const { return size_nd(); } 00329 00331 size_t size(size_t d) const { return sizes[d]; } 00332 00334 size_t ndims() const { return ndim; } 00337 using iter_nd_interface::first_to_last; 00338 using common_base_class::first_to_last; 00339 00340 using iter_nd_interface::begin_to_end; 00341 using common_base_class::begin_to_end; 00342 00345 00346 00347 00348 00349 00350 00351 00352 void init(const size_t newsize, const T& s); 00353 00355 void init(const size_t newsize); 00356 00358 template <class S> 00359 void init(const array<size_t, S>& newsize, const T& s); 00360 00362 template <class S> 00363 void init(const array<size_t, S>& newsize); 00364 // 00372 void resize(const size_t newsize, const T& s); 00373 00375 void resize(const size_t newsize); 00376 00378 template <class S> 00379 void resize(const array<size_t, S>& newsize, const T& s); 00380 00382 template <class S> 00383 void resize(const array<size_t, S>& newsize); 00384 // 00392 void reshape(const size_t newsize, const T& s); 00393 00395 void reshape(const size_t newsize); 00396 00398 template <class S> 00399 void reshape(const array<size_t, S>& newsize, const T& s); 00400 00402 template <class S> 00403 void reshape(const array<size_t, S>& newsize); 00406 // Operators 00407 00408 /* 00409 TODO: do something for this. you need to disable this operator for the array_nd, 00410 since it is forbidden to resize the underlying array, that would cause data corruption. 00411 this might possibly be handled with the derived mechanism and promote the return 00412 value of this function to a non-resizable type when the Derived type is an 00413 array_nd...... 00414 00415 static_indirect_array<T, false> operator[](const size_array& idx) 00416 { return static_indirect_array<T, false>(idx, this->base_ptr); } 00417 00418 static_mask_array<T, false> operator[](const bool_array& idx) 00419 { return static_mask_array<T, false>(idx, this->get_base_ptr()); } 00420 */ 00421 00422 00426 //using common_base_class::operator=; 00427 template<class K> 00428 derived_type& operator=(const K& k) 00429 { common_base_class::operator=(k); return derived(); } 00430 00432 this_type& operator=(const this_type& in) 00433 { common_base_class::operator=(in); return *this; } 00434 00437 }; 00438 00439 00440 // init 00441 00442 template <class T, class D> 00443 void array_nd<T, D>::init(size_t newsize) 00444 // override the base data init because it will be now invalid. 00445 { 00446 // call array data class init first 00447 base_class::init(newsize); 00448 00449 ndim = 1; 00450 sizes.init(1, newsize); 00451 strides.init(1, 1); 00452 } 00453 00454 template <class T, class D> 00455 void array_nd<T, D>::init(size_t newsize, const T& s) 00456 // override the base data init because it will be now invalid. 00457 { 00458 // call array data class init first 00459 base_class::init(newsize, s); 00460 00461 ndim = 1; 00462 sizes.init(1, newsize); 00463 strides.init(1, 1); 00464 } 00465 00466 template <class T, class D> 00467 template<class S> 00468 void array_nd<T, D>::init(const array<size_t, S>& newsize) 00469 { 00470 // call array data class init first 00471 base_class::init(prod(newsize)); 00472 00473 ndim = newsize.length(); 00474 sizes = newsize; 00475 strides = cumprod<size_t>(shift(sizes, 1, size_t(1))); 00476 } 00477 00478 template <class T, class D> 00479 template<class S> 00480 void array_nd<T, D>::init(const array<size_t, S>& newsize, const T& s) 00481 { 00482 // call array data class init first 00483 base_class::init(prod(newsize), s); 00484 00485 ndim = newsize.length(); 00486 sizes = newsize; 00487 strides = cumprod<size_t>(shift(sizes, 1, size_t(1))); 00488 } 00489 00490 // reshape 00491 00492 template <class T, class D> 00493 void array_nd<T, D>::reshape(size_t newsize) 00494 // override the base data resize because it will be now invalid. 00495 { 00496 // call array data class resize first 00497 base_class::resize(newsize); 00498 00499 ndim = 1; 00500 sizes.resize(1, newsize); 00501 strides.resize(1, 1); 00502 } 00503 00504 template <class T, class D> 00505 void array_nd<T, D>::reshape(size_t newsize, const T& s) 00506 // override the base data resize because it will be now invalid. 00507 { 00508 // call array data class resize first 00509 base_class::resize(newsize, s); 00510 00511 ndim = 1; 00512 sizes.resize(1, newsize); 00513 strides.resize(1, 1); 00514 } 00515 00516 template <class T, class D> 00517 template<class S> 00518 void array_nd<T, D>::reshape(const array<size_t, S>& newsize) 00519 { 00520 // call array data class resize first 00521 base_class::resize(prod(newsize)); 00522 00523 ndim = newsize.length(); 00524 sizes = newsize; 00525 strides = cumprod<size_t>(shift(sizes, 1, size_t(1))); 00526 } 00527 00528 template <class T, class D> 00529 template<class S> 00530 void array_nd<T, D>::reshape(const array<size_t, S>& newsize, const T& s) 00531 { 00532 // call array data class resize first 00533 base_class::resize(prod(newsize), s); 00534 00535 ndim = newsize.length(); 00536 sizes = newsize; 00537 strides = cumprod<size_t>(shift(sizes, 1, size_t(1))); 00538 } 00539 00540 00541 // resize 00542 00543 template <class T, class D> 00544 void array_nd<T, D>::resize(size_t newsize) 00545 // override the base data resize because it will be now invalid. 00546 { 00547 // call array data class resize first 00548 array_nd_details::shrink_rearrange(*this, idx(newsize), idx(1)); 00549 base_class::resize(newsize); 00550 array_nd_details::enlarge_rearrange(*this, idx(newsize), idx(1)); 00551 00552 ndim = 1; 00553 sizes.resize(1, newsize); 00554 strides.resize(1, 1); 00555 00556 } 00557 00558 template <class T, class D> 00559 void array_nd<T, D>::resize(size_t newsize, const T& s) 00560 // override the base data resize because it will be now invalid. 00561 { 00562 // call array data class resize first 00563 array_nd_details::shrink_rearrange(*this, idx(newsize), idx(1), s); 00564 base_class::resize(newsize/*, s*/); 00565 array_nd_details::enlarge_rearrange(*this, idx(newsize), idx(1), s); 00566 00567 ndim = 1; 00568 sizes.resize(1, newsize); 00569 strides.resize(1, 1); 00570 } 00571 00572 template <class T, class D> 00573 template<class S> 00574 void array_nd<T, D>::resize(const array<size_t, S>& newsize) 00575 { 00576 array<size_t, tiny> new_stride = 00577 cumprod<size_t>(shift(newsize, 1, size_t(1))); 00578 00579 // call array data class resize first 00580 array_nd_details::shrink_rearrange(*this, newsize, new_stride); 00581 base_class::resize(prod(newsize)); 00582 array_nd_details::enlarge_rearrange(*this, newsize, new_stride); 00583 00584 ndim = newsize.length(); 00585 sizes = newsize; 00586 strides = new_stride; 00587 } 00588 00589 template <class T, class D> 00590 template<class S> 00591 void array_nd<T, D>::resize(const array<size_t, S>& newsize, const T& s) 00592 { 00593 array<size_t, tiny> new_stride = 00594 cumprod<size_t>(shift(newsize, 1, size_t(1))); 00595 00596 // call array data class resize first 00597 array_nd_details::shrink_rearrange(*this, newsize, new_stride, s); 00598 base_class::resize(prod(newsize) /*, s*/); 00599 array_nd_details::enlarge_rearrange(*this, newsize, new_stride, s); 00600 00601 ndim = newsize.length(); 00602 sizes = newsize; 00603 strides = new_stride; 00604 } 00605 00606 // ------------------------------------------------------------- 00607 #if 0 00608 //VC2005 Crashes with this! OMG...... 00609 00610 template<class T, class D, class P> 00611 inline 00612 typename array_nd<T, D, P>::best_reference 00613 array_nd<T, D, P>::operator()(size_t s1) 00614 { 00615 return (*this)[s1]; 00616 } 00617 00618 template<class T, class D, class P> 00619 inline 00620 typename array_nd<T, D, P>::best_reference 00621 array_nd<T, D, P>::operator()(size_t s1, size_t s2) 00622 { 00623 return (*this)[s1 + s2 * strides[1]]; 00624 } 00625 00626 template<class T, class D, class P> 00627 inline 00628 typename array_nd<T, D, P>::best_reference 00629 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3) 00630 { 00631 return (*this)[s1 + s2 * strides[1] + s3 * strides[2]]; 00632 } 00633 00634 template<class T, class D, class P> 00635 inline 00636 typename array_nd<T, D, P>::best_reference 00637 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3, size_t s4) 00638 { 00639 return (*this)[s1 + s2 * strides[1] + 00640 s3 * strides[2] + s4 * strides[3]]; 00641 } 00642 00643 template<class T, class D, class P> 00644 inline 00645 typename array_nd<T, D, P>::best_reference 00646 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3, 00647 size_t s4, size_t s5) 00648 { 00649 return (*this)[s1 + s2 * strides[1] + s3 * strides[2] 00650 + s4 * strides[3] + s5 * strides[4]]; 00651 } 00652 00653 template<class T, class D, class P> 00654 inline 00655 typename array_nd<T, D, P>::best_reference 00656 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3, size_t s4, 00657 size_t s5, size_t s6) 00658 { 00659 return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00660 s4 * strides[3] + s5 * strides[4] + s6 * strides[5]]; 00661 } 00662 00663 template<class T, class D, class P> 00664 inline 00665 typename array_nd<T, D, P>::const_reference 00666 array_nd<T, D, P>::operator()(size_t s1) const 00667 { 00668 return (*this)[s1]; 00669 } 00670 00671 template<class T, class D, class P> 00672 inline 00673 typename array_nd<T, D, P>::const_reference 00674 array_nd<T, D, P>::operator()(size_t s1, size_t s2) const 00675 { 00676 return (*this)[s1 + s2 * strides[1]]; 00677 } 00678 00679 template<class T, class D, class P> 00680 inline 00681 typename array_nd<T, D, P>::const_reference 00682 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3) const 00683 { 00684 return (*this)[s1 + s2 * strides[1] + s3 * strides[2]]; 00685 } 00686 00687 template<class T, class D, class P> 00688 inline 00689 typename array_nd<T, D, P>::const_reference 00690 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3, 00691 size_t s4) const 00692 { 00693 return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00694 s4 * strides[3]]; 00695 } 00696 template<class T, class D, class P> 00697 inline 00698 typename array_nd<T, D, P>::const_reference 00699 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3, 00700 size_t s4, size_t s5) const 00701 { 00702 return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00703 s4 * strides[3] + s5 * strides[4]]; 00704 } 00705 00706 template<class T, class D, class P> 00707 inline 00708 typename array_nd<T, D, P>::const_reference 00709 array_nd<T, D, P>::operator()(size_t s1, size_t s2, size_t s3, 00710 size_t s4, size_t s5, size_t s6) const 00711 { 00712 return (*this)[s1 + s2 * strides[1] + s3 * strides[2] + 00713 s4 * strides[3] + s5 * strides[4] + s6 * strides[5]]; 00714 } 00715 00716 #endif