LCOV - code coverage report
Current view: top level - synthesis/Utilities - FFT2D.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 273 319 85.6 %
Date: 2024-11-06 17:42:47 Functions: 18 19 94.7 %

          Line data    Source code
       1             : //# FFT2D.cc: implementation of FFT2D
       2             : //# Copyright (C) 2016
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU  General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU  General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be adressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //#
      27             : //# $kgolap$
      28             : //DEDICATED TO HONGLIN YE 
      29             : 
      30             : #include <casacore/casa/Arrays/ArrayMath.h>
      31             : #include <casacore/casa/Arrays/Array.h>
      32             : #include <casacore/casa/OS/HostInfo.h>
      33             : #include <synthesis/Utilities/FFT2D.h>
      34             : #include <casacore/lattices/Lattices/Lattice.h>
      35             : #ifdef _OPENMP
      36             : #include <omp.h>
      37             : #endif
      38             : using namespace casacore;
      39             : namespace casa { //# NAMESPACE CASA - BEGIN
      40             : 
      41             : // Utility function to try to give as much info as possible - CAS-12604
      42           0 : void throw_programmer_error(Long nx_p, Long ny_p, Long x, Long y, const char *file,
      43             :                             int line)
      44             : {
      45           0 :   AipsError exc;
      46           0 :   ostringstream msg;
      47           0 :   msg << "Programmer error: called FFT2D with wrong size. In " << file << ":" << line
      48           0 :       << ", with nx_p: " << nx_p << ", ny_p: " << ny_p << ", x: " << x << ", y: " << y
      49           0 :       << "\n Stack trace: " << exc.getStackTrace();
      50           0 :   exc.setMessage(msg.str());
      51           0 :   throw(exc);
      52           0 : }
      53             : 
      54        9641 :   FFT2D::FFT2D(Bool useFFTW):planC2C_forw_p(nullptr),planC2C_back_p(nullptr), planR2C_p(nullptr), planC2CD_forw_p(nullptr), planC2CD_back_p(nullptr),  useFFTW_p(useFFTW), wsave_p(0), lsav_p(0), nx_p(-1), ny_p(-1) {
      55        9641 :     if(useFFTW_p){
      56        9641 :       Int numThreads=HostInfo::numCPUs(true);
      57             : #ifdef _OPENMP
      58        9641 :       numThreads=omp_get_max_threads();
      59             : #endif      
      60        9641 :       fftwf_init_threads();
      61        9641 :       fftwf_plan_with_nthreads(numThreads);
      62             :       ///For double precision
      63        9641 :       fftw_init_threads();
      64        9641 :       fftw_plan_with_nthreads(numThreads);
      65             :     }
      66             :    
      67        9641 :   }
      68        9637 :   FFT2D::~FFT2D(){
      69        9637 :     if(useFFTW_p){
      70        9637 :       if(planC2CD_forw_p)
      71         142 :         fftw_destroy_plan(planC2CD_forw_p);
      72        9637 :       if(planC2C_forw_p)
      73         589 :         fftwf_destroy_plan(planC2C_forw_p);
      74        9637 :       if(planR2C_p)
      75          20 :          fftwf_destroy_plan(planR2C_p);
      76        9637 :       if(planC2CD_back_p)
      77        1356 :         fftw_destroy_plan(planC2CD_back_p);
      78        9637 :       if(planC2C_back_p)
      79         204 :         fftwf_destroy_plan(planC2C_back_p);
      80             :       ////Have to leak the cleanup part as it is thread unsafe to perform this, see CAS-12486
      81             :       // fftw_cleanup_threads();
      82             :       // fftw_cleanup();
      83             :       // fftwf_cleanup_threads();
      84             :       // fftwf_cleanup();
      85             : 
      86        9637 :       planC2CD_forw_p=nullptr;
      87        9637 :       planC2C_forw_p=nullptr;
      88        9637 :       planC2CD_back_p=nullptr;
      89        9637 :       planC2C_back_p=nullptr;
      90             :     }
      91        9637 :   }
      92             : 
      93        5666 :   FFT2D& FFT2D::operator=(const FFT2D& other){
      94        5666 :     if(this != &other){
      95             :       /*planC2C_forw_p=other.planC2C_forw_p;
      96             :       planR2C_p=other.planR2C_p;
      97             :       planC2CD_forw_p=other.planC2CD_forw_p;
      98             :       planC2C_back_p=other.planC2C_back_p;
      99             :       planC2CD_back_p=other.planC2CD_back_p;
     100             :       */
     101        5666 :       planC2C_forw_p=nullptr;
     102        5666 :       planR2C_p=nullptr;
     103        5666 :       planC2CD_forw_p=nullptr;
     104        5666 :       planC2C_back_p=nullptr;
     105        5666 :       planC2CD_back_p=nullptr;
     106             :       //cerr << "copy: planc2cd " <<  planC2CD_back_p << endl;
     107        5666 :       useFFTW_p=other.useFFTW_p;
     108        5666 :       wsave_p.resize(other.wsave_p.size());
     109        5666 :       wsave_p=other.wsave_p;
     110        5666 :       lsav_p=other.lsav_p;
     111        5666 :       nx_p=-1;
     112        5666 :       ny_p=-1;
     113             : 
     114             :     }
     115        5666 :     return *this;
     116             :   }
     117             : 
     118          20 :   void FFT2D::r2cFFT(Lattice<Complex>& out, Lattice<Float>& in){
     119             :     
     120          20 :     IPosition shp=in.shape();
     121          20 :     if(shp.nelements() <2)
     122           0 :       throw(AipsError("Lattice has to be 2 dimensional to use FFT2D"));
     123          20 :     Long x= in.shape()(0);
     124          20 :     Long y=in.shape()(1);
     125          20 :     if(out.shape()(0) < (x/2+1))
     126           0 :       throw(AipsError("out shape has to be x/2+1 in size  for real to complex FFT2D"));
     127          80 :     for(uInt k=1; k < shp.nelements(); ++k){
     128          60 :       if(shp(k) != out.shape()(k))
     129           0 :         throw(AipsError("shapes of out lattice does not match in lattice for FFT2D")); 
     130             :     }
     131          20 :     Long numplanes=shp.product()/x/y;
     132          20 :     IPosition blc(shp.nelements(), 0);
     133          20 :     IPosition shape=in.shape();
     134             :    
     135          60 :     for (uInt ax=2; ax < shp.nelements(); ++ax)
     136          40 :       shape(ax)=1;
     137          20 :     IPosition outshape=shape;
     138          20 :     outshape(0)=x/2+1;
     139             :  
     140          20 :     Array<Complex> arr;
     141          20 :     Array<Float> arrf;
     142             :     Bool isRef;
     143             :     Bool del;
     144             :     Bool delf;
     145             :     Complex *scr;
     146             :     Float *scrf;
     147             :     
     148             :     
     149             :     
     150          40 :     for (Long n=0; n< numplanes; ++n){
     151          20 :       isRef=out.getSlice(arr, blc, outshape); 
     152          20 :       scr=arr.getStorage(del);
     153             :       ///Use this method rather than arrf=in.getSlice(blc,shape) 
     154             :       ///as this may be a reference ..the other is a copy always...
     155             :       /// can gain 0.8s or so for a 10000x10000 array circa 2016
     156          20 :       in.getSlice( arrf, blc, shape);
     157          20 :       scrf=arrf.getStorage(delf);
     158          20 :       r2cFFT(scr, scrf, x, y);      
     159          20 :       arr.putStorage(scr, del);
     160          20 :       arrf.putStorage(scrf, delf);
     161             :       
     162          20 :       if(!isRef){
     163           0 :         out.putSlice(arr, blc);
     164             :         
     165             :       }
     166             :       //Now calculate next plane
     167             :        
     168          20 :       Bool addNextAx=true;
     169          60 :       for (uInt ax=2; ax < shp.nelements(); ++ax){
     170          40 :         if(addNextAx){
     171          40 :           blc(ax) +=1;
     172          40 :           addNextAx=false;
     173             :         }
     174          40 :         if(blc(ax)> shp(ax)-1){
     175          40 :           blc(ax)=0;
     176          40 :           addNextAx=true;
     177             :         }
     178             :        
     179             :       }
     180             :       
     181             :     }
     182          20 :   }
     183          20 :   void  FFT2D::r2cFFT(Complex*& out,  Float*& in, Long x, Long y){
     184          20 :     if(x%2 != 0 || y%2 != 0)
     185           0 :       throw(AipsError("Programmer error: FFT2D does not deal with odd numbers on x-y plane"));
     186          20 :     fftShift(in, x, y);
     187          20 :     doFFT(out, in, x, y);
     188             :     //fft1_p.plan_r2c(IPosition(2,x,y), in, out);
     189             :     //fft1_p.r2c(IPosition(2,x,y), in, out);
     190             :     //flipArray out is of shape x/2+1, y
     191          20 :     Complex* scr=out;
     192          20 :     Matrix<Complex> tmpo(x/2+1, y/2);
     193             :     Bool gool;
     194          20 :     Complex* tmpptr=tmpo.getStorage(gool);
     195          20 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     196             :     for (Long jj=0; jj< y/2; ++jj){
     197             :       for(Long ii=0; ii < (x/2+1); ++ii){
     198             :         tmpptr[jj*(x/2+1)+ii]=scr[jj*(x/2+1)+ii];
     199             :         scr[jj*(x/2+1)+ii]=scr[(y/2)*(x/2+1)+jj*(x/2+1)+ii];
     200             :       }
     201             :     }
     202          20 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     203             :         for (Long jj=0; jj< y/2; ++jj){
     204             :           for(Long ii=0; ii < x/2; ++ii){
     205             :             scr[(y/2)*(x/2+1)+jj*(x/2+1)+ii]=tmpptr[jj*(x/2+1)+ii];
     206             :           }
     207             :         } 
     208             : 
     209          20 :   }
     210        1084 :   void FFT2D::c2cFFT(Lattice<Complex>& inout, Bool toFreq){
     211        1084 :     IPosition shp=inout.shape();
     212        1084 :     if(shp.nelements() <2)
     213           0 :       throw(AipsError("Lattice has to be 2 dimensional to use FFT2D"));
     214        1084 :     Long x= inout.shape()(0);
     215        1084 :     Long y=inout.shape()(1);
     216        1084 :     Long numplanes=inout.shape().product()/x/y;
     217        1084 :     IPosition blc(inout.shape().nelements(), 0);
     218        1084 :     IPosition shape=inout.shape();
     219        3252 :     for (uInt ax=2; ax < shp.nelements(); ++ax)
     220        2168 :       shape(ax)=1;
     221        1084 :     Array<Complex> arr;
     222             :     Bool isRef;
     223             :     Bool del;
     224             :     Complex *scr;
     225             : 
     226        4733 :     for (Long n=0; n< numplanes; ++n){
     227        3649 :       isRef=inout.getSlice(arr, blc, shape); 
     228        3649 :       scr=arr.getStorage(del);
     229        3649 :       c2cFFT(scr, x, y, toFreq);
     230        3649 :       arr.putStorage(scr, del);
     231        3649 :       if(!isRef)
     232           0 :         inout.putSlice(arr, blc);
     233             :       //Now calculate next plane 
     234        3649 :       Bool addNextAx=true;
     235       10947 :       for (uInt ax=2; ax < shp.nelements(); ++ax){
     236        7298 :         if(addNextAx){
     237        7027 :           blc(ax) +=1;
     238        7027 :           addNextAx=false;
     239             :         }
     240        7298 :         if(blc(ax)> shp(ax)-1){
     241        4462 :           blc(ax)=0;
     242        4462 :           addNextAx=true;
     243             :         }
     244             :        
     245             :       }
     246             :     }
     247        1084 :   }
     248        1266 : void FFT2D::c2cFFTInDouble(Lattice<Complex>& inout, Bool toFreq){
     249        1266 :     IPosition shp=inout.shape();
     250        1266 :     if(shp.nelements() <2)
     251           0 :       throw(AipsError("Lattice has to be 2 dimensional to use FFT2D"));
     252        1266 :     Long x= inout.shape()(0);
     253        1266 :     Long y=inout.shape()(1);
     254        1266 :     Long numplanes=inout.shape().product()/x/y;
     255        1266 :     IPosition blc(inout.shape().nelements(), 0);
     256        1266 :     IPosition shape=inout.shape();
     257        3798 :     for (uInt ax=2; ax < shp.nelements(); ++ax)
     258        2532 :       shape(ax)=1;
     259        1266 :     Array<Complex> arr;
     260             :     Bool isRef;
     261             :     Bool del, delD;
     262             :     Complex *scr;
     263             :     DComplex *scrD;
     264        1266 :     Array<DComplex> arrD(shape);
     265        1266 :     scrD=arrD.getStorage(delD);
     266        2532 :     for (Long n=0; n< numplanes; ++n){
     267        1266 :       isRef=inout.getSlice(arr, blc, shape);
     268        1266 :       scr=arr.getStorage(del);
     269        1266 :       complexConvert(scrD, scr, (ooLong)shape(0)*(ooLong)shape(1), False); 
     270        1266 :       c2cFFT(scrD, x, y, toFreq);
     271        1266 :       complexConvert(scrD, scr, (ooLong)shape(0)*(ooLong)shape(1), True); 
     272        1266 :       arr.putStorage(scr, del);
     273        1266 :       if(!isRef)
     274           0 :         inout.putSlice(arr, blc);
     275             :       //Now calculate next plane 
     276        1266 :       Bool addNextAx=true;
     277        3798 :       for (uInt ax=2; ax < shp.nelements(); ++ax){
     278        2532 :         if(addNextAx){
     279        2532 :           blc(ax) +=1;
     280        2532 :           addNextAx=false;
     281             :         }
     282        2532 :         if(blc(ax)> shp(ax)-1){
     283        2532 :           blc(ax)=0;
     284        2532 :           addNextAx=true;
     285             :         }
     286             :        
     287             :       }
     288             :     }
     289        1266 :     arrD.putStorage(scrD, delD);
     290        1266 :   }
     291        2382 :   void FFT2D::c2cFFT(Lattice<DComplex>& inout, Bool toFreq){
     292        2382 :     IPosition shp=inout.shape();
     293        2382 :     if(shp.nelements() <2)
     294           0 :       throw(AipsError("Lattice has to be 2 dimensional to use FFT2D"));
     295        2382 :     Long x= inout.shape()(0);
     296        2382 :     Long y=inout.shape()(1);
     297        2382 :     Long numplanes=inout.shape().product()/x/y;
     298        2382 :     IPosition blc(inout.shape().nelements(), 0);
     299        2382 :     IPosition shape=inout.shape();
     300        7146 :     for (uInt ax=2; ax < shp.nelements(); ++ax)
     301        4764 :       shape(ax)=1;
     302        2382 :     Array<DComplex> arr;
     303             :     Bool isRef;
     304             :     Bool del;
     305             :     DComplex *scr;
     306             : 
     307       11195 :     for (Long n=0; n< numplanes; ++n){
     308        8813 :       isRef=inout.getSlice(arr, blc, shape); 
     309        8813 :       scr=arr.getStorage(del);
     310        8813 :       c2cFFT(scr, x, y, toFreq);
     311        8813 :       arr.putStorage(scr, del);
     312        8813 :       if(!isRef)
     313           0 :         inout.putSlice(arr, blc);
     314             :       //Now calculate next plane 
     315        8813 :       Bool addNextAx=true;
     316       26439 :       for (uInt ax=2; ax < shp.nelements(); ++ax){
     317       17626 :         if(addNextAx){
     318       16834 :           blc(ax) +=1;
     319       16834 :           addNextAx=false;
     320             :         }
     321       17626 :         if(blc(ax)> shp(ax)-1){
     322       10403 :           blc(ax)=0;
     323       10403 :           addNextAx=true;
     324             :         }
     325             :        
     326             :       }
     327             :     }
     328        2382 :   }
     329             : 
     330        3649 :   void FFT2D::c2cFFT(Complex*& out, Long x, Long y, Bool toFreq){
     331        3649 :     if(x%2 != 0 || y%2 !=0)
     332           0 :       throw(AipsError("Programmer error: FFT2D does not deal with odd numbers on x-y plane"));
     333        3649 :     fftShift(out, x, y, true);
     334        3649 :     doFFT(out, x, y, toFreq);
     335             :     /*Int dim[2]={Int(x), Int(y)};
     336             :     if(toFreq){
     337             :       
     338             :       planC2C_p=fftwf_plan_dft(2, dim,  reinterpret_cast<fftwf_complex *>(out),  reinterpret_cast<fftwf_complex *>(out), FFTW_FORWARD, FFTW_ESTIMATE);
     339             :       
     340             :       //fft1_p.plan_c2c_forward(IPosition(2, x, y),  out);
     341             :     }
     342             :     else{
     343             :        planC2C_p=fftwf_plan_dft(2, dim,  reinterpret_cast<fftwf_complex *>(out),  reinterpret_cast<fftwf_complex *>(out), FFTW_BACKWARD, FFTW_ESTIMATE);
     344             :       //  fft1_p.plan_c2c_backward(IPosition(2, x, y),  out);
     345             :     }
     346             :     fftwf_execute(planC2C_p);
     347             :     */
     348        3649 :     fftShift(out, x, y, toFreq);
     349             : 
     350        3649 :   }
     351       10079 :  void FFT2D::c2cFFT(DComplex*& out, Long x, Long y, Bool toFreq){
     352       10079 :     if(x%2 != 0 || y%2 !=0)
     353           0 :       throw(AipsError("Programmer error: FFT2D does not deal with odd numbers on x-y plane"));
     354       10079 :     fftShift(out, x, y, true);
     355       10079 :     doFFT(out, x, y, toFreq); 
     356       10079 :     fftShift(out, x, y, toFreq);
     357             : 
     358       10079 :   }
     359       10079 :   void FFT2D::doFFT(DComplex*& out, Long x, Long y, Bool toFreq){
     360       10079 :     if(useFFTW_p){
     361             :       //Will need to seperate the plan from the execute if we want to run this in multiple threads
     362       10079 :       Int dim[2]={Int(y), Int(x)};
     363       10079 :       if(toFreq){
     364        1266 :         if(!planC2CD_forw_p){
     365         143 :           planC2CD_forw_p=fftw_plan_dft(2, dim,  reinterpret_cast<fftw_complex *>(out),  reinterpret_cast<fftw_complex *>(out), FFTW_FORWARD, FFTW_ESTIMATE);
     366         143 :           fftw_execute(planC2CD_forw_p);
     367         143 :           nx_p=x;
     368         143 :           ny_p=y;
     369             :         }
     370             :         else{
     371        1123 :           if((nx_p != x) || (ny_p !=y)) {
     372           0 :             throw_programmer_error(nx_p, ny_p, x, y, __FILE__, __LINE__);
     373             :           }
     374        1123 :           fftw_execute_dft(planC2CD_forw_p,  reinterpret_cast<fftw_complex *>(out), reinterpret_cast<fftw_complex *>(out));
     375             :         }
     376             :         //fft1_p.plan_c2c_forward(IPosition(2, x, y),  out);
     377             :       }
     378             :       else{
     379        8813 :         if(!planC2CD_back_p){
     380        1356 :           planC2CD_back_p=fftw_plan_dft(2, dim,  reinterpret_cast<fftw_complex *>(out),  reinterpret_cast<fftw_complex *>(out), FFTW_BACKWARD, FFTW_ESTIMATE);
     381        1356 :           fftw_execute(planC2CD_back_p);
     382        1356 :           nx_p=x;
     383        1356 :           ny_p=y;
     384             :         }
     385             :         else{
     386        7457 :           if((nx_p != x) || (ny_p !=y)) {
     387           0 :             throw_programmer_error(nx_p, ny_p, x, y, __FILE__,  __LINE__);
     388             :           }
     389        7457 :           fftw_execute_dft(planC2CD_back_p,  reinterpret_cast<fftw_complex *>(out), reinterpret_cast<fftw_complex *>(out));
     390             :         }
     391             :         //  fft1_p.plan_c2c_backward(IPosition(2, x, y),  out);
     392             :       }
     393             :     }
     394             :     else{
     395           0 :       throw(AipsError("Double precision FFT with FFTPack is not implemented"));
     396             :     }
     397       10079 :   }
     398        3649 :    void FFT2D::doFFT(Complex*& out, Long x, Long y, Bool toFreq){
     399        3649 :     if(useFFTW_p){
     400             :       //Will need to seperate the plan from the execute if we want to run this in multiple threads
     401        3649 :       Int dim[2]={Int(y), Int(x)};
     402        3649 :       if(toFreq){
     403        3187 :         if(!planC2C_forw_p){
     404         591 :           planC2C_forw_p=fftwf_plan_dft(2, dim,  reinterpret_cast<fftwf_complex *>(out),  reinterpret_cast<fftwf_complex *>(out), FFTW_FORWARD, FFTW_ESTIMATE);
     405         591 :           fftwf_execute(planC2C_forw_p);
     406         591 :           nx_p=x;
     407         591 :           ny_p=y;
     408             :           
     409             :         }
     410             :         else{
     411        2596 :           if((nx_p != x) || (ny_p !=y))  {
     412           0 :             throw_programmer_error(nx_p, ny_p, x, y, __FILE__, __LINE__);
     413             :           }
     414        2596 :           fftwf_execute_dft(planC2C_forw_p, reinterpret_cast<fftwf_complex *>(out),  reinterpret_cast<fftwf_complex *>(out) );
     415             :         }
     416             :         //fft1_p.plan_c2c_forward(IPosition(2, x, y),  out);
     417             :       }
     418             :       else{
     419         462 :         if(!planC2C_back_p){
     420         206 :         planC2C_back_p=fftwf_plan_dft(2, dim,  reinterpret_cast<fftwf_complex *>(out),  reinterpret_cast<fftwf_complex *>(out), FFTW_BACKWARD, FFTW_ESTIMATE);
     421         206 :         fftwf_execute(planC2C_back_p);
     422         206 :         nx_p=x;
     423         206 :         ny_p=y;
     424             :         }
     425             :         else{
     426         256 :           if((nx_p != x) || (ny_p !=y)) {
     427           0 :             throw_programmer_error(nx_p, ny_p, x, y, __FILE__,  __LINE__);
     428             :           }
     429         256 :           fftwf_execute_dft(planC2C_back_p, reinterpret_cast<fftwf_complex *>(out),  reinterpret_cast<fftwf_complex *>(out) );
     430             :         }
     431             :         //  fft1_p.plan_c2c_backward(IPosition(2, x, y),  out);
     432             :       }
     433             :       
     434             :       
     435             :     }
     436             :     else{
     437             :       Int ier;
     438           0 :       Int x1=Int(x);
     439           0 :       Int y1=Int(y);
     440           0 :       if(wsave_p.size()==0){
     441           0 :         wsave_p.resize(2*x1*y1+15);
     442           0 :         lsav_p=2*x1*y1+15;
     443           0 :         Float *wsaveptr=wsave_p.data();
     444           0 :         FFTPack::cfft2i(x1, y1, wsaveptr, lsav_p, ier);
     445             :       }
     446           0 :       std::vector<Float> work(2*x1*y1);
     447           0 :       Int lenwrk=2*x1*y1;
     448           0 :       Float* workptr=work.data();
     449           0 :       Float* wsaveptr=wsave_p.data();
     450           0 :       if(toFreq)
     451           0 :         FFTPack::cfft2f(x1, x1, y1, out, wsaveptr, lsav_p, workptr, lenwrk, ier);
     452             :       else
     453           0 :         FFTPack::cfft2b(x1, x1, y1, out, wsaveptr, lsav_p, workptr, lenwrk, ier);
     454           0 :     }
     455        3649 :   }
     456          20 :   void FFT2D::doFFT(Complex*& out, Float*& in, Long x, Long y){
     457          20 :     if(useFFTW_p){
     458          20 :       Int dim[2]={Int(y), Int(x)};
     459          20 :       if(!planR2C_p){
     460          20 :         planR2C_p=fftwf_plan_dft_r2c(2, dim,  in, reinterpret_cast<fftwf_complex *>(out), FFTW_ESTIMATE);
     461             :       
     462             :       //fft1_p.plan_c2c_forward(IPosition(2, x, y),  out);
     463             :      
     464          20 :         fftwf_execute(planR2C_p);
     465          20 :         nx_p=x;
     466          20 :         ny_p=y;
     467             :       }
     468             :       else{
     469           0 :         if((nx_p != x) || (ny_p !=y)) {
     470           0 :             throw_programmer_error(nx_p, ny_p, x, y, __FILE__, __LINE__);
     471             :           }
     472           0 :         fftwf_execute_dft_r2c(planR2C_p,  in, reinterpret_cast<fftwf_complex *>(out));
     473             :       }
     474             :     }
     475             :     else{
     476             :       /*
     477             :       Int ier;
     478             :       Int x1=Int(x);
     479             :       Int y1=Int(y);
     480             :       if(wsave_p.size()==0){
     481             :         wsave_p.resize(2*x1*y1+15);
     482             :         lsav_p=2*x1*y1+15;
     483             :         Float *wsaveptr=wsave_p.data();
     484             :         FFTPack::cfft2i(x1, y1, wsaveptr, lsav_p, ier);
     485             :       }
     486             :       std::vector<Float> work(2*x1*y1);
     487             :       Int lenwrk=2*x1*y1;
     488             :       Float* workptr=work.data();
     489             :       Float* wsaveptr=wsave_p.data();
     490             :       if(toFreq)
     491             :         FFTPack::cfft2f(x1, y1, x1, out, wsaveptr, lsav_p, workptr, lenwrk, ier);
     492             :       else
     493             :         FFTPack::cfft2b(x1, y1, x1, out, wsaveptr, lsav_p, workptr, lenwrk, ier);
     494             :       */
     495           0 :       throw(AipsError("Not implemented FFTPack r2c yet"));
     496             :     }
     497          20 :   }
     498             : 
     499        7298 :   void FFT2D::fftShift(Complex*& s,  Long x, Long y, Bool toFreq){
     500             :     ////Lets try our own flip
     501             :     
     502             :     Bool gool;
     503        7298 :     Complex* scr=s;
     504             :     {
     505        7298 :       Matrix<Complex> tmpo(x/2, y/2);
     506        7298 :       Complex* tmpptr=tmpo.getStorage(gool);
     507             :       ////TEST
     508             :           //omp_set_num_threads(1);
     509             :           /////
     510             :           /*
     511             :             #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     512             :             for (Long jj=0; jj< y/2; ++jj){
     513             :             for(Long ii=0; ii < x/2; ++ii){
     514             :             tmpptr[jj*x/2+ii]=scr[(y/2-jj-1)*x+(x/2-ii-1)];
     515             :             scr[(y/2)*x+(jj*x+x/2)+ii]=scr[jj*x+ii];
     516             :             }
     517             :             }
     518             :           */
     519        7298 :       Float divid=1.0f;
     520        7298 :       if(!toFreq)
     521         462 :         divid=1.0f/(Float(x)*Float(y));
     522        7298 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr, divid)
     523             :       for (Long jj=0; jj< y/2; ++jj){
     524             :         for(Long ii=0; ii < x/2; ++ii){
     525             :           tmpptr[jj*x/2+ii]=scr[(y/2)*x+(jj*x+x/2)+ii]*divid;
     526             :           scr[(y/2)*x+(jj*x+x/2)+ii]=scr[jj*x+ii]*divid;
     527             :         }
     528             :       }
     529        7298 : #pragma omp parallel for default(none) firstprivate(x,y, tmpptr, scr)
     530             :           for (Long jj=0; jj< y/2; ++jj){
     531             :             for(Long ii=0; ii < x/2; ++ii){
     532             :               scr[jj*x+ii]=tmpptr[jj*x/2+ii];
     533             :             }
     534             :           }
     535        7298 : #pragma omp parallel for default(none) firstprivate(x,y, tmpptr, scr, divid)
     536             :           for (Long jj=0; jj< y/2; ++jj){
     537             :             for(Long ii=0; ii < x/2; ++ii){
     538             :               tmpptr[jj*x/2+ii]=scr[(jj*x+x/2)+ii]*divid;
     539             :               scr[(jj*x+x/2)+ii]=scr[(y/2)*x+jj*x+ii]*divid;
     540             :             }
     541             :           }
     542        7298 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     543             :           for (Long jj=0; jj< y/2; ++jj){
     544             :             for(Long ii=0; ii < x/2; ++ii){
     545             :               scr[(y/2)*x+jj*x+ii]=tmpptr[jj*x/2+ii];
     546             :             }
     547             :           }
     548        7298 :           tmpo.putStorage(tmpptr, gool);
     549        7298 :     }
     550             :     
     551             :     ////
     552             :     
     553             :     //if(rot)
     554             :     /*{
     555             :       
     556             :       Matrix<Complex> tmpo(x, y/2);
     557             :       Complex* tmpptr=tmpo.getStorage(gool);
     558             :       for (Long jj=0; jj< y/2; ++jj){
     559             :       for(Long ii=0; ii < x; ++ii){
     560             :       tmpptr[jj*x+ii]=scr[(y-jj-1)*x+(x-ii-1)];
     561             :       scr[(y-jj-1)*x+(x-ii-1)]=scr[jj*x+ii];
     562             :       }
     563             :       }
     564             :       for (Long jj=0; jj< y/2; ++jj){
     565             :       for(Long ii=0; ii < x; ++ii){
     566             :       scr[jj*x+ii]= tmpptr[jj*x+ii];
     567             :       }
     568             :       }
     569             :       }*/
     570             :     
     571             :     
     572             :     
     573             : 
     574        7298 :   }
     575             : 
     576       20158 : void FFT2D::fftShift(DComplex*& s,  Long x, Long y, Bool toFreq){
     577             :     ////Lets try our own flip
     578             :     
     579             :     Bool gool;
     580       20158 :     DComplex* scr=s;
     581             :     {
     582       20158 :       Matrix<DComplex> tmpo(x/2, y/2);
     583       20158 :       DComplex* tmpptr=tmpo.getStorage(gool);
     584             :       ////TEST
     585             :           //omp_set_num_threads(1);
     586             :           /////
     587             :           /*
     588             :             #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     589             :             for (Long jj=0; jj< y/2; ++jj){
     590             :             for(Long ii=0; ii < x/2; ++ii){
     591             :             tmpptr[jj*x/2+ii]=scr[(y/2-jj-1)*x+(x/2-ii-1)];
     592             :             scr[(y/2)*x+(jj*x+x/2)+ii]=scr[jj*x+ii];
     593             :             }
     594             :             }
     595             :           */
     596       20158 :       Double divid=1.0f;
     597       20158 :       if(!toFreq)
     598        8813 :         divid=1.0f/(Double(x)*Double(y));
     599       20158 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr, divid)
     600             :       for (Long jj=0; jj< y/2; ++jj){
     601             :         for(Long ii=0; ii < x/2; ++ii){
     602             :           tmpptr[jj*x/2+ii]=scr[(y/2)*x+(jj*x+x/2)+ii]*divid;
     603             :           scr[(y/2)*x+(jj*x+x/2)+ii]=scr[jj*x+ii]*divid;
     604             :         }
     605             :       }
     606       20158 : #pragma omp parallel for default(none) firstprivate(x,y, tmpptr, scr)
     607             :           for (Long jj=0; jj< y/2; ++jj){
     608             :             for(Long ii=0; ii < x/2; ++ii){
     609             :               scr[jj*x+ii]=tmpptr[jj*x/2+ii];
     610             :             }
     611             :           }
     612       20158 : #pragma omp parallel for default(none) firstprivate(x,y, tmpptr, scr, divid)
     613             :           for (Long jj=0; jj< y/2; ++jj){
     614             :             for(Long ii=0; ii < x/2; ++ii){
     615             :               tmpptr[jj*x/2+ii]=scr[(jj*x+x/2)+ii]*divid;
     616             :               scr[(jj*x+x/2)+ii]=scr[(y/2)*x+jj*x+ii]*divid;
     617             :             }
     618             :           }
     619       20158 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     620             :           for (Long jj=0; jj< y/2; ++jj){
     621             :             for(Long ii=0; ii < x/2; ++ii){
     622             :               scr[(y/2)*x+jj*x+ii]=tmpptr[jj*x/2+ii];
     623             :             }
     624             :           }
     625       20158 :           tmpo.putStorage(tmpptr, gool);
     626       20158 :     }
     627             :     
     628             :     ////
     629             :     
     630             :     //if(rot)
     631             :     /*{
     632             :       
     633             :       Matrix<Complex> tmpo(x, y/2);
     634             :       Complex* tmpptr=tmpo.getStorage(gool);
     635             :       for (Long jj=0; jj< y/2; ++jj){
     636             :       for(Long ii=0; ii < x; ++ii){
     637             :       tmpptr[jj*x+ii]=scr[(y-jj-1)*x+(x-ii-1)];
     638             :       scr[(y-jj-1)*x+(x-ii-1)]=scr[jj*x+ii];
     639             :       }
     640             :       }
     641             :       for (Long jj=0; jj< y/2; ++jj){
     642             :       for(Long ii=0; ii < x; ++ii){
     643             :       scr[jj*x+ii]= tmpptr[jj*x+ii];
     644             :       }
     645             :       }
     646             :       }*/
     647             :     
     648             :     
     649             :     
     650             : 
     651       20158 :   }
     652          20 :   void FFT2D::fftShift(Float*& s,  Long x, Long y){
     653             :     ////Lets try our own flip
     654             :       
     655             :     Bool gool;
     656          20 :     Float* scr=s;
     657          20 :     Matrix<Float> tmpo(x/2, y/2);
     658          20 :     Float* tmpptr=tmpo.getStorage(gool);
     659             :     ////TEST
     660             :     //omp_set_num_threads(1);
     661             :     /////
     662          20 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     663             :     for (Long jj=0; jj< y/2; ++jj){
     664             :       for(Long ii=0; ii < x/2; ++ii){
     665             :         tmpptr[jj*x/2+ii]=scr[(y/2)*x+(jj*x+x/2)+ii];
     666             :         scr[(y/2)*x+(jj*x+x/2)+ii]=scr[jj*x+ii];
     667             :       }
     668             :     }
     669          20 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     670             :     for (Long jj=0; jj< y/2; ++jj){
     671             :       for(Long ii=0; ii < x/2; ++ii){
     672             :         scr[jj*x+ii]=tmpptr[jj*x/2+ii];
     673             :       }
     674             :     }
     675          20 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     676             :     for (Long jj=0; jj< y/2; ++jj){
     677             :       for(Long ii=0; ii < x/2; ++ii){
     678             :         tmpptr[jj*x/2+ii]=scr[(jj*x+x/2)+ii];
     679             :         scr[(jj*x+x/2)+ii]=scr[(y/2)*x+jj*x+ii];
     680             :       }
     681             :     }
     682          20 : #pragma omp parallel for default(none) firstprivate(x, y, tmpptr, scr)
     683             :     for (Long jj=0; jj< y/2; ++jj){
     684             :       for(Long ii=0; ii < x/2; ++ii){
     685             :         scr[(y/2)*x+jj*x+ii]=tmpptr[jj*x/2+ii];
     686             :       }
     687             :     }
     688             :     
     689             : 
     690             :     
     691          20 :   }
     692        2532 :   void FFT2D::complexConvert(DComplex*& scrD, Complex*& scr,  const ooLong len, const Bool down){
     693        2532 :     if(down){
     694   899158770 :       for(ooLong k=0; k< len; ++k){
     695   899157504 :         scr[k]=(Complex)(scrD[k]);
     696             :       }
     697             :     }
     698             :     else{
     699   899158770 :       for(ooLong k=0; k< len; ++k){
     700   899157504 :         scrD[k]=(DComplex)(scr[k]);
     701             :       }
     702             :     }
     703        2532 :   }
     704         633 :   std::tuple<Long, Long> FFT2D::getShape() { 
     705             :       
     706         633 :       return std::make_tuple(nx_p, ny_p); 
     707             :   }
     708             :   
     709             : 
     710             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16