Mercurial > octave
diff liboctave/numeric/oct-fftw.cc @ 23058:5839d16828cb
move fftw classes inside octave namespace
* oct-fftw.h, oct-fftw.cc (fftw_planner, fftw_float_planner, fftw):
Move inside octave namespace and rename without octave_ prefix.
Change all uses.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 17 Jan 2017 11:42:25 -0500 |
parents | 3a2b891d0b33 |
children | 9ca0829b160e |
line wrap: on
line diff
--- a/liboctave/numeric/oct-fftw.cc Tue Jan 17 11:19:44 2017 -0500 +++ b/liboctave/numeric/oct-fftw.cc Tue Jan 17 11:42:25 2017 -0500 @@ -44,1113 +44,1107 @@ #if defined (HAVE_FFTW) -octave_fftw_planner *octave_fftw_planner::instance = 0; - -// Helper class to create and cache FFTW plans for both 1D and -// 2D. This implementation defaults to using FFTW_ESTIMATE to create -// the plans, which in theory is suboptimal, but provides quite -// reasonable performance in practice. +namespace octave +{ + fftw_planner *fftw_planner::instance = 0; -// Also note that if FFTW_ESTIMATE is not used then the planner in FFTW3 -// will destroy the input and output arrays. We must, therefore, create a -// temporary input array with the same size and 16-byte alignment as -// the original array when using a different planner strategy. -// Note that we also use any wisdom that is available, either in a -// FFTW3 system wide file or as supplied by the user. + // Helper class to create and cache FFTW plans for both 1D and + // 2D. This implementation defaults to using FFTW_ESTIMATE to create + // the plans, which in theory is suboptimal, but provides quite + // reasonable performance in practice. + + // Also note that if FFTW_ESTIMATE is not used then the planner in FFTW3 + // will destroy the input and output arrays. We must, therefore, create a + // temporary input array with the same size and 16-byte alignment as + // the original array when using a different planner strategy. + // Note that we also use any wisdom that is available, either in a + // FFTW3 system wide file or as supplied by the user. -// FIXME: if we can ensure 16 byte alignment in Array<T> -// (<T> *data) the FFTW3 can use SIMD instructions for further -// acceleration. + // FIXME: if we can ensure 16 byte alignment in Array<T> + // (<T> *data) the FFTW3 can use SIMD instructions for further + // acceleration. -// Note that it is profitable to store the FFTW3 plans, for small FFTs. + // Note that it is profitable to store the FFTW3 plans, for small FFTs. -octave_fftw_planner::octave_fftw_planner (void) - : meth (ESTIMATE), rplan (0), rd (0), rs (0), rr (0), rh (0), rn (), - rsimd_align (false), nthreads (1) -{ - plan[0] = plan[1] = 0; - d[0] = d[1] = s[0] = s[1] = r[0] = r[1] = h[0] = h[1] = 0; - simd_align[0] = simd_align[1] = false; - inplace[0] = inplace[1] = false; - n[0] = n[1] = dim_vector (); + fftw_planner::fftw_planner (void) + : meth (ESTIMATE), rplan (0), rd (0), rs (0), rr (0), rh (0), rn (), + rsimd_align (false), nthreads (1) + { + plan[0] = plan[1] = 0; + d[0] = d[1] = s[0] = s[1] = r[0] = r[1] = h[0] = h[1] = 0; + simd_align[0] = simd_align[1] = false; + inplace[0] = inplace[1] = false; + n[0] = n[1] = dim_vector (); #if defined (HAVE_FFTW3_THREADS) - int init_ret = fftw_init_threads (); - if (! init_ret) - (*current_liboctave_error_handler) ("Error initializing FFTW threads"); + int init_ret = fftw_init_threads (); + if (! init_ret) + (*current_liboctave_error_handler) ("Error initializing FFTW threads"); - // Use number of processors available to the current process - // This can be later changed with fftw ("threads", nthreads). - nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT); - fftw_plan_with_nthreads (nthreads); + // Use number of processors available to the current process + // This can be later changed with fftw ("threads", nthreads). + nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT); + fftw_plan_with_nthreads (nthreads); #endif - // If we have a system wide wisdom file, import it. - fftw_import_system_wisdom (); -} + // If we have a system wide wisdom file, import it. + fftw_import_system_wisdom (); + } -octave_fftw_planner::~octave_fftw_planner (void) -{ - fftw_plan *plan_p; + fftw_planner::~fftw_planner (void) + { + fftw_plan *plan_p; - plan_p = reinterpret_cast<fftw_plan *> (&rplan); - if (*plan_p) - fftw_destroy_plan (*plan_p); + plan_p = reinterpret_cast<fftw_plan *> (&rplan); + if (*plan_p) + fftw_destroy_plan (*plan_p); - plan_p = reinterpret_cast<fftw_plan *> (&plan[0]); - if (*plan_p) - fftw_destroy_plan (*plan_p); + plan_p = reinterpret_cast<fftw_plan *> (&plan[0]); + if (*plan_p) + fftw_destroy_plan (*plan_p); - plan_p = reinterpret_cast<fftw_plan *> (&plan[1]); - if (*plan_p) - fftw_destroy_plan (*plan_p); -} + plan_p = reinterpret_cast<fftw_plan *> (&plan[1]); + if (*plan_p) + fftw_destroy_plan (*plan_p); + } -bool -octave_fftw_planner::instance_ok (void) -{ - bool retval = true; + bool + fftw_planner::instance_ok (void) + { + bool retval = true; - if (! instance) - { - instance = new octave_fftw_planner (); + if (! instance) + { + instance = new fftw_planner (); - if (instance) - singleton_cleanup_list::add (cleanup_instance); - } + if (instance) + singleton_cleanup_list::add (cleanup_instance); + } - if (! instance) - (*current_liboctave_error_handler) - ("unable to create octave_fftw_planner object!"); + if (! instance) + (*current_liboctave_error_handler) + ("unable to create fftw_planner object!"); - return retval; -} + return retval; + } -void -octave_fftw_planner::threads (int nt) -{ + void + fftw_planner::threads (int nt) + { #if defined (HAVE_FFTW3_THREADS) - if (instance_ok () && nt != threads ()) - { - instance->nthreads = nt; - fftw_plan_with_nthreads (nt); - // Clear the current plans. - instance->rplan = instance->plan[0] = instance->plan[1] = 0; - } + if (instance_ok () && nt != threads ()) + { + instance->nthreads = nt; + fftw_plan_with_nthreads (nt); + // Clear the current plans. + instance->rplan = instance->plan[0] = instance->plan[1] = 0; + } #else - (*current_liboctave_warning_handler) - ("unable to change number of threads without FFTW thread support"); + (*current_liboctave_warning_handler) + ("unable to change number of threads without FFTW thread support"); #endif -} + } #define CHECK_SIMD_ALIGNMENT(x) \ (((reinterpret_cast<ptrdiff_t> (x)) & 0xF) == 0) -void * -octave_fftw_planner::do_create_plan (int dir, const int rank, - const dim_vector dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const Complex *in, Complex *out) -{ - int which = (dir == FFTW_FORWARD) ? 0 : 1; - fftw_plan *cur_plan_p = reinterpret_cast<fftw_plan *> (&plan[which]); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - bool ioinplace = (in == out); + void * + fftw_planner::do_create_plan (int dir, const int rank, + const dim_vector dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const Complex *in, Complex *out) + { + int which = (dir == FFTW_FORWARD) ? 0 : 1; + fftw_plan *cur_plan_p = reinterpret_cast<fftw_plan *> (&plan[which]); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + bool ioinplace = (in == out); + + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. + + if (plan[which] == 0 || d[which] != dist || s[which] != stride + || r[which] != rank || h[which] != howmany + || ioinplace != inplace[which] + || ((ioalign != simd_align[which]) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. + + for (int i = 0; i < rank; i++) + if (dims(i) != n[which](i)) + { + create_new_plan = true; + break; + } + } - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. + if (create_new_plan) + { + d[which] = dist; + s[which] = stride; + r[which] = rank; + h[which] = howmany; + simd_align[which] = ioalign; + inplace[which] = ioinplace; + n[which] = dims; + + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); + + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } + + int plan_flags = 0; + bool plan_destroys_in = true; - if (plan[which] == 0 || d[which] != dist || s[which] != stride - || r[which] != rank || h[which] != howmany - || ioinplace != inplace[which] - || ((ioalign != simd_align[which]) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. - - for (int i = 0; i < rank; i++) - if (dims(i) != n[which](i)) + switch (meth) { - create_new_plan = true; + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } break; } - } - if (create_new_plan) - { - d[which] = dist; - s[which] = stride; - r[which] = rank; - h[which] = howmany; - simd_align[which] = ioalign; - inplace[which] = ioinplace; - n[which] = dims; + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); + if (*cur_plan_p) + fftw_destroy_plan (*cur_plan_p); - for (int i = 0, j = rank-1; i < rank; i++, j--) - { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (Complex, itmp, nn * howmany + 32); + itmp = reinterpret_cast<Complex *> + (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + + ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); - switch (meth) - { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } - break; - } + *cur_plan_p = + fftw_plan_many_dft (rank, tmp, howmany, + reinterpret_cast<fftw_complex *> (itmp), + 0, stride, dist, + reinterpret_cast<fftw_complex *> (out), + 0, stride, dist, dir, plan_flags); + } + else + { + *cur_plan_p = + fftw_plan_many_dft (rank, tmp, howmany, + reinterpret_cast<fftw_complex *> (const_cast<Complex *> (in)), + 0, stride, dist, + reinterpret_cast<fftw_complex *> (out), + 0, stride, dist, dir, plan_flags); + } - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + if (*cur_plan_p == 0) + (*current_liboctave_error_handler) ("Error creating fftw plan"); + } + + return *cur_plan_p; + } + + void * + fftw_planner::do_create_plan (const int rank, const dim_vector dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const double *in, Complex *out) + { + fftw_plan *cur_plan_p = reinterpret_cast<fftw_plan *> (&rplan); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. - if (*cur_plan_p) - fftw_destroy_plan (*cur_plan_p); - - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (Complex, itmp, nn * howmany + 32); - itmp = reinterpret_cast<Complex *> - (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + - ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); + if (rplan == 0 || rd != dist || rs != stride || rr != rank + || rh != howmany || ((ioalign != rsimd_align) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. - *cur_plan_p = - fftw_plan_many_dft (rank, tmp, howmany, - reinterpret_cast<fftw_complex *> (itmp), - 0, stride, dist, - reinterpret_cast<fftw_complex *> (out), - 0, stride, dist, dir, plan_flags); - } - else - { - *cur_plan_p = - fftw_plan_many_dft (rank, tmp, howmany, - reinterpret_cast<fftw_complex *> (const_cast<Complex *> (in)), - 0, stride, dist, - reinterpret_cast<fftw_complex *> (out), - 0, stride, dist, dir, plan_flags); - } + for (int i = 0; i < rank; i++) + if (dims(i) != rn(i)) + { + create_new_plan = true; + break; + } + } + + if (create_new_plan) + { + rd = dist; + rs = stride; + rr = rank; + rh = howmany; + rsimd_align = ioalign; + rn = dims; + + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); - if (*cur_plan_p == 0) - (*current_liboctave_error_handler) ("Error creating fftw plan"); - } + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } - return *cur_plan_p; -} + int plan_flags = 0; + bool plan_destroys_in = true; -void * -octave_fftw_planner::do_create_plan (const int rank, const dim_vector dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const double *in, Complex *out) -{ - fftw_plan *cur_plan_p = reinterpret_cast<fftw_plan *> (&rplan); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. - - if (rplan == 0 || rd != dist || rs != stride || rr != rank - || rh != howmany || ((ioalign != rsimd_align) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. - - for (int i = 0; i < rank; i++) - if (dims(i) != rn(i)) + switch (meth) { - create_new_plan = true; + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } break; } - } - if (create_new_plan) - { - rd = dist; - rs = stride; - rr = rank; - rh = howmany; - rsimd_align = ioalign; - rn = dims; + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); + if (*cur_plan_p) + fftw_destroy_plan (*cur_plan_p); - for (int i = 0, j = rank-1; i < rank; i++, j--) - { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (double, itmp, nn + 32); + itmp = reinterpret_cast<double *> + (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + + ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); - switch (meth) - { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } - break; - } + *cur_plan_p = + fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp, + 0, stride, dist, + reinterpret_cast<fftw_complex *> (out), + 0, stride, dist, plan_flags); + } + else + { + *cur_plan_p = + fftw_plan_many_dft_r2c (rank, tmp, howmany, + (const_cast<double *> (in)), + 0, stride, dist, + reinterpret_cast<fftw_complex *> (out), + 0, stride, dist, plan_flags); + } - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + if (*cur_plan_p == 0) + (*current_liboctave_error_handler) ("Error creating fftw plan"); + } - if (*cur_plan_p) - fftw_destroy_plan (*cur_plan_p); + return *cur_plan_p; + } - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (double, itmp, nn + 32); - itmp = reinterpret_cast<double *> - (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + - ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); - - *cur_plan_p = - fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp, - 0, stride, dist, - reinterpret_cast<fftw_complex *> (out), - 0, stride, dist, plan_flags); - } - else - { - *cur_plan_p = - fftw_plan_many_dft_r2c (rank, tmp, howmany, - (const_cast<double *> (in)), - 0, stride, dist, - reinterpret_cast<fftw_complex *> (out), - 0, stride, dist, plan_flags); - } - - if (*cur_plan_p == 0) - (*current_liboctave_error_handler) ("Error creating fftw plan"); - } - - return *cur_plan_p; -} - -octave_fftw_planner::FftwMethod -octave_fftw_planner::do_method (void) -{ - return meth; -} + fftw_planner::FftwMethod + fftw_planner::do_method (void) + { + return meth; + } -octave_fftw_planner::FftwMethod -octave_fftw_planner::do_method (FftwMethod _meth) -{ - FftwMethod ret = meth; - if (_meth == ESTIMATE || _meth == MEASURE - || _meth == PATIENT || _meth == EXHAUSTIVE - || _meth == HYBRID) - { - if (meth != _meth) - { - meth = _meth; - if (rplan) - fftw_destroy_plan (reinterpret_cast<fftw_plan> (rplan)); - if (plan[0]) - fftw_destroy_plan (reinterpret_cast<fftw_plan> (plan[0])); - if (plan[1]) - fftw_destroy_plan (reinterpret_cast<fftw_plan> (plan[1])); - rplan = plan[0] = plan[1] = 0; - } - } - else - ret = UNKNOWN; - return ret; -} + fftw_planner::FftwMethod + fftw_planner::do_method (FftwMethod _meth) + { + FftwMethod ret = meth; + if (_meth == ESTIMATE || _meth == MEASURE + || _meth == PATIENT || _meth == EXHAUSTIVE + || _meth == HYBRID) + { + if (meth != _meth) + { + meth = _meth; + if (rplan) + fftw_destroy_plan (reinterpret_cast<fftw_plan> (rplan)); + if (plan[0]) + fftw_destroy_plan (reinterpret_cast<fftw_plan> (plan[0])); + if (plan[1]) + fftw_destroy_plan (reinterpret_cast<fftw_plan> (plan[1])); + rplan = plan[0] = plan[1] = 0; + } + } + else + ret = UNKNOWN; + return ret; + } -octave_float_fftw_planner *octave_float_fftw_planner::instance = 0; + float_fftw_planner *float_fftw_planner::instance = 0; -octave_float_fftw_planner::octave_float_fftw_planner (void) - : meth (ESTIMATE), rplan (0), rd (0), rs (0), rr (0), rh (0), rn (), - rsimd_align (false), nthreads (1) -{ - plan[0] = plan[1] = 0; - d[0] = d[1] = s[0] = s[1] = r[0] = r[1] = h[0] = h[1] = 0; - simd_align[0] = simd_align[1] = false; - inplace[0] = inplace[1] = false; - n[0] = n[1] = dim_vector (); + float_fftw_planner::float_fftw_planner (void) + : meth (ESTIMATE), rplan (0), rd (0), rs (0), rr (0), rh (0), rn (), + rsimd_align (false), nthreads (1) + { + plan[0] = plan[1] = 0; + d[0] = d[1] = s[0] = s[1] = r[0] = r[1] = h[0] = h[1] = 0; + simd_align[0] = simd_align[1] = false; + inplace[0] = inplace[1] = false; + n[0] = n[1] = dim_vector (); #if defined (HAVE_FFTW3F_THREADS) - int init_ret = fftwf_init_threads (); - if (! init_ret) - (*current_liboctave_error_handler) ("Error initializing FFTW3F threads"); + int init_ret = fftwf_init_threads (); + if (! init_ret) + (*current_liboctave_error_handler) ("Error initializing FFTW3F threads"); - // Use number of processors available to the current process - // This can be later changed with fftw ("threads", nthreads). - nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT); - fftwf_plan_with_nthreads (nthreads); + // Use number of processors available to the current process + // This can be later changed with fftw ("threads", nthreads). + nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT); + fftwf_plan_with_nthreads (nthreads); #endif - // If we have a system wide wisdom file, import it. - fftwf_import_system_wisdom (); -} + // If we have a system wide wisdom file, import it. + fftwf_import_system_wisdom (); + } -octave_float_fftw_planner::~octave_float_fftw_planner (void) -{ - fftwf_plan *plan_p; + float_fftw_planner::~float_fftw_planner (void) + { + fftwf_plan *plan_p; - plan_p = reinterpret_cast<fftwf_plan *> (&rplan); - if (*plan_p) - fftwf_destroy_plan (*plan_p); + plan_p = reinterpret_cast<fftwf_plan *> (&rplan); + if (*plan_p) + fftwf_destroy_plan (*plan_p); - plan_p = reinterpret_cast<fftwf_plan *> (&plan[0]); - if (*plan_p) - fftwf_destroy_plan (*plan_p); + plan_p = reinterpret_cast<fftwf_plan *> (&plan[0]); + if (*plan_p) + fftwf_destroy_plan (*plan_p); - plan_p = reinterpret_cast<fftwf_plan *> (&plan[1]); - if (*plan_p) - fftwf_destroy_plan (*plan_p); -} + plan_p = reinterpret_cast<fftwf_plan *> (&plan[1]); + if (*plan_p) + fftwf_destroy_plan (*plan_p); + } -bool -octave_float_fftw_planner::instance_ok (void) -{ - bool retval = true; + bool + float_fftw_planner::instance_ok (void) + { + bool retval = true; - if (! instance) - { - instance = new octave_float_fftw_planner (); + if (! instance) + { + instance = new float_fftw_planner (); - if (instance) - singleton_cleanup_list::add (cleanup_instance); - } + if (instance) + singleton_cleanup_list::add (cleanup_instance); + } - if (! instance) - (*current_liboctave_error_handler) - ("unable to create octave_fftw_planner object!"); + if (! instance) + (*current_liboctave_error_handler) + ("unable to create fftw_planner object!"); - return retval; -} + return retval; + } -void -octave_float_fftw_planner::threads (int nt) -{ + void + float_fftw_planner::threads (int nt) + { #if defined (HAVE_FFTW3F_THREADS) - if (instance_ok () && nt != threads ()) - { - instance->nthreads = nt; - fftwf_plan_with_nthreads (nt); - // Clear the current plans. - instance->rplan = instance->plan[0] = instance->plan[1] = 0; - } + if (instance_ok () && nt != threads ()) + { + instance->nthreads = nt; + fftwf_plan_with_nthreads (nt); + // Clear the current plans. + instance->rplan = instance->plan[0] = instance->plan[1] = 0; + } #else - (*current_liboctave_warning_handler) - ("unable to change number of threads without FFTW thread support"); + (*current_liboctave_warning_handler) + ("unable to change number of threads without FFTW thread support"); #endif -} + } + + void * + float_fftw_planner::do_create_plan (int dir, const int rank, + const dim_vector dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const FloatComplex *in, + FloatComplex *out) + { + int which = (dir == FFTW_FORWARD) ? 0 : 1; + fftwf_plan *cur_plan_p = reinterpret_cast<fftwf_plan *> (&plan[which]); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + bool ioinplace = (in == out); + + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. + + if (plan[which] == 0 || d[which] != dist || s[which] != stride + || r[which] != rank || h[which] != howmany + || ioinplace != inplace[which] + || ((ioalign != simd_align[which]) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. -void * -octave_float_fftw_planner::do_create_plan (int dir, const int rank, - const dim_vector dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const FloatComplex *in, - FloatComplex *out) -{ - int which = (dir == FFTW_FORWARD) ? 0 : 1; - fftwf_plan *cur_plan_p = reinterpret_cast<fftwf_plan *> (&plan[which]); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - bool ioinplace = (in == out); + for (int i = 0; i < rank; i++) + if (dims(i) != n[which](i)) + { + create_new_plan = true; + break; + } + } + + if (create_new_plan) + { + d[which] = dist; + s[which] = stride; + r[which] = rank; + h[which] = howmany; + simd_align[which] = ioalign; + inplace[which] = ioinplace; + n[which] = dims; + + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); + + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. + int plan_flags = 0; + bool plan_destroys_in = true; - if (plan[which] == 0 || d[which] != dist || s[which] != stride - || r[which] != rank || h[which] != howmany - || ioinplace != inplace[which] - || ((ioalign != simd_align[which]) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. - - for (int i = 0; i < rank; i++) - if (dims(i) != n[which](i)) + switch (meth) { - create_new_plan = true; + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } break; } - } - if (create_new_plan) - { - d[which] = dist; - s[which] = stride; - r[which] = rank; - h[which] = howmany; - simd_align[which] = ioalign; - inplace[which] = ioinplace; - n[which] = dims; + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); + if (*cur_plan_p) + fftwf_destroy_plan (*cur_plan_p); - for (int i = 0, j = rank-1; i < rank; i++, j--) - { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (FloatComplex, itmp, nn * howmany + 32); + itmp = reinterpret_cast<FloatComplex *> + (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + + ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); - switch (meth) - { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } - break; - } + *cur_plan_p = + fftwf_plan_many_dft (rank, tmp, howmany, + reinterpret_cast<fftwf_complex *> (itmp), + 0, stride, dist, + reinterpret_cast<fftwf_complex *> (out), + 0, stride, dist, dir, plan_flags); + } + else + { + *cur_plan_p = + fftwf_plan_many_dft (rank, tmp, howmany, + reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *> (in)), + 0, stride, dist, + reinterpret_cast<fftwf_complex *> (out), + 0, stride, dist, dir, plan_flags); + } - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + if (*cur_plan_p == 0) + (*current_liboctave_error_handler) ("Error creating fftw plan"); + } + + return *cur_plan_p; + } - if (*cur_plan_p) - fftwf_destroy_plan (*cur_plan_p); + void * + float_fftw_planner::do_create_plan (const int rank, const dim_vector dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const float *in, FloatComplex *out) + { + fftwf_plan *cur_plan_p = reinterpret_cast<fftwf_plan *> (&rplan); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (FloatComplex, itmp, nn * howmany + 32); - itmp = reinterpret_cast<FloatComplex *> - (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + - ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); + if (rplan == 0 || rd != dist || rs != stride || rr != rank + || rh != howmany || ((ioalign != rsimd_align) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. - *cur_plan_p = - fftwf_plan_many_dft (rank, tmp, howmany, - reinterpret_cast<fftwf_complex *> (itmp), - 0, stride, dist, - reinterpret_cast<fftwf_complex *> (out), - 0, stride, dist, dir, plan_flags); - } - else - { - *cur_plan_p = - fftwf_plan_many_dft (rank, tmp, howmany, - reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *> (in)), - 0, stride, dist, - reinterpret_cast<fftwf_complex *> (out), - 0, stride, dist, dir, plan_flags); - } + for (int i = 0; i < rank; i++) + if (dims(i) != rn(i)) + { + create_new_plan = true; + break; + } + } - if (*cur_plan_p == 0) - (*current_liboctave_error_handler) ("Error creating fftw plan"); - } + if (create_new_plan) + { + rd = dist; + rs = stride; + rr = rank; + rh = howmany; + rsimd_align = ioalign; + rn = dims; + + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); - return *cur_plan_p; -} + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } -void * -octave_float_fftw_planner::do_create_plan (const int rank, - const dim_vector dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const float *in, FloatComplex *out) -{ - fftwf_plan *cur_plan_p = reinterpret_cast<fftwf_plan *> (&rplan); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + int plan_flags = 0; + bool plan_destroys_in = true; - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. - - if (rplan == 0 || rd != dist || rs != stride || rr != rank - || rh != howmany || ((ioalign != rsimd_align) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. - - for (int i = 0; i < rank; i++) - if (dims(i) != rn(i)) + switch (meth) { - create_new_plan = true; + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } break; } - } + + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - if (create_new_plan) - { - rd = dist; - rs = stride; - rr = rank; - rh = howmany; - rsimd_align = ioalign; - rn = dims; + if (*cur_plan_p) + fftwf_destroy_plan (*cur_plan_p); + + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (float, itmp, nn + 32); + itmp = reinterpret_cast<float *> + (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + + ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); + *cur_plan_p = + fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp, + 0, stride, dist, + reinterpret_cast<fftwf_complex *> (out), + 0, stride, dist, plan_flags); + } + else + { + *cur_plan_p = + fftwf_plan_many_dft_r2c (rank, tmp, howmany, + (const_cast<float *> (in)), + 0, stride, dist, + reinterpret_cast<fftwf_complex *> (out), + 0, stride, dist, plan_flags); + } - for (int i = 0, j = rank-1; i < rank; i++, j--) - { - tmp[i] = dims(j); - nn *= dims(j); - } + if (*cur_plan_p == 0) + (*current_liboctave_error_handler) ("Error creating fftw plan"); + } - int plan_flags = 0; - bool plan_destroys_in = true; + return *cur_plan_p; + } + + float_fftw_planner::FftwMethod + float_fftw_planner::do_method (void) + { + return meth; + } - switch (meth) - { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } - break; - } - - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; - - if (*cur_plan_p) - fftwf_destroy_plan (*cur_plan_p); + float_fftw_planner::FftwMethod + float_fftw_planner::do_method (FftwMethod _meth) + { + FftwMethod ret = meth; + if (_meth == ESTIMATE || _meth == MEASURE + || _meth == PATIENT || _meth == EXHAUSTIVE + || _meth == HYBRID) + { + if (meth != _meth) + { + meth = _meth; + if (rplan) + fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (rplan)); + if (plan[0]) + fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (plan[0])); + if (plan[1]) + fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (plan[1])); + rplan = plan[0] = plan[1] = 0; + } + } + else + ret = UNKNOWN; + return ret; + } - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (float, itmp, nn + 32); - itmp = reinterpret_cast<float *> - (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) + - ((reinterpret_cast<ptrdiff_t> (in)) & 0xF)); + template <typename T> + static inline void + convert_packcomplex_1d (T *out, size_t nr, size_t nc, + octave_idx_type stride, octave_idx_type dist) + { + octave_quit (); + + // Fill in the missing data. + + for (size_t i = 0; i < nr; i++) + for (size_t j = nc/2+1; j < nc; j++) + out[j*stride + i*dist] = conj (out[(nc - j)*stride + i*dist]); - *cur_plan_p = - fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp, - 0, stride, dist, - reinterpret_cast<fftwf_complex *> (out), - 0, stride, dist, plan_flags); - } - else - { - *cur_plan_p = - fftwf_plan_many_dft_r2c (rank, tmp, howmany, - (const_cast<float *> (in)), - 0, stride, dist, - reinterpret_cast<fftwf_complex *> (out), - 0, stride, dist, plan_flags); - } + octave_quit (); + } - if (*cur_plan_p == 0) - (*current_liboctave_error_handler) ("Error creating fftw plan"); - } + template <typename T> + static inline void + convert_packcomplex_Nd (T *out, const dim_vector &dv) + { + size_t nc = dv(0); + size_t nr = dv(1); + size_t np = (dv.ndims () > 2 ? dv.numel () / nc / nr : 1); + size_t nrp = nr * np; + T *ptr1, *ptr2; - return *cur_plan_p; -} + octave_quit (); -octave_float_fftw_planner::FftwMethod -octave_float_fftw_planner::do_method (void) -{ - return meth; -} + // Create space for the missing elements. -octave_float_fftw_planner::FftwMethod -octave_float_fftw_planner::do_method (FftwMethod _meth) -{ - FftwMethod ret = meth; - if (_meth == ESTIMATE || _meth == MEASURE - || _meth == PATIENT || _meth == EXHAUSTIVE - || _meth == HYBRID) - { - if (meth != _meth) - { - meth = _meth; - if (rplan) - fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (rplan)); - if (plan[0]) - fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (plan[0])); - if (plan[1]) - fftwf_destroy_plan (reinterpret_cast<fftwf_plan> (plan[1])); - rplan = plan[0] = plan[1] = 0; - } - } - else - ret = UNKNOWN; - return ret; -} + for (size_t i = 0; i < nrp; i++) + { + ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2); + ptr2 = out + i * nc; + for (size_t j = 0; j < nc/2+1; j++) + *ptr2++ = *ptr1++; + } + + octave_quit (); + + // Fill in the missing data for the rank = 2 case directly for speed. -template <typename T> -static inline void -convert_packcomplex_1d (T *out, size_t nr, size_t nc, - octave_idx_type stride, octave_idx_type dist) -{ - octave_quit (); + for (size_t i = 0; i < np; i++) + { + for (size_t j = 1; j < nr; j++) + for (size_t k = nc/2+1; k < nc; k++) + out[k + (j + i*nr)*nc] = conj (out[nc - k + ((i+1)*nr - j)*nc]); + + for (size_t j = nc/2+1; j < nc; j++) + out[j + i*nr*nc] = conj (out[(i*nr+1)*nc - j]); + } + + octave_quit (); - // Fill in the missing data. + // Now do the permutations needed for rank > 2 cases. - for (size_t i = 0; i < nr; i++) - for (size_t j = nc/2+1; j < nc; j++) - out[j*stride + i*dist] = conj (out[(nc - j)*stride + i*dist]); - - octave_quit (); -} + size_t jstart = dv(0) * dv(1); + size_t kstep = dv(0); + size_t nel = dv.numel (); -template <typename T> -static inline void -convert_packcomplex_Nd (T *out, const dim_vector &dv) -{ - size_t nc = dv(0); - size_t nr = dv(1); - size_t np = (dv.ndims () > 2 ? dv.numel () / nc / nr : 1); - size_t nrp = nr * np; - T *ptr1, *ptr2; - - octave_quit (); + for (int inner = 2; inner < dv.ndims (); inner++) + { + size_t jmax = jstart * dv(inner); + for (size_t i = 0; i < nel; i+=jmax) + for (size_t j = jstart, jj = jmax-jstart; j < jj; + j+=jstart, jj-=jstart) + for (size_t k = 0; k < jstart; k+= kstep) + for (size_t l = nc/2+1; l < nc; l++) + { + T tmp = out[i+ j + k + l]; + out[i + j + k + l] = out[i + jj + k + l]; + out[i + jj + k + l] = tmp; + } + jstart = jmax; + } - // Create space for the missing elements. - - for (size_t i = 0; i < nrp; i++) - { - ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2); - ptr2 = out + i * nc; - for (size_t j = 0; j < nc/2+1; j++) - *ptr2++ = *ptr1++; - } - - octave_quit (); - - // Fill in the missing data for the rank = 2 case directly for speed. + octave_quit (); + } - for (size_t i = 0; i < np; i++) - { - for (size_t j = 1; j < nr; j++) - for (size_t k = nc/2+1; k < nc; k++) - out[k + (j + i*nr)*nc] = conj (out[nc - k + ((i+1)*nr - j)*nc]); + int + fftw::fft (const double *in, Complex *out, size_t npts, + size_t nsamples, octave_idx_type stride, octave_idx_type dist) + { + dist = (dist < 0 ? npts : dist); - for (size_t j = nc/2+1; j < nc; j++) - out[j + i*nr*nc] = conj (out[(i*nr+1)*nc - j]); - } - - octave_quit (); - - // Now do the permutations needed for rank > 2 cases. - - size_t jstart = dv(0) * dv(1); - size_t kstep = dv(0); - size_t nel = dv.numel (); + dim_vector dv (npts, 1); + void *vplan = fftw_planner::create_plan (1, dv, nsamples, + stride, dist, in, out); + fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); - for (int inner = 2; inner < dv.ndims (); inner++) - { - size_t jmax = jstart * dv(inner); - for (size_t i = 0; i < nel; i+=jmax) - for (size_t j = jstart, jj = jmax-jstart; j < jj; - j+=jstart, jj-=jstart) - for (size_t k = 0; k < jstart; k+= kstep) - for (size_t l = nc/2+1; l < nc; l++) - { - T tmp = out[i+ j + k + l]; - out[i + j + k + l] = out[i + jj + k + l]; - out[i + jj + k + l] = tmp; - } - jstart = jmax; - } + fftw_execute_dft_r2c (plan, (const_cast<double *>(in)), + reinterpret_cast<fftw_complex *> (out)); + + // Need to create other half of the transform. + + convert_packcomplex_1d (out, nsamples, npts, stride, dist); - octave_quit (); -} + return 0; + } + + int + fftw::fft (const Complex *in, Complex *out, size_t npts, + size_t nsamples, octave_idx_type stride, octave_idx_type dist) + { + dist = (dist < 0 ? npts : dist); -int -octave_fftw::fft (const double *in, Complex *out, size_t npts, - size_t nsamples, octave_idx_type stride, octave_idx_type dist) -{ - dist = (dist < 0 ? npts : dist); + dim_vector dv (npts, 1); + void *vplan = fftw_planner::create_plan (FFTW_FORWARD, 1, dv, + nsamples, stride, + dist, in, out); + fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); - dim_vector dv (npts, 1); - void *vplan = octave_fftw_planner::create_plan (1, dv, nsamples, - stride, dist, in, out); - fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); + fftw_execute_dft (plan, + reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), + reinterpret_cast<fftw_complex *> (out)); - fftw_execute_dft_r2c (plan, (const_cast<double *>(in)), - reinterpret_cast<fftw_complex *> (out)); - - // Need to create other half of the transform. - - convert_packcomplex_1d (out, nsamples, npts, stride, dist); + return 0; + } - return 0; -} - -int -octave_fftw::fft (const Complex *in, Complex *out, size_t npts, - size_t nsamples, octave_idx_type stride, octave_idx_type dist) -{ - dist = (dist < 0 ? npts : dist); + int + fftw::ifft (const Complex *in, Complex *out, size_t npts, + size_t nsamples, octave_idx_type stride, + octave_idx_type dist) + { + dist = (dist < 0 ? npts : dist); - dim_vector dv (npts, 1); - void *vplan = octave_fftw_planner::create_plan (FFTW_FORWARD, 1, dv, - nsamples, stride, - dist, in, out); - fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); + dim_vector dv (npts, 1); + void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, nsamples, + stride, dist, in, out); + fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); - fftw_execute_dft (plan, - reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), - reinterpret_cast<fftw_complex *> (out)); + fftw_execute_dft (plan, + reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), + reinterpret_cast<fftw_complex *> (out)); - return 0; -} + const Complex scale = npts; + for (size_t j = 0; j < nsamples; j++) + for (size_t i = 0; i < npts; i++) + out[i*stride + j*dist] /= scale; -int -octave_fftw::ifft (const Complex *in, Complex *out, size_t npts, - size_t nsamples, octave_idx_type stride, - octave_idx_type dist) -{ - dist = (dist < 0 ? npts : dist); + return 0; + } - dim_vector dv (npts, 1); - void *vplan = octave_fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, - nsamples, stride, - dist, in, out); - fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); + int + fftw::fftNd (const double *in, Complex *out, const int rank, + const dim_vector &dv) + { + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - fftw_execute_dft (plan, - reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), - reinterpret_cast<fftw_complex *> (out)); + // Fool with the position of the start of the output matrix, so that + // creating other half of the matrix won't cause cache problems. - const Complex scale = npts; - for (size_t j = 0; j < nsamples; j++) - for (size_t i = 0; i < npts; i++) - out[i*stride + j*dist] /= scale; + octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); + + void *vplan = fftw_planner::create_plan (rank, dv, 1, 1, dist, + in, out + offset); + fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); - return 0; -} + fftw_execute_dft_r2c (plan, (const_cast<double *>(in)), + reinterpret_cast<fftw_complex *> (out+ offset)); + + // Need to create other half of the transform. -int -octave_fftw::fftNd (const double *in, Complex *out, const int rank, - const dim_vector &dv) -{ - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + convert_packcomplex_Nd (out, dv); - // Fool with the position of the start of the output matrix, so that - // creating other half of the matrix won't cause cache problems. + return 0; + } - octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); - - void *vplan = octave_fftw_planner::create_plan (rank, dv, 1, 1, dist, - in, out + offset); - fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); + int + fftw::fftNd (const Complex *in, Complex *out, const int rank, + const dim_vector &dv) + { + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - fftw_execute_dft_r2c (plan, (const_cast<double *>(in)), - reinterpret_cast<fftw_complex *> (out+ offset)); - - // Need to create other half of the transform. + void *vplan = fftw_planner::create_plan (FFTW_FORWARD, rank, dv, + 1, 1, dist, in, out); + fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); - convert_packcomplex_Nd (out, dv); - - return 0; -} + fftw_execute_dft (plan, + reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), + reinterpret_cast<fftw_complex *> (out)); -int -octave_fftw::fftNd (const Complex *in, Complex *out, const int rank, - const dim_vector &dv) -{ - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + return 0; + } - void *vplan = octave_fftw_planner::create_plan (FFTW_FORWARD, rank, - dv, 1, 1, dist, in, out); - fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); + int + fftw::ifftNd (const Complex *in, Complex *out, const int rank, + const dim_vector &dv) + { + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - fftw_execute_dft (plan, - reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), - reinterpret_cast<fftw_complex *> (out)); + void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, rank, dv, + 1, 1, dist, in, out); + fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); - return 0; -} + fftw_execute_dft (plan, + reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), + reinterpret_cast<fftw_complex *> (out)); -int -octave_fftw::ifftNd (const Complex *in, Complex *out, const int rank, - const dim_vector &dv) -{ - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + const size_t npts = dv.numel (); + const Complex scale = npts; + for (size_t i = 0; i < npts; i++) + out[i] /= scale; - void *vplan = octave_fftw_planner::create_plan (FFTW_BACKWARD, rank, - dv, 1, 1, dist, in, out); - fftw_plan plan = reinterpret_cast<fftw_plan> (vplan); + return 0; + } - fftw_execute_dft (plan, - reinterpret_cast<fftw_complex *> (const_cast<Complex *>(in)), - reinterpret_cast<fftw_complex *> (out)); + int + fftw::fft (const float *in, FloatComplex *out, size_t npts, + size_t nsamples, octave_idx_type stride, octave_idx_type dist) + { + dist = (dist < 0 ? npts : dist); - const size_t npts = dv.numel (); - const Complex scale = npts; - for (size_t i = 0; i < npts; i++) - out[i] /= scale; - - return 0; -} + dim_vector dv (npts, 1); + void *vplan = float_fftw_planner::create_plan (1, dv, nsamples, stride, + dist, in, out); + fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); -int -octave_fftw::fft (const float *in, FloatComplex *out, size_t npts, - size_t nsamples, octave_idx_type stride, octave_idx_type dist) -{ - dist = (dist < 0 ? npts : dist); + fftwf_execute_dft_r2c (plan, (const_cast<float *>(in)), + reinterpret_cast<fftwf_complex *> (out)); + + // Need to create other half of the transform. + + convert_packcomplex_1d (out, nsamples, npts, stride, dist); - dim_vector dv (npts, 1); - void *vplan = octave_float_fftw_planner::create_plan (1, dv, nsamples, - stride, dist, - in, out); - fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + return 0; + } - fftwf_execute_dft_r2c (plan, (const_cast<float *>(in)), - reinterpret_cast<fftwf_complex *> (out)); - - // Need to create other half of the transform. - - convert_packcomplex_1d (out, nsamples, npts, stride, dist); + int + fftw::fft (const FloatComplex *in, FloatComplex *out, size_t npts, + size_t nsamples, octave_idx_type stride, octave_idx_type dist) + { + dist = (dist < 0 ? npts : dist); - return 0; -} + dim_vector dv (npts, 1); + void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, 1, dv, + nsamples, stride, dist, + in, out); + fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); -int -octave_fftw::fft (const FloatComplex *in, FloatComplex *out, size_t npts, - size_t nsamples, octave_idx_type stride, octave_idx_type dist) -{ - dist = (dist < 0 ? npts : dist); + fftwf_execute_dft (plan, + reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), + reinterpret_cast<fftwf_complex *> (out)); - dim_vector dv (npts, 1); - void *vplan = octave_float_fftw_planner::create_plan (FFTW_FORWARD, 1, - dv, nsamples, - stride, dist, - in, out); - fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + return 0; + } - fftwf_execute_dft (plan, - reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), - reinterpret_cast<fftwf_complex *> (out)); - - return 0; -} - -int -octave_fftw::ifft (const FloatComplex *in, FloatComplex *out, size_t npts, - size_t nsamples, octave_idx_type stride, - octave_idx_type dist) -{ - dist = (dist < 0 ? npts : dist); + int + fftw::ifft (const FloatComplex *in, FloatComplex *out, size_t npts, + size_t nsamples, octave_idx_type stride, + octave_idx_type dist) + { + dist = (dist < 0 ? npts : dist); - dim_vector dv (npts, 1); - void *vplan = octave_float_fftw_planner::create_plan (FFTW_BACKWARD, 1, - dv, nsamples, - stride, dist, - in, out); - fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + dim_vector dv (npts, 1); + void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, + nsamples, stride, dist, + in, out); + fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); - fftwf_execute_dft (plan, - reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), - reinterpret_cast<fftwf_complex *> (out)); + fftwf_execute_dft (plan, + reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), + reinterpret_cast<fftwf_complex *> (out)); + + const FloatComplex scale = npts; + for (size_t j = 0; j < nsamples; j++) + for (size_t i = 0; i < npts; i++) + out[i*stride + j*dist] /= scale; - const FloatComplex scale = npts; - for (size_t j = 0; j < nsamples; j++) - for (size_t i = 0; i < npts; i++) - out[i*stride + j*dist] /= scale; - - return 0; -} + return 0; + } -int -octave_fftw::fftNd (const float *in, FloatComplex *out, const int rank, - const dim_vector &dv) -{ - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + int + fftw::fftNd (const float *in, FloatComplex *out, const int rank, + const dim_vector &dv) + { + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - // Fool with the position of the start of the output matrix, so that - // creating other half of the matrix won't cause cache problems. + // Fool with the position of the start of the output matrix, so that + // creating other half of the matrix won't cause cache problems. + + octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); - octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); - - void *vplan = octave_float_fftw_planner::create_plan (rank, dv, 1, 1, - dist, in, - out + offset); - fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + void *vplan = float_fftw_planner::create_plan (rank, dv, 1, 1, dist, + in, out + offset); + fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); - fftwf_execute_dft_r2c (plan, (const_cast<float *>(in)), - reinterpret_cast<fftwf_complex *> (out+ offset)); + fftwf_execute_dft_r2c (plan, (const_cast<float *>(in)), + reinterpret_cast<fftwf_complex *> (out+ offset)); - // Need to create other half of the transform. + // Need to create other half of the transform. - convert_packcomplex_Nd (out, dv); + convert_packcomplex_Nd (out, dv); - return 0; -} + return 0; + } -int -octave_fftw::fftNd (const FloatComplex *in, FloatComplex *out, const int rank, - const dim_vector &dv) -{ - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + int + fftw::fftNd (const FloatComplex *in, FloatComplex *out, const int rank, + const dim_vector &dv) + { + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - void *vplan = octave_float_fftw_planner::create_plan (FFTW_FORWARD, - rank, dv, 1, 1, - dist, in, out); - fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, rank, dv, + 1, 1, dist, in, out); + fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); - fftwf_execute_dft (plan, - reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), - reinterpret_cast<fftwf_complex *> (out)); + fftwf_execute_dft (plan, + reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), + reinterpret_cast<fftwf_complex *> (out)); - return 0; -} + return 0; + } -int -octave_fftw::ifftNd (const FloatComplex *in, FloatComplex *out, const int rank, - const dim_vector &dv) -{ - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + int + fftw::ifftNd (const FloatComplex *in, FloatComplex *out, const int rank, + const dim_vector &dv) + { + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - void *vplan = octave_float_fftw_planner::create_plan (FFTW_BACKWARD, - rank, dv, 1, 1, - dist, in, out); - fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, rank, dv, + 1, 1, dist, in, out); + fftwf_plan plan = reinterpret_cast<fftwf_plan> (vplan); + + fftwf_execute_dft (plan, + reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), + reinterpret_cast<fftwf_complex *> (out)); - fftwf_execute_dft (plan, - reinterpret_cast<fftwf_complex *> (const_cast<FloatComplex *>(in)), - reinterpret_cast<fftwf_complex *> (out)); + const size_t npts = dv.numel (); + const FloatComplex scale = npts; + for (size_t i = 0; i < npts; i++) + out[i] /= scale; - const size_t npts = dv.numel (); - const FloatComplex scale = npts; - for (size_t i = 0; i < npts; i++) - out[i] /= scale; - - return 0; -} + return 0; + } #endif -std::string -octave_fftw_version (void) -{ + std::string + fftw_version (void) + { #if defined (HAVE_FFTW) - return fftw_version; + return ::fftw_version; #else - return "none"; + return "none"; #endif -} + } -std::string -octave_fftwf_version (void) -{ + std::string + fftwf_version (void) + { #if defined (HAVE_FFTW) - return fftwf_version; + return ::fftwf_version; #else - return "none"; + return "none"; #endif + } } -