26 #if defined (HAVE_CONFIG_H)
30 #if defined (HAVE_FFTW3_H)
40 #if defined (HAVE_FFTW3_THREADS) || defined (HAVE_FFTW3F_THREADS)
46 #if defined (HAVE_FFTW)
69 : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0),
70 m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1)
78 #if defined (HAVE_FFTW3_THREADS)
79 int init_ret = fftw_init_threads ();
81 (*current_liboctave_error_handler) (
"Error initializing FFTW threads");
97 fftw_import_system_wisdom ();
104 plan_p =
reinterpret_cast<fftw_plan *
> (&
m_rplan);
106 fftw_destroy_plan (*plan_p);
108 plan_p =
reinterpret_cast<fftw_plan *
> (&
m_plan[0]);
110 fftw_destroy_plan (*plan_p);
112 plan_p =
reinterpret_cast<fftw_plan *
> (&
m_plan[1]);
114 fftw_destroy_plan (*plan_p);
134 #if defined (HAVE_FFTW3_THREADS)
138 fftw_plan_with_nthreads (nt);
144 octave_unused_parameter (nt);
146 (*current_liboctave_warning_handler)
147 (
"unable to change number of threads without FFTW thread support");
151 #define CHECK_SIMD_ALIGNMENT(x) \
152 (((reinterpret_cast<std::ptrdiff_t> (x)) & 0xF) == 0)
162 int which = (dir == FFTW_FORWARD) ? 0 : 1;
163 fftw_plan *cur_plan_p =
reinterpret_cast<fftw_plan *
> (&
m_plan[which]);
164 bool create_new_plan =
false;
166 bool ioinplace = (in == out);
172 if (
m_plan[which] ==
nullptr ||
m_d[which] != dist ||
m_s[which] != stride
173 ||
m_r[which] != rank ||
m_h[which] != howmany
175 || ((ioalign !=
m_simd_align[which]) ? ! ioalign :
false))
176 create_new_plan =
true;
181 for (
int i = 0; i < rank; i++)
182 if (dims(i) !=
m_n[which](i))
184 create_new_plan =
true;
194 m_h[which] = howmany;
203 for (
int i = 0, j = rank-1; i < rank; i++, j--)
210 bool plan_destroys_in =
true;
216 plan_flags |= FFTW_ESTIMATE;
217 plan_destroys_in =
false;
220 plan_flags |= FFTW_MEASURE;
223 plan_flags |= FFTW_PATIENT;
226 plan_flags |= FFTW_EXHAUSTIVE;
230 plan_flags |= FFTW_MEASURE;
233 plan_flags |= FFTW_ESTIMATE;
234 plan_destroys_in =
false;
240 plan_flags &= ~FFTW_UNALIGNED;
242 plan_flags |= FFTW_UNALIGNED;
245 fftw_destroy_plan (*cur_plan_p);
247 if (plan_destroys_in)
251 itmp =
reinterpret_cast<Complex *
>
252 (((
reinterpret_cast<std::ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
253 ((
reinterpret_cast<std::ptrdiff_t
> (in)) & 0xF));
256 = fftw_plan_many_dft (rank, tmp, howmany,
257 reinterpret_cast<fftw_complex *
> (itmp),
258 nullptr, stride, dist,
259 reinterpret_cast<fftw_complex *
> (out),
260 nullptr, stride, dist, dir, plan_flags);
265 = fftw_plan_many_dft (rank, tmp, howmany,
266 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
> (in)),
267 nullptr, stride, dist,
268 reinterpret_cast<fftw_complex *
> (out),
269 nullptr, stride, dist, dir, plan_flags);
272 if (*cur_plan_p ==
nullptr)
273 (*current_liboctave_error_handler) (
"Error creating FFTW plan");
284 const double *in,
Complex *out)
286 fftw_plan *cur_plan_p =
reinterpret_cast<fftw_plan *
> (&
m_rplan);
287 bool create_new_plan =
false;
296 create_new_plan =
true;
301 for (
int i = 0; i < rank; i++)
302 if (dims(i) !=
m_rn(i))
304 create_new_plan =
true;
322 for (
int i = 0, j = rank-1; i < rank; i++, j--)
329 bool plan_destroys_in =
true;
335 plan_flags |= FFTW_ESTIMATE;
336 plan_destroys_in =
false;
339 plan_flags |= FFTW_MEASURE;
342 plan_flags |= FFTW_PATIENT;
345 plan_flags |= FFTW_EXHAUSTIVE;
349 plan_flags |= FFTW_MEASURE;
352 plan_flags |= FFTW_ESTIMATE;
353 plan_destroys_in =
false;
359 plan_flags &= ~FFTW_UNALIGNED;
361 plan_flags |= FFTW_UNALIGNED;
364 fftw_destroy_plan (*cur_plan_p);
366 if (plan_destroys_in)
370 itmp =
reinterpret_cast<double *
>
371 (((
reinterpret_cast<std::ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
372 ((
reinterpret_cast<std::ptrdiff_t
> (in)) & 0xF));
375 = fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp,
376 nullptr, stride, dist,
377 reinterpret_cast<fftw_complex *
> (out),
378 nullptr, stride, dist, plan_flags);
383 = fftw_plan_many_dft_r2c (rank, tmp, howmany,
384 (
const_cast<double *
> (in)),
385 nullptr, stride, dist,
386 reinterpret_cast<fftw_complex *
> (out),
387 nullptr, stride, dist, plan_flags);
390 if (*cur_plan_p ==
nullptr)
391 (*current_liboctave_error_handler) (
"Error creating FFTW plan");
415 fftw_destroy_plan (
reinterpret_cast<fftw_plan
> (
m_rplan));
417 fftw_destroy_plan (
reinterpret_cast<fftw_plan
> (
m_plan[0]));
419 fftw_destroy_plan (
reinterpret_cast<fftw_plan
> (
m_plan[1]));
431 : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0),
432 m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1)
440 #if defined (HAVE_FFTW3F_THREADS)
441 int init_ret = fftwf_init_threads ();
443 (*current_liboctave_error_handler) (
"Error initializing FFTW3F threads");
454 fftwf_import_system_wisdom ();
461 plan_p =
reinterpret_cast<fftwf_plan *
> (&
m_rplan);
463 fftwf_destroy_plan (*plan_p);
465 plan_p =
reinterpret_cast<fftwf_plan *
> (&
m_plan[0]);
467 fftwf_destroy_plan (*plan_p);
469 plan_p =
reinterpret_cast<fftwf_plan *
> (&
m_plan[1]);
471 fftwf_destroy_plan (*plan_p);
491 #if defined (HAVE_FFTW3F_THREADS)
495 fftwf_plan_with_nthreads (nt);
501 octave_unused_parameter (nt);
503 (*current_liboctave_warning_handler)
504 (
"unable to change number of threads without FFTW thread support");
517 int which = (dir == FFTW_FORWARD) ? 0 : 1;
518 fftwf_plan *cur_plan_p =
reinterpret_cast<fftwf_plan *
> (&
m_plan[which]);
519 bool create_new_plan =
false;
521 bool ioinplace = (in == out);
527 if (
m_plan[which] ==
nullptr ||
m_d[which] != dist ||
m_s[which] != stride
528 ||
m_r[which] != rank ||
m_h[which] != howmany
530 || ((ioalign !=
m_simd_align[which]) ? ! ioalign :
false))
531 create_new_plan =
true;
536 for (
int i = 0; i < rank; i++)
537 if (dims(i) !=
m_n[which](i))
539 create_new_plan =
true;
549 m_h[which] = howmany;
558 for (
int i = 0, j = rank-1; i < rank; i++, j--)
565 bool plan_destroys_in =
true;
571 plan_flags |= FFTW_ESTIMATE;
572 plan_destroys_in =
false;
575 plan_flags |= FFTW_MEASURE;
578 plan_flags |= FFTW_PATIENT;
581 plan_flags |= FFTW_EXHAUSTIVE;
585 plan_flags |= FFTW_MEASURE;
588 plan_flags |= FFTW_ESTIMATE;
589 plan_destroys_in =
false;
595 plan_flags &= ~FFTW_UNALIGNED;
597 plan_flags |= FFTW_UNALIGNED;
600 fftwf_destroy_plan (*cur_plan_p);
602 if (plan_destroys_in)
607 (((
reinterpret_cast<std::ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
608 ((
reinterpret_cast<std::ptrdiff_t
> (in)) & 0xF));
611 = fftwf_plan_many_dft (rank, tmp, howmany,
612 reinterpret_cast<fftwf_complex *
> (itmp),
613 nullptr, stride, dist,
614 reinterpret_cast<fftwf_complex *
> (out),
615 nullptr, stride, dist, dir, plan_flags);
620 = fftwf_plan_many_dft (rank, tmp, howmany,
621 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
> (in)),
622 nullptr, stride, dist,
623 reinterpret_cast<fftwf_complex *
> (out),
624 nullptr, stride, dist, dir, plan_flags);
627 if (*cur_plan_p ==
nullptr)
628 (*current_liboctave_error_handler) (
"Error creating FFTW plan");
641 fftwf_plan *cur_plan_p =
reinterpret_cast<fftwf_plan *
> (&
m_rplan);
642 bool create_new_plan =
false;
651 create_new_plan =
true;
656 for (
int i = 0; i < rank; i++)
657 if (dims(i) !=
m_rn(i))
659 create_new_plan =
true;
677 for (
int i = 0, j = rank-1; i < rank; i++, j--)
684 bool plan_destroys_in =
true;
690 plan_flags |= FFTW_ESTIMATE;
691 plan_destroys_in =
false;
694 plan_flags |= FFTW_MEASURE;
697 plan_flags |= FFTW_PATIENT;
700 plan_flags |= FFTW_EXHAUSTIVE;
704 plan_flags |= FFTW_MEASURE;
707 plan_flags |= FFTW_ESTIMATE;
708 plan_destroys_in =
false;
714 plan_flags &= ~FFTW_UNALIGNED;
716 plan_flags |= FFTW_UNALIGNED;
719 fftwf_destroy_plan (*cur_plan_p);
721 if (plan_destroys_in)
725 itmp =
reinterpret_cast<float *
>
726 (((
reinterpret_cast<std::ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
727 ((
reinterpret_cast<std::ptrdiff_t
> (in)) & 0xF));
730 = fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp,
731 nullptr, stride, dist,
732 reinterpret_cast<fftwf_complex *
> (out),
733 nullptr, stride, dist, plan_flags);
738 = fftwf_plan_many_dft_r2c (rank, tmp, howmany,
739 (
const_cast<float *
> (in)),
740 nullptr, stride, dist,
741 reinterpret_cast<fftwf_complex *
> (out),
742 nullptr, stride, dist, plan_flags);
745 if (*cur_plan_p ==
nullptr)
746 (*current_liboctave_error_handler) (
"Error creating FFTW plan");
770 fftwf_destroy_plan (
reinterpret_cast<fftwf_plan
> (
m_rplan));
772 fftwf_destroy_plan (
reinterpret_cast<fftwf_plan
> (
m_plan[0]));
774 fftwf_destroy_plan (
reinterpret_cast<fftwf_plan
> (
m_plan[1]));
783 template <
typename T>
792 for (std::size_t i = 0; i < nr; i++)
793 for (std::size_t j = nc/2+1; j < nc; j++)
794 out[j*stride + i*dist] =
conj (out[(nc - j)*stride + i*dist]);
799 template <
typename T>
803 std::size_t nc = dv(0);
804 std::size_t nr = dv(1);
805 std::size_t np = (dv.
ndims () > 2 ? dv.
numel () / nc / nr : 1);
806 std::size_t nrp = nr * np;
813 for (std::size_t i = 0; i < nrp; i++)
815 ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2);
817 for (std::size_t j = 0; j < nc/2+1; j++)
825 for (std::size_t i = 0; i < np; i++)
827 for (std::size_t j = 1; j < nr; j++)
828 for (std::size_t k = nc/2+1; k < nc; k++)
829 out[k + (j + i*nr)*nc] =
conj (out[nc - k + ((i+1)*nr - j)*nc]);
831 for (std::size_t j = nc/2+1; j < nc; j++)
832 out[j + i*nr*nc] =
conj (out[(i*nr+1)*nc - j]);
839 std::size_t jstart = dv(0) * dv(1);
840 std::size_t kstep = dv(0);
841 std::size_t nel = dv.
numel ();
843 for (
int inner = 2; inner < dv.
ndims (); inner++)
845 std::size_t jmax = jstart * dv(inner);
846 for (std::size_t i = 0; i < nel; i+=jmax)
847 for (std::size_t j = jstart, jj = jmax-jstart; j < jj;
848 j+=jstart, jj-=jstart)
849 for (std::size_t k = 0; k < jstart; k+= kstep)
850 for (std::size_t l = nc/2+1; l < nc; l++)
852 T tmp = out[i+ j + k + l];
853 out[i + j + k + l] = out[i + jj + k + l];
854 out[i + jj + k + l] = tmp;
867 dist = (dist < 0 ? npts : dist);
871 stride, dist, in, out);
872 fftw_plan m_plan =
reinterpret_cast<fftw_plan
> (vplan);
874 fftw_execute_dft_r2c (m_plan, (
const_cast<double *
>(in)),
875 reinterpret_cast<fftw_complex *
> (out));
889 dist = (dist < 0 ? npts : dist);
895 fftw_plan m_plan =
reinterpret_cast<fftw_plan
> (vplan);
897 fftw_execute_dft (m_plan,
898 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
899 reinterpret_cast<fftw_complex *
> (out));
909 dist = (dist < 0 ? npts : dist);
913 stride, dist, in, out);
914 fftw_plan m_plan =
reinterpret_cast<fftw_plan
> (vplan);
916 fftw_execute_dft (m_plan,
917 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
918 reinterpret_cast<fftw_complex *
> (out));
921 for (std::size_t j = 0; j < nsamples; j++)
922 for (std::size_t i = 0; i < npts; i++)
923 out[i*stride + j*dist] /=
scale;
933 for (
int i = 0; i < rank; i++)
943 fftw_plan m_plan =
reinterpret_cast<fftw_plan
> (vplan);
945 fftw_execute_dft_r2c (m_plan, (
const_cast<double *
>(in)),
946 reinterpret_cast<fftw_complex *
> (out+ offset));
960 for (
int i = 0; i < rank; i++)
964 1, 1, dist, in, out);
965 fftw_plan m_plan =
reinterpret_cast<fftw_plan
> (vplan);
967 fftw_execute_dft (m_plan,
968 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
969 reinterpret_cast<fftw_complex *
> (out));
979 for (
int i = 0; i < rank; i++)
983 1, 1, dist, in, out);
984 fftw_plan m_plan =
reinterpret_cast<fftw_plan
> (vplan);
986 fftw_execute_dft (m_plan,
987 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
988 reinterpret_cast<fftw_complex *
> (out));
990 const std::size_t npts = dv.
numel ();
992 for (std::size_t i = 0; i < npts; i++)
1003 dist = (dist < 0 ? npts : dist);
1008 fftwf_plan m_plan =
reinterpret_cast<fftwf_plan
> (vplan);
1010 fftwf_execute_dft_r2c (m_plan, (
const_cast<float *
>(in)),
1011 reinterpret_cast<fftwf_complex *
> (out));
1025 dist = (dist < 0 ? npts : dist);
1029 nsamples, stride, dist,
1031 fftwf_plan m_plan =
reinterpret_cast<fftwf_plan
> (vplan);
1033 fftwf_execute_dft (m_plan,
1034 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1035 reinterpret_cast<fftwf_complex *
> (out));
1045 dist = (dist < 0 ? npts : dist);
1049 nsamples, stride, dist,
1051 fftwf_plan m_plan =
reinterpret_cast<fftwf_plan
> (vplan);
1053 fftwf_execute_dft (m_plan,
1054 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1055 reinterpret_cast<fftwf_complex *
> (out));
1058 for (std::size_t j = 0; j < nsamples; j++)
1059 for (std::size_t i = 0; i < npts; i++)
1060 out[i*stride + j*dist] /=
scale;
1070 for (
int i = 0; i < rank; i++)
1080 fftwf_plan m_plan =
reinterpret_cast<fftwf_plan
> (vplan);
1082 fftwf_execute_dft_r2c (m_plan, (
const_cast<float *
>(in)),
1083 reinterpret_cast<fftwf_complex *
> (out+ offset));
1097 for (
int i = 0; i < rank; i++)
1101 1, 1, dist, in, out);
1102 fftwf_plan m_plan =
reinterpret_cast<fftwf_plan
> (vplan);
1104 fftwf_execute_dft (m_plan,
1105 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1106 reinterpret_cast<fftwf_complex *
> (out));
1116 for (
int i = 0; i < rank; i++)
1120 1, 1, dist, in, out);
1121 fftwf_plan m_plan =
reinterpret_cast<fftwf_plan
> (vplan);
1123 fftwf_execute_dft (m_plan,
1124 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1125 reinterpret_cast<fftwf_complex *
> (out));
1127 const std::size_t npts = dv.
numel ();
1129 for (std::size_t i = 0; i < npts; i++)
1140 #if defined (HAVE_FFTW)
1150 #if defined (HAVE_FFTW)
ComplexColumnVector conj(const ComplexColumnVector &a)
Vector representing the dimensions (size) of an Array.
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
octave_idx_type ndims(void) const
Number of dimensions.
static fftw_planner * s_instance
static void cleanup_instance(void)
void * 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)
static bool instance_ok(void)
FftwMethod do_method(void)
static void * 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)
static int ifftNd(const Complex *, Complex *, const int, const dim_vector &)
static int fft(const double *in, Complex *out, std::size_t npts, std::size_t nsamples=1, octave_idx_type stride=1, octave_idx_type dist=-1)
static int ifft(const Complex *in, Complex *out, std::size_t npts, std::size_t nsamples=1, octave_idx_type stride=1, octave_idx_type dist=-1)
static int fftNd(const double *, Complex *, const int, const dim_vector &)
~float_fftw_planner(void)
static bool instance_ok(void)
static void cleanup_instance(void)
static void * 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)
void * 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)
FftwMethod do_method(void)
static float_fftw_planner * s_instance
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void scale(Matrix &m, double x, double y, double z)
unsigned long int octave_num_processors_wrapper(enum octave_nproc_query octave_query)
@ OCTAVE_NPROC_CURRENT_OVERRIDABLE
std::complex< double > Complex
std::complex< float > FloatComplex
static void convert_packcomplex_1d(T *out, std::size_t nr, std::size_t nc, octave_idx_type stride, octave_idx_type dist)
static void convert_packcomplex_Nd(T *out, const dim_vector &dv)
std::string fftwf_version(void)
#define CHECK_SIMD_ALIGNMENT(x)
std::string fftw_version(void)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)