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 namespace data { 00026 00027 template<int N> 00028 struct get_channels 00029 { 00030 template<class A> 00031 inline static size_t from (const A& a) { return N; } 00032 }; 00033 00034 template<> 00035 struct get_channels<0> 00036 { 00037 template<class A> 00038 inline static size_t from (const A& a) { return a[2]; } 00039 }; 00040 00041 template<int N> 00042 struct image_stride_2 00043 { 00044 size_t s; 00045 image_stride_2(size_t sz0, size_t sz1) : s(sz0 * sz1) { } 00046 inline const size_t& get() const { return s; } 00047 }; 00048 00049 template<> 00050 struct image_stride_2<1> 00051 { 00052 image_stride_2(size_t sz0, size_t sz1) { } 00053 inline size_t get() const { return 0; } 00054 }; 00055 00056 00057 }; //namespace data 00058 00059 00078 template <class T, 00079 int N, 00080 class DERIVED_INFO 00081 > 00082 00083 class array_nd<T, data::normal_image<N, DERIVED_INFO> > 00084 : 00085 public 00086 array_common_base<array_nd<T, 00087 data::normal_image<N, DERIVED_INFO> > >, 00088 00089 public 00090 array_nd_details::basic_iterator_nd_interface<array_nd<T, 00091 data::normal_image<N, DERIVED_INFO> > > 00092 { 00093 private: 00094 typedef array_nd prv_this_type; 00095 typedef typename prv_this_type::common_base_class common_base_class; 00096 typedef typename prv_this_type::iter_nd_interface_class iter_nd_interface; 00097 00099 size_dims<3> sizes; 00100 00101 data::image_stride_2<N> stride_2; 00102 00103 // disable 1-dim resize functions for this type of array 00104 00106 void resize(const size_t newsize, const T& s); 00107 00109 void resize(const size_t newsize); 00110 00111 protected: 00112 00113 // faster access to specific members 00114 inline size_t get_channels() const { return data::get_channels<N>(sizes); } 00115 00116 inline size_t get_stride2() const { return stride_2.get(); } 00117 00118 public: 00119 typedef array_nd this_type; 00120 00121 typedef this_type this_array_nd_type; 00122 00123 typedef typename common_base_class::derived_type derived_type; 00124 00125 typedef typename common_base_class::base_class base_class; 00126 00127 typedef this_type array_type; 00128 00130 typedef array<size_t, tiny> size_type; 00131 00133 typedef const size_dims<3>& size_nd_ref_type; 00134 00136 typedef array<size_t, tiny> stride_ref_type; 00137 00139 typedef types::t_false has_1d_parenthesis; 00140 typedef types::t_false has_2d_parenthesis; 00141 typedef types::t_true has_3d_parenthesis; 00142 typedef types::t_false has_nd_parenthesis; 00143 00144 using base_class::derived; 00145 00147 base_class& base() { return *this; } 00148 const base_class& base() const { return *this; } 00149 00156 using base_class::operator[]; 00157 using base_class::length; 00158 using base_class::numel; 00159 00160 using common_base_class::operator(); 00161 00168 T& operator()(size_t s1, size_t s2, size_t s3 = 0) 00169 { 00170 CHECK(s3 < data::get_channels<N>::from(sizes), erange); 00171 CHECK(s2 < sizes[1], erange); 00172 CHECK(s1 < sizes[0], erange); 00173 return derived()[s1 + sizes[0] * s2 + get_stride2() * s3]; 00174 } 00175 00178 template<class S> 00179 T& operator()(const array<size_t, S>& indx) 00180 { 00181 CHECK(indx.length() == 2 + (N != 1) || indx.length() == 3, edims); 00182 CHECK(indx.length() == 2 || 00183 indx[2] < data::get_channels<N>::from(sizes), erange); 00184 CHECK(indx[1] < sizes[1], erange); 00185 CHECK(indx[0] < sizes[0], erange); 00186 00187 return derived()[indx[0] + sizes[0] * indx[1] + 00188 get_stride2() * indx[2]]; 00189 } 00190 00191 const T& operator()(size_t s1, size_t s2, size_t s3 = 0) const 00192 { 00193 CHECK(s3 < data::get_channels<N>::from(sizes), erange); 00194 CHECK(s2 < sizes[1], erange); 00195 CHECK(s1 < sizes[0], erange); 00196 return derived()[s1 + sizes[0] * s2 + get_stride2() * s3]; 00197 } 00198 00201 template<class S> 00202 const T& operator()(const array<size_t, S>& indx) const 00203 { 00204 CHECK(indx.length() == 2 + (N != 1) || indx.length() == 3, edims); 00205 CHECK(indx.length() == 2 || 00206 indx[2] < data::get_channels<N>::from(sizes), erange); 00207 CHECK(indx[1] < sizes[1], erange); 00208 CHECK(indx[0] < sizes[0], erange); 00209 00210 return derived()[indx[0] + sizes[0] * indx[1] + 00211 get_stride2() * indx[2]]; 00212 } 00214 00215 00219 00220 array_nd() : sizes(0, 0, 0), stride_2(0, 0) {}; 00221 00224 00225 template<class S> 00226 array_nd(const array<size_t, S>& sz) : 00227 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz)), 00228 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)), 00229 stride_2(sz[0], sz[1]) 00230 { CHECK((sz.length() == 2 + (N != 1)) || 00231 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); } 00232 00235 template<class S> 00236 array_nd(const array<size_t, S>& sz, const T& s) : 00237 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz), s), 00238 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)), 00239 stride_2(sz[0], sz[1]) 00240 { CHECK((sz.length() == 2 + (N != 1)) || 00241 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); } 00242 00245 template<class S> 00246 array_nd(const array<size_t, S>& sz, const T* ptr) : 00247 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz), ptr), 00248 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)), 00249 stride_2(sz[0], sz[1]) 00250 { CHECK((sz.length() == 2 + (N != 1)) || 00251 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); } 00252 00255 template<class S, class J, class D> 00256 array_nd(const array<size_t, S>& sz, const array<J, D>& a) : 00257 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz), a), 00258 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)), 00259 stride_2(sz[0], sz[1]) 00260 { CHECK((sz.length() == 2 + (N != 1)) || 00261 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); } 00262 00264 array_nd(const this_type& a) : 00265 common_base_class(a), sizes(a.sizes), stride_2(a.stride_2) {}; 00266 00268 template<class J, class S> 00269 array_nd(const array_nd<J, S>& a) : 00270 common_base_class(a), 00271 sizes(a.size_nd()[0], a.size_nd()[1], 00272 data::get_channels<N>::from(a.size_nd())), 00273 stride_2(a.size_nd()[0], a.size_nd()[1]) 00274 { CHECK((a.size_nd().length() == 2 + (N != 1)) || ((N == 1) 00275 && a.size_nd().length() == 3 && a.size_nd()[2] == 1), edims); } 00276 00277 #ifdef IVL_MATLAB 00278 00287 array_nd(const mxArray* mx); 00288 #endif 00289 00290 00298 00299 size_nd_ref_type size_nd() const 00300 { 00301 return sizes; 00302 } 00303 00305 size_t size_nd(size_t d) const 00306 { 00307 return sizes[d]; 00308 } 00309 00311 stride_ref_type stride() const 00312 { 00313 return size_dims<3>(1, sizes[0], get_stride2()); 00314 } 00315 00317 size_t stride(size_t dim) const 00318 { 00319 return (dim == 0 ? 1 : (dim == 1 ? sizes[0] : get_stride2())); 00320 } 00321 00323 size_type size() const { return size_nd(); } 00325 size_t size(size_t d) const { return sizes[d]; } 00326 00328 size_t ndims() const { return 3; } 00335 00336 template <class S> 00337 void resize(const array<size_t, S>& newsize, const T& s); 00338 00340 template <class S> 00341 void resize(const array<size_t, S>& newsize); 00342 00344 template <class S> 00345 void reshape(const array<size_t, S>& newsize, const T& s); 00346 00348 template <class S> 00349 void reshape(const array<size_t, S>& newsize); 00352 // Operators 00353 00358 using common_base_class::operator=; 00360 this_type& operator=(const this_type& in) 00361 { common_base_class::operator=(in); return *this; } 00362 00367 }; 00368 00369 00370 template <class T, int N, class P> 00371 template <class S> 00372 void array_nd<T, data::normal_image<N, P> > 00373 ::resize(const array<size_t, S>& sz) 00374 { 00375 CHECK((sz.length() == 2 + (N != 1)) || 00376 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); 00377 // call array data class resize first 00378 base_class::resize(sz[0] * sz[1] * data::get_channels<N>::from(sz)); 00379 00380 sizes[0] = sz[0]; 00381 sizes[1] = sz[1]; 00382 sizes[2] = data::get_channels<N>::from(sz); 00383 stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]); 00384 } 00385 00386 template <class T, int N, class P> 00387 template <class S> 00388 void array_nd<T, data::normal_image<N, P> > 00389 ::resize(const array<size_t, S>& sz, const T& s) 00390 { 00391 CHECK((sz.length() == 2 + (N != 1)) || 00392 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); 00393 // call array data class resize first 00394 base_class::resize(sz[0] * sz[1] * data::get_channels<N>::from(sz), s); 00395 00396 sizes[0] = sz[0]; 00397 sizes[1] = sz[1]; 00398 sizes[2] = data::get_channels<N>::from(sz); 00399 stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]); 00400 } 00401 00402 00403 template <class T, int N, class P> 00404 template <class S> 00405 void array_nd<T, data::normal_image<N, P> > 00406 ::reshape(const array<size_t, S>& sz) 00407 { 00408 CHECK((sz.length() == 2 + (N != 1)) || 00409 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); 00410 // call array data class resize first 00411 base_class::reshape(sz[0] * sz[1] * data::get_channels<N>::from(sz)); 00412 00413 sizes[0] = sz[0]; 00414 sizes[1] = sz[1]; 00415 sizes[2] = data::get_channels<N>::from(sz); 00416 stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]); 00417 } 00418 00419 template <class T, int N, class P> 00420 template <class S> 00421 void array_nd<T, data::normal_image<N, P> > 00422 ::reshape(const array<size_t, S>& sz, const T& s) 00423 { 00424 CHECK((sz.length() == 2 + (N != 1)) || 00425 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); 00426 // call array data class resize first 00427 base_class::reshape(sz[0] * sz[1] * data::get_channels<N>::from(sz), s); 00428 00429 sizes[0] = sz[0]; 00430 sizes[1] = sz[1]; 00431 sizes[2] = data::get_channels<N>::from(sz); 00432 stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]); 00433 }