Highly Efficient FFT for Exascale: HeFFTe v2.3
heffte_backend_stock.h
1 /*
2  -- heFFTe --
3  Univ. of Tennessee, Knoxville
4  @date
5 */
6 
7 #ifndef HEFFTE_BACKEND_STOCK_FFT_H
8 #define HEFFTE_BACKEND_STOCK_FFT_H
9 
10 #include "heffte_r2r_executor.h"
11 
12 #include "stock_fft/heffte_stock_tree.h"
13 
21 namespace heffte{
22 
23 namespace backend{
28  template<> struct is_enabled<stock> : std::true_type{};
33  template<> struct is_enabled<stock_cos> : std::true_type{};
38  template<> struct is_enabled<stock_sin> : std::true_type{};
39 
40 // Specialization is not necessary since the default behavior assumes CPU parameters.
41 // template<>
42 // struct buffer_traits<stock>{
43 // using location = tag::cpu;
44 // template<typename T> using container = std::vector<T>;
45 // };
46 }
47 
49 template<> struct is_ccomplex<stock::Complex<float, 1>> : std::true_type{};
50 template<> struct is_zcomplex<stock::Complex<double, 1>> : std::true_type{};
51 #ifdef Heffte_ENABLE_AVX
56 template<> struct is_ccomplex<stock::Complex<float, 4>> : std::true_type{};
57 template<> struct is_ccomplex<stock::Complex<float, 8>> : std::true_type{};
58 #ifdef Heffte_ENABLE_AVX512
59 template<> struct is_ccomplex<stock::Complex<float, 16>> : std::true_type{};
60 #endif // Heffte_ENABLE_AVX512
61 
66 template<> struct is_zcomplex<stock::Complex<double, 2>> : std::true_type{};
67 template<> struct is_zcomplex<stock::Complex<double, 4>> : std::true_type{};
68 #ifdef Heffte_ENABLE_AVX512
69 template<> struct is_zcomplex<stock::Complex<double, 8>> : std::true_type{};
70 #endif // Heffte_ENABLE_AVX512
71 #endif // Heffte_ENABLE_AVX
72 
73 #ifdef Heffte_ENABLE_AVX
74 
76 template<typename F, int L>
77 stock::Complex<F, L> copy_pad(std::complex<F> const *c, int c_len, int i_stride) {
78  if(c_len > L/2) {
79  throw std::runtime_error("Invalid padding requested!\n");
80  }
81  std::complex<F> ret[L];
82  for(int i = 0; i < c_len; i++) ret[i] = c[i*i_stride];
83  return stock::Complex<F,L> (ret);
84 }
86 template<typename F, int L>
87 stock::Complex<F,L> copy_pad(F const *c, int c_len, int i_stride) {
88  if(c_len > L/2) {
89  throw std::runtime_error("Invalid padding requested!\n");
90  }
91  std::complex<F> ret[L];
92  for(int i = 0; i < c_len; i++) ret[i] = std::complex<F>(c[i*i_stride], 0.0);
93  return stock::Complex<F,L> (ret);
94 }
95 
96 template<typename F> struct pack_size { };
97 #ifdef Heffte_ENABLE_AVX512
98 template<> struct pack_size<float> {constexpr static int size = 16;};
99 template<> struct pack_size<double>{constexpr static int size = 8;};
100 #else
101 template<> struct pack_size<float> {constexpr static int size = 8;};
102 template<> struct pack_size<double>{constexpr static int size = 4;};
103 #endif // Heffte_ENABLE_AVX512
104 
114 template<typename F, direction dir>
115 struct plan_stock_fft{
125  plan_stock_fft(int size, int howmanyffts, int stride, int rdist, int cdist):
126  N(size), num_ffts(howmanyffts), stride_sz(stride), real_d(rdist), comp_d(cdist) {
127  numNodes = stock::getNumNodes(N);
128  root = std::unique_ptr<stock::biFuncNode<F,L>[]>(new stock::biFuncNode<F,L>[numNodes]);
129  init_fft_tree(root.get(), N);
130  }
132  int N, num_ffts, stride_sz, real_d, comp_d, numNodes;
133  constexpr static int L = pack_size<F>::size;
134  std::unique_ptr<stock::biFuncNode<F,L>[]> root;
136  void execute(std::complex<F> const idata[], F odata[]) {
137  // Allocate input and output temporary arrays
138  stock::complex_vector<F,L> inp (N);
139  stock::complex_vector<F,L> out (N);
140 
141  // Perform batch transform on everything save for the remainder
142  for(int p = 0; p+((L/2)-1) < num_ffts; p += (L/2)) {
143  // Convert types
144  inp[0] = stock::Complex<F,L> (&idata[p*comp_d], comp_d);
145  for(int i = 1; i < (N+2)/2; i++) {
146  int idx = p*comp_d + i*stride_sz;
147  inp[i] = stock::Complex<F,L> (&idata[idx], comp_d);
148  inp[N-i] = inp[i].conjugate();
149  }
150  // Perform fft
151  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
152  // Convert type back
153  for(int i = 0; i < N; i++) {
154  int idx = p*real_d + i*stride_sz;
155  stock::Complex<F,L> arr = out[i];
156  for(int j = 0; j < L/2; j++) odata[idx+j*real_d] = arr[j].real();
157  }
158  }
159 
160  // Handle remainder
161  if(num_ffts % (L/2) > 0) {
162  int rem = num_ffts % (L/2);
163  // Init p for ease of use
164  int p = num_ffts - rem;
165  inp[0] = copy_pad<F,L>(&idata[p*comp_d], rem, comp_d);
166  for(int i = 1; i < (N+2)/2; i++) {
167  int idx = p*comp_d + i*stride_sz;
168  inp[i] = copy_pad<F,L>(&idata[idx], rem, comp_d);
169  inp[N-i] = inp[i].conjugate();
170  }
171  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
172  for(int i = 0; i < N; i++) {
173  int idx = p*real_d + i*stride_sz;
174  stock::Complex<F,L> arr = out[i];
175  // Only need first k columns
176  for(int k = 0; k < rem; k++) {
177  odata[idx + k*real_d] = arr[k].real();
178  }
179  }
180  }
181  }
183  void execute(F const idata[], std::complex<F> odata[]) {
184  // Allocate input and output temporary arrays
185  stock::complex_vector<F,L> inp (N);
186  stock::complex_vector<F,L> out (N);
187 
188  // Perform batch transform on everything save for the remainder
189  for(int p = 0; p+((L/2)-1) < num_ffts; p += L/2) {
190  // Convert types
191  for(int i = 0; i < N; i++) {
192  int idx = p*real_d + i*stride_sz;
193  inp[i] = copy_pad<F,L>(&idata[idx], L/2, real_d);
194  }
195  // Perform fft
196  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
197  // Convert type back
198  for(int i = 0; i < (N+2)/2; i++) {
199  int idx = p*comp_d + i*stride_sz;
200  stock::Complex<F,L> arr = out[i];
201  for(int j = 0; j < L/2; j++) odata[idx+j*comp_d] = arr[j];
202  }
203  }
204 
205  // Handle remainder
206  if(num_ffts % (L/2) > 0) {
207  int rem = num_ffts % (L/2);
208  // Init p for ease of use
209  int p = num_ffts - rem;
210  for(int i = 0; i < N; i++) {
211  int idx = p*real_d + i*stride_sz;
212  // remainder columns are all zeros
213  inp[i] = copy_pad<F,L>(&idata[idx], rem, real_d);
214  }
215  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
216  for(int i = 0; i < (N+2)/2; i++) {
217  int idx = p*comp_d + i*stride_sz;
218  stock::Complex<F,L> arr = out[i];
219  // Only need first k columns
220  for(int k = 0; k < rem; k++) {
221  odata[idx + k*comp_d] = arr[k];
222  }
223  }
224  }
225  }
226 };
227 
234 template<typename F, direction dir>
235 struct plan_stock_fft<std::complex<F>, dir>{
244  plan_stock_fft(int size, int howmanyffts, int stride, int dist):
245  N(size), num_ffts(howmanyffts), stride_sz(stride), idist(dist), odist(dist) {
246  numNodes = stock::getNumNodes(N);
247  root = std::unique_ptr<stock::biFuncNode<F,L>[]>(new stock::biFuncNode<F,L>[numNodes]);
248  init_fft_tree(root.get(), N);
249  }
250 
251  int N, num_ffts, stride_sz, idist, odist, numNodes;
252  constexpr static int L = pack_size<F>::size;
253  std::unique_ptr<stock::biFuncNode<F, L>[]> root;
255  void execute(std::complex<F> data[]) {
256  // Allocate input and output temporary arrays
257  stock::complex_vector<F,L> inp (N);
258  stock::complex_vector<F,L> out (N);
259 
260  // Perform batch transform on everything save for the remainder
261  for(int p = 0; p + (L/2 - 1) < num_ffts; p += L/2) {
262  // Convert types
263  for(int i = 0; i < N; i++) {
264  int idx = p*idist + i*stride_sz;
265  inp[i] = stock::Complex<F,L> (&data[idx], idist);
266  }
267  // Perform fft
268  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
269  // Convert type back
270  for(int i = 0; i < N; i++) {
271  int idx = p*odist + i*stride_sz;
272  stock::Complex<F,L> arr = out[i];
273  for(int j = 0; j < L/2; j++) data[idx+j*odist] = arr[j];
274  }
275  }
276 
277  // Handle remainder
278  if(num_ffts % (L/2) > 0) {
279  int rem = num_ffts % (L/2);
280  // Init p for ease of use
281  int p = num_ffts - rem;
282  for(int i = 0; i < N; i++) {
283  int idx = p*idist + i*stride_sz;
284  // remainder columns are all zeros
285  inp[i] = copy_pad<F,L>(&data[idx], rem, idist);
286  }
287  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
288  for(int i = 0; i < N; i++) {
289  int idx = p*odist + i*stride_sz;
290  stock::Complex<F,L> arr = out[i];
291  // Only need first k columns
292  for(int k = 0; k < rem; k++) {
293  data[idx + k*odist] = arr[k];
294  }
295  }
296  }
297  }
298 };
299 
300 #else
301 
302 // In the case the user does not have AVX installed
303 
308 template<typename F, direction dir>
319  plan_stock_fft(int size, int howmanyffts, int stride, int rdist, int cdist):
320  N(size), num_ffts(howmanyffts), stride_sz(stride), real_d(rdist), comp_d(cdist) {
321  numNodes = stock::getNumNodes(N);
322  root = std::unique_ptr<stock::biFuncNode<F,1>[]>(new stock::biFuncNode<F,1>[numNodes]);
323  init_fft_tree(root.get(), N);
324  }
326  int N, num_ffts, stride_sz, real_d, comp_d, numNodes;
327  std::unique_ptr<stock::biFuncNode<F, 1>[]> root;
329  void execute(std::complex<F> const idata[], F odata[]) {
330  // Allocate input and output temporary arrays
331  stock::complex_vector<F,1> inp (N);
332  stock::complex_vector<F,1> out (N);
333 
334  // Perform batch transform on everything save for the remainder
335  for(int p = 0; p < num_ffts; p++) {
336  // Convert types
337  inp[0] = stock::Complex<F,1> {idata[p*comp_d]};
338  for(int i = 1; i < (N+2)/2; i++) {
339  int idx = p*comp_d + i*stride_sz;
340  inp[i] = stock::Complex<F,1> {idata[idx]};
341  inp[N-i] = inp[i].conjugate();
342  }
343  // Perform fft
344  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
345  // Convert type back
346  for(int i = 0; i < N; i++) {
347  int idx = p*real_d + i*stride_sz;
348  stock::Complex<F,1> arr = out[i];
349  odata[idx+0*real_d] = arr[0].real();
350  }
351  }
352  }
354  void execute(F const idata[], std::complex<F> odata[]) {
355  // Allocate input and output temporary arrays
356  stock::complex_vector<F,1> inp (N);
357  stock::complex_vector<F,1> out (N);
358 
359  // Perform batch transform on everything save for the remainder
360  for(int p = 0; p < num_ffts; p++) {
361  // Convert types
362  for(int i = 0; i < N; i++) {
363  int idx = p*real_d + i*stride_sz;
364  inp[i] = stock::Complex<F,1> {idata[idx+0*real_d], 0};
365  }
366  // Perform fft
367  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
368  // Convert type back
369  for(int i = 0; i < (N+2)/2; i++) {
370  int idx = p*comp_d + i*stride_sz;
371  stock::Complex<F,1> arr = out[i];
372  odata[idx+0*comp_d] = arr[0];
373  }
374  }
375  }
376 };
377 
384 template<typename F, direction dir>
385 struct plan_stock_fft<std::complex<F>, dir>{
394  plan_stock_fft(int size, int howmanyffts, int stride, int dist):
395  N(size), num_ffts(howmanyffts), stride_sz(stride), idist(dist), odist(dist) {
396  numNodes = stock::getNumNodes(N);
397  root = std::unique_ptr<stock::biFuncNode<F,1>[]>(new stock::biFuncNode<F,1>[numNodes]);
398  init_fft_tree(root.get(), N);
399  }
400 
401  int N, num_ffts, stride_sz, idist, odist, numNodes;
402  std::unique_ptr<stock::biFuncNode<F,1>[]> root;
404  void execute(std::complex<F> data[]) {
405  // Allocate input and output temporary arrays
406  stock::complex_vector<F,1> inp (N);
407  stock::complex_vector<F,1> out (N);
408 
409  // Perform batch transform on everything save for the remainder
410  for(int p = 0; p < num_ffts; p++) {
411  // Convert types
412  for(int i = 0; i < N; i++) {
413  int idx = p*idist + i*stride_sz;
414  inp[i] = stock::Complex<F, 1> {data[idx+0*idist]};
415  }
416  // Perform fft
417  root[0].fptr(inp.data(), out.data(), 1, 1, root.get(), dir);
418  // Convert type back
419  for(int i = 0; i < N; i++) {
420  int idx = p*odist + i*stride_sz;
421  stock::Complex<F, 1> arr = out[i];
422  data[idx+0*odist] = arr[0];
423  }
424  }
425  }
426 };
427 #endif // Heffte_ENABLE_AVX512
428 
442 public:
450  template<typename index>
451  stock_fft_executor(void*, box3d<index> const box, int dimension) :
452  size(box.size[dimension]),
453  num_ffts(fft1d_get_howmany(box, dimension)),
454  stride(fft1d_get_stride(box, dimension)),
455  dist((dimension == box.order[0]) ? size : 1),
456  blocks((dimension == box.order[1]) ? box.osize(2) : 1),
457  block_stride(box.osize(0) * box.osize(1)),
458  total_size(box.count())
459  {}
461  template<typename index> stock_fft_executor(void*, box3d<index> const, int, int){
462  throw std::runtime_error("2D transforms for the stock backend are not available yet!");
463  }
465  template<typename index> stock_fft_executor(void*, box3d<index> const){
466  throw std::runtime_error("3D transforms for the stock backend are not available yet!");
467  }
468 
470  void forward(std::complex<float> data[], std::complex<float>*) const override{
471  make_plan(cforward);
472  for(int i=0; i<blocks; i++) {
473  cforward->execute(data + i * block_stride);
474  }
475  }
477  void backward(std::complex<float> data[], std::complex<float>*) const override{
478  make_plan(cbackward);
479  for(int i=0; i<blocks; i++) {
480  cbackward->execute(data + i * block_stride);
481  }
482  }
484  void forward(std::complex<double> data[], std::complex<double>*) const override{
485  make_plan(zforward);
486  for(int i=0; i<blocks; i++) {
487  zforward->execute(data + i * block_stride);
488  }
489  }
491  void backward(std::complex<double> data[], std::complex<double>*) const override{
492  make_plan(zbackward);
493  for(int i=0; i<blocks; i++) {
494  zbackward->execute(data + i * block_stride);
495  }
496  }
497 
499  void forward(float const indata[], std::complex<float> outdata[], std::complex<float> *workspace) const override{
500  for(int i=0; i<total_size; i++) outdata[i] = std::complex<float>(indata[i]);
501  forward(outdata, workspace);
502  }
504  void backward(std::complex<float> indata[], float outdata[], std::complex<float> *workspace) const override{
505  backward(indata, workspace);
506  for(int i=0; i<total_size; i++) outdata[i] = std::real(indata[i]);
507  }
509  void forward(double const indata[], std::complex<double> outdata[], std::complex<double> *workspace) const override{
510  for(int i=0; i<total_size; i++) outdata[i] = std::complex<double>(indata[i]);
511  forward(outdata, workspace);
512  }
514  void backward(std::complex<double> indata[], double outdata[], std::complex<double> *workspace) const override{
515  backward(indata, workspace);
516  for(int i=0; i<total_size; i++) outdata[i] = std::real(indata[i]);
517  }
518 
520  int box_size() const override{ return total_size; }
521 
523  size_t workspace_size() const override{ return 0; }
524 
525 private:
527  template<typename scalar_type, direction dir>
528  void make_plan(std::unique_ptr<plan_stock_fft<scalar_type, dir>> &plan) const{
529  if (!plan) plan = std::unique_ptr<plan_stock_fft<scalar_type, dir>>(new plan_stock_fft<scalar_type, dir>(size, num_ffts, stride, dist));
530  }
531 
532  int size, num_ffts, stride, dist, blocks, block_stride, total_size;
533  mutable std::unique_ptr<plan_stock_fft<std::complex<float>, direction::forward>> cforward;
534  mutable std::unique_ptr<plan_stock_fft<std::complex<float>, direction::backward>> cbackward;
535  mutable std::unique_ptr<plan_stock_fft<std::complex<double>, direction::forward>> zforward;
536  mutable std::unique_ptr<plan_stock_fft<std::complex<double>, direction::backward>> zbackward;
537 };
538 
548 public:
558  template<typename index>
559  stock_fft_executor_r2c(void*, box3d<index> const box, int dimension) :
560  size(box.size[dimension]),
561  num_ffts(fft1d_get_howmany(box, dimension)),
562  stride(fft1d_get_stride(box, dimension)),
563  blocks((dimension == box.order[1]) ? box.osize(2) : 1),
564  rdist((dimension == box.order[0]) ? size : 1),
565  cdist((dimension == box.order[0]) ? size/2 + 1 : 1),
566  rblock_stride(box.osize(0) * box.osize(1)),
567  cblock_stride(box.osize(0) * (box.osize(1)/2 + 1)),
568  rsize(box.count()),
569  csize(box.r2c(dimension).count())
570  {}
571 
573  void forward(float const indata[], std::complex<float> outdata[], std::complex<float>*) const override{
574  make_plan(sforward);
575  for(int i=0; i<blocks; i++) {
576  sforward->execute(indata + i*rblock_stride, outdata + i*cblock_stride);
577  }
578  }
580  void backward(std::complex<float> indata[], float outdata[], std::complex<float>*) const override{
581  make_plan(sbackward);
582  for(int i=0; i<blocks; i++) {
583  sbackward->execute(indata + i*cblock_stride, outdata + i*rblock_stride);
584  }
585  }
587  void forward(double const indata[], std::complex<double> outdata[], std::complex<double>*) const override{
588  make_plan(dforward);
589  for(int i=0; i<blocks; i++) {
590  dforward->execute(indata + i*rblock_stride, outdata + i*cblock_stride);
591  }
592  }
594  void backward(std::complex<double> indata[], double outdata[], std::complex<double>*) const override{
595  make_plan(dbackward);
596  for(int i=0; i<blocks; i++) {
597  dbackward->execute(indata + i*cblock_stride, outdata + i*rblock_stride);
598  }
599  }
600 
602  int box_size() const override{ return rsize; }
604  int complex_size() const override{ return csize; }
606  size_t workspace_size() const override{ return 0; }
607 
608 private:
610  template<typename scalar_type, direction dir>
611  void make_plan(std::unique_ptr<plan_stock_fft<scalar_type, dir>> &plan) const{
612  if (!plan) plan = std::unique_ptr<plan_stock_fft<scalar_type, dir>>(new plan_stock_fft<scalar_type, dir>(size, num_ffts, stride, rdist, cdist));
613  }
614 
615  int size, num_ffts, stride, blocks;
616  int rdist, cdist, rblock_stride, cblock_stride, rsize, csize;
617  mutable std::unique_ptr<plan_stock_fft<float, direction::forward>> sforward;
618  mutable std::unique_ptr<plan_stock_fft<double, direction::forward>> dforward;
619  mutable std::unique_ptr<plan_stock_fft<float, direction::backward>> sbackward;
620  mutable std::unique_ptr<plan_stock_fft<double, direction::backward>> dbackward;
621 };
628 template<> struct one_dim_backend<backend::stock>{
633 };
640 template<> struct one_dim_backend<backend::stock_cos>{
644  using executor_r2c = void;
645 };
652 template<> struct one_dim_backend<backend::stock_sin>{
656  using executor_r2c = void;
657 };
658 
663 template<> struct default_plan_options<backend::stock>{
665  static const bool use_reorder = true;
666 };
671 template<> struct default_plan_options<backend::stock_cos>{
673  static const bool use_reorder = true;
674 };
679 template<> struct default_plan_options<backend::stock_sin>{
681  static const bool use_reorder = true;
682 };
683 
684 }
685 
686 #endif /* HEFFTE_BACKEND_STOCK_FFT_H */
Base class for all backend executors.
Definition: heffte_common.h:486
virtual int complex_size() const
Return the size of the complex-box (r2c executors).
Definition: heffte_common.h:519
virtual void backward(float[], float *) const
Backward r2r, single precision.
Definition: heffte_common.h:495
virtual void forward(float[], float *) const
Forward r2r, single precision.
Definition: heffte_common.h:491
Custom complex type taking advantage of vectorization A Complex Type intrinsic to HeFFTe that takes a...
Definition: heffte_stock_complex.h:29
Complex< F, L > conjugate()
Conjugate the current complex number.
Definition: heffte_stock_complex.h:183
Wrapper to stock API for real-to-complex transform with shortening of the data.
Definition: heffte_backend_stock.h:547
int box_size() const override
Returns the size of the box with real data.
Definition: heffte_backend_stock.h:602
int complex_size() const override
Returns the size of the box with complex coefficients.
Definition: heffte_backend_stock.h:604
size_t workspace_size() const override
Return the size of the needed workspace.
Definition: heffte_backend_stock.h:606
void backward(std::complex< float > indata[], float outdata[], std::complex< float > *) const override
Backward transform, single precision.
Definition: heffte_backend_stock.h:580
void forward(float const indata[], std::complex< float > outdata[], std::complex< float > *) const override
Forward transform, single precision.
Definition: heffte_backend_stock.h:573
stock_fft_executor_r2c(void *, box3d< index > const box, int dimension)
Constructor defines the box and the dimension of reduction.
Definition: heffte_backend_stock.h:559
void forward(double const indata[], std::complex< double > outdata[], std::complex< double > *) const override
Forward transform, double precision.
Definition: heffte_backend_stock.h:587
void backward(std::complex< double > indata[], double outdata[], std::complex< double > *) const override
Backward transform, double precision.
Definition: heffte_backend_stock.h:594
Wrapper around the Stock FFT API.
Definition: heffte_backend_stock.h:441
void forward(float const indata[], std::complex< float > outdata[], std::complex< float > *workspace) const override
Converts the real data to complex and performs float-complex forward transform.
Definition: heffte_backend_stock.h:499
virtual void backward(float[], float *) const
Bring forth method that have not been overloaded.
Definition: heffte_common.h:495
void backward(std::complex< float > indata[], float outdata[], std::complex< float > *workspace) const override
Performs backward float-complex transform and truncates the complex part of the result.
Definition: heffte_backend_stock.h:504
size_t workspace_size() const override
Return the size of the needed workspace.
Definition: heffte_backend_stock.h:523
void forward(std::complex< double > data[], std::complex< double > *) const override
Forward fft, double-complex case.
Definition: heffte_backend_stock.h:484
void forward(std::complex< float > data[], std::complex< float > *) const override
Forward fft, float-complex case.
Definition: heffte_backend_stock.h:470
void backward(std::complex< double > data[], std::complex< double > *) const override
Backward fft, double-complex case.
Definition: heffte_backend_stock.h:491
virtual void forward(float[], float *) const
Bring forth method that have not been overloaded.
Definition: heffte_common.h:491
stock_fft_executor(void *, box3d< index > const, int, int)
Placeholder, unimplemented.
Definition: heffte_backend_stock.h:461
void backward(std::complex< float > data[], std::complex< float > *) const override
Backward fft, float-complex case.
Definition: heffte_backend_stock.h:477
void forward(double const indata[], std::complex< double > outdata[], std::complex< double > *workspace) const override
Converts the deal data to complex and performs double-complex forward transform.
Definition: heffte_backend_stock.h:509
stock_fft_executor(void *, box3d< index > const)
Placeholder, unimplemented.
Definition: heffte_backend_stock.h:465
int box_size() const override
Returns the size of the box.
Definition: heffte_backend_stock.h:520
void backward(std::complex< double > indata[], double outdata[], std::complex< double > *workspace) const override
Performs backward double-complex transform and truncates the complex part of the result.
Definition: heffte_backend_stock.h:514
stock_fft_executor(void *, box3d< index > const box, int dimension)
Constructor, specifies the box and dimension.
Definition: heffte_backend_stock.h:451
int fft1d_get_howmany(box3d< index > const box, int const dimension)
Return the number of 1-D ffts contained in the box in the given dimension.
Definition: heffte_geometry.h:159
int fft1d_get_stride(box3d< index > const box, int const dimension)
Return the stride of the 1-D ffts contained in the box in the given dimension.
Definition: heffte_geometry.h:169
@ backward
Inverse DFT transform.
@ forward
Forward DFT transform.
Namespace containing all HeFFTe methods and classes.
Definition: heffte_backend_cuda.h:38
Allows to define whether a specific backend interface has been enabled.
Definition: heffte_common.h:201
Type-tag for the Cosine Transform using the stock FFT backend.
Definition: heffte_common.h:120
Type-tag for the Sine Transform using the stock FFT backend.
Definition: heffte_common.h:125
Type-tag for the stock FFT backend.
Definition: heffte_common.h:115
A generic container that describes a 3d box of indexes.
Definition: heffte_geometry.h:67
Defines a set of default plan options for a given backend.
Definition: heffte_common.h:642
Struct to specialize to allow HeFFTe to recognize custom single precision complex types.
Definition: heffte_utils.h:251
Struct to specialize to allow HeFFTe to recognize custom double precision complex types.
Definition: heffte_utils.h:269
void executor_r2c
There is no real-to-complex variant.
Definition: heffte_backend_stock.h:644
void executor_r2c
There is no real-to-complex variant.
Definition: heffte_backend_stock.h:656
Indicates the structure that will be used by the fft backend.
Definition: heffte_common.h:546
plan_stock_fft(int size, int howmanyffts, int stride, int dist)
Constructor to plan out an FFT using the stock backend.
Definition: heffte_backend_stock.h:394
void execute(std::complex< F > data[])
Execute an FFT inplace on std::complex<F> data.
Definition: heffte_backend_stock.h:404
Specialization for r2c single precision.
Definition: heffte_backend_stock.h:309
void execute(std::complex< F > const idata[], F odata[])
Execute C2R FFT.
Definition: heffte_backend_stock.h:329
void execute(F const idata[], std::complex< F > odata[])
Execute R2C FFT.
Definition: heffte_backend_stock.h:354
plan_stock_fft(int size, int howmanyffts, int stride, int rdist, int cdist)
Constructor taking into account the different sizes for the real and complex parts.
Definition: heffte_backend_stock.h:319
int N
Identical to the F-complex specialization.
Definition: heffte_backend_stock.h:326
Template algorithm for the Sine and Cosine transforms.
Definition: heffte_r2r_executor.h:135
Class to represent the call-graph nodes.
Definition: heffte_stock_algos.h:78