annotate armadillo-3.900.4/include/armadillo_bits/op_fft_meat.hpp @ 84:55a047986812 tip

Update library URI so as not to be document-local
author Chris Cannam
date Wed, 22 Apr 2020 14:21:57 +0100
parents 1ec0e2823891
children
rev   line source
Chris@49 1 // Copyright (C) 2013 Conrad Sanderson
Chris@49 2 // Copyright (C) 2013 NICTA (www.nicta.com.au)
Chris@49 3 //
Chris@49 4 // This Source Code Form is subject to the terms of the Mozilla Public
Chris@49 5 // License, v. 2.0. If a copy of the MPL was not distributed with this
Chris@49 6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
Chris@49 7
Chris@49 8
Chris@49 9
Chris@49 10 //! \addtogroup op_fft
Chris@49 11 //! @{
Chris@49 12
Chris@49 13
Chris@49 14
Chris@49 15 //
Chris@49 16 // op_fft_real
Chris@49 17
Chris@49 18
Chris@49 19
Chris@49 20 template<typename T1>
Chris@49 21 inline
Chris@49 22 void
Chris@49 23 op_fft_real::apply( Mat< std::complex<typename T1::pod_type> >& out, const mtOp<std::complex<typename T1::pod_type>,T1,op_fft_real>& in )
Chris@49 24 {
Chris@49 25 arma_extra_debug_sigprint();
Chris@49 26
Chris@49 27 typedef typename T1::pod_type in_eT;
Chris@49 28 typedef typename std::complex<in_eT> out_eT;
Chris@49 29
Chris@49 30 const Proxy<T1> P(in.m);
Chris@49 31
Chris@49 32 const uword n_rows = P.get_n_rows();
Chris@49 33 const uword n_cols = P.get_n_cols();
Chris@49 34 const uword n_elem = P.get_n_elem();
Chris@49 35
Chris@49 36 const bool is_vec = ( (n_rows == 1) || (n_cols == 1) );
Chris@49 37
Chris@49 38 const uword N_orig = (is_vec) ? n_elem : n_rows;
Chris@49 39 const uword N_user = (in.aux_uword_b == 0) ? in.aux_uword_a : N_orig;
Chris@49 40
Chris@49 41 fft_engine<out_eT,false> worker(N_user);
Chris@49 42
Chris@49 43 // no need to worry about aliasing, as we're going from a real object to complex complex, which by definition cannot alias
Chris@49 44
Chris@49 45 if(is_vec)
Chris@49 46 {
Chris@49 47 (n_cols == 1) ? out.set_size(N_user, 1) : out.set_size(1, N_user);
Chris@49 48
Chris@49 49 if( (out.n_elem == 0) || (N_orig == 0) )
Chris@49 50 {
Chris@49 51 out.zeros();
Chris@49 52 return;
Chris@49 53 }
Chris@49 54
Chris@49 55 if( (N_user == 1) && (N_orig >= 1) )
Chris@49 56 {
Chris@49 57 out[0] = out_eT( P[0] );
Chris@49 58 return;
Chris@49 59 }
Chris@49 60
Chris@49 61 podarray<out_eT> data(N_user);
Chris@49 62
Chris@49 63 out_eT* data_mem = data.memptr();
Chris@49 64
Chris@49 65 if(N_user > N_orig) { arrayops::inplace_set( &data_mem[N_orig], out_eT(0), (N_user - N_orig) ); }
Chris@49 66
Chris@49 67 const uword N = (std::min)(N_user, N_orig);
Chris@49 68
Chris@49 69 if(Proxy<T1>::prefer_at_accessor == false)
Chris@49 70 {
Chris@49 71 typename Proxy<T1>::ea_type X = P.get_ea();
Chris@49 72
Chris@49 73 for(uword i=0; i < N; ++i) { data_mem[i] = out_eT( X[i], in_eT(0) ); }
Chris@49 74 }
Chris@49 75 else
Chris@49 76 {
Chris@49 77 if(n_cols == 1)
Chris@49 78 {
Chris@49 79 for(uword i=0; i < N; ++i) { data_mem[i] = out_eT( P.at(i,0), in_eT(0) ); }
Chris@49 80 }
Chris@49 81 else
Chris@49 82 {
Chris@49 83 for(uword i=0; i < N; ++i) { data_mem[i] = out_eT( P.at(0,i), in_eT(0) ); }
Chris@49 84 }
Chris@49 85 }
Chris@49 86
Chris@49 87 worker.run( out.memptr(), data_mem );
Chris@49 88 }
Chris@49 89 else
Chris@49 90 {
Chris@49 91 // process each column seperately
Chris@49 92
Chris@49 93 out.set_size(N_user, n_cols);
Chris@49 94
Chris@49 95 if( (out.n_elem == 0) || (N_orig == 0) )
Chris@49 96 {
Chris@49 97 out.zeros();
Chris@49 98 return;
Chris@49 99 }
Chris@49 100
Chris@49 101 if( (N_user == 1) && (N_orig >= 1) )
Chris@49 102 {
Chris@49 103 for(uword col=0; col < n_cols; ++col) { out.at(0,col) = out_eT( P.at(0,col) ); }
Chris@49 104
Chris@49 105 return;
Chris@49 106 }
Chris@49 107
Chris@49 108 podarray<out_eT> data(N_user);
Chris@49 109
Chris@49 110 out_eT* data_mem = data.memptr();
Chris@49 111
Chris@49 112 if(N_user > N_orig) { arrayops::inplace_set( &data_mem[N_orig], out_eT(0), (N_user - N_orig) ); }
Chris@49 113
Chris@49 114 const uword N = (std::min)(N_user, N_orig);
Chris@49 115
Chris@49 116 for(uword col=0; col < n_cols; ++col)
Chris@49 117 {
Chris@49 118 for(uword i=0; i < N; ++i) { data_mem[i] = P.at(i, col); }
Chris@49 119
Chris@49 120 worker.run( out.colptr(col), data_mem );
Chris@49 121 }
Chris@49 122 }
Chris@49 123 }
Chris@49 124
Chris@49 125
Chris@49 126
Chris@49 127 //
Chris@49 128 // op_fft_cx
Chris@49 129
Chris@49 130
Chris@49 131 template<typename T1>
Chris@49 132 inline
Chris@49 133 void
Chris@49 134 op_fft_cx::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_fft_cx>& in)
Chris@49 135 {
Chris@49 136 arma_extra_debug_sigprint();
Chris@49 137
Chris@49 138 typedef typename T1::elem_type eT;
Chris@49 139
Chris@49 140 const Proxy<T1> P(in.m);
Chris@49 141
Chris@49 142 if(P.is_alias(out) == false)
Chris@49 143 {
Chris@49 144 op_fft_cx::apply_noalias<T1,false>(out, P, in.aux_uword_a, in.aux_uword_b);
Chris@49 145 }
Chris@49 146 else
Chris@49 147 {
Chris@49 148 Mat<eT> tmp;
Chris@49 149
Chris@49 150 op_fft_cx::apply_noalias<T1,false>(tmp, P, in.aux_uword_a, in.aux_uword_b);
Chris@49 151
Chris@49 152 out.steal_mem(tmp);
Chris@49 153 }
Chris@49 154 }
Chris@49 155
Chris@49 156
Chris@49 157
Chris@49 158 template<typename T1, bool inverse>
Chris@49 159 inline
Chris@49 160 void
Chris@49 161 op_fft_cx::apply_noalias(Mat<typename T1::elem_type>& out, const Proxy<T1>& P, const uword a, const uword b)
Chris@49 162 {
Chris@49 163 arma_extra_debug_sigprint();
Chris@49 164
Chris@49 165 typedef typename T1::elem_type eT;
Chris@49 166
Chris@49 167 const uword n_rows = P.get_n_rows();
Chris@49 168 const uword n_cols = P.get_n_cols();
Chris@49 169 const uword n_elem = P.get_n_elem();
Chris@49 170
Chris@49 171 const bool is_vec = ( (n_rows == 1) || (n_cols == 1) );
Chris@49 172
Chris@49 173 const uword N_orig = (is_vec) ? n_elem : n_rows;
Chris@49 174 const uword N_user = (b == 0) ? a : N_orig;
Chris@49 175
Chris@49 176 fft_engine<eT,inverse> worker(N_user);
Chris@49 177
Chris@49 178 if(is_vec)
Chris@49 179 {
Chris@49 180 (n_cols == 1) ? out.set_size(N_user, 1) : out.set_size(1, N_user);
Chris@49 181
Chris@49 182 if( (out.n_elem == 0) || (N_orig == 0) )
Chris@49 183 {
Chris@49 184 out.zeros();
Chris@49 185 return;
Chris@49 186 }
Chris@49 187
Chris@49 188 if( (N_user == 1) && (N_orig >= 1) )
Chris@49 189 {
Chris@49 190 out[0] = P[0];
Chris@49 191 return;
Chris@49 192 }
Chris@49 193
Chris@49 194 if( (N_user > N_orig) || (is_Mat<typename Proxy<T1>::stored_type>::value == false) )
Chris@49 195 {
Chris@49 196 podarray<eT> data(N_user);
Chris@49 197
Chris@49 198 eT* data_mem = data.memptr();
Chris@49 199
Chris@49 200 if(N_user > N_orig) { arrayops::inplace_set( &data_mem[N_orig], eT(0), (N_user - N_orig) ); }
Chris@49 201
Chris@49 202 op_fft_cx::copy_vec( data_mem, P, (std::min)(N_user, N_orig) );
Chris@49 203
Chris@49 204 worker.run( out.memptr(), data_mem );
Chris@49 205 }
Chris@49 206 else
Chris@49 207 {
Chris@49 208 const unwrap< typename Proxy<T1>::stored_type > tmp(P.Q);
Chris@49 209
Chris@49 210 worker.run( out.memptr(), tmp.M.memptr() );
Chris@49 211 }
Chris@49 212 }
Chris@49 213 else
Chris@49 214 {
Chris@49 215 // process each column seperately
Chris@49 216
Chris@49 217 out.set_size(N_user, n_cols);
Chris@49 218
Chris@49 219 if( (out.n_elem == 0) || (N_orig == 0) )
Chris@49 220 {
Chris@49 221 out.zeros();
Chris@49 222 return;
Chris@49 223 }
Chris@49 224
Chris@49 225 if( (N_user == 1) && (N_orig >= 1) )
Chris@49 226 {
Chris@49 227 for(uword col=0; col < n_cols; ++col) { out.at(0,col) = P.at(0,col); }
Chris@49 228
Chris@49 229 return;
Chris@49 230 }
Chris@49 231
Chris@49 232 if( (N_user > N_orig) || (is_Mat<typename Proxy<T1>::stored_type>::value == false) )
Chris@49 233 {
Chris@49 234 podarray<eT> data(N_user);
Chris@49 235
Chris@49 236 eT* data_mem = data.memptr();
Chris@49 237
Chris@49 238 if(N_user > N_orig) { arrayops::inplace_set( &data_mem[N_orig], eT(0), (N_user - N_orig) ); }
Chris@49 239
Chris@49 240 const uword N = (std::min)(N_user, N_orig);
Chris@49 241
Chris@49 242 for(uword col=0; col < n_cols; ++col)
Chris@49 243 {
Chris@49 244 for(uword i=0; i < N; ++i) { data_mem[i] = P.at(i, col); }
Chris@49 245
Chris@49 246 worker.run( out.colptr(col), data_mem );
Chris@49 247 }
Chris@49 248 }
Chris@49 249 else
Chris@49 250 {
Chris@49 251 const unwrap< typename Proxy<T1>::stored_type > tmp(P.Q);
Chris@49 252
Chris@49 253 for(uword col=0; col < n_cols; ++col)
Chris@49 254 {
Chris@49 255 worker.run( out.colptr(col), tmp.M.colptr(col) );
Chris@49 256 }
Chris@49 257 }
Chris@49 258 }
Chris@49 259
Chris@49 260
Chris@49 261 // correct the scaling for the inverse transform
Chris@49 262 if(inverse == true)
Chris@49 263 {
Chris@49 264 typedef typename get_pod_type<eT>::result T;
Chris@49 265
Chris@49 266 const T k = T(1) / T(N_user);
Chris@49 267
Chris@49 268 eT* out_mem = out.memptr();
Chris@49 269
Chris@49 270 const uword out_n_elem = out.n_elem;
Chris@49 271
Chris@49 272 for(uword i=0; i < out_n_elem; ++i) { out_mem[i] *= k; }
Chris@49 273 }
Chris@49 274 }
Chris@49 275
Chris@49 276
Chris@49 277
Chris@49 278 template<typename T1>
Chris@49 279 arma_hot
Chris@49 280 inline
Chris@49 281 void
Chris@49 282 op_fft_cx::copy_vec(typename Proxy<T1>::elem_type* dest, const Proxy<T1>& P, const uword N)
Chris@49 283 {
Chris@49 284 arma_extra_debug_sigprint();
Chris@49 285
Chris@49 286 if(is_Mat< typename Proxy<T1>::stored_type >::value == true)
Chris@49 287 {
Chris@49 288 op_fft_cx::copy_vec_unwrap(dest, P, N);
Chris@49 289 }
Chris@49 290 else
Chris@49 291 {
Chris@49 292 op_fft_cx::copy_vec_proxy(dest, P, N);
Chris@49 293 }
Chris@49 294 }
Chris@49 295
Chris@49 296
Chris@49 297
Chris@49 298 template<typename T1>
Chris@49 299 arma_hot
Chris@49 300 inline
Chris@49 301 void
Chris@49 302 op_fft_cx::copy_vec_unwrap(typename Proxy<T1>::elem_type* dest, const Proxy<T1>& P, const uword N)
Chris@49 303 {
Chris@49 304 arma_extra_debug_sigprint();
Chris@49 305
Chris@49 306 const unwrap< typename Proxy<T1>::stored_type > tmp(P.Q);
Chris@49 307
Chris@49 308 arrayops::copy(dest, tmp.M.memptr(), N);
Chris@49 309 }
Chris@49 310
Chris@49 311
Chris@49 312
Chris@49 313 template<typename T1>
Chris@49 314 arma_hot
Chris@49 315 inline
Chris@49 316 void
Chris@49 317 op_fft_cx::copy_vec_proxy(typename Proxy<T1>::elem_type* dest, const Proxy<T1>& P, const uword N)
Chris@49 318 {
Chris@49 319 arma_extra_debug_sigprint();
Chris@49 320
Chris@49 321 if(Proxy<T1>::prefer_at_accessor == false)
Chris@49 322 {
Chris@49 323 typename Proxy<T1>::ea_type X = P.get_ea();
Chris@49 324
Chris@49 325 for(uword i=0; i < N; ++i) { dest[i] = X[i]; }
Chris@49 326 }
Chris@49 327 else
Chris@49 328 {
Chris@49 329 if(P.get_n_cols() == 1)
Chris@49 330 {
Chris@49 331 for(uword i=0; i < N; ++i) { dest[i] = P.at(i,0); }
Chris@49 332 }
Chris@49 333 else
Chris@49 334 {
Chris@49 335 for(uword i=0; i < N; ++i) { dest[i] = P.at(0,i); }
Chris@49 336 }
Chris@49 337 }
Chris@49 338 }
Chris@49 339
Chris@49 340
Chris@49 341
Chris@49 342 //
Chris@49 343 // op_ifft_cx
Chris@49 344
Chris@49 345
Chris@49 346 template<typename T1>
Chris@49 347 inline
Chris@49 348 void
Chris@49 349 op_ifft_cx::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_ifft_cx>& in)
Chris@49 350 {
Chris@49 351 arma_extra_debug_sigprint();
Chris@49 352
Chris@49 353 typedef typename T1::elem_type eT;
Chris@49 354
Chris@49 355 const Proxy<T1> P(in.m);
Chris@49 356
Chris@49 357 if(P.is_alias(out) == false)
Chris@49 358 {
Chris@49 359 op_fft_cx::apply_noalias<T1,true>(out, P, in.aux_uword_a, in.aux_uword_b);
Chris@49 360 }
Chris@49 361 else
Chris@49 362 {
Chris@49 363 Mat<eT> tmp;
Chris@49 364
Chris@49 365 op_fft_cx::apply_noalias<T1,true>(tmp, P, in.aux_uword_a, in.aux_uword_b);
Chris@49 366
Chris@49 367 out.steal_mem(tmp);
Chris@49 368 }
Chris@49 369 }
Chris@49 370
Chris@49 371
Chris@49 372
Chris@49 373 //! @}