36 #ifndef VIGRA_RFFTW_HXX 
   37 #define VIGRA_RFFTW_HXX 
   39 #include "array_vector.hxx" 
   47 struct FFTWSinCosConfig
 
   49     ArrayVector<fftw_real> twiddles;
 
   50     ArrayVector<fftw_real> fftwInput;
 
   51     ArrayVector<fftw_complex> fftwTmpResult;
 
   53     rfftwnd_plan fftwPlan;
 
   56 template <
class SrcIterator, 
class SrcAccessor,
 
   57           class DestIterator, 
class DestAccessor,
 
   60 cosineTransformLineImpl(SrcIterator s, SrcIterator send, SrcAccessor src, 
 
   61                         DestIterator d, DestAccessor dest,
 
   72     fftw_real 
const * twiddles = config.twiddles.begin();
 
   73     fftw_real * fftwInput = config.fftwInput.begin();
 
   74     fftw_complex * fftwTmpResult = config.fftwTmpResult.begin();
 
   75     fftw_real 
norm = config.norm;
 
   76     rfftwnd_plan fftwPlan = config.fftwPlan;
 
   82         dest.set(src(s) / norm, d);
 
   87         dest.set((src(s) + src(s, 1)) / norm, d);
 
   88         dest.set((src(s) - src(s, 1)) / norm, d, 1);
 
   93         fftw_real x1p3 = src(s) + src(s, 2);
 
   94         fftw_real tx2 =  2.0 * src(s, 1);
 
   96         dest.set((x1p3 + tx2) / norm, d, 0);
 
   97         dest.set((src(s) - src(s, 2)) / norm, d, 1);
 
   98         dest.set((x1p3 - tx2) / norm, d, 2);
 
  103         fftw_real c1 = src(s) - src(s, nm1);
 
  104         fftwInput[0] = src(s) + src(s, nm1);
 
  105         for(
int k=1; k<ns2; ++k)
 
  108             fftw_real t1 = src(s, k) + src(s, kc);
 
  109             fftw_real t2 = src(s, k) - src(s, kc);
 
  110             c1 = c1 + twiddles[kc] * t2;
 
  111             t2 = twiddles[k] * t2;
 
  112             fftwInput[k] = t1 - t2;
 
  113             fftwInput[kc] = t1 + t2;
 
  118             fftwInput[ns2] = 2.0*src(s, ns2);
 
  120         rfftwnd_one_real_to_complex(fftwPlan, fftwInput, fftwTmpResult);
 
  121         dest.set(fftwTmpResult[0].re / norm, d, 0);
 
  122         for(
int k=1; k<(size+1)/2; ++k)
 
  124             dest.set(fftwTmpResult[k].re, d, 2*k-1);
 
  125             dest.set(fftwTmpResult[k].im, d, 2*k);
 
  127         fftw_real xim2 = dest(d, 1);
 
  128         dest.set(c1 / norm, d, 1);
 
  129         for(
int k=3; k<size; k+=2)
 
  131             fftw_real xi = dest(d, k);
 
  132             dest.set(dest(d, k-2) - dest(d, k-1) / norm, d, k);
 
  133             dest.set(xim2 / norm, d, k-1);
 
  138             dest.set(xim2 / norm, d, size-1);
 
  146 template <
class SrcTraverser, 
class SrcAccessor,
 
  147           class DestTraverser, 
class DestAccessor>
 
  148 void cosineTransformX(SrcTraverser sul, SrcTraverser slr, SrcAccessor src,
 
  149                       DestTraverser dul, DestAccessor dest, fftw_real norm)
 
  151     int w = slr.x - sul.x;
 
  152     int h = slr.y - sul.y;
 
  154     detail::FFTWSinCosConfig config;
 
  161     config.twiddles.resize(w+1);
 
  162     config.fftwInput.resize(w+1);
 
  163     config.fftwTmpResult.resize(w+1);
 
  165     config.fftwPlan = rfftw2d_create_plan(1, nm1, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE );
 
  167     fftw_real dt = M_PI / nm1;
 
  168     for(
int k=1; k<ns2; ++k)
 
  170         fftw_real f = dt * k;
 
  175     for(; sul.y != slr.y; ++sul.y, ++dul.y)
 
  177         typename SrcTraverser::row_iterator s = sul.rowIterator();
 
  178         typename SrcTraverser::row_iterator send = s + w;
 
  179         typename DestTraverser::row_iterator d = dul.rowIterator();
 
  180         cosineTransformLineImpl(s, send, src, d, dest, config);
 
  183     rfftwnd_destroy_plan(config.fftwPlan);
 
  186 template <
class SrcTraverser, 
class SrcAccessor,
 
  187           class DestTraverser, 
class DestAccessor>
 
  188 void cosineTransformY(SrcTraverser sul, SrcTraverser slr, SrcAccessor src,
 
  189                       DestTraverser dul, DestAccessor dest, fftw_real norm)
 
  191     int w = slr.x - sul.x;
 
  192     int h = slr.y - sul.y;
 
  194     detail::FFTWSinCosConfig config;
 
  201     config.twiddles.resize(h + 1);
 
  202     config.fftwInput.resize(h + 1);
 
  203     config.fftwTmpResult.resize(h + 1);
 
  205     config.fftwPlan = rfftw2d_create_plan(1, nm1, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE );
 
  207     fftw_real dt = M_PI / nm1;
 
  208     for(
int k=1; k<ns2; ++k)
 
  210         fftw_real f = dt * k;
 
  215     for(; sul.x != slr.x; ++sul.x, ++dul.x)
 
  217         typename SrcTraverser::column_iterator s = sul.columnIterator();
 
  218         typename SrcTraverser::column_iterator send = s + h;
 
  219         typename DestTraverser::column_iterator d = dul.columnIterator();
 
  220         cosineTransformLineImpl(s, send, src, d, dest, config);
 
  223     rfftwnd_destroy_plan(config.fftwPlan);
 
  226 template <
class SrcTraverser, 
class SrcAccessor,
 
  227           class DestTraverser, 
class DestAccessor>
 
  229 realFourierTransformXEvenYEven(SrcTraverser sul, SrcTraverser slr, SrcAccessor src,
 
  230                       DestTraverser dul, DestAccessor dest, fftw_real norm)
 
  232     BasicImage<fftw_real> tmp(slr - sul);
 
  233     cosineTransformX(sul, slr, src, tmp.upperLeft(), tmp.accessor(), 1.0);
 
  234     cosineTransformY(tmp.upperLeft(), tmp.lowerRight(), tmp.accessor(), dul, dest, 
norm);
 
  237 template <
class SrcTraverser, 
class SrcAccessor,
 
  238           class DestTraverser, 
class DestAccessor>
 
  240 realFourierTransformXEvenYEven(triple<SrcTraverser, SrcTraverser, SrcAccessor> src,
 
  241                       pair<DestTraverser, DestAccessor> dest, fftw_real norm)
 
  243     realFourierTransformXEvenYEven(src.first, src.second, src.third, dest.first, dest.second, norm);
 
  248 #endif // VIGRA_RFFTW_HXX 
linalg::TemporaryMatrix< T > sin(MultiArrayView< 2, T, C > const &v)
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude) 
Definition: fftw3.hxx:1037
linalg::TemporaryMatrix< T > cos(MultiArrayView< 2, T, C > const &v)