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