ivl 679
ivl/details/array_nd/impl/specialization/array_nd_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 
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations