HOPS
HOPS class reference
MHO_MultidimensionalFastFourierTransform.hh
Go to the documentation of this file.
1 #ifndef MHO_MultidimensionalFastFourierTransform_HH__
2 #define MHO_MultidimensionalFastFourierTransform_HH__
3 
4 #include <cstring>
5 
6 #include "MHO_Message.hh"
7 #include "MHO_Meta.hh"
8 #include "MHO_NDArrayWrapper.hh"
9 #include "MHO_UnaryOperator.hh"
10 
14 
16 #include "MHO_TableContainer.hh"
17 
18 namespace hops
19 {
20 
32 template< typename XArgType >
35 {
36  public:
38  "Array element type must be a complex floating point type.");
39  using complex_value_type = typename XArgType::value_type;
40  using floating_point_value_type = typename XArgType::value_type::value_type;
41 
43 
45 
46  protected:
54  virtual bool InitializeInPlace(XArgType* in) override
55  {
56  this->fInitialized = false;
57  if(in == nullptr)
58  {
59  return false;
60  }
61  in->GetDimensions(this->fDimensionSize);
62  AllocateWorkspace();
63  this->fInitialized = true;
64 #ifdef HOPS_ENABLE_DEBUG_MSG
65  msg_debug("operators", "initialized a native FFT plan." << eom);
66  for(std::size_t i = 0; i < XArgType::rank::value; i++)
67  {
68  msg_debug("operators", "fft plan dimension: " << i << " has size: " << this->fDimensionSize[i] << ", enabled? "
69  << this->fAxesToXForm[i] << "." << eom);
70  }
71 #endif
72  return true;
73  }
74 
83  virtual bool InitializeOutOfPlace(const XArgType* in, XArgType* out) override
84  {
85  this->fInitialized = false;
86  if(in == nullptr || out == nullptr)
87  {
88  return false;
89  }
90  if(!HaveSameDimensions(in, out))
91  {
92  out->Resize(in->GetDimensions());
93  }
94  in->GetDimensions(this->fDimensionSize);
95  AllocateWorkspace();
96  this->fInitialized = true;
97 #ifdef HOPS_ENABLE_DEBUG_MSG
98  msg_debug("operators", "initialized a native FFT plan." << eom);
99  for(std::size_t i = 0; i < XArgType::rank::value; i++)
100  {
101  msg_debug("operators", "fft plan dimension: " << i << " has size: " << this->fDimensionSize[i] << ", enabled? "
102  << this->fAxesToXForm[i] << "." << eom);
103  }
104 #endif
105  return true;
106  }
107 
115  virtual bool ExecuteInPlace(XArgType* in) override
116  {
117  if(this->fInitialized)
118  {
119  size_t total_size = 1;
120  for(size_t i = 0; i < XArgType::rank::value; i++)
121  {
122  total_size *= this->fDimensionSize[i];
123  }
124 
125  size_t index[XArgType::rank::value];
126  size_t non_active_dimension_size[XArgType::rank::value - 1];
127  size_t non_active_dimension_value[XArgType::rank::value - 1];
128  size_t non_active_dimension_index[XArgType::rank::value - 1];
129 
130  //select the dimension on which to perform the FFT
131  for(size_t d = 0; d < XArgType::rank::value; d++)
132  {
133  if(this->fAxesToXForm[d])
134  {
135  //now we loop over all dimensions not specified by d
136  //first compute the number of FFTs to perform
137  size_t n_fft = 1;
138  size_t count = 0;
139  for(size_t i = 0; i < XArgType::rank::value; i++)
140  {
141  if(i != d)
142  {
143  n_fft *= this->fDimensionSize[i];
144  non_active_dimension_index[count] = i;
145  non_active_dimension_size[count] = this->fDimensionSize[i];
146  count++;
147  }
148  }
149 
150  //loop over the number of FFTs to perform
151  for(size_t n = 0; n < n_fft; n++)
152  {
153  //invert place in list to obtain indices of block in array
154  MHO_NDArrayMath::RowMajorIndexFromOffset< XArgType::rank::value - 1 >(n, non_active_dimension_size,
155  non_active_dimension_value);
156 
157  //copy the value of the non-active dimensions in to index
158  for(size_t i = 0; i < XArgType::rank::value - 1; i++)
159  {
160  index[non_active_dimension_index[i]] = non_active_dimension_value[i];
161  }
162 
163  size_t data_location;
164  complex_value_type* data;
165  index[d] = 0;
166  data_location =
167  MHO_NDArrayMath::OffsetFromRowMajorIndex< XArgType::rank::value >(this->fDimensionSize, index);
168  data = &((in->GetData())[data_location]);
169 
170  //compute the FFT of the row selected
171  unsigned int stride =
172  MHO_NDArrayMath::StrideFromRowMajorIndex< XArgType::rank::value >(d, this->fDimensionSize);
173  if(fW[d].IsRadix2())
174  {
175  FFTRadix2(data, fW[d], this->fForward, stride);
176  }
177  else
178  {
179  FFTBluestein(data, fW[d], this->fForward, stride);
180  }
181  }
182  }
183 
184  this->IfTableTransformAxis(in, d);
185  }
186  //successful
187  return true;
188  }
189  else
190  {
191  //error
192  msg_error("math", "FFT input/output array dimensions are not valid or intialization failed. Aborting transform."
193  << eom);
194  return false;
195  }
196  }
197 
206  virtual bool ExecuteOutOfPlace(const XArgType* in, XArgType* out) override
207  {
208  //if input and output point to the same array, don't bother copying data over
209  if(in && out && in != out)
210  {
211  out->Copy(*in);
212  }
213  return ExecuteInPlace(out);
214  }
215 
216  private:
220  void AllocateWorkspace()
221  {
222  for(size_t i = 0; i < XArgType::rank::value; i++)
223  {
224  if(fW[i].fN != this->fDimensionSize[i])
225  {
226  fW[i].Resize(this->fDimensionSize[i]);
227  }
228  }
229  }
230 
231  //workspace for transforms
233 };
234 
235 } // namespace hops
236 
237 #endif
#define msg_debug(xKEY, xCONTENT)
Definition: MHO_Message.hh:297
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:244
template meta-programming helper functions, mostly tuple access/modification
void Resize(unsigned int n)
Resizes the internal data structure to a new size and fills it.
Definition: MHO_FastFourierTransformWorkspace.hh:72
Class MHO_MultidimensionalFastFourierTransformInterface.
Definition: MHO_MultidimensionalFastFourierTransformInterface.hh:25
size_t fDimensionSize[XArgType::rank::value]
Definition: MHO_MultidimensionalFastFourierTransformInterface.hh:236
std::enable_if< !std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type IfTableTransformAxis(XArgType *, std::size_t)
Transforms axis of input data if transformation is enabled and axis was transformed.
Definition: MHO_MultidimensionalFastFourierTransformInterface.hh:129
bool fForward
Definition: MHO_MultidimensionalFastFourierTransformInterface.hh:232
bool fAxesToXForm[XArgType::rank::value]
Definition: MHO_MultidimensionalFastFourierTransformInterface.hh:237
bool fInitialized
Definition: MHO_MultidimensionalFastFourierTransformInterface.hh:233
Class MHO_MultidimensionalFastFourierTransform.
Definition: MHO_MultidimensionalFastFourierTransform.hh:35
virtual bool ExecuteInPlace(XArgType *in) override
Function ExecuteInPlace, does FFT in-place.
Definition: MHO_MultidimensionalFastFourierTransform.hh:115
typename XArgType::value_type complex_value_type
Definition: MHO_MultidimensionalFastFourierTransform.hh:39
virtual bool InitializeInPlace(XArgType *in) override
Initializes in-place operation and allocates workspace.
Definition: MHO_MultidimensionalFastFourierTransform.hh:54
typename XArgType::value_type::value_type floating_point_value_type
Definition: MHO_MultidimensionalFastFourierTransform.hh:40
MHO_MultidimensionalFastFourierTransform()
Definition: MHO_MultidimensionalFastFourierTransform.hh:42
virtual ~MHO_MultidimensionalFastFourierTransform()
Definition: MHO_MultidimensionalFastFourierTransform.hh:44
virtual bool ExecuteOutOfPlace(const XArgType *in, XArgType *out) override
Copies input data to output if they're not the same array and executes FFT in-place on output.
Definition: MHO_MultidimensionalFastFourierTransform.hh:206
virtual bool InitializeOutOfPlace(const XArgType *in, XArgType *out) override
Function InitializeOutOfPlace.
Definition: MHO_MultidimensionalFastFourierTransform.hh:83
static void RowMajorIndexFromOffset(std::size_t offset, const std::size_t *DimSize, std::size_t *Index)
Function RowMajorIndexFromOffset.
Definition: MHO_NDArrayMath.hh:121
Class MHO_UnaryOperator.
Definition: MHO_UnaryOperator.hh:24
Definition: MHO_ChannelLabeler.hh:17
void FFTBluestein(std::complex< XFloatType > *data, MHO_FastFourierTransformWorkspace< XFloatType > &work, bool isForward, unsigned int stride=1)
Performs Bluestein's FFT algorithm on complex data using a workspace for arbitrary N....
Definition: MHO_FastFourierTransformCalls.hh:68
void FFTRadix2(std::complex< XFloatType > *data, MHO_FastFourierTransformWorkspace< XFloatType > &work, bool isForward, unsigned int stride=1)
Performs a Radix-2 Decimation-in-time (DIT) FFT algorithm on complex data using a workspace for arbit...
Definition: MHO_FastFourierTransformCalls.hh:37
Definition: MHO_Meta.hh:341