ivl 679
ivl/details/array_nd/functions/array_nd_functions.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 
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations