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 #ifndef IVL_MFUNC_PADARRAY 00026 #define IVL_MFUNC_PADARRAY 00027 00028 namespace ivl { 00029 00030 //------ padarray function stuff 00031 00033 enum padarray_direction 00034 { 00035 pre, // pad before the array elements 00036 post, // pad after the 00037 both // pad both sides 00038 }; 00039 00040 enum padarray_method { 00041 circular, 00042 replicate, 00043 symmetric 00044 }; 00045 00047 template<class T, class D> 00048 typename array_nd<T, D>::NewDerived padarray(const array_nd<T, D>& in, size_array sz, 00049 T padval = 0, padarray_direction dir = both) 00050 { 00051 // Constant pad 00052 size_t ndims = in.ndims(); 00053 if(sz.length() < ndims) // \todo fix this. resize does not keep contents... 00054 sz.resize(ndims, 0); 00055 00056 array<index_array> indx(ndims); 00057 size_array size_b(ndims); 00058 00059 for(size_t k = 0; k < ndims; k++) { 00060 00061 size_t m = in.size()[k]; 00062 00063 switch(dir) { 00064 00065 case pre: 00066 indx[k] = size_range(sz[k], sz[k] + m - 1); 00067 size_b[k] = m + sz[k]; 00068 break; 00069 00070 case post: 00071 indx[k] = size_range(0, m - 1); 00072 size_b[k] = m + sz[k]; 00073 break; 00074 00075 case both: 00076 indx[k] = size_range(sz[k], sz[k] + m - 1); 00077 size_b[k] = m + 2 * sz[k]; 00078 00079 } // switch(dir) 00080 } //for 00081 00082 typename array_nd<T, D>::NewDerived b(size_b, padval); 00083 b(indx) = in; 00084 return b; 00085 } 00086 00087 //---- padarray helper functions 00088 00089 namespace array_nd_details { 00090 00091 template <class T, class D> 00092 typename array_nd<T, D>::create_new circular_pad( 00093 const array_nd<T, D>& in, size_array sz, 00094 padarray_direction dir = both) 00095 { 00096 size_t ndims = in.ndims(); 00097 if(sz.length() < ndims) 00098 sz.resize(ndims, 0); 00099 00100 array<index_array> indx(ndims); 00101 size_t k; 00102 00103 for(k = 0; k < ndims; k++) { 00104 00105 size_t m = in.size()[k]; 00106 size_t p = sz[k]; 00107 00108 switch(dir) { 00109 00110 case pre: 00111 indx[k] = ivl::cast<size_t>(mod(array<int>( 00112 range<int>(-int(p), int(m) - 1)), int(m))); 00113 break; 00114 00115 case post: 00116 indx[k] = mod(size_array(ivl::rng(0, m + p - 1)), m); 00117 break; 00118 00119 case both: 00120 indx[k] = ivl::cast<size_t>(mod(array<int>( 00121 range<int>(-int(p), int(m) + int(p) - 1)), 00122 int(m))); 00123 00124 } //switch 00125 } //for 00126 00127 return typename array_nd<T, D>::create_new(in(indx)); 00128 } 00129 00130 // Does symmetric pad for padarray 00131 template <class T, class D> 00132 typename array_nd<T, D>::create_new symmetric_pad( 00133 const array_nd<T, D>& in, size_array sz, 00134 padarray_direction dir = both) 00135 { 00136 size_t ndims = in.ndims(); 00137 if(sz.length() < ndims) 00138 sz.resize(ndims, 0); 00139 00140 array<index_array> indx(ndims); 00141 size_t k; 00142 00143 for(k = 0; k < ndims; k++) { 00144 00145 size_t m = in.size()[k]; 00146 size_t p = sz[k]; 00147 00148 switch(dir) { 00149 00150 case pre: 00151 indx[k] = ivl::cast<size_t>(mod(array<int>( 00152 range<int>(-int(p), int(m) - 1)), 2 * int(m))); 00153 break; 00154 00155 case post: 00156 indx[k] = mod(size_array(rng(0, m + p - 1)), 2 * m); 00157 break; 00158 00159 case both: 00160 indx[k] = ivl::cast<size_t>(mod(array<int>( 00161 range<int>(-int(p), int(m) + int(p) - 1)), 00162 2 * int(m))); 00163 00164 } //switch 00165 00166 size_t idx_len = indx[k].length(); 00167 index_array& ia(indx[k]); 00168 00169 for(size_t j = 0; j < idx_len; j++) { 00170 if(ia[j] >= m) 00171 ia[j] = 2 * m - ia[j] - 1; 00172 } 00173 } //for 00174 00175 return typename array_nd<T, D>::create_new(in(indx)); 00176 } 00177 00178 template <class T, class D> 00179 typename array_nd<T, D>::create_new replicate_pad( 00180 const array_nd<T, D>& in, size_array sz, 00181 padarray_direction dir = both) 00182 { 00183 size_t ndims = in.ndims(); 00184 if(sz.length() < ndims) 00185 sz.resize(ndims, 0); 00186 00187 array<index_array> indx(ndims); 00188 size_t k; 00189 00190 for(k = 0; k < ndims; k++) { 00191 00192 size_t m = in.size()[k]; 00193 size_t p = sz[k]; 00194 index_array& ia(indx[k]); 00195 00196 switch(dir) { 00197 00198 case pre: 00199 indx[k] = size_array(p + m, size_t(0)); 00200 for(size_t j = 0; j < m; j++) 00201 ia[j + p] = j; 00202 break; 00203 00204 case post: 00205 indx[k] = size_array(p + m, m - 1); 00206 for(size_t j = 0; j < m; j++) 00207 ia[j] = j; 00208 break; 00209 00210 case both: 00211 indx[k] = size_array(2 * p + m, m - 1); 00212 for(size_t j = 0; j < p; j++) 00213 ia[j] = 0; 00214 for(size_t j = 0; j < m; j++) 00215 ia[j + p] = j; 00216 } //switch 00217 } //for 00218 00219 return typename array_nd<T, D>::create_new(in(indx)); 00220 } 00221 00222 }; //namespace array_nd_details 00223 00225 template <class T, class D> 00226 typename array_nd<T, D>::create_new padarray( 00227 const array_nd<T, D>& in, size_array sz, 00228 padarray_method mthd, padarray_direction dir = both) 00229 { 00230 using namespace array_nd_details; 00231 00232 switch(mthd) 00233 { 00234 case circular: 00235 return circular_pad(in, sz, dir); 00236 break; 00237 00238 case replicate: 00239 return replicate_pad(in, sz, dir); 00240 break; 00241 00242 case symmetric: 00243 return symmetric_pad(in, sz, dir); 00244 } //switch 00245 00246 CHECK(1, etype); 00247 return typename array_nd<T, D>::create_new(in);// used only for compiler 00248 } 00249 00250 } // namespace ivl 00251 00252 #endif // IVL_MFUNC_PADARRAY