HOPS
HOPS class reference
MHO_EndZeroPadder.hh
Go to the documentation of this file.
1 #ifndef MHO_EndZeroPadder_HH__
2 #define MHO_EndZeroPadder_HH__
3 
4 #include <bitset>
5 #include <cstring>
6 #include <set>
7 #include <vector>
8 
9 #include "MHO_Message.hh"
10 #include "MHO_NDArrayWrapper.hh"
11 #include "MHO_TableContainer.hh"
12 #include "MHO_UnaryOperator.hh"
13 
14 namespace hops
15 {
16 
28 template< typename XArgType > class MHO_EndZeroPadder: public MHO_UnaryOperator< XArgType >
29 {
30  public:
32  {
33  fPaddingFactor = 1;
34  fPaddedSize = 0;
35  for(std::size_t i = 0; i < XArgType::rank::value; i++)
36  {
37  fInputDimensionSize[i] = 0;
38  fOutputDimensionSize[i] = 0;
39  fAxesToXForm[i] = true;
40  }
41 
42  fIsValid = false;
43  fInitialized = false;
44  fFlipped = false; //chooses which end we pad
45  fNormFXMode = true; //when enabled, then when flipped, copies the last element to N/2
46  fPreserveWorkspace = false; //when false tmp workspace will be destroyed after every use
47  fCopyTags = true; //copy tags if available is enabled by default
48  fTmpWorkspace = nullptr;
49  };
50 
51  virtual ~MHO_EndZeroPadder() { delete fTmpWorkspace; };
52 
60  virtual void SetPaddingFactor(std::size_t factor) { fPaddingFactor = factor; };
61 
69  virtual void SetPaddedSize(std::size_t new_size)
70  {
71  fPaddedSize = new_size;
72  fPaddingFactor = 1;
73  }
74 
79  virtual void SetEndPadded() { fFlipped = false; }; //
80 
85  virtual void SetReverseEndPadded() { fFlipped = true; };
86 
91  virtual void DisableNormFXMode() { fNormFXMode = false; };
92 
97  virtual void EnableNormFXMode() { fNormFXMode = true; };
98 
103  virtual void PreserveWorkspace()
104  {
105  fPreserveWorkspace = true;
106  } //keep the memory reserved for the workspace around after exectution
107 
112  virtual void DoNotPreserveWorkspace() { fPreserveWorkspace = false; }
113 
118  virtual void DisableTagCopy() { fCopyTags = false; }
119 
124  virtual void EnableTagCopy() { fCopyTags = true; }
125 
126 
133  {
134  for(std::size_t i = 0; i < XArgType::rank::value; i++)
135  {
136  fAxesToXForm[i] = true;
137  }
138  }
139 
144  {
145  for(std::size_t i = 0; i < XArgType::rank::value; i++)
146  {
147  fAxesToXForm[i] = false;
148  }
149  }
150 
156  void SelectAxis(std::size_t axis_index)
157  {
158  if(axis_index < XArgType::rank::value)
159  {
160  fAxesToXForm[axis_index] = true;
161  }
162  else
163  {
164  msg_error("operators", "Cannot transform axis with index: " << axis_index << "for array with rank: "
165  << XArgType::rank::value << eom);
166  }
167  }
168 
169  protected:
177  virtual bool InitializeInPlace(XArgType* in)
178  {
179  if(fTmpWorkspace == nullptr)
180  {
181  fTmpWorkspace = new XArgType();
182  }
183  return InitializeOutOfPlace(in, fTmpWorkspace);
184  }
185 
193  virtual bool ExecuteInPlace(XArgType* in)
194  {
195  bool status = ExecuteOutOfPlace(in, fTmpWorkspace);
196  //"in-place" execution requires a copy from the workspace back to the object we are modifying
197  in->Copy(*fTmpWorkspace);
198  if(!fPreserveWorkspace)
199  {
200  //destroy the temporary workspace when we are done
201  delete fTmpWorkspace;
202  fTmpWorkspace = nullptr;
203  }
204  return status;
205  }
206 
215  virtual bool InitializeOutOfPlace(const XArgType* in, XArgType* out)
216  {
217  if(in != nullptr && out != nullptr && in != out)
218  {
219  fIsValid = true;
220  }
221 
222  if(fIsValid)
223  {
224  //output dimensions must be factor of fPaddingFactor bigger than input dims
225  in->GetDimensions(fInputDimensionSize);
226  out->GetDimensions(fOutputDimensionSize);
227  ConditionallyResizeOutput(in->GetDimensionArray(), out);
228  fInitialized = true;
229  }
230  return (fInitialized && fIsValid);
231  }
232 
241  virtual bool ExecuteOutOfPlace(const XArgType* in, XArgType* out)
242  {
243  if(fIsValid && fInitialized)
244  {
245  //zero out the output array
246  out->ZeroArray();
247  if(!fFlipped)
248  {
249  //zero padding is placed at the end of the array
250  auto in_iter = in->cbegin();
251  auto in_iter_end = in->cend();
252  std::array< std::size_t, XArgType::rank::value > in_indices;
253  while(in_iter != in_iter_end)
254  {
255  //copy the input data to the same 'index' location in the output array
256 
257  //get the input indices for each dimension
258  MHO_NDArrayMath::RowMajorIndexFromOffset< XArgType::rank::value >(
259  in_iter.GetOffset(), fInputDimensionSize, &(in_indices[0]));
260  std::size_t out_loc = MHO_NDArrayMath::OffsetFromRowMajorIndex< XArgType::rank::value >(
261  fOutputDimensionSize, &(in_indices[0]));
262  (*(out))[out_loc] = *in_iter;
263  ++in_iter;
264  }
265  }
266  else
267  {
268  //zero padding is placed at the start of the array
269  auto in_iter = in->cbegin();
270  auto in_iter_end = in->cend();
271  std::array< std::size_t, XArgType::rank::value > in_index;
272  std::size_t out_index[XArgType::rank::value];
273  while(in_iter != in_iter_end)
274  {
275  //copy the input data to the flipped location in the output array
276  MHO_NDArrayMath::RowMajorIndexFromOffset< XArgType::rank::value >(in_iter.GetOffset(),
277  in->GetDimensions(), &(in_index[0]));
278  for(std::size_t i = 0; i < XArgType::rank::value; i++)
279  {
280  if(fAxesToXForm[i])
281  {
282  out_index[i] = (fOutputDimensionSize[i] - 1) - in_index[i];
283  //The way were are setting the indexes here when fNormFXMode is enabled
284  //(with n=0 mapping to N/2 is done for compatibility with norm_fx)
285  //TODO...figure out why it is done this way
286  if(fNormFXMode)
287  {
288  out_index[i] = fOutputDimensionSize[i] - in_index[i];
289  if(in_index[i] == 0)
290  {
291  out_index[i] = fOutputDimensionSize[i] / 2;
292  }
293  }
294  }
295  else
296  {
297  out_index[i] = in_index[i];
298  }
299  }
300  std::size_t out_loc =
301  MHO_NDArrayMath::OffsetFromRowMajorIndex< XArgType::rank::value >(fOutputDimensionSize, out_index);
302  (*(out))[out_loc] = *in_iter;
303  ++in_iter;
304  }
305  }
306 
307  IfTableTransformAxis(in, out);
308  //successful
309  return true;
310  }
311  else
312  {
313  //error
314  msg_error("operators", "Array dimensions are not valid or intialization failed. Aborting zero padding." << eom);
315  return false;
316  }
317  }
318 
319  private:
320  //default...does nothing
328  template< typename XCheckType = XArgType >
329  typename std::enable_if< !std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
330  IfTableTransformAxis(const XArgType* , XArgType* ){};
331 
332  //use SFINAE to generate specialization for MHO_TableContainer types
333  template< typename XCheckType = XArgType >
334  typename std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
335  IfTableTransformAxis(const XArgType* in, XArgType* out)
336  {
337  for(size_t i = 0; i < XArgType::rank::value; i++) //apply to all axes
338  {
339  TransformAxis axis_transformer(fAxesToXForm[i], fFlipped, fCopyTags);
340  apply_at2< typename XArgType::axis_pack_tuple_type, TransformAxis >(*in, *out, i, axis_transformer);
341  }
342  out->CopyTags(*in); //make sure the table tags get copied
343  }
344 
345  class TransformAxis
346  {
347  public:
348  TransformAxis(bool modify, bool flipped, bool copy_tags)
349  : fModify(modify), fFlipped(flipped), fCopyTags(copy_tags){};
350 
351  ~TransformAxis(){};
352 
353  //generic axis, do nothing
354  template< typename XAxisType > void operator()(const XAxisType& axis1, XAxisType& axis2)
355  {
356  if(!fCopyTags)
357  {
358  CopyLabelsWithoutTags(axis1, axis2);
359  }
360  else
361  {
362  axis2.Copy(axis1);
363  }
364  if(!fModify)
365  {
366  return;
367  } //just copy this axis
368  };
369 
370  void operator()(const MHO_Axis< double >& axis1, MHO_Axis< double >& axis2)
371  {
372  std::size_t ax1_size = axis1.GetSize();
373  std::size_t ax2_size = axis2.GetSize();
374  if(!fCopyTags)
375  {
376  CopyLabelsWithoutTags(axis1, axis2);
377  }
378  else
379  {
380  axis2.Copy(axis1);
381  }
382  if(!fModify)
383  {
384  return;
385  } //just copy this axis
386  axis2.Resize(ax2_size);
387  //assumes uniform labeling, probably ok as we only need this for FFTs
388  double delta = axis1(1) - axis1(0);
389  if(!fFlipped)
390  {
391  for(std::size_t i = 0; i < ax1_size; i++)
392  {
393  axis2(i) = axis1(i);
394  }
395  for(std::size_t i = ax1_size; i < ax2_size; i++)
396  {
397  axis2(i) = axis1(ax1_size - 1) + (i - (ax1_size - 1)) * delta;
398  }
399  }
400  else
401  {
402  for(std::size_t i = 0; i < ax1_size; i++)
403  {
404  axis2(i) = axis1(ax1_size - 1 - i);
405  }
406  for(std::size_t i = ax1_size; i < ax2_size; i++)
407  {
408  axis2(i) = axis1(0) - (i - (ax1_size - 1)) * delta;
409  }
410  }
411  }
412 
413  void operator()(const MHO_Axis< float >& axis1, MHO_Axis< float >& axis2)
414  {
415  std::size_t ax1_size = axis1.GetSize();
416  std::size_t ax2_size = axis2.GetSize();
417  if(!fCopyTags)
418  {
419  CopyLabelsWithoutTags(axis1, axis2);
420  }
421  else
422  {
423  axis2.Copy(axis1);
424  }
425  if(!fModify)
426  {
427  return;
428  } //just copy this axis
429  axis2.Resize(ax2_size);
430  //assumes uniform labeling, probably ok as we only need this for FFTs
431  double delta = axis1(1) - axis1(0);
432  if(!fFlipped)
433  {
434  for(std::size_t i = 0; i < ax1_size; i++)
435  {
436  axis2(i) = axis1(i);
437  }
438  for(std::size_t i = ax1_size; i < ax2_size; i++)
439  {
440  axis2(i) = axis1(ax1_size - 1) + (i - (ax1_size - 1)) * delta;
441  }
442  }
443  else
444  {
445  for(std::size_t i = 0; i < ax1_size; i++)
446  {
447  axis2(i) = axis1(ax1_size - 1 - i);
448  }
449  for(std::size_t i = ax1_size; i < ax2_size; i++)
450  {
451  axis2(i) = axis1(0) - (i - (ax1_size - 1)) * delta;
452  }
453  }
454  }
455 
456  private:
457  template< typename XAxisType > void CopyLabelsWithoutTags(const XAxisType& axis1, XAxisType& axis2)
458  {
459  //just copy axis labels
460  std::size_t ax1_size = axis1.GetSize();
461  std::size_t ax2_size = axis2.GetSize();
462  std::size_t s = std::min(ax1_size, ax2_size);
463  for(std::size_t i = 0; i < s; i++)
464  {
465  axis2(i) = axis1(i);
466  }
467  }
468 
469  bool fModify;
470  bool fFlipped;
471  bool fCopyTags;
472  };
473 
474  void ConditionallyResizeOutput(const std::array< std::size_t, XArgType::rank::value >& dims, XArgType* out)
475  {
476  auto out_dim = out->GetDimensionArray();
477  bool have_to_resize = false;
478  for(std::size_t i = 0; i < XArgType::rank::value; i++)
479  {
480  if(fAxesToXForm[i])
481  {
482  if(dims[i] * fPaddingFactor != out_dim[i])
483  {
484  have_to_resize = true;
485  out_dim[i] = dims[i] * fPaddingFactor;
486  }
487  if(fPaddingFactor == 1)
488  {
489  if(dims[i] != fPaddedSize)
490  {
491  have_to_resize = true;
492  out_dim[i] = fPaddedSize;
493  }
494  }
495  }
496  else
497  {
498  if(dims[i] != out_dim[i])
499  {
500  have_to_resize = true;
501  out_dim[i] = dims[i];
502  }
503  }
504  }
505  if(have_to_resize)
506  {
507  out->Resize(&(out_dim[0]));
508  }
509  out->GetDimensions(fOutputDimensionSize);
510  }
511 
512  bool fIsValid;
513  bool fInitialized;
514  bool fFlipped;
515  bool fNormFXMode;
516  bool fPreserveWorkspace;
517  bool fCopyTags;
518 
519  std::size_t fPaddingFactor;
520  std::size_t fPaddedSize;
521  std::size_t fInputDimensionSize[XArgType::rank::value];
522  std::size_t fOutputDimensionSize[XArgType::rank::value];
523  bool fAxesToXForm[XArgType::rank::value];
524 
525  XArgType* fTmpWorkspace;
526 };
527 
528 } // namespace hops
529 
530 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:244
virtual void Copy(const MHO_Axis &rhs)
Expensive copy for MHO_Axis that handles special treatment of index/interval labels.
Definition: MHO_Axis.hh:202
Class MHO_EndZeroPadder.
Definition: MHO_EndZeroPadder.hh:29
virtual void SetReverseEndPadded()
Setter for reverse end padded, place data at end of array and zero pad out to start.
Definition: MHO_EndZeroPadder.hh:85
void DeselectAllAxes()
Deselects all axes by setting each axis to false.
Definition: MHO_EndZeroPadder.hh:143
virtual void DoNotPreserveWorkspace()
Sets preserve workspace flag to false, delete memory after execution.
Definition: MHO_EndZeroPadder.hh:112
virtual bool ExecuteInPlace(XArgType *in)
Executes operation in-place by copying temporary workspace back to input object.
Definition: MHO_EndZeroPadder.hh:193
virtual ~MHO_EndZeroPadder()
Definition: MHO_EndZeroPadder.hh:51
virtual bool ExecuteOutOfPlace(const XArgType *in, XArgType *out)
Function ExecuteOutOfPlace.
Definition: MHO_EndZeroPadder.hh:241
virtual void EnableTagCopy()
Enables copying of tags.
Definition: MHO_EndZeroPadder.hh:124
void SelectAllAxes()
Selects all axes for transformation. sometimes we may want to select/deselect particular dimensions o...
Definition: MHO_EndZeroPadder.hh:132
virtual bool InitializeInPlace(XArgType *in)
Initializes in-place by creating a temporary workspace and calling InitializeOutOfPlace.
Definition: MHO_EndZeroPadder.hh:177
virtual void PreserveWorkspace()
Sets a flag to preserve workspace memory after execution.
Definition: MHO_EndZeroPadder.hh:103
virtual void EnableNormFXMode()
Enables Normalized FX Mode by setting fNormFXMode to true. UNUSED - TODO REMOVE ME!
Definition: MHO_EndZeroPadder.hh:97
virtual bool InitializeOutOfPlace(const XArgType *in, XArgType *out)
Initializes out-of-place processing for input and output arrays.
Definition: MHO_EndZeroPadder.hh:215
virtual void SetPaddingFactor(std::size_t factor)
Setter for padding factor, the factor M by which the new array will be extended (original array,...
Definition: MHO_EndZeroPadder.hh:60
void SelectAxis(std::size_t axis_index)
Selects an axis for transformation if its index is within the array rank.
Definition: MHO_EndZeroPadder.hh:156
virtual void SetEndPadded()
Setter for end padded, zero padding from end of data out to end of the array.
Definition: MHO_EndZeroPadder.hh:79
virtual void DisableTagCopy()
Disables copying tags by setting fCopyTags to false.
Definition: MHO_EndZeroPadder.hh:118
MHO_EndZeroPadder()
Definition: MHO_EndZeroPadder.hh:31
virtual void SetPaddedSize(std::size_t new_size)
Setter for padded size, instead of a multiplicative factor, the original array, length N is padded ou...
Definition: MHO_EndZeroPadder.hh:69
virtual void DisableNormFXMode()
Disables Normal Mapping FX Mode by setting fNormFXMode to false. UNUSED - TODO REMOVE ME!
Definition: MHO_EndZeroPadder.hh:91
virtual void Resize(const std::size_t *dim)
Resize an externally managed array using provided dimensions.
Definition: MHO_NDArrayWrapper_1.hh:52
std::size_t GetSize() const
Getter for size.
Definition: MHO_NDArrayWrapper_1.hh:107
Class MHO_UnaryOperator.
Definition: MHO_UnaryOperator.hh:24
struct type_status status
Definition: fourfit3.c:53
#define min(a, b)
Definition: max555.c:9
Definition: MHO_ChannelLabeler.hh:17