ivl 679
ivl/details/array_nd/impl/common/resize_details.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 #ifndef IVL_ARRAY_ND_DETAILS_COMMON_RESIZE_DETAILS_HPP
00025 #define IVL_ARRAY_ND_DETAILS_COMMON_RESIZE_DETAILS_HPP
00026 
00027 namespace ivl {
00028 namespace array_nd_details {
00029 
00030 template <class T, class S, class D, class L>
00031 void resize_rearrange(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00032                                                 const array<size_t, L>& new_stride,
00033                                                 bool pad = false, const T& padval = T())
00034 {
00035         bool skip_flag = true;
00036         size_t dm = std::min(size_t(a.ndims()), size_t(new_sz.length()));
00037         array<index_array, tiny> id(a.ndims());
00038 
00039         for(size_t i = dm; i < a.ndims(); i++)
00040                 id[i] = idx(0);
00041 
00042         array<size_t, tiny> junc(dm);
00043         for(size_t i = 0; i < dm; i++)
00044                 junc[i] = std::min(new_sz[i], a.size_nd(i));
00045 
00046         for(size_t i = 0; i < dm; i++) {
00047                 // should some dims be reverse and some not
00048                 if(a.stride(i) >= new_stride[i])
00049                         id[i] = size_range(0, junc[i] - 1);
00050                 else
00051                         id[i] = size_range(junc[i] - 1, 0);
00052                 if(a.stride(i) != new_stride[i] &&
00053                         !(new_sz[i] == 1) && !(a.size_nd(i) == 1))
00054                         skip_flag = false;
00055         }
00056 
00057         // if data is in the same position, it needs no repositioning.
00058         if(!skip_flag) {
00059                 // shape of the old array, but with same number of dims as the new array
00060                 array<size_t, tiny> new_szm(a.ndims(), 1);
00061                 size_range new_szr(0, std::min(new_sz.length() - 1, a.ndims() - 1));
00062                 new_szm[new_szr] = new_sz[new_szr];
00063 
00064                 // performs shape manipulation on the array without resizing it:
00065                 array_nd<T, data::ref_iterator<array_nd<T, S> > >
00066                         new_arr(new_szm/* */, a);
00067                 //new_arr.init(a);
00068 
00069                 //TODO: ivl::serial(.)
00070                 //and worry about dimension sorting
00071                 force(new_arr(id)) = a(id);
00072         }
00073 
00074         if(pad) {
00075                 id.resize(new_sz.length(), idx(0));
00076                 array_nd<T, data::ref_iterator<array_nd<T, S> > >
00077                         new_arr(new_sz, a);
00078 
00079                 // padding common dimensions
00080                 for(size_t i = 0; i < dm; i++) {
00081                         id[i] = size_range(junc[i], new_sz[i] - 1);
00082                         new_arr(id) = padval;
00083                         id[i] = all();
00084                 }
00085 
00086                 // padding extra dimensions
00087                 for(size_t i = dm; i < new_sz.length(); i++) {
00088                         id[i] = size_range(1, new_sz[i] - 1);
00089                         new_arr(id) = padval;
00090                         id[i] = all();
00091                 }
00092         }
00093 }
00094 
00095 // since an array can be of many types, we have to see if it is resizeable
00096 template <class IS_RESIZEABLE>
00097 struct resize_rearrange_detail
00098 {
00099         template <class T, class S, class D, class L>
00100         static inline
00101         void operate(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00102                                 const array<size_t, L>& new_stride, const T& p = T()) { }
00103 };
00104 
00105 template <>
00106 struct resize_rearrange_detail<types::t_true>
00107 {
00108         template <class T, class S, class D, class L>
00109         static inline
00110         void operate(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00111                                 const array<size_t, L>& new_stride)
00112         {
00113                 resize_rearrange(a, new_sz, new_stride);
00114         }
00115         template <class T, class S, class D, class L>
00116         static inline
00117         void operate(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00118                                 const array<size_t, L>& new_stride, const T& padval)
00119         {
00120                 resize_rearrange(a, new_sz, new_stride, true, padval);
00121         }
00122 };
00123 
00124 template <class T, class S, class D, class L>
00125 void enlarge_rearrange(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00126                                                 const array<size_t, L>& new_stride)
00127 {
00128         if(a.ndims() > 0) {
00129                 size_t ldim = a.ndims() - 1;
00130                 size_t old_len = a.size_nd(ldim) * a.stride(ldim);
00131                 if(a.length() > old_len && old_len > 0)
00132                         resize_rearrange_detail<typename array_nd<T, S>::is_resizeable>
00133                                 ::operate(a, new_sz, new_stride);
00134         }
00135 }
00136 
00137 template <class T, class S, class D, class L>
00138 void shrink_rearrange(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00139                                                 const array<size_t, L>& new_stride)
00140 {
00141         size_t new_len = (*new_sz.rbegin()) * (*new_stride.rbegin());
00142         if(new_len <= a.length() && !a.size().isequal(new_sz))
00143                 resize_rearrange_detail<typename array_nd<T, S>::is_resizeable>
00144                         ::operate(a, new_sz, new_stride);
00145 }
00146 
00147 template <class T, class S, class D, class L>
00148 void enlarge_rearrange(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00149                                                 const array<size_t, L>& new_stride, const T& pad)
00150 {
00151         if(a.ndims() > 0) {
00152                 size_t ldim = a.ndims() - 1;
00153                 size_t old_len = a.size_nd(ldim) * a.stride(ldim);
00154                 if(a.length() > old_len && old_len > 0)
00155                         resize_rearrange_detail<typename array_nd<T, S>::is_resizeable>
00156                                 ::operate(a, new_sz, new_stride, pad);
00157         }
00158 }
00159 
00160 template <class T, class S, class D, class L>
00161 void shrink_rearrange(array_nd<T, S>& a, const array<size_t, D>& new_sz,
00162                                                 const array<size_t, L>& new_stride, const T& pad)
00163 {
00164         size_t new_len = (*new_sz.rbegin()) * (*new_stride.rbegin());
00165         if(new_len <= a.length() && !a.size().isequal(new_sz))
00166                 resize_rearrange_detail<typename array_nd<T, S>::is_resizeable>
00167                         ::operate(a, new_sz, new_stride, pad);
00168 }
00169 } /* namespace array_nd_details */
00170 } /* namespace ivl */
00171 
00172 #endif // IVL_ARRAY_ND_DETAILS_COMMON_RESIZE_DETAILS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations