ivl 679
ivl/details/array_nd/impl/specialization/array_nd_2d_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 namespace array_details {
00025 
00026 template<class T, class S>
00027 array<size_t, data::fixed<2> > dims_for_2d(const array<T, S>& sz)
00028 {
00029         if(sz.length() == 2) return sz;
00030         array<size_t, data::fixed<2> > r;
00031         if(sz.length() == 1) { r[0] = sz[0]; r[1] = 1; return r; }
00032         if(sz.length() == 0) { r[0] = r[1] = 0; return r; }
00033         size_t l = sz.length();
00034         while (l && sz[l-1]==1) l--;
00035         r[0] = sz[0];
00036         r[1] = sz[1];
00037         CHECK(l <= 2, erange);
00038         return r;
00039 }
00040 
00041 } // namespace array_details
00042 
00062 template <class T,
00063                  class DERIVED_INFO
00064              >
00065 class array_nd<T, data::normal_2d<DERIVED_INFO> >:
00066         public
00067                 array_common_base<array_nd<T,
00068                         data::normal_2d<DERIVED_INFO> > >,
00069 
00070         public
00071         array_nd_details::
00072                 basic_iterator_nd_interface<
00073                         array_nd<T, data::normal_2d<DERIVED_INFO> > >
00074 {
00075 private:
00076         typedef array_nd prv_this_type;
00077 
00078         typedef typename prv_this_type::common_base_class common_base_class;
00079 
00081         size_dims<2> sizes;
00082 
00083 public:
00084         typedef array_nd this_type;
00085 
00086         typedef this_type this_array_nd_type;
00087 
00088         typedef typename common_base_class::derived_type derived_type;
00089 
00090         typedef typename common_base_class::base_class base_class;
00091 
00092         typedef this_type array_type;
00093 
00095         typedef array<size_t, tiny> size_type;
00096 
00098         typedef const size_dims<2>& size_nd_ref_type;
00099 
00101         typedef size_dims<2> stride_ref_type;
00102 
00103         using base_class::derived;
00104 
00106         base_class& base() { return *this; }
00107         const base_class& base() const { return *this; }
00108 
00115         using base_class::operator[];
00116         using base_class::length;
00117         using base_class::numel;
00118         using common_base_class::operator();
00119 
00126         T& operator()(size_t s1, size_t s2)
00127         {
00128                 return derived()[s1 + sizes[0] * s2];
00129         }
00130 
00133         template<class S>
00134         T& operator()(const array<size_t, S>& indx)
00135         {
00136                 CHECK(indx.length() == 2, edims);
00137                 return derived()[indx[0] + sizes[0] * indx[1]];
00138         }
00139 
00140         const T& operator()(size_t s1, size_t s2) const
00141         {
00142                 return derived()[s1 + sizes[0] * s2];
00143         }
00144 
00147         template<class S>
00148         const T& operator()(const array<size_t, S>& indx) const
00149         {
00150                 CHECK(indx.length() == 2, edims);
00151                 return derived()[indx[0] + sizes[0] * indx[1]];
00152         }
00154 
00155 
00156 
00160 
00161         array_nd() : sizes(0, 0) {};
00162 
00165 
00166         template<class S>
00167         array_nd(const array<size_t, S>& sz) :
00168                 common_base_class(size_t(sz[0] * sz[1])), sizes(sz)
00169                 { CHECK(sz.length() == 2, edims); }
00170 
00173         template<class S>
00174         array_nd(const array<size_t, S>& sz, const T& s) :
00175                 common_base_class(size_t(sz[0] * sz[1]), s), sizes(sz)
00176                 { CHECK(sz.length() == 2, edims); }
00177 
00180         template<class S>
00181         array_nd(const array<size_t, S>& sz, const T* ptr) :
00182                 common_base_class(size_t(sz[0] * sz[1]), ptr), sizes(sz)
00183                 { CHECK(sz.length() == 2, edims); }
00184 
00187         template<class S, class J, class D>
00188         array_nd(const array<size_t, S>& sz, const array<J, D>& a) :
00189                 common_base_class(size_t(sz[0] * sz[1]), a), sizes(sz)
00190                 { CHECK(sz.length() == 2, edims); }
00191 
00193         array_nd(const this_type& a) :
00194                 common_base_class(a), sizes(a.sizes) { };
00195 
00197         template<class J, class S>
00198         array_nd(const array_nd<J, S>& a) :
00199                 common_base_class(a), sizes(array_details::dims_for_2d(a.size()))
00200                 {
00201                 }
00202 
00203 #ifdef IVL_MATLAB
00204 
00213         array_nd(const mxArray* mx);
00214 #endif
00215 
00216 
00224 
00225         size_nd_ref_type size_nd() const
00226         {
00227                 return sizes;
00228         }
00229 
00231         size_t size_nd(size_t dim) const
00232         {
00233                 return sizes[dim];
00234         }
00235 
00237         stride_ref_type stride() const
00238         {
00239                 return size_dims<2>(1, sizes[0]);
00240         }
00241 
00242         size_t stride(size_t dim) const { return (dim == 0 ? 1 : sizes[0]); }
00243 
00245         size_type size() const { return size_nd(); }
00246 
00248         size_t size(size_t dim) const
00249         {
00250                 return sizes[dim];
00251         }
00252 
00254         size_t ndims() const { return 2; }
00259 
00260         template <class S>
00261         void resize(const array<size_t, S>& newsize, const T& s);
00262 
00264         template <class S>
00265         void resize(const array<size_t, S>& newsize);
00266 
00268         template <class S>
00269         void reshape(const array<size_t, S>& newsize, const T& s);
00270 
00272         template <class S>
00273         void reshape(const array<size_t, S>& newsize);
00274 
00275 
00277         template <class S>
00278         void init(const array<size_t, S>& newsize, const T& s);
00279 
00281         template <class S>
00282         void init(const array<size_t, S>& newsize);
00283 
00284         void init(const this_type& a)
00285         {
00286                 sizes = a.sizes;
00287                 base_class::init(sizes[0] * sizes[1], a);
00288         }
00291         // Operators
00292 
00293 /*
00294 TODO: do something for this
00295 
00296         static_indirect_array<T, false> operator[](const size_array& idx)
00297                 { return static_indirect_array<T, false>(idx, this->base_ptr); }
00298 
00299         static_mask_array<T, false> operator[](const bool_array& idx)
00300                 { return static_mask_array<T, false>(idx, this->get_base_ptr()); }
00301 */
00302 
00303 
00304 
00305 #if 0
00306 // TODO: have to implement
00307 
00308         T& operator()(size_t s1);
00309         T& operator()(size_t s1, size_t s2);
00310         T& operator()(size_t s1, size_t s2, size_t s3);
00311         T& operator()(size_t s1, size_t s2, size_t s3, size_t s4);
00312         T& operator()(size_t s1, size_t s2, size_t s3, size_t s4, size_t s5);
00313         T& operator()(size_t s1, size_t s2, size_t s3, size_t s4, size_t s5, size_t s6);
00314 
00317         template<class S>
00318         typename types::best_iterator<array_nd>::type::reference operator()(
00319                         const array<size_t, S>& indx)
00320                 { return derived()[sub2ind(derived(), indx)]; }
00321 
00322         const T& operator()(size_t s1) const;
00323         const T& operator()(size_t s1, size_t s2) const;
00324         const T& operator()(size_t s1, size_t s2, size_t s3) const;
00325         const T& operator()(size_t s1, size_t s2, size_t s3, size_t s4) const;
00326         const T& operator()(size_t s1, size_t s2, size_t s3, size_t s4, size_t s5) const;
00327         const T& operator()(size_t s1, size_t s2, size_t s3, size_t s4, size_t s5, size_t s6) const;
00328 
00331         template<class S>
00332         typename array_nd::const_iterator::reference operator()
00333                 (const array<size_t, S>& indx) const
00334                 { return derived()[sub2ind(derived(), indx)]; }
00335 
00336 #endif
00337 
00338 #if 0
00339         NewDerived operator()(const gslice& gsl) const;
00340         gslice_array<T> operator()(const gslice& gsl);
00341 
00342         NewDerived operator()(const array<slice>& as) const;
00343         gslice_array<T> operator()(const array<slice>& as);
00344 #endif
00345 
00346 
00350         //using common_base_class::operator=;
00351         template<class K>
00352         derived_type& operator=(const K& k)
00353         { common_base_class::operator=(k); return derived(); }
00354 
00356         this_type& operator=(const this_type& in)
00357         { common_base_class::operator=(in); return *this; }
00358 /*
00360         derived_type& operator=(const T& s);
00361 
00363         template<class S, class K>
00364         derived_type& operator=(const array_nd<T, S, K>& a)
00365         { common_base_class::operator=(a); return this->derived(); }
00366 */
00370 };
00371 
00372 
00373 template <class T, class P>
00374 template <class S>
00375 void array_nd<T, data::normal_2d<P> >
00376         ::resize(const array<size_t, S>& newsize)
00377 {
00378         CHECK(newsize.length() == 2, edims);
00379 
00380         array<size_t, tiny> new_stride =
00381                 cumprod<size_t>(shift(newsize, 1, size_t(1)));
00382 
00383         // call array data class resize first
00384         array_nd_details::shrink_rearrange(*this, newsize, new_stride);
00385         // call array data class resize first
00386         base_class::resize(newsize[0] * newsize[1]);
00387         array_nd_details::enlarge_rearrange(*this, newsize, new_stride);
00388 
00389         //static_cast<typename size_dims<2>::base_class::base_class&>
00390         //todo: there is some strange error somewhere here
00391         (sizes) = newsize;
00392 }
00393 
00394 template <class T, class P>
00395 template <class S>
00396 void array_nd<T, data::normal_2d<P> >
00397         ::resize(const array<size_t, S>& newsize, const T& s)
00398 {
00399         CHECK(newsize.length() == 2, edims);
00400 
00401         array<size_t, tiny> new_stride =
00402                 cumprod<size_t>(shift(newsize, 1, size_t(1)));
00403 
00404         // call array data class resize first
00405         array_nd_details::shrink_rearrange(*this, newsize, new_stride);
00406         // call array data class resize first
00407         base_class::resize(newsize[0] * newsize[1], s);
00408         array_nd_details::enlarge_rearrange(*this, newsize, new_stride);
00409 
00410         sizes = newsize;
00411 }
00412 
00413 
00414 template <class T, class P>
00415 template<class S>
00416 void array_nd<T, data::normal_2d<P> >
00417 	::reshape(const array<size_t, S>& newsize)
00418 {
00419         CHECK(newsize.length() == 2, edims);
00420 
00421         // call array data class resize first
00422         base_class::resize(newsize[0] * newsize[1]);
00423 
00424         static_cast<typename size_dims<2>::base_class::base_class&> (sizes) = newsize;
00425 }
00426 
00427 template <class T, class P>
00428 template<class S>
00429 void array_nd<T, data::normal_2d<P> >
00430 	::reshape(const array<size_t, S>& newsize, const T& s)
00431 {
00432         CHECK(newsize.length() == 2, edims);
00433 
00434         // call array data class resize first
00435         base_class::resize(newsize[0] * newsize[1], s);
00436 
00437         sizes = newsize;
00438 }
00439 
00440 
00441 template <class T, class P>
00442 template<class S>
00443 void array_nd<T, data::normal_2d<P> >
00444         ::init(const array<size_t, S>& newsize)
00445 {
00446         CHECK(newsize.length() == 2, edims);
00447 
00448         // call array data class init first
00449         base_class::init(newsize[0] * newsize[1]);
00450 
00451         static_cast<typename size_dims<2>::base_class::base_class&> (sizes) = newsize;
00452 }
00453 
00454 template <class T, class P>
00455 template<class S>
00456 void array_nd<T, data::normal_2d<P> >
00457         ::init(const array<size_t, S>& newsize, const T& s)
00458 {
00459         CHECK(newsize.length() == 2, edims);
00460 
00461         // call array data class init first
00462         base_class::init(newsize[0] * newsize[1], s);
00463 
00464         sizes = newsize;
00465 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations