/* GridFlow Copyright (c) 2001-2011 by Mathieu Bouchard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See file ../COPYING for further informations on licensing terms. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gridflow.hxx.fcs" #include #define C(x) ((fftwf_complex *)x) \class GridFFT { fftwf_plan plan; Dim lastdim; /* of last input (for plan cache) */ bool haslastdim; long lastchans; /* of last input (for plan cache) */ \attr int sign; /* -1 or +1 */ \attr int skip; /* 0 (y and x) or 1 (x only) */ \attr bool real; bool lastreal; \constructor () {sign=-1; plan=0; haslastdim=false; lastchans=0; skip=0; real=false;} \grin 0 float32 }; \def 0 sign (int sign) { if (sign!=-1 && sign!=1) RAISE("sign should be -1 or +1"); this->sign=sign; fftwf_destroy_plan(plan); } \def 0 skip (int skip) { if (skip<0 || skip>1) RAISE("skip should be 0 or 1"); this->skip=skip; if (plan) {fftwf_destroy_plan(plan); plan=0;} } GRID_INLET(0) { if (in.nt != float32_e) RAISE("expecting float32"); if (real && sign==-1) { if (in.dim.n != 2 && in.dim.n != 3) RAISE("expecting 2 or 3 dimensions: rows,columns,channels?"); } else { if (in.dim.n != 3 && in.dim.n != 4) RAISE("expecting 3 or 4 dimensions: rows,columns,channels?,complex"); if (in.dim[in.dim.n-1]!=2) RAISE("expecting Dim(...,2): real,imaginary (got %d)",in.dim[2]); } in.set_chunk(0); } GRID_FLOW { if (skip==1 && real) RAISE("can't do 1-D FFT in real mode, sorry"); Dim dim; if (!real) dim = in.dim; else if (sign==-1) { int v[Dim::MAX_DIM]; for (int i=0; i=3 ? in.dim[2] : 1; CHECK_ALIGN16(data,in.nt) CHECK_ALIGN16(tada,in.nt) if (plan && haslastdim && lastdim != in.dim && chans!=lastchans && real==lastreal) {fftwf_destroy_plan(plan); plan=0;} int v[] = {in.dim[0],in.dim[1],in.dim.n>2?in.dim[2]:1}; // if (chans==1) { // if (skip==0) plan = fftwf_plan_dft_2d(v[0],v[1],data,tada,sign,0); // if (skip==1) plan = fftwf_plan_many_dft(1,&v[1],v[0],data,0,1,v[1],tada,0,1,v[1],sign,0); // } if (skip==0) { //plan = fftwf_plan_dft_2d(v[0],v[1],data,tada,sign,0); if (!plan) { int embed[] = {dim[0],dim[1]}; if (!real) {plan=fftwf_plan_many_dft( 2,&v[0],chans,C(data),0 ,chans,1,C(tada),0 ,chans,1,sign,0);} else if (sign==-1) {plan=fftwf_plan_many_dft_r2c(2,&v[0],chans, data ,embed,chans,1,C(tada),embed,chans,1,0);} else {plan=fftwf_plan_many_dft_c2r(2,&v[0],chans,C(data),embed,chans,1, tada ,embed,chans,1,0);} } if (!real) fftwf_execute_dft( plan,C(data),C(tada)); else if (sign==-1) fftwf_execute_dft_r2c(plan, data ,C(tada)); else fftwf_execute_dft_c2r(plan,C(data), tada ); } if (skip==1) { if (!plan) plan=fftwf_plan_many_dft(1,&v[1],chans,C(data),0,chans,1,C(tada),0,chans,1,sign,0); //plan = fftwf_plan_many_dft(1,&v[1],v[0],C(data),0,1,v[1],C(tada),0,1,v[1],sign,0); long incr = v[1]*chans; for (int i=0; i