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