Highly Efficient FFT for Exascale: HeFFTe v2.3
heffte_fft3d.h
1 /*
2  -- heFFTe --
3  Univ. of Tennessee, Knoxville
4  @date
5 */
6 
7 #ifndef HEFFTE_FFT3D_H
8 #define HEFFTE_FFT3D_H
9 
10 #include "heffte_compute_transform.h"
11 
46 namespace heffte {
47 
58 template<typename scalar_type> struct fft_output{
60  using type = scalar_type;
61 };
66 template<> struct fft_output<float>{
68  using type = std::complex<float>;
69 };
74 template<> struct fft_output<double>{
76  using type = std::complex<double>;
77 };
78 
85 template<typename scalar_type, typename backend_tag, typename = void>
91 template<typename scalar_type, typename backend_tag>
92 struct transform_output<scalar_type, backend_tag, typename std::enable_if<backend::uses_fft_types<backend_tag>::value>::type>{
95 };
100 template<typename scalar_type, typename backend_tag>
101 struct transform_output<scalar_type, backend_tag, typename std::enable_if<not backend::uses_fft_types<backend_tag>::value>::type>{
103  using type = scalar_type;
104 };
105 
106 
113 enum class scale{
115  none,
117  full,
119  symmetric
120 };
121 
212 template<typename backend_tag, typename index = int>
213 class fft3d : public backend::device_instance<typename backend::buffer_traits<backend_tag>::location>{
214 public:
224  template<typename T> using buffer_container = typename backend::buffer_traits<backend_tag>::template container<T>;
229 
234 
243  fft3d(box3d<index> const inbox, box3d<index> const outbox, MPI_Comm const comm,
244  plan_options const options = default_options<backend_tag>()) :
245  fft3d(plan_operations(mpi::gather_boxes(inbox, outbox, comm), -1, set_options<backend_tag>(options), mpi::comm_rank(comm)), comm){
246  static_assert(backend::is_enabled<backend_tag>::value, "The requested backend is invalid or has not been enabled.");
247  }
266  box3d<index> const inbox, box3d<index> const outbox, MPI_Comm const comm,
267  plan_options const options = default_options<backend_tag>()) :
268  fft3d(gpu_stream, plan_operations(mpi::gather_boxes(inbox, outbox, comm), -1, set_options<backend_tag>(options), mpi::comm_rank(comm)), comm){
269  static_assert(backend::is_enabled<backend_tag>::value, "The requested backend is invalid or has not been enabled.");
270  }
271 
272 
274  fft3d(int il0, int il1, int il2, int ih0, int ih1, int ih2, int io0, int io1, int io2,
275  int ol0, int ol1, int ol2, int oh0, int oh1, int oh2, int oo0, int oo1, int oo2,
276  MPI_Comm const comm,
277  bool use_reorder, int algorithm, bool use_pencils)
278  : fft3d(box3d<index>({il0, il1, il2}, {ih0, ih1, ih2}, {io0, io1, io2}),
279  box3d<index>({ol0, ol1, ol2}, {oh0, oh1, oh2}, {oo0, oo1, oo2}),
280  comm,
281  plan_options(use_reorder, static_cast<reshape_algorithm>(algorithm), use_pencils))
282  {}
284  fft3d(int il0, int il1, int il2, int ih0, int ih1, int ih2, int io0, int io1, int io2,
285  int ol0, int ol1, int ol2, int oh0, int oh1, int oh2, int oo0, int oo1, int oo2,
286  MPI_Comm const comm)
287  : fft3d(box3d<index>({il0, il1, il2}, {ih0, ih1, ih2}, {io0, io1, io2}),
288  box3d<index>({ol0, ol1, ol2}, {oh0, oh1, oh2}, {oo0, oo1, oo2}),
289  comm)
290  {}
292  fft3d(int il0, int il1, int il2, int ih0, int ih1, int ih2,
293  int ol0, int ol1, int ol2, int oh0, int oh1, int oh2,
294  MPI_Comm const comm)
295  : fft3d(box3d<index>({il0, il1, il2}, {ih0, ih1, ih2}), box3d<index>({ol0, ol1, ol2}, {oh0, oh1, oh2}), comm)
296  {}
297 
299  long long size_inbox() const{ return pinbox->count(); }
301  long long size_outbox() const{ return poutbox->count(); }
303  box3d<index> inbox() const{ return *pinbox; }
305  box3d<index> outbox() const{ return *poutbox; }
306 
326  template<typename input_type, typename output_type>
327  void forward(input_type const input[], output_type output[], scale scaling = scale::none) const{
329  "Using either an unknown complex type or an incompatible pair of types!");
330 
331  auto workspace = make_buffer_container<typename transform_output<typename define_standard_type<output_type>::type, backend_tag>::type>(this->stream(), size_workspace());
332  forward(input, output, workspace.data(), scaling);
333  }
334 
347  template<typename input_type, typename output_type>
348  void forward(input_type const input[], output_type output[], output_type workspace[], scale scaling = scale::none) const{
350  "Using either an unknown complex type or an incompatible pair of types!");
351 
352  compute_transform<location_tag, index>(this->stream(), 1, convert_to_standard(input), convert_to_standard(output),
353  convert_to_standard(workspace),
354  executor_buffer_offset, size_comm_buffers(), forward_shaper,
355  forward_executors(), direction::forward);
356  apply_scale(1, direction::forward, scaling, output);
357  }
364  template<typename input_type, typename output_type>
365  void forward(int const batch_size, input_type const input[], output_type output[],
366  output_type workspace[], scale scaling = scale::none) const{
368  "Using either an unknown complex type or an incompatible pair of types!");
369 
370  compute_transform<location_tag, index>(this->stream(), batch_size, convert_to_standard(input), convert_to_standard(output),
371  convert_to_standard(workspace),
372  executor_buffer_offset, size_comm_buffers(), forward_shaper,
373  forward_executors(), direction::forward);
374  apply_scale(batch_size, direction::forward, scaling, output);
375  }
379  template<typename input_type, typename output_type>
380  void forward(int const batch_size, input_type const input[], output_type output[], scale scaling = scale::none) const{
382  "Using either an unknown complex type or an incompatible pair of types!");
383 
384  auto workspace = make_buffer_container<typename transform_output<typename define_standard_type<output_type>::type, backend_tag>::type>(this->stream(), batch_size * size_workspace());
385 
386  forward(batch_size, input, output, workspace.data(), scaling);
387  }
388 
413  template<typename input_type>
415  if (input.size() < static_cast<size_t>(size_inbox()))
416  throw std::invalid_argument("The input vector is smaller than size_inbox(), i.e., not enough entries provided to fill the inbox.");
417  auto output = make_buffer_container<typename transform_output<input_type, backend_tag>::type>(this->stream(), size_outbox());
418  forward(input.data(), output.data(), scaling);
419  return output;
420  }
421 
441  template<typename input_type, typename output_type>
442  void backward(input_type const input[], output_type output[], scale scaling = scale::none) const{
444  "Using either an unknown complex type or an incompatible pair of types!");
445 
446  auto workspace = make_buffer_container<typename transform_output<input_type, backend_tag>::type>(this->stream(), size_workspace());
447  backward(input, output, workspace.data(), scaling);
448  }
449 
453  template<typename input_type, typename output_type>
454  void backward(input_type const input[], output_type output[], input_type workspace[], scale scaling = scale::none) const{
456  "Using either an unknown complex type or an incompatible pair of types!");
457 
458  compute_transform<location_tag, index>(this->stream(), 1, convert_to_standard(input), convert_to_standard(output),
459  convert_to_standard(workspace),
460  executor_buffer_offset, size_comm_buffers(), backward_shaper,
461  backward_executors(), direction::backward);
462  apply_scale(1, direction::backward, scaling, output);
463  }
467  template<typename input_type, typename output_type>
468  void backward(int const batch_size, input_type const input[], output_type output[],
469  input_type workspace[], scale scaling = scale::none) const{
471  "Using either an unknown complex type or an incompatible pair of types!");
472 
473  compute_transform<location_tag, index>(this->stream(), batch_size, convert_to_standard(input), convert_to_standard(output),
474  convert_to_standard(workspace),
475  executor_buffer_offset, size_comm_buffers(), backward_shaper,
476  backward_executors(), direction::backward);
477  apply_scale(batch_size, direction::backward, scaling, output);
478  }
482  template<typename input_type, typename output_type>
483  void backward(int const batch_size, input_type const input[], output_type output[], scale scaling = scale::none) const{
485  "Using either an unknown complex type or an incompatible pair of types!");
486 
487  auto workspace = make_buffer_container<typename transform_output<input_type, backend_tag>::type>(this->stream(), batch_size * size_workspace());
488  backward(batch_size, input, output, workspace.data(), scaling);
489  }
490 
494  template<typename scalar_type>
497  "Either calling backward() with non-complex input or using an unknown complex type.");
498  if (input.size() < static_cast<size_t>(size_outbox()))
499  throw std::invalid_argument("The input vector is smaller than size_outbox(), i.e., not enough entries provided to fill the outbox.");
500  auto result = make_buffer_container<scalar_type>(this->stream(), size_inbox());
501  backward(input.data(), result.data(), scaling);
502  return result;
503  }
504 
508  template<typename scalar_type>
511  "Either calling backward() with non-complex input or using an unknown complex type.");
512  auto result = make_buffer_container<typename define_standard_type<scalar_type>::type::value_type>(this->stream(), size_inbox());
513  backward(input.data(), result.data(), scaling);
514  return result;
515  }
516 
518  double get_scale_factor(scale scaling) const{
520  return (scaling == scale::symmetric) ? std::sqrt(scale_factor) : scale_factor;
521  }else{
522  return (scaling == scale::symmetric) ? std::sqrt(scale_factor / 64.0) : scale_factor / 64.0;
523  }
524  }
525 
527  size_t size_workspace() const{ return size_buffer_work; }
529  size_t size_comm_buffers() const{ return comm_buffer_offset; }
530 
531 private:
551  fft3d(logic_plan3d<index> const &plan, MPI_Comm const comm) :
552  backend::device_instance<location_tag>(),
553  pinbox(new box3d<index>(plan.in_shape[0][plan.mpi_rank])), poutbox(new box3d<index>(plan.out_shape[3][plan.mpi_rank])),
554  scale_factor(1.0 / static_cast<double>(plan.index_count))
555  #ifdef Heffte_ENABLE_MAGMA
556  , hmagma(this->stream())
557  #endif
558  {
559  setup(plan, comm);
560  }
561 
564  logic_plan3d<index> const &plan, MPI_Comm const comm) :
565  backend::device_instance<location_tag>(gpu_stream),
566  pinbox(new box3d<index>(plan.in_shape[0][plan.mpi_rank])), poutbox(new box3d<index>(plan.out_shape[3][plan.mpi_rank])),
567  scale_factor(1.0 / static_cast<double>(plan.index_count))
568  #ifdef Heffte_ENABLE_MAGMA
569  , hmagma(this->stream())
570  #endif
571  {
572  setup(plan, comm);
573  }
574 
576  void setup(logic_plan3d<index> const &plan, MPI_Comm const comm){
577  for(int i=0; i<4; i++){
578  forward_shaper[i] = make_reshape3d<backend_tag>(this->stream(), plan.in_shape[i], plan.out_shape[i], comm, plan.options);
579  backward_shaper[3-i] = make_reshape3d<backend_tag>(this->stream(), plan.out_shape[i], plan.in_shape[i], comm, plan.options);
580  }
581 
582  int const my_rank = plan.mpi_rank;
583 
584  if (has_executor3d<backend_tag>() and not forward_shaper[1] and not forward_shaper[2]){
585  executors[0] = make_executor<backend_tag>(this->stream(), plan.out_shape[0][my_rank]);
586  }else if (has_executor2d<backend_tag>() and (not forward_shaper[1] or not forward_shaper[2])){
587  if (not forward_shaper[1]){
588  executors[0] = make_executor<backend_tag>(this->stream(), plan.out_shape[0][my_rank],
589  plan.fft_direction[0], plan.fft_direction[1]);
590  executors[2] = make_executor<backend_tag>(this->stream(), plan.out_shape[2][my_rank], plan.fft_direction[2]);
591  }else{
592  executors[0] = make_executor<backend_tag>(this->stream(), plan.out_shape[0][my_rank], plan.fft_direction[0]);
593  executors[2] = make_executor<backend_tag>(this->stream(), plan.out_shape[2][my_rank],
594  plan.fft_direction[1], plan.fft_direction[2]);
595  }
596  }else{
597  executors[0] = make_executor<backend_tag>(this->stream(), plan.out_shape[0][my_rank], plan.fft_direction[0]);
598  executors[1] = make_executor<backend_tag>(this->stream(), plan.out_shape[1][my_rank], plan.fft_direction[1]);
599  executors[2] = make_executor<backend_tag>(this->stream(), plan.out_shape[2][my_rank], plan.fft_direction[2]);
600  }
601 
602  size_t executor_workspace_size = get_max_work_size(executors);
603  comm_buffer_offset = std::max(get_workspace_size(forward_shaper), get_workspace_size(backward_shaper));
604  // the last junk of (fft0->box_size() + 1) / 2 is used only when doing complex-to-real backward transform
605  // maybe update the API to call for different size buffers for different complex/real types
606  int last_chunk = (executors[0] == nullptr) ? 0 : (((backward_shaper[3]) ? (executors[0]->box_size() + 1) / 2 : 0));
607  size_buffer_work = comm_buffer_offset + executor_workspace_size
608  + get_max_box_size(executors)
609  + last_chunk;
610  executor_buffer_offset = (executor_workspace_size == 0) ? 0 : size_buffer_work - executor_workspace_size;
611  }
613  std::array<executor_base*, 3> forward_executors() const{
614  return std::array<executor_base*, 3>{executors[0].get(), executors[1].get(), executors[2].get()};
615  }
617  std::array<executor_base*, 3> backward_executors() const{
618  return std::array<executor_base*, 3>{executors[2].get(), executors[1].get(), executors[0].get()};
619  }
620 
622  template<typename scalar_type>
623  void apply_scale(int const batch_size, direction dir, scale scaling, scalar_type data[]) const{
624  if (scaling != scale::none){
625  add_trace name("scale");
626  #ifdef Heffte_ENABLE_MAGMA
627  if (std::is_same<typename backend::buffer_traits<backend_tag>::location, tag::gpu>::value){
628  hmagma.scal(batch_size * ((dir == direction::forward) ? size_outbox() : size_inbox()),
629  get_scale_factor(scaling), data);
630  return;
631  }
632  #endif
634  this->stream(),
635  batch_size * ((dir == direction::forward) ? size_outbox() : size_inbox()),
636  data, get_scale_factor(scaling));
637  }
638  }
639 
640  std::unique_ptr<box3d<index>> pinbox, poutbox; // inbox/output for this process
641  double scale_factor;
642  std::array<std::unique_ptr<reshape3d_base<index>>, 4> forward_shaper;
643  std::array<std::unique_ptr<reshape3d_base<index>>, 4> backward_shaper;
644 
645  std::array<std::unique_ptr<executor_base>, 3> executors;
646  #ifdef Heffte_ENABLE_MAGMA
647  gpu::magma_handle<typename backend::buffer_traits<backend_tag>::location> hmagma;
648  #endif
649 
650  // cache some values for faster read
651  size_t size_buffer_work, comm_buffer_offset, executor_buffer_offset;
652 };
653 
662 template<typename backend_tag, typename index = int>
664 
708 template<typename backend_tag, typename index = int>
710 
715 template<typename backend_tag, typename index>
716 fft3d<backend_tag, index> make_fft3d(box3d<index> const inbox, box3d<index> const outbox, MPI_Comm const comm,
717  plan_options const options = default_options<backend_tag>()){
718  static_assert(std::is_same<index, int>::value or std::is_same<index, long long>::value,
719  "heFFTe works with 'int' and 'long long' indexing only");
721  "the backend_tag is not valid, perhaps it needs to be enabled in the build system");
722  return fft3d<backend_tag, index>(inbox, outbox, comm, options);
723 }
724 
725 }
726 
727 #endif
Defines the plan for a 3-dimensional discrete Fourier transform performed on a MPI distributed data.
Definition: heffte_fft3d.h:213
long long size_inbox() const
Returns the size of the inbox defined in the constructor.
Definition: heffte_fft3d.h:299
void forward(int const batch_size, input_type const input[], output_type output[], output_type workspace[], scale scaling=scale::none) const
An overload allowing for a batch of FFTs to be performed in a single command.
Definition: heffte_fft3d.h:365
real_buffer_container< scalar_type > backward_real(buffer_container< scalar_type > const &input, scale scaling=scale::none)
Perform complex-to-real backward FFT using vector API (truncates the complex part).
Definition: heffte_fft3d.h:509
fft3d(box3d< index > const inbox, box3d< index > const outbox, MPI_Comm const comm, plan_options const options=default_options< backend_tag >())
Constructor creating a plan for FFT transform across the given communicator and using the box geometr...
Definition: heffte_fft3d.h:243
void backward(input_type const input[], output_type output[], scale scaling=scale::none) const
Performs a backward Fourier transform using two arrays.
Definition: heffte_fft3d.h:442
void forward(input_type const input[], output_type output[], scale scaling=scale::none) const
Performs a forward Fourier transform using two arrays.
Definition: heffte_fft3d.h:327
box3d< index > inbox() const
Returns the inbox.
Definition: heffte_fft3d.h:303
buffer_container< typename transform_output< T, backend_tag >::type > output_buffer_container
Container of the output type corresponding to T, see the table of compatible input and output types.
Definition: heffte_fft3d.h:228
double get_scale_factor(scale scaling) const
Returns the scale factor for the given scaling.
Definition: heffte_fft3d.h:518
typename backend::buffer_traits< backend_tag >::location location_tag
Type-tag that is either tag::cpu or tag::gpu to indicate the location of the data.
Definition: heffte_fft3d.h:233
box3d< index > outbox() const
Returns the outbox.
Definition: heffte_fft3d.h:305
fft3d(int il0, int il1, int il2, int ih0, int ih1, int ih2, int io0, int io1, int io2, int ol0, int ol1, int ol2, int oh0, int oh1, int oh2, int oo0, int oo1, int oo2, MPI_Comm const comm)
Internal use only, used by the Fortran interface.
Definition: heffte_fft3d.h:284
long long size_outbox() const
Returns the size of the outbox defined in the constructor.
Definition: heffte_fft3d.h:301
buffer_container< scalar_type > backward(buffer_container< scalar_type > const &input, scale scaling=scale::none)
Perform complex-to-complex backward FFT using vector API.
Definition: heffte_fft3d.h:495
void backward(input_type const input[], output_type output[], input_type workspace[], scale scaling=scale::none) const
Overload with user-provided workspace buffer, see the corresponding overload of forward().
Definition: heffte_fft3d.h:454
void backward(int const batch_size, input_type const input[], output_type output[], scale scaling=scale::none) const
Overload for batch transforms with internally allocated workspace.
Definition: heffte_fft3d.h:483
void forward(input_type const input[], output_type output[], output_type workspace[], scale scaling=scale::none) const
An overload utilizing a user-allocated workspace buffer.
Definition: heffte_fft3d.h:348
size_t size_workspace() const
Returns the workspace size that will be used, size is measured in complex numbers.
Definition: heffte_fft3d.h:527
fft3d(typename backend::device_instance< location_tag >::stream_type gpu_stream, box3d< index > const inbox, box3d< index > const outbox, MPI_Comm const comm, plan_options const options=default_options< backend_tag >())
Identical to the other constructor but accepts a GPU stream or queue.
Definition: heffte_fft3d.h:265
void backward(int const batch_size, input_type const input[], output_type output[], input_type workspace[], scale scaling=scale::none) const
Overload for batch transforms, see the corresponding overload of forward().
Definition: heffte_fft3d.h:468
typename one_dim_backend< backend_tag >::executor backend_executor
Alias to the wrapper class for the one dimensional backend library.
Definition: heffte_fft3d.h:216
buffer_container< typename define_standard_type< T >::type::value_type > real_buffer_container
Container of real values corresponding to the complex type T.
Definition: heffte_fft3d.h:226
fft3d(int il0, int il1, int il2, int ih0, int ih1, int ih2, int ol0, int ol1, int ol2, int oh0, int oh1, int oh2, MPI_Comm const comm)
Internal use only, used by the Fortran interface.
Definition: heffte_fft3d.h:292
output_buffer_container< input_type > forward(buffer_container< input_type > const &input, scale scaling=scale::none)
Vector variant of forward() using input and output buffer_container classes.
Definition: heffte_fft3d.h:414
typename backend::buffer_traits< backend_tag >::template container< T > buffer_container
Alias to the container template associated with the backend.
Definition: heffte_fft3d.h:224
size_t size_comm_buffers() const
Returns the size used by the communication workspace buffers (internal use).
Definition: heffte_fft3d.h:529
void forward(int const batch_size, input_type const input[], output_type output[], scale scaling=scale::none) const
An overload that allocates workspace internally.
Definition: heffte_fft3d.h:380
fft3d(int il0, int il1, int il2, int ih0, int ih1, int ih2, int io0, int io1, int io2, int ol0, int ol1, int ol2, int oh0, int oh1, int oh2, int oo0, int oo1, int oo2, MPI_Comm const comm, bool use_reorder, int algorithm, bool use_pencils)
Internal use only, used by the Fortran interface.
Definition: heffte_fft3d.h:274
reshape_algorithm
Defines list of potential communication algorithms.
Definition: heffte_plan_logic.h:48
plan_options set_options(plan_options opts)
Adjusts the user provided options to what can be handled by the backend.
Definition: heffte_plan_logic.h:207
scale
Indicates the scaling factor to apply on the result of an FFT operation.
Definition: heffte_fft3d.h:113
fft3d< backend_tag, index > make_fft3d(box3d< index > const inbox, box3d< index > const outbox, MPI_Comm const comm, plan_options const options=default_options< backend_tag >())
Factory method that auto-detects the index type based on the box.
Definition: heffte_fft3d.h:716
@ none
No scale, leave the result unperturbed similar to the FFTW API.
@ full
Apply the full scale, divide by the number of elements in the world box.
@ symmetric
Symmetric scaling, apply the square-root of the full scaling.
std::string name()
Returns the human readable name of the backend.
Definition: heffte_common.h:240
direction
Indicates the direction of the FFT (internal use only).
Definition: heffte_common.h:535
size_t get_max_box_size(std::array< some_class, 3 > const &executors)
Returns the max of the box_size() for each of the executors.
Definition: heffte_utils.h:402
size_t get_max_work_size(std::array< some_class, 3 > const &executors)
Returns the max of the workspace_size() for each of the executors.
Definition: heffte_utils.h:423
@ backward
Inverse DFT transform.
@ forward
Forward DFT transform.
logic_plan3d< index > plan_operations(ioboxes< index > const &boxes, int r2c_direction, plan_options const options, int const mpi_rank)
Creates the logic plan with the provided user input.
Definition: heffte_plan_logic.cpp:421
void apply(cudaStream_t stream, index num_entries, scalar_type *data, double scale_factor)
Simply multiply the num_entries in the data by the scale_factor.
Definition: heffte_backend_cuda.h:796
int comm_rank(MPI_Comm const comm)
Returns the rank of this process within the specified comm.
Definition: heffte_utils.h:78
ioboxes< index > gather_boxes(box3d< index > const my_inbox, box3d< index > const my_outbox, MPI_Comm const comm)
Gather all boxes across all ranks in the comm.
Definition: heffte_geometry.h:697
size_t get_workspace_size(std::array< std::unique_ptr< reshape3d_base< index >>, 4 > const &shapers)
Returns the maximum workspace size used by the shapers.
Definition: heffte_reshape3d.h:115
Namespace containing all HeFFTe methods and classes.
Definition: heffte_backend_cuda.h:38
define_standard_type< scalar_type >::type * convert_to_standard(scalar_type input[])
Converts an array of some type to an array of the C++ equivalent type.
Definition: heffte_utils.h:354
Defines the container for the temporary buffers.
Definition: heffte_common.h:212
tag::cpu location
Tags the raw-array location tag::cpu or tag::gpu, used by the packers.
Definition: heffte_common.h:214
Set to true/false type depending whether the types are compatible with the backend transform.
Definition: heffte_common.h:395
Holds the auxiliary variables needed by each backend.
Definition: heffte_common.h:358
void * stream_type
The type for the internal stream, the cpu uses just a void pointer.
Definition: heffte_common.h:370
void * stream()
Returns the nullptr.
Definition: heffte_common.h:364
device_instance(void *=nullptr)
Empty constructor.
Definition: heffte_common.h:360
Allows to define whether a specific backend interface has been enabled.
Definition: heffte_common.h:201
Defines whether the backend accepts the standard FFT real-complex or complex-complex transform.
Definition: heffte_common.h:389
A generic container that describes a 3d box of indexes.
Definition: heffte_geometry.h:67
std::complex< double > type
The output for a double data is std::complex<double>
Definition: heffte_fft3d.h:76
std::complex< float > type
The output for a float data is std::complex<float>
Definition: heffte_fft3d.h:68
Defines the relationship between pairs of input-output types in the FFT algorithms.
Definition: heffte_fft3d.h:58
scalar_type type
The output type corresponding to the scalar_type.
Definition: heffte_fft3d.h:60
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
The logic plan incorporates the order and types of operations in a transform.
Definition: heffte_plan_logic.h:275
Indicates the structure that will be used by the fft backend.
Definition: heffte_common.h:546
Defines a set of tweaks and options to use in the plan generation.
Definition: heffte_plan_logic.h:131
Indicates the use of cpu backend and that all input/output data and arrays will be bound to the cpu.
Definition: heffte_common.h:38
scalar_type type
The output type corresponding to the scalar_type and backend_tag (Cosine Transform case).
Definition: heffte_fft3d.h:103
typename fft_output< scalar_type >::type type
The output type corresponding to the scalar_type and backend_tag (FFT case).
Definition: heffte_fft3d.h:94
Defines the relationship between pairs of input-output types in a general transform algorithm.
Definition: heffte_fft3d.h:86