static void LTFAT_NAME(dctMexAtExitFnc)()
{
    if (LTFAT_NAME(p_old) != 0)
    {
        LTFAT_FFTW(destroy_plan)(LTFAT_NAME(p_old));
    }
}
示例#2
0
void LTFAT_NAME(fftrealAtExit)()
{
   if(LTFAT_NAME(p_old)!=0)
   {
     LTFAT_FFTW(destroy_plan)(LTFAT_NAME(p_old));
   }
}
示例#3
0
文件: memalloc.c 项目: ltfat/ltfat
LTFAT_API void
ltfat_free(const void* ptr)
{
    if (ltfat_custom_free)
        (*ltfat_custom_free)((void*)ptr);
    else
#ifdef FFTW
        LTFAT_FFTW(free)((void*)ptr);
#elif KISS
        ltfat_aligned_free((void*)ptr);
#endif
}
示例#4
0
文件: memalloc.c 项目: ltfat/ltfat
LTFAT_API void*
ltfat_malloc (size_t n)
{
    void* outp;

    if (ltfat_custom_malloc)
        outp = (*ltfat_custom_malloc)(n);
    else
#ifdef FFTW
        outp = LTFAT_FFTW(malloc)(n);
#elif KISS
        outp = ltfat_aligned_malloc(n);
#else
#error "No FFT backend specified. Use -DKISS or -DFFTW"
#endif
    return outp;
}
示例#5
0
void LTFAT_NAME(ltfatMexFnc)( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[] )
{
  #ifdef LTFAT_DOUBLE
  if(p_old==0)
  {
      mexAtExit(ifftrealAtExit);
  }
  #endif
  mwSize ii, L, W, L2;
  LTFAT_FFTW(plan) p;
  LTFAT_REAL *f, s;
  LTFAT_REAL *fin_r, *fin_i;


  L2 = (mwSize) mxGetM(prhs[0]);
  W  = (mwSize) mxGetN(prhs[0]);
  L  = (mwSize) mxGetScalar(prhs[1]);


  if(L/2+1!=L2)
    mexErrMsgTxt("Invalid output length");

  fin_r = (LTFAT_REAL*)mxGetPr(prhs[0]);
  fin_i = (LTFAT_REAL*)mxGetPi(prhs[0]);
  // Case when input is real
  if(!mxIsComplex(prhs[0]))
  {
    mxArray* tmpIn = ltfatCreateMatrix(L2, W, LTFAT_MX_CLASSID , mxCOMPLEX);
    LTFAT_REAL *fin_r_old = (LTFAT_REAL*)mxGetPr(prhs[0]);
    fin_r = (LTFAT_REAL*)mxGetPr(tmpIn);
    fin_i = (LTFAT_REAL*)mxGetPi(tmpIn);
    for(mwIndex jj=0;jj<L2*W;jj++)
    {
        fin_r[jj]= fin_r_old[jj];
        fin_i[jj]= (LTFAT_REAL )0.0;
    }
  }

  // Create output and get pointer
  plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID , mxREAL);
  f= (LTFAT_REAL*) mxGetPr(plhs[0]);

  // This section is not being compiled. It contains a segmentation
  // faults. The idea is to pass Matlab's split memory layout directly
  // to FFTW

  LTFAT_FFTW(iodim) dims[1], howmanydims[1];

  // Create plan. Copy data from cin to f.
  dims[0].n = L;
  dims[0].is = 1;
  dims[0].os = 1;

  howmanydims[0].n = W;
  howmanydims[0].is = L2;
  howmanydims[0].os = L;

  // The calling prototype

  // fftw_plan fftw_plan_guru_split_dft_c2r(
  //        int rank, const fftw_iodim *dims,
  //        int howmany_rank, const fftw_iodim *howmany_dims,
  //        double *ri, double *ii, double *out,
  //        unsigned flags);


  p = LTFAT_FFTW(plan_guru_split_dft_c2r)(1, dims,
				   1, howmanydims,
				   fin_r,fin_i,f, FFTW_OPTITYPE);

  if(p_old!=0)
  {
    fftw_destroy_plan(*p_old);
    free(p_old);
  }
  p_old = malloc(sizeof(p));
  memcpy(p_old,&p,sizeof(p));


  // Real IFFT.
  LTFAT_FFTW(execute)(p);

  //LTFAT_FFTW(destroy_plan)(p);

  // Scale, because FFTW's normalization is different.
  s  = (LTFAT_REAL) (1.0/((LTFAT_REAL)L));
  for (ii=0; ii<L*W; ii++)
    {
      f[ii] *=s;
    }

  return;
}
示例#6
0
LTFAT_EXTERN void
LTFAT_NAME(idgt_fb)(const LTFAT_COMPLEX *cin, const LTFAT_COMPLEX *g,
			 const int L, const int gl, const int W,
			 const int a, const int M,
			 LTFAT_COMPLEX *f)

{ 
  /*  --------- initial declarations -------------- */

   const int N=L/a;

   int ep, sp;

   /* This is a floor operation. */
   const int glh=gl/2;

   /* This is a ceil operation. */
   const int glh_d_a=(int)ceil((glh*1.0)/(a));
   LTFAT_COMPLEX *fw;

   LTFAT_COMPLEX *cbuf = (LTFAT_COMPLEX*)ltfat_malloc(M*sizeof(LTFAT_COMPLEX));

   /* Create plan. In-place. */
   LTFAT_FFTW(plan) p_small = LTFAT_FFTW(plan_dft_1d)(M, cbuf, cbuf, FFTW_BACKWARD, FFTW_MEASURE);

   /* % The fftshift actually makes some things easier. */
   LTFAT_COMPLEX *gw  = (LTFAT_COMPLEX*)ltfat_malloc(gl*sizeof(LTFAT_COMPLEX));
   for (int l=0;l<glh;l++)
   {
      gw[l][0] = g[l+(gl-glh)][0];
      gw[l][1] = g[l+(gl-glh)][1];
   }
   for (int l=glh;l<gl;l++)
   {
      gw[l][0] = g[l-glh][0];
      gw[l][1] = g[l-glh][1];
   }
   
   LTFAT_COMPLEX *ff  = (LTFAT_COMPLEX*)ltfat_malloc(gl*sizeof(LTFAT_COMPLEX));
   
   for (int w=0; w<W; w++)
   {
      fw=f+w*L;
      for (int l=0;l<L;l++)
      {
	 fw[l][0]=0.0;
	 fw[l][1]=0.0;
      }
      /* ----- Handle the first boundary using periodic boundary conditions. --- */
      for (int n=0; n<glh_d_a; n++)
      {

	 THE_SUM;

	 sp=positiverem(n*a-glh,L);
	 ep=positiverem(n*a-glh+gl-1,L);

	 /* % Add the ff vector to f at position sp. */
	 for (int ii=0;ii<L-sp;ii++)
	 {
	    fw[sp+ii][0]+=ff[ii][0];
	    fw[sp+ii][1]+=ff[ii][1];
	 }
	 for (int ii=0; ii<ep+1;ii++)
	 {
	    fw[ii][0] +=ff[L-sp+ii][0];
	    fw[ii][1] +=ff[L-sp+ii][1];
	 }
      }
   

      /* ----- Handle the middle case. --------------------- */
      for (int n=glh_d_a; n<(L-(gl+1)/2)/a+1; n++)
      {

	 THE_SUM;

      	 sp=positiverem(n*a-glh,L);
      	 ep=positiverem(n*a-glh+gl-1,L);
	 
      	 /* Add the ff vector to f at position sp. */
      	 for (int ii=0;ii<ep-sp+1;ii++)
      	 {
      	    fw[ii+sp][0] += ff[ii][0];
      	    fw[ii+sp][1] += ff[ii][1];
      	 }
      }
      
      /* Handle the last boundary using periodic boundary conditions. */
      for (int n=(L-(gl+1)/2)/a+1; n<N; n++)
      {

	 THE_SUM;
	 
      	 sp=positiverem(n*a-glh,L);
      	 ep=positiverem(n*a-glh+gl-1,L);
	 
      	 /* Add the ff vector to f at position sp. */
      	 for (int ii=0;ii<L-sp;ii++)
      	 {
      	    fw[sp+ii][0]+=ff[ii][0];
      	    fw[sp+ii][1]+=ff[ii][1];
      	 }
      	 for (int ii=0; ii<ep+1;ii++)
      	 {
      	    fw[ii][0] +=ff[L-sp+ii][0];
      	    fw[ii][1] +=ff[L-sp+ii][1];
      	 }
	 
      }
   }
   
   ltfat_free(cbuf);
   ltfat_free(ff);
   ltfat_free(gw);
   
   LTFAT_FFTW(destroy_plan)(p_small);

}
void
LTFAT_NAME(ltfatMexFnc)( int UNUSED(nlhs), mxArray *plhs[],
                         int UNUSED(nrhs), const mxArray *prhs[] )
{
    // Register exit function only once
    static int atExitFncRegistered = 0;
    if (!atExitFncRegistered)
    {
        LTFAT_NAME(ltfatMexAtExit)(LTFAT_NAME(dctMexAtExitFnc));
        atExitFncRegistered = 1;
    }

    LTFAT_REAL *c_r, *c_i=NULL;
    const LTFAT_REAL *f_r, *f_i=NULL;
    dct_kind kind = DCTI; // This is overwritten

    mwIndex L = mxGetM(prhs[0]);
    mwIndex W = mxGetN(prhs[0]);
    mwIndex type = (mwIndex) mxGetScalar(prhs[1]);

// Copy inputs and get pointers
    if ( mxIsComplex(prhs[0]))
    {
        f_i =  mxGetImagData(prhs[0]);
        plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID, mxCOMPLEX);
        c_i = mxGetImagData(plhs[0]);
    }
    else
    {
        plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID, mxREAL);
    }

    f_r = mxGetData(prhs[0]);
    c_r = mxGetData(plhs[0]);

    switch (type)
    {
    case 1:
        kind = DCTI;
        break;
    case 2:
        kind = DCTII;
        break;
    case 3:
        kind = DCTIII;
        break;
    case 4:
        kind = DCTIV;
        break;
    default:
        mexErrMsgTxt("Unknown type.");
    }



    LTFAT_FFTW(plan) p = LTFAT_NAME(dct_init)( L, W, c_r, kind);
    /*
    The old plan is freed after the new one is cretaed.
    According to the FFTW doc. creating new plan is quick as long as there
    already exists a plan for the same length.
    */


    LTFAT_NAME(dctMexAtExitFnc)();
    LTFAT_NAME(p_old) = p;

    LTFAT_NAME(dct_execute)(p, f_r, L, W, c_r, kind);

    if ( mxIsComplex(prhs[0]))
    {
        LTFAT_NAME(dct_execute)(p, f_i, L, W, c_i, kind);
    }


    return;
}
示例#8
0
/* wfac for real valued input. */
LTFAT_EXTERN void
LTFAT_NAME(wfac_r)(const LTFAT_REAL *g, const int L, const int R, 
			const int a, const int M,
			LTFAT_COMPLEX *gf)
{
  
   int h_a, h_m;   

   LTFAT_REAL *sbuf, *gfp;

   int s;
   int rem, negrem;

   LTFAT_FFTW(plan) p_before;   
   
   const int b=L/M;
   const int c=gcd(a, M,&h_a, &h_m);
   const int p=a/c;
   const int q=M/c;
   const int d=b/p;

   const double sqrtM=sqrt(M);
   
   sbuf = (LTFAT_REAL*)ltfat_malloc(2*d*sizeof(LTFAT_REAL));
     
   /* Create plan. In-place. */
   p_before = LTFAT_FFTW(plan_dft_1d)(d, (LTFAT_COMPLEX*)sbuf,
				      (LTFAT_COMPLEX*)sbuf,
				      FFTW_FORWARD, FFTW_MEASURE);

   const int ld3=c*p*q*R;
   gfp=(LTFAT_REAL*)gf;
   for (int r=0;r<c;r++)
   {      
      for (int w=0;w<R;w++)
      {
	 for (int l=0;l<q;l++)
	 {
	    for (int k=0;k<p;k++)
	    {
	       negrem = positiverem(k*M-l*a,L);
	       for (s=0;s<d;s++)
	       {		  
		  rem = (negrem+s*p*M)%L;
		  sbuf[2*s]   = sqrtM*g[r+rem+L*w];
		  sbuf[2*s+1] = 0.0;
	       }

	       LTFAT_FFTW(execute)(p_before);	  

	       for (s=0;s<2*d;s+=2)
	       {		  
		  gfp[s*ld3]  = sbuf[s];
		  gfp[s*ld3+1]= sbuf[s+1];
	       }
	       gfp+=2;
	    }
	 }
      }
   }
   
   ltfat_free(sbuf);
}
示例#9
0
/* wfac for real valued input. Produces only half the output coefficients of wfac_r */
LTFAT_EXTERN void
LTFAT_NAME(wfacreal)(const LTFAT_REAL *g, const int L, const int R, 
			const int a, const int M,
			LTFAT_COMPLEX *gf)
{
  
   int h_a, h_m;   

   LTFAT_REAL *gfp;

   int s;
   int rem, negrem;

   LTFAT_FFTW(plan) p_before;   
   
   const int b=L/M;
   const int c=gcd(a, M,&h_a, &h_m);
   const int p=a/c;
   const int q=M/c;
   const int d=b/p;

   /* This is a floor operation. */
   const int d2= d/2+1;

   const double sqrtM=sqrt(M);
   
   LTFAT_REAL *sbuf = (LTFAT_REAL*)ltfat_malloc(d*sizeof(LTFAT_REAL));
   LTFAT_COMPLEX *cbuf = (LTFAT_COMPLEX*)ltfat_malloc(d2*sizeof(LTFAT_COMPLEX));
     
   /* Create plan. In-place. */
   p_before = LTFAT_FFTW(plan_dft_r2c_1d)(d, sbuf, cbuf, FFTW_MEASURE);

   const int ld3=2*c*p*q*R;
   gfp=(LTFAT_REAL*)gf;
   for (int r=0;r<c;r++)
   {      
      for (int w=0;w<R;w++)
      {
	 for (int l=0;l<q;l++)
	 {
	    for (int k=0;k<p;k++)
	    {
	       negrem = positiverem(k*M-l*a,L);
	       for (s=0;s<d;s++)
	       {		  
		  rem = (negrem+s*p*M)%L;
		  sbuf[s]   = sqrtM*g[r+rem+L*w];
	       }

	       LTFAT_FFTW(execute)(p_before);	  

	       for (s=0;s<d2;s++)
	       {		  
		  gfp[s*ld3]  = cbuf[s][0];
		  gfp[s*ld3+1]= cbuf[s][1];
	       }
	       gfp+=2;
	    }
	 }
      }
   }
   
   ltfat_free(sbuf);
}
示例#10
0
void LTFAT_NAME(ltfatMexFnc)( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[] )
{
  #ifdef LTFAT_DOUBLE
  if(p_old==0)
  {
      mexAtExit(fftrealAtExit);
  }
  #endif

  int L, W, L2;
  LTFAT_REAL *f, *cout_r, *cout_i;
  LTFAT_FFTW(iodim) dims[1], howmanydims[1];
  LTFAT_FFTW(plan) p;

  L = mxGetM(prhs[0]);
  W = mxGetN(prhs[0]);

  L2 = (L/2)+1;

  // Get pointer to input.
  f= (LTFAT_REAL*) mxGetPr(prhs[0]);

  plhs[0] = ltfatCreateMatrix(L2, W, LTFAT_MX_CLASSID, mxCOMPLEX);

  // Get pointer to output.
  cout_r = (LTFAT_REAL*) mxGetPr(plhs[0]);
  cout_i = (LTFAT_REAL*) mxGetPi(plhs[0]);

  // Create plan. Copy data from f to cout.
  dims[0].n = L;
  dims[0].is = 1;
  dims[0].os = 1;

  howmanydims[0].n = W;
  howmanydims[0].is = L;
  howmanydims[0].os = L2;

  // The calling prototype
  //fftw_plan fftw_plan_guru_split_dft_r2c(
  //        int rank, const fftw_iodim *dims,
  //        int howmany_rank, const fftw_iodim *howmany_dims,
  //        double *in, double *ro, double *io,
  //        unsigned flags);

  /* We are violating this here:
  You must create the plan before initializing the input, because FFTW_MEASURE overwrites the in/out arrays.
  (Technically, FFTW_ESTIMATE does not touch your arrays, but you should always create plans first just to be sure.)
  */
  p = LTFAT_FFTW(plan_guru_split_dft_r2c)(1, dims,
				   1, howmanydims,
				   f, cout_r, cout_i, FFTW_ESTIMATE);
  /*
  FFTW documentation qote http://www.fftw.org/fftw3_doc/New_002darray-Execute-Functions.html#New_002darray-Execute-Functions:
  ...
  creating a new plan is quick once one exists for a given size
  ...
  so why not to store the old plan..
  */


  if(p_old!=0)
  {
    fftw_destroy_plan(*p_old);
    free(p_old);
  }
  p_old = malloc(sizeof(p));
  memcpy(p_old,&p,sizeof(p));


  // Real FFT.
  LTFAT_FFTW(execute)(p);

  // LTFAT_FFTW(destroy_plan)(p);

  return;
}
示例#11
0
void 
LTFAT_NAME(ltfatMexFnc)( int nlhs, mxArray *plhs[],
                         int nrhs, const mxArray *prhs[] )
{
  static int atExitRegistered = 0;
  if(!atExitRegistered)
  {
      LTFAT_NAME(ltfatMexAtExit)(LTFAT_NAME(fftrealAtExit));
      atExitRegistered = 1;
  }

  mwSignedIndex L, W, L2;
  LTFAT_REAL *f, *cout_r, *cout_i;
  LTFAT_FFTW(iodim) dims[1], howmanydims[1];
  LTFAT_FFTW(plan) p;

  L = mxGetM(prhs[0]);
  W = mxGetN(prhs[0]);

  L2 = (L/2)+1;

  // Get pointer to input.
  f= mxGetData(prhs[0]);

  plhs[0] = ltfatCreateMatrix(L2, W, LTFAT_MX_CLASSID, mxCOMPLEX);

  // Get pointer to output.
  cout_r = mxGetData(plhs[0]);
  cout_i = mxGetImagData(plhs[0]);

  // Create plan. Copy data from f to cout.
  dims[0].n = L;
  dims[0].is = 1;
  dims[0].os = 1;

  howmanydims[0].n = W;
  howmanydims[0].is = L;
  howmanydims[0].os = L2;

  // The calling prototype
  //fftw_plan fftw_plan_guru_split_dft_r2c(
  //        int rank, const fftw_iodim *dims,
  //        int howmany_rank, const fftw_iodim *howmany_dims,
  //        double *in, double *ro, double *io,
  //        unsigned flags);

  /* We are violating this here:
  You must create the plan before initializing the input, because FFTW_MEASURE overwrites the in/out arrays.
  (Technically, FFTW_ESTIMATE does not touch your arrays, but you should always create plans first just to be sure.)
  */
  p = LTFAT_FFTW(plan_guru_split_dft_r2c)(1, dims,
				   1, howmanydims,
				   f, cout_r, cout_i, FFTW_ESTIMATE);
  /*
  ...
  creating a new plan is quick once one exists for a given size
  ...
  so why not to store the old plan..
  */


  LTFAT_NAME(fftrealAtExit)();
  LTFAT_NAME(p_old) = p;


  // Real FFT.
  LTFAT_FFTW(execute)(p);

  // LTFAT_FFTW(destroy_plan)(p);

  return;
}
示例#12
0
void 
LTFAT_NAME(ltfatMexFnc)( int nlhs, mxArray *plhs[],
                      int nrhs, const mxArray *prhs[] )
{
  // Register exit function only once
    static int atExitFncRegistered = 0;
    if(!atExitFncRegistered)
    {
        LTFAT_NAME(ltfatMexAtExit)(LTFAT_NAME(dctMexAtExitFnc));
        atExitFncRegistered = 1;
    }

  LTFAT_REAL *c_r, *c_i;
  const LTFAT_REAL *f_r, *f_i;
  dct_kind kind;

  mwIndex L = mxGetM(prhs[0]);
  mwIndex W = mxGetN(prhs[0]);
  mwIndex type = (mwIndex) mxGetScalar(prhs[1]);

 // Copy inputs and get pointers
  if( mxIsComplex(prhs[0]))
  {
     f_i =  mxGetImagData(prhs[0]); 
     plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID, mxCOMPLEX);
     c_i = mxGetImagData(plhs[0]);
  }
  else
  {
     plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID, mxREAL);
  }

  f_r = mxGetData(prhs[0]);
  c_r = mxGetData(plhs[0]);

  switch(type)
  {
	 case 1:
        kind = DSTI;
     break;
	 case 2:
        kind = DSTII;
     break;
	 case 3:
        kind = DSTIII;
     break;
	 case 4:
        kind = DSTIV;
     break;
     default:
		 mexErrMsgTxt("Unknown type.");
  }



  LTFAT_FFTW(plan) p = LTFAT_NAME(dst_init)( L, W, c_r, kind);



  LTFAT_NAME(dctMexAtExitFnc)();
  LTFAT_NAME(p_old) = p;


  LTFAT_NAME(dst_execute)(p,f_r,L,W,c_r,kind);
  if( mxIsComplex(prhs[0]))
  {
      LTFAT_NAME(dst_execute)(p,f_i,L,W,c_i,kind);
  }


  return;
}
示例#13
0
void LTFAT_NAME(ltfatMexFnc)( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[] )
{
    // Register exit function only once
#ifdef LTFAT_DOUBLE
    if(p_old==0)
    {
        mexAtExit(fftrealAtExit);
    }
#endif

    mwIndex L, W, N, type;
    LTFAT_REAL *f_r, *f_i;
    LTFAT_FFTW(iodim) dims[1], howmanydims[1];
    LTFAT_FFTW(plan) p;
    LTFAT_FFTW(r2r_kind) kind[1];

    L = mxGetM(prhs[0]);
    W = mxGetN(prhs[0]);
    N = 2*L;
    type = (mwIndex) mxGetScalar(prhs[1]);

    // Copy inputs and get pointers
    if( mxIsComplex(prhs[0]))
    {
        plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID, mxCOMPLEX);
        f_i = (LTFAT_REAL*) mxGetPi(plhs[0]);
        memcpy(f_i,mxGetPi(prhs[0]),W*L*sizeof(LTFAT_REAL));
    }
    else
    {
        plhs[0] = ltfatCreateMatrix(L, W, LTFAT_MX_CLASSID, mxREAL);
    }
    f_r = (LTFAT_REAL*) mxGetPr(plhs[0]);
    memcpy(f_r,mxGetPr(prhs[0]),W*L*sizeof(LTFAT_REAL));

    // Create plan. Copy data from f to cout.
    dims[0].n = L;
    dims[0].is = 1;
    dims[0].os = 1;

    howmanydims[0].n = W;
    howmanydims[0].is = L;
    howmanydims[0].os = L;

    LTFAT_REAL sqrt2 = (LTFAT_REAL) sqrt(2.0);
    LTFAT_REAL postScale = (LTFAT_REAL) 1.0/sqrt2;
    LTFAT_REAL scale = (LTFAT_REAL) sqrt2*(1.0/(double)N)*sqrt((double)L);

    // Re-allocate and prescale input
    if(type==1||type==3)
    {
        for(mwIndex ii=0; ii<W; ii++)
        {
            f_r[ii*L] *= sqrt2;
        }
        if(mxIsComplex(prhs[0]))
        {
            for(mwIndex ii=0; ii<W; ii++)
            {
                f_i[ii*L] *= sqrt2;
            }
        }
    }

    switch(type)
    {
    case 1:
        N -= 2;
        for(mwIndex ii=0; ii<W; ii++)
        {
            f_r[(ii+1)*L-1] *= sqrt2;
        }

        if(mxIsComplex(prhs[0]))
        {
            for(mwIndex ii=0; ii<W; ii++)
            {
                f_i[(ii+1)*L-1] *= sqrt2;
            }
        }

        scale = (LTFAT_REAL) sqrt2*(1.0/((double)N))*sqrt((double)L-1);
        kind[0] = FFTW_REDFT00;
        break;
    case 2:
        kind[0] = FFTW_REDFT10;
        break;
    case 3:
        kind[0] = FFTW_REDFT01;
        break;
    case 4:
        kind[0] = FFTW_REDFT11;
        break;
    default:
        mexErrMsgTxt("Unknown type.");
    }



    // The calling prototype
    //fftw_plan fftw_plan_guru_split_dft_r2c(
    //        int rank, const fftw_iodim *dims,
    //        int howmany_rank, const fftw_iodim *howmany_dims,
    //        double *in, double *ro, double *io,
    //        unsigned flags);


    p = LTFAT_FFTW(plan_guru_r2r)(1, dims,
                                  1, howmanydims,
                                  f_r, f_r,
                                  kind,
                                  FFTW_OPTITYPE);
    /*
    FFTW documentation qote http://www.fftw.org/fftw3_doc/New_002darray-Execute-Functions.html#New_002darray-Execute-Functions:
    ...
    creating a new plan is quick once one exists for a given size
    ...
    so why not to store the old plan..
    */


    if(p_old!=0)
    {
        fftw_destroy_plan(*p_old);
        free(p_old);
    }
    p_old = malloc(sizeof(p));
    memcpy(p_old,&p,sizeof(p));


    // Real FFT.
    LTFAT_FFTW(execute)(p);


    // Do the normalization
    for(int ii=0; ii<L*W; ii++)
    {
        f_r[ii] *= scale;
    }

    if(type==1||type==2)
    {
        // Scale DC component
        for(int ii=0; ii<W; ii++)
        {
            f_r[ii*L] *= postScale;
        }
    }

    if(type==1)
    {
        // Scale AC component
        for(int ii=0; ii<W; ii++)
        {
            f_r[(ii+1)*L-1] *= postScale;
        }
    }

    // If the input is complex, process the imaginary part
    if(mxIsComplex(prhs[0]))
    {
        LTFAT_FFTW(execute_r2r)(p,f_i,f_i);
        // Do the normalization
        for(int ii=0; ii<L*W; ii++)
        {
            f_i[ii] *= scale;
        }
        if(type==1||type==2)
        {
            // Scale DC component
            for(int ii=0; ii<W; ii++)
            {
                f_i[ii*L] *= postScale;
            }
        }
        if(type==1)
        {
            // Scale AC component
            for(int ii=0; ii<W; ii++)
            {
                f_i[(ii+1)*L-1] *= postScale;
            }
        }
    }

    // LTFAT_FFTW(destroy_plan)(p);

    return;
}