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 00029 #ifndef IVL_ARRAY_ND_DETAILS_ARRAY_ND_FUNCTIONS_HPP 00030 #define IVL_ARRAY_ND_DETAILS_ARRAY_ND_FUNCTIONS_HPP 00031 00032 #include <limits> 00033 00034 namespace ivl { 00035 00036 //-------------------------------------------------------------- 00037 // array_nd MEMBER FUNCTIONS 00038 00039 namespace array_nd_details { 00040 00041 00042 } /* namespace array_nd_details */ 00043 00044 //-------------------------------------------------------------- 00045 // array_nd NON-MEMBER FUNCTIONS 00046 00053 #if 0 // this find is now implemented as an ivl function: 00054 00060 template<class T, class S> 00061 inline 00062 array<array<size_t, stack<3> > > find( 00063 const array_nd<T, S>& a, const T& what) 00064 { 00065 array<array<size_t, stack<3> > > b(0); 00066 size_t n = 0; 00067 00068 for (size_t i = 0; i < a.length(); i++) 00069 if (a[i] == what) 00070 b.push_back(ind2sub(a, i)); 00071 00072 return b; 00073 } 00074 #endif 00075 00077 template<class T, class S> 00078 inline 00079 array<size_t, stack<3> > ind2sub(const array_nd<T, S>& a, size_t s) 00080 { 00081 CHECK (s <= a.length(), erange()); 00082 00083 array<size_t, stack<3> > b(a.ndims()); 00084 00085 for (size_t i = 0; i < b.length(); i++) { 00086 b[b.length() - i - 1] = s / a.stride()[b.length() - i - 1]; 00087 s %= a.stride()[b.length() - i - 1]; 00088 } 00089 00090 return b; 00091 } 00092 00099 template<class T, class S, class D> 00100 typename array_nd<T, S>::create_new permute( 00101 const array_nd<T, S>& a, const array<size_t, D>& sz) 00102 { 00103 CHECK (a.ndims() == sz.length(), eshape()); 00104 00105 array<size_t, stack<3> > newsz(a.ndims()); 00106 00107 for (size_t i = 0; i < a.ndims(); i++) 00108 newsz[i] = a.size_nd()[sz[i] - 1]; 00109 00110 return reshape(a, newsz); 00111 00112 } 00113 00114 00124 template<class T, class S, class D> 00125 typename array_nd<T, S>::create_new reshape( 00126 const array_nd<T, S>& src, const array<size_t, D>& sz) 00127 { 00128 CHECK (src.length() == prod(sz), eshape()); 00129 00130 return typename array_nd<T, S>::create_new(sz, src); 00131 } 00132 00133 00135 template<class T, class S> 00136 array<typename array_nd<T, S>::create_new> split( 00137 const array_nd<T, S>& a, size_t spoint, size_t dim) 00138 { 00139 return split(a, idx(spoint), dim); 00140 } 00141 00143 template<class T, class S, class D> 00144 array<typename array_nd<T, S>::create_new> split( 00145 const array_nd<T, S>& a, const array<size_t, D>& spoint , size_t dim) 00146 { 00147 CHECK (dim < a.ndims(), edims()); 00148 CHECK (dim >= 0, edims()); 00149 00150 array<typename array_nd<T, S>::create_new> result(spoint.length() + 1); 00151 00152 for (size_t j = 0; j < spoint.length(); j++) 00153 CHECK(spoint[j] <= a.size_nd()[dim], erange()); 00154 00155 00156 for (size_t j = 0; j < spoint.length() + 1; j++) { 00157 std::cout << j << std::endl; 00158 array<index_array, tiny> indx(a.ndims()); 00159 for (size_t i = 0; i < a.ndims(); i++) { 00160 if(i != dim) 00161 indx[i] = size_array( 00162 size_range(0, a.size_nd()[i] - 1)); 00163 else 00164 indx[i] = size_array(size_range((j == 0 ? 0 : spoint[j - 1]), 00165 (j == (spoint.length()) ? 00166 a.size_nd()[i] - 1 : spoint[j] - 1) )); 00167 } 00168 result[j] = a(indx); 00169 } 00170 return result; 00171 } 00172 00174 template<class T, class S, class D> 00175 inline 00176 size_t sub2ind(const array_nd<T, S>& a, const array<size_t, D>& b) 00177 { 00178 size_t offs = b[0]; 00179 size_t ndims = a.ndims(); 00180 00181 for(size_t i = 1; i < ndims; i++) 00182 offs += a.stride()[i] * b[i]; 00183 00184 CHECK (offs < a.length(), erange()); 00185 00186 return offs; 00187 } 00188 00194 template <class T, class D> 00195 inline 00196 array_nd<T> ones(const array<size_t, D>& sz) 00197 { 00198 return array_nd<T>(sz, T(1)); 00199 } 00200 00206 template <class T, class D> 00207 inline 00208 array_nd<T> zeros(const array<size_t, D>& sz) 00209 { 00210 return array_nd<T>(sz, T(0)); 00211 } 00212 00219 template <class T, class D> 00220 inline 00221 array_nd<T> inf(const array<size_t, D>& sz) 00222 { 00223 return array_nd<T>(sz, std::numeric_limits<T>::infinity()); 00224 } 00225 00226 00227 #if 0 00228 // creates a mesh grid of the two arrays. 00229 template <class T> inline 00230 array<array_2d<T> > meshgrid(const index_array& a, const index_array& b) 00231 { 00232 array<array_nd<T> > c(2); 00233 c[0] = repmat(array_nd<T>(idx(1,a.length()),a.cast()), idx(b.length() - 1,0)); 00234 c[1] = repmat(array_nd<T>(idx(b.length(),1),b.cast()), idx(0,a.length() - 1)); 00235 return c; 00236 } 00237 00238 template <class T> inline 00239 array_2d<T> meshgrid(const index_array& a) 00240 { 00241 return meshgrid(a, a); 00242 } 00243 #endif 00244 00246 00247 //-------------------------------------------------------------- 00248 // Template functions for array_nd / image etc. 00249 00251 template<class T, class S> 00252 typename array_nd<T, S>::create_similar flipdim( 00253 const array_nd<T, S>& a, size_t dim) 00254 { 00255 CHECK (dim < a.ndims(), edims()); 00256 CHECK (dim >= 0, edims()); 00257 array<index_array> indx(a.ndims()); 00258 for (size_t i = 0; i < a.ndims(); i++) 00259 indx[i] = index_array(); // Select all. 00260 00261 indx[dim] = size_range(a.size_nd()[dim] - 1, -1, 0); 00262 return typename array_nd<T, S>::create_similar(a(indx)); 00263 } 00264 00265 //-------------------------------------------------------------- 00266 00268 template <class T, class S> 00269 inline 00270 typename array_nd<T, S>::create_new cat( 00271 size_t dim, const array<array_nd<T, S> >& a) 00272 { 00273 for (size_t i = 0; i < a.length() - 1; i++) { 00274 CHECK (a[i].ndims() == a[i + 1].ndims(), eshape()); 00275 for (size_t j = 0; j < a[i].ndims(); j++) 00276 if (j != dim) 00277 CHECK(a[i].size_nd()[j] == a[i + 1].size_nd()[j], eshape()); 00278 } 00279 CHECK(dim < a[0].ndims(), edims()); 00280 CHECK(dim >= 0, edims()); 00281 size_array sz(a[0].ndims()); 00282 00283 for (size_t i = 0; i < a[0].ndims(); i++) 00284 sz[i] = a[0].size_nd()[i]; 00285 sz[dim] = 0; 00286 for (size_t j = 0; j < a.length(); j++) 00287 sz[dim] += a[j].size_nd()[dim]; 00288 typename array_nd<T, S>::create_new c(sz); 00289 00290 size_t offs = 0; 00291 for (size_t j = 0; j < a.length(); j++) { 00292 array<index_array> indx(a[j].ndims()); 00293 00294 for (size_t i = 0; i < a[j].ndims(); i++) 00295 indx[i] = size_range((i == dim) ? offs : 0, 00296 a[j].size_nd()[i] - 1 + ((i == dim) ? offs : 0)); 00297 00298 offs += a[j].size_nd()[dim]; 00299 c(indx) = a[j]; 00300 } 00301 return c; 00302 } 00303 00304 template <class T, class S1, class S2> 00305 inline 00306 array_nd<T> cat(size_t dim, 00307 const array_nd<T, S1>& a1, const array_nd<T, S2>& a2) 00308 { 00309 CHECK(dim < a1.ndims(), edims()); 00310 CHECK(dim >= 0, edims()); 00311 CHECK (a1.ndims() == a2.ndims(), eshape()); 00312 00313 for (size_t j = 0; j < a1.ndims(); j++) 00314 if (j != dim) 00315 CHECK(a1.size_nd()[j] == a2.size_nd()[j], eshape()); 00316 00317 size_array sz(a1.size()); 00318 sz[dim] = a1.size_nd(dim); 00319 sz[dim] += a2.size_nd(dim); 00320 array_nd<T> c(sz); 00321 00322 array<index_array> indx(a1.ndims(), all()); 00323 indx[dim] = size_range(0, a1.size_nd(dim) - 1); 00324 c(indx).base() = a1; 00325 indx[dim] = size_range(a1.size_nd(dim), indx[dim].last + a2.size_nd(dim)); 00326 c(indx) = a2; 00327 return c; 00328 } 00329 00330 00331 template <class T, class S1, class S2, class S3> 00332 inline 00333 array_nd<T> cat(size_t dim, const array_nd<T, S1>& a1, 00334 const array_nd<T, S2>& a2, const array_nd<T, S3>& a3) 00335 { 00336 CHECK(dim < a1.ndims(), edims()); 00337 CHECK(dim >= 0, edims()); 00338 CHECK (a1.ndims() == a2.ndims(), eshape()); 00339 CHECK (a2.ndims() == a3.ndims(), eshape()); 00340 for (size_t j = 0; j < a1.ndims(); j++) 00341 if (j != dim) { 00342 CHECK(a1.size_nd()[j] == a2.size_nd()[j], eshape()); 00343 CHECK(a2.size_nd()[j] == a3.size_nd()[j], eshape()); 00344 } 00345 00346 size_array sz(a1.size()); 00347 sz[dim] = a1.size_nd(dim); 00348 sz[dim] += a2.size_nd(dim); 00349 sz[dim] += a3.size_nd(dim); 00350 array_nd<T> c(sz); 00351 00352 array<index_array> indx(a1.ndims(), all()); 00353 indx[dim] = size_range(0, a1.size_nd(dim) - 1); 00354 c(indx) = a1; 00355 indx[dim] = size_range(indx[dim].last + 1, 00356 indx[dim].last + a2.size_nd(dim)); 00357 c(indx) = a2; 00358 indx[dim] = size_range(indx[dim].last + 1, 00359 indx[dim].last + a3.size_nd(dim)); 00360 c(indx) = a3; 00361 return c; 00362 } 00363 00364 template <class T, class S1, class S2, class S3, class S4> 00365 inline 00366 array_nd<T> cat(size_t dim, const array_nd<T, S1>& a1, 00367 const array_nd<T, S2>& a2, const array_nd<T, S3>& a3, 00368 const array_nd<T, S4>& a4) 00369 { 00370 CHECK(dim < a1.ndims(), edims()); 00371 CHECK(dim >= 0, edims()); 00372 CHECK (a1.ndims() == a2.ndims(), eshape()); 00373 CHECK (a2.ndims() == a3.ndims(), eshape()); 00374 CHECK (a3.ndims() == a4.ndims(), eshape()); 00375 for (size_t j = 0; j < a1.ndims(); j++) 00376 if (j != dim) { 00377 CHECK(a1.size_nd()[j] == a2.size_nd()[j], eshape()); 00378 CHECK(a2.size_nd()[j] == a3.size_nd()[j], eshape()); 00379 CHECK(a3.size_nd()[j] == a4.size_nd()[j], eshape()); 00380 } 00381 00382 size_array sz(a1.size()); 00383 sz[dim] = a1.size_nd(dim); 00384 sz[dim] += a2.size_nd(dim); 00385 sz[dim] += a3.size_nd(dim); 00386 sz[dim] += a4.size_nd(dim); 00387 array_nd<T> c(sz); 00388 00389 array<index_array> indx(a1.ndims(), all()); 00390 indx[dim] = size_range(0, a1.size_nd(dim) - 1); 00391 c(indx) = a1; 00392 indx[dim] = size_range(indx[dim].last + 1, 00393 indx[dim].last + a2.size_nd(dim)); 00394 c(indx) = a2; 00395 indx[dim] = size_range(indx[dim].last + 1, 00396 indx[dim].last + a3.size_nd(dim)); 00397 c(indx) = a3; 00398 indx[dim] = size_range(indx[dim].last + 1, 00399 indx[dim].last + a4.size_nd(dim)); 00400 c(indx) = a4; 00401 return c; 00402 } 00403 00412 template<class T> 00413 array_nd<T> repmat(const array_nd<T>& a, const size_array& sz) 00414 { 00415 CHECK (sz.length() <= a.ndims(), eshape()); 00416 00417 array_nd<T> c(a); 00418 00419 for (size_t i = 0; i < sz.length(); i++) { 00420 array_nd<T> tmp(c); 00421 for (size_t j = 0; j < sz[i]; j++) 00422 c = cat<T>(i, c, tmp); 00423 } 00424 return c; 00425 } 00426 00427 //-------------------------------------------------------------- 00428 // Auxiliary functions for array<index_array> construction 00429 // (for sub_array indexing) 00430 00431 inline 00432 array<index_array> idxn(const index_array& p1) 00433 { 00434 return arr<index_array>(p1); 00435 } 00436 00437 inline 00438 array<index_array> idxn(const index_array& p1, const index_array& p2) 00439 { 00440 return arr<index_array>(p1, p2); 00441 } 00442 00443 inline 00444 array<index_array> idxn(const index_array& p1, const index_array& p2, 00445 const index_array& p3) 00446 { 00447 return arr<index_array>(p1, p2, p3); 00448 } 00449 00450 inline 00451 array<index_array> idxn(const index_array& p1, const index_array& p2, 00452 const index_array& p3, const index_array& p4) 00453 { 00454 return arr<index_array>(p1, p2, p3, p4); 00455 } 00456 00457 inline 00458 array<index_array> idxn(const index_array& p1, const index_array& p2, 00459 const index_array& p3, const index_array& p4, 00460 const index_array& p5) 00461 { 00462 return arr<index_array>(p1, p2, p3, p4, p5); 00463 } 00464 00465 inline 00466 array<index_array> idxn(const index_array& p1, const index_array& p2, 00467 const index_array& p3, const index_array& p4, 00468 const index_array& p5, const index_array& p6) 00469 { 00470 return arr<index_array>(p1, p2, p3, p4, p5, p6); 00471 } 00472 00473 } // namespace ivl 00474 00475 #endif // IVL_ARRAY_ND_DETAILS_ARRAY_ND_FUNCTIONS_HPP