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 : meth (ESTIMATE), rplan (nullptr), rd (0), rs (0), rr (0), rh (0), rn (),
70 rsimd_align (false), nthreads (1)
73 d[0] =
d[1] =
s[0] =
s[1] =
r[0] =
r[1] =
h[0] =
h[1] = 0;
78 #if defined (HAVE_FFTW3_THREADS)
79 int init_ret = fftw_init_threads ();
81 (*current_liboctave_error_handler) (
"Error initializing FFTW threads");
90 fftw_import_system_wisdom ();
97 plan_p =
reinterpret_cast<fftw_plan *
> (&
rplan);
99 fftw_destroy_plan (*plan_p);
101 plan_p =
reinterpret_cast<fftw_plan *
> (&
plan[0]);
103 fftw_destroy_plan (*plan_p);
105 plan_p =
reinterpret_cast<fftw_plan *
> (&
plan[1]);
107 fftw_destroy_plan (*plan_p);
127 #if defined (HAVE_FFTW3_THREADS)
131 fftw_plan_with_nthreads (nt);
136 octave_unused_parameter (nt);
138 (*current_liboctave_warning_handler)
139 (
"unable to change number of threads without FFTW thread support");
143 #define CHECK_SIMD_ALIGNMENT(x) \
144 (((reinterpret_cast<ptrdiff_t> (x)) & 0xF) == 0)
154 int which = (dir == FFTW_FORWARD) ? 0 : 1;
155 fftw_plan *cur_plan_p =
reinterpret_cast<fftw_plan *
> (&
plan[which]);
156 bool create_new_plan =
false;
158 bool ioinplace = (in == out);
164 if (
plan[which] ==
nullptr ||
d[which] != dist ||
s[which] != stride
165 ||
r[which] != rank ||
h[which] != howmany
167 || ((ioalign !=
simd_align[which]) ? ! ioalign :
false))
168 create_new_plan =
true;
173 for (
int i = 0; i < rank; i++)
174 if (dims(i) !=
n[which](i))
176 create_new_plan =
true;
195 for (
int i = 0, j = rank-1; i < rank; i++, j--)
202 bool plan_destroys_in =
true;
208 plan_flags |= FFTW_ESTIMATE;
209 plan_destroys_in =
false;
212 plan_flags |= FFTW_MEASURE;
215 plan_flags |= FFTW_PATIENT;
218 plan_flags |= FFTW_EXHAUSTIVE;
222 plan_flags |= FFTW_MEASURE;
225 plan_flags |= FFTW_ESTIMATE;
226 plan_destroys_in =
false;
232 plan_flags &= ~FFTW_UNALIGNED;
234 plan_flags |= FFTW_UNALIGNED;
237 fftw_destroy_plan (*cur_plan_p);
239 if (plan_destroys_in)
243 itmp =
reinterpret_cast<Complex *
>
244 (((
reinterpret_cast<ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
245 ((
reinterpret_cast<ptrdiff_t
> (in)) & 0xF));
248 = fftw_plan_many_dft (rank, tmp, howmany,
249 reinterpret_cast<fftw_complex *
> (itmp),
250 nullptr, stride, dist,
251 reinterpret_cast<fftw_complex *
> (out),
252 nullptr, stride, dist, dir, plan_flags);
257 = fftw_plan_many_dft (rank, tmp, howmany,
258 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
> (in)),
259 nullptr, stride, dist,
260 reinterpret_cast<fftw_complex *
> (out),
261 nullptr, stride, dist, dir, plan_flags);
264 if (*cur_plan_p ==
nullptr)
265 (*current_liboctave_error_handler) (
"Error creating fftw plan");
276 const double *in,
Complex *out)
278 fftw_plan *cur_plan_p =
reinterpret_cast<fftw_plan *
> (&
rplan);
279 bool create_new_plan =
false;
286 if (
rplan ==
nullptr ||
rd != dist ||
rs != stride ||
rr != rank
287 ||
rh != howmany || ((ioalign !=
rsimd_align) ? ! ioalign :
false))
288 create_new_plan =
true;
293 for (
int i = 0; i < rank; i++)
294 if (dims(i) !=
rn(i))
296 create_new_plan =
true;
314 for (
int i = 0, j = rank-1; i < rank; i++, j--)
321 bool plan_destroys_in =
true;
327 plan_flags |= FFTW_ESTIMATE;
328 plan_destroys_in =
false;
331 plan_flags |= FFTW_MEASURE;
334 plan_flags |= FFTW_PATIENT;
337 plan_flags |= FFTW_EXHAUSTIVE;
341 plan_flags |= FFTW_MEASURE;
344 plan_flags |= FFTW_ESTIMATE;
345 plan_destroys_in =
false;
351 plan_flags &= ~FFTW_UNALIGNED;
353 plan_flags |= FFTW_UNALIGNED;
356 fftw_destroy_plan (*cur_plan_p);
358 if (plan_destroys_in)
362 itmp =
reinterpret_cast<double *
>
363 (((
reinterpret_cast<ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
364 ((
reinterpret_cast<ptrdiff_t
> (in)) & 0xF));
367 = fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp,
368 nullptr, stride, dist,
369 reinterpret_cast<fftw_complex *
> (out),
370 nullptr, stride, dist, plan_flags);
375 = fftw_plan_many_dft_r2c (rank, tmp, howmany,
376 (
const_cast<double *
> (in)),
377 nullptr, stride, dist,
378 reinterpret_cast<fftw_complex *
> (out),
379 nullptr, stride, dist, plan_flags);
382 if (*cur_plan_p ==
nullptr)
383 (*current_liboctave_error_handler) (
"Error creating fftw plan");
407 fftw_destroy_plan (
reinterpret_cast<fftw_plan
> (
rplan));
409 fftw_destroy_plan (
reinterpret_cast<fftw_plan
> (
plan[0]));
411 fftw_destroy_plan (
reinterpret_cast<fftw_plan
> (
plan[1]));
423 : meth (ESTIMATE), rplan (nullptr), rd (0), rs (0), rr (0), rh (0), rn (),
424 rsimd_align (false), nthreads (1)
427 d[0] =
d[1] =
s[0] =
s[1] =
r[0] =
r[1] =
h[0] =
h[1] = 0;
432 #if defined (HAVE_FFTW3F_THREADS)
433 int init_ret = fftwf_init_threads ();
435 (*current_liboctave_error_handler) (
"Error initializing FFTW3F threads");
440 fftwf_plan_with_nthreads (
nthreads);
444 fftwf_import_system_wisdom ();
451 plan_p =
reinterpret_cast<fftwf_plan *
> (&
rplan);
453 fftwf_destroy_plan (*plan_p);
455 plan_p =
reinterpret_cast<fftwf_plan *
> (&
plan[0]);
457 fftwf_destroy_plan (*plan_p);
459 plan_p =
reinterpret_cast<fftwf_plan *
> (&
plan[1]);
461 fftwf_destroy_plan (*plan_p);
481 #if defined (HAVE_FFTW3F_THREADS)
485 fftwf_plan_with_nthreads (nt);
490 octave_unused_parameter (nt);
492 (*current_liboctave_warning_handler)
493 (
"unable to change number of threads without FFTW thread support");
506 int which = (dir == FFTW_FORWARD) ? 0 : 1;
507 fftwf_plan *cur_plan_p =
reinterpret_cast<fftwf_plan *
> (&
plan[which]);
508 bool create_new_plan =
false;
510 bool ioinplace = (in == out);
516 if (
plan[which] ==
nullptr ||
d[which] != dist ||
s[which] != stride
517 ||
r[which] != rank ||
h[which] != howmany
519 || ((ioalign !=
simd_align[which]) ? ! ioalign :
false))
520 create_new_plan =
true;
525 for (
int i = 0; i < rank; i++)
526 if (dims(i) !=
n[which](i))
528 create_new_plan =
true;
547 for (
int i = 0, j = rank-1; i < rank; i++, j--)
554 bool plan_destroys_in =
true;
560 plan_flags |= FFTW_ESTIMATE;
561 plan_destroys_in =
false;
564 plan_flags |= FFTW_MEASURE;
567 plan_flags |= FFTW_PATIENT;
570 plan_flags |= FFTW_EXHAUSTIVE;
574 plan_flags |= FFTW_MEASURE;
577 plan_flags |= FFTW_ESTIMATE;
578 plan_destroys_in =
false;
584 plan_flags &= ~FFTW_UNALIGNED;
586 plan_flags |= FFTW_UNALIGNED;
589 fftwf_destroy_plan (*cur_plan_p);
591 if (plan_destroys_in)
596 (((
reinterpret_cast<ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
597 ((
reinterpret_cast<ptrdiff_t
> (in)) & 0xF));
600 = fftwf_plan_many_dft (rank, tmp, howmany,
601 reinterpret_cast<fftwf_complex *
> (itmp),
602 nullptr, stride, dist,
603 reinterpret_cast<fftwf_complex *
> (out),
604 nullptr, stride, dist, dir, plan_flags);
609 = fftwf_plan_many_dft (rank, tmp, howmany,
610 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
> (in)),
611 nullptr, stride, dist,
612 reinterpret_cast<fftwf_complex *
> (out),
613 nullptr, stride, dist, dir, plan_flags);
616 if (*cur_plan_p ==
nullptr)
617 (*current_liboctave_error_handler) (
"Error creating fftw plan");
630 fftwf_plan *cur_plan_p =
reinterpret_cast<fftwf_plan *
> (&
rplan);
631 bool create_new_plan =
false;
638 if (
rplan ==
nullptr ||
rd != dist ||
rs != stride ||
rr != rank
639 ||
rh != howmany || ((ioalign !=
rsimd_align) ? ! ioalign :
false))
640 create_new_plan =
true;
645 for (
int i = 0; i < rank; i++)
646 if (dims(i) !=
rn(i))
648 create_new_plan =
true;
666 for (
int i = 0, j = rank-1; i < rank; i++, j--)
673 bool plan_destroys_in =
true;
679 plan_flags |= FFTW_ESTIMATE;
680 plan_destroys_in =
false;
683 plan_flags |= FFTW_MEASURE;
686 plan_flags |= FFTW_PATIENT;
689 plan_flags |= FFTW_EXHAUSTIVE;
693 plan_flags |= FFTW_MEASURE;
696 plan_flags |= FFTW_ESTIMATE;
697 plan_destroys_in =
false;
703 plan_flags &= ~FFTW_UNALIGNED;
705 plan_flags |= FFTW_UNALIGNED;
708 fftwf_destroy_plan (*cur_plan_p);
710 if (plan_destroys_in)
714 itmp =
reinterpret_cast<float *
>
715 (((
reinterpret_cast<ptrdiff_t
> (itmp) + 15) & ~ 0xF) +
716 ((
reinterpret_cast<ptrdiff_t
> (in)) & 0xF));
719 = fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp,
720 nullptr, stride, dist,
721 reinterpret_cast<fftwf_complex *
> (out),
722 nullptr, stride, dist, plan_flags);
727 = fftwf_plan_many_dft_r2c (rank, tmp, howmany,
728 (
const_cast<float *
> (in)),
729 nullptr, stride, dist,
730 reinterpret_cast<fftwf_complex *
> (out),
731 nullptr, stride, dist, plan_flags);
734 if (*cur_plan_p ==
nullptr)
735 (*current_liboctave_error_handler) (
"Error creating fftw plan");
759 fftwf_destroy_plan (
reinterpret_cast<fftwf_plan
> (
rplan));
761 fftwf_destroy_plan (
reinterpret_cast<fftwf_plan
> (
plan[0]));
763 fftwf_destroy_plan (
reinterpret_cast<fftwf_plan
> (
plan[1]));
772 template <
typename T>
781 for (
size_t i = 0; i < nr; i++)
782 for (
size_t j = nc/2+1; j < nc; j++)
783 out[j*stride + i*dist] =
conj (out[(nc - j)*stride + i*dist]);
788 template <
typename T>
794 size_t np = (dv.
ndims () > 2 ? dv.
numel () / nc / nr : 1);
795 size_t nrp = nr * np;
802 for (
size_t i = 0; i < nrp; i++)
804 ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2);
806 for (
size_t j = 0; j < nc/2+1; j++)
814 for (
size_t i = 0; i < np; i++)
816 for (
size_t j = 1; j < nr; j++)
817 for (
size_t k = nc/2+1; k < nc; k++)
818 out[k + (j + i*nr)*nc] =
conj (out[nc - k + ((i+1)*nr - j)*nc]);
820 for (
size_t j = nc/2+1; j < nc; j++)
821 out[j + i*nr*nc] =
conj (out[(i*nr+1)*nc - j]);
828 size_t jstart = dv(0) * dv(1);
829 size_t kstep = dv(0);
830 size_t nel = dv.
numel ();
832 for (
int inner = 2; inner < dv.
ndims (); inner++)
834 size_t jmax = jstart * dv(inner);
835 for (
size_t i = 0; i < nel; i+=jmax)
836 for (
size_t j = jstart, jj = jmax-jstart; j < jj;
837 j+=jstart, jj-=jstart)
838 for (
size_t k = 0; k < jstart; k+= kstep)
839 for (
size_t l = nc/2+1; l < nc; l++)
841 T tmp = out[i+ j + k + l];
842 out[i + j + k + l] = out[i + jj + k + l];
843 out[i + jj + k + l] = tmp;
855 dist = (dist < 0 ? npts : dist);
859 stride, dist, in, out);
860 fftw_plan plan =
reinterpret_cast<fftw_plan
> (vplan);
862 fftw_execute_dft_r2c (plan, (
const_cast<double *
>(in)),
863 reinterpret_cast<fftw_complex *
> (out));
876 dist = (dist < 0 ? npts : dist);
882 fftw_plan plan =
reinterpret_cast<fftw_plan
> (vplan);
884 fftw_execute_dft (plan,
885 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
886 reinterpret_cast<fftw_complex *
> (out));
896 dist = (dist < 0 ? npts : dist);
900 stride, dist, in, out);
901 fftw_plan plan =
reinterpret_cast<fftw_plan
> (vplan);
903 fftw_execute_dft (plan,
904 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
905 reinterpret_cast<fftw_complex *
> (out));
908 for (
size_t j = 0; j < nsamples; j++)
909 for (
size_t i = 0; i < npts; i++)
910 out[i*stride + j*dist] /=
scale;
920 for (
int i = 0; i < rank; i++)
930 fftw_plan plan =
reinterpret_cast<fftw_plan
> (vplan);
932 fftw_execute_dft_r2c (plan, (
const_cast<double *
>(in)),
933 reinterpret_cast<fftw_complex *
> (out+ offset));
947 for (
int i = 0; i < rank; i++)
951 1, 1, dist, in, out);
952 fftw_plan plan =
reinterpret_cast<fftw_plan
> (vplan);
954 fftw_execute_dft (plan,
955 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
956 reinterpret_cast<fftw_complex *
> (out));
966 for (
int i = 0; i < rank; i++)
970 1, 1, dist, in, out);
971 fftw_plan plan =
reinterpret_cast<fftw_plan
> (vplan);
973 fftw_execute_dft (plan,
974 reinterpret_cast<fftw_complex *
> (
const_cast<Complex *
>(in)),
975 reinterpret_cast<fftw_complex *
> (out));
977 const size_t npts = dv.
numel ();
979 for (
size_t i = 0; i < npts; i++)
989 dist = (dist < 0 ? npts : dist);
994 fftwf_plan plan =
reinterpret_cast<fftwf_plan
> (vplan);
996 fftwf_execute_dft_r2c (plan, (
const_cast<float *
>(in)),
997 reinterpret_cast<fftwf_complex *
> (out));
1010 dist = (dist < 0 ? npts : dist);
1014 nsamples, stride, dist,
1016 fftwf_plan plan =
reinterpret_cast<fftwf_plan
> (vplan);
1018 fftwf_execute_dft (plan,
1019 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1020 reinterpret_cast<fftwf_complex *
> (out));
1030 dist = (dist < 0 ? npts : dist);
1034 nsamples, stride, dist,
1036 fftwf_plan plan =
reinterpret_cast<fftwf_plan
> (vplan);
1038 fftwf_execute_dft (plan,
1039 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1040 reinterpret_cast<fftwf_complex *
> (out));
1043 for (
size_t j = 0; j < nsamples; j++)
1044 for (
size_t i = 0; i < npts; i++)
1045 out[i*stride + j*dist] /=
scale;
1055 for (
int i = 0; i < rank; i++)
1065 fftwf_plan plan =
reinterpret_cast<fftwf_plan
> (vplan);
1067 fftwf_execute_dft_r2c (plan, (
const_cast<float *
>(in)),
1068 reinterpret_cast<fftwf_complex *
> (out+ offset));
1082 for (
int i = 0; i < rank; i++)
1086 1, 1, dist, in, out);
1087 fftwf_plan plan =
reinterpret_cast<fftwf_plan
> (vplan);
1089 fftwf_execute_dft (plan,
1090 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1091 reinterpret_cast<fftwf_complex *
> (out));
1101 for (
int i = 0; i < rank; i++)
1105 1, 1, dist, in, out);
1106 fftwf_plan plan =
reinterpret_cast<fftwf_plan
> (vplan);
1108 fftwf_execute_dft (plan,
1109 reinterpret_cast<fftwf_complex *
> (
const_cast<FloatComplex *
>(in)),
1110 reinterpret_cast<fftwf_complex *
> (out));
1112 const size_t npts = dv.
numel ();
1114 for (
size_t i = 0; i < npts; i++)
1125 #if defined (HAVE_FFTW)
1135 #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 * instance
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 bool instance_ok(void)
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 int fft(const double *in, Complex *out, size_t npts, 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 &)
static int ifftNd(const Complex *, Complex *, const int, const dim_vector &)
static int ifft(const Complex *in, Complex *out, size_t npts, size_t nsamples=1, octave_idx_type stride=1, octave_idx_type dist=-1)
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 FloatComplex *in, FloatComplex *out)
static bool instance_ok(void)
FftwMethod do_method(void)
~float_fftw_planner(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)
static float_fftw_planner * instance
void scale(Matrix &m, double x, double y, double z)
static void convert_packcomplex_Nd(T *out, const dim_vector &dv)
std::string fftw_version(void)
std::string fftwf_version(void)
static void convert_packcomplex_1d(T *out, size_t nr, size_t nc, octave_idx_type stride, octave_idx_type dist)
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
#define CHECK_SIMD_ALIGNMENT(x)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
octave_value::octave_value(const Array< char > &chm, char type) return retval