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 
132  {
133  for(std::size_t i = 0; i < XArgType::rank::value; i++)
134  {
135  fAxesToXForm[i] = true;
136  }
137  }
138 
143  {
144  for(std::size_t i = 0; i < XArgType::rank::value; i++)
145  {
146  fAxesToXForm[i] = false;
147  }
148  }
149 
155  void SelectAxis(std::size_t axis_index)
156  {
157  if(axis_index < XArgType::rank::value)
158  {
159  fAxesToXForm[axis_index] = true;
160  }
161  else
162  {
163  msg_error("operators", "Cannot transform axis with index: " << axis_index << "for array with rank: "
164  << XArgType::rank::value << eom);
165  }
166  }
167 
168  protected:
176  virtual bool InitializeInPlace(XArgType* in) override
177  {
178  if(fTmpWorkspace == nullptr)
179  {
180  fTmpWorkspace = new XArgType();
181  }
182  return InitializeOutOfPlace(in, fTmpWorkspace);
183  }
184 
192  virtual bool ExecuteInPlace(XArgType* in) override
193  {
194  bool status = ExecuteOutOfPlace(in, fTmpWorkspace);
195  //"in-place" execution requires a copy from the workspace back to the object we are modifying
196  in->Copy(*fTmpWorkspace);
197  if(!fPreserveWorkspace)
198  {
199  //destroy the temporary workspace when we are done
200  delete fTmpWorkspace;
201  fTmpWorkspace = nullptr;
202  }
203  return status;
204  }
205 
213  virtual bool InitializeOutOfPlace(const XArgType* in, XArgType* out) override
214  {
215  if(in != nullptr && out != nullptr && in != out)
216  {
217  fIsValid = true;
218  }
219 
220  if(fIsValid)
221  {
222  //output dimensions must be factor of fPaddingFactor bigger than input dims
223  in->GetDimensions(fInputDimensionSize);
224  out->GetDimensions(fOutputDimensionSize);
225  ConditionallyResizeOutput(in->GetDimensionArray(), out);
226  fInitialized = true;
227  }
228  return (fInitialized && fIsValid);
229  }
230 
239  virtual bool ExecuteOutOfPlace(const XArgType* in, XArgType* out) override
240  {
241  if(fIsValid && fInitialized)
242  {
243  profiler_scope();
244  //zero out the output array
245  out->ZeroArray();
246  if(!fFlipped)
247  {
248  //zero padding is placed at the end of the array
249  auto in_iter = in->cbegin();
250  auto in_iter_end = in->cend();
251  std::array< std::size_t, XArgType::rank::value > in_indices;
252  while(in_iter != in_iter_end)
253  {
254  //copy the input data to the same 'index' location in the output array
255 
256  //get the input indices for each dimension
257  MHO_NDArrayMath::RowMajorIndexFromOffset< XArgType::rank::value >(
258  in_iter.GetOffset(), fInputDimensionSize, &(in_indices[0]));
259  std::size_t out_loc = MHO_NDArrayMath::OffsetFromRowMajorIndex< XArgType::rank::value >(
260  fOutputDimensionSize, &(in_indices[0]));
261  (*(out))[out_loc] = *in_iter;
262  ++in_iter;
263  }
264  }
265  else
266  {
267  //zero padding is placed at the start of the array
268  auto in_iter = in->cbegin();
269  auto in_iter_end = in->cend();
270  std::array< std::size_t, XArgType::rank::value > in_index;
271  std::size_t out_index[XArgType::rank::value];
272  while(in_iter != in_iter_end)
273  {
274  //copy the input data to the flipped location in the output array
275  MHO_NDArrayMath::RowMajorIndexFromOffset< XArgType::rank::value >(in_iter.GetOffset(),
276  in->GetDimensions(), &(in_index[0]));
277  for(std::size_t i = 0; i < XArgType::rank::value; i++)
278  {
279  if(fAxesToXForm[i])
280  {
281  out_index[i] = (fOutputDimensionSize[i] - 1) - in_index[i];
282  //The way were are setting the indexes here when fNormFXMode is enabled
283  //(with n=0 mapping to N/2 is done for compatibility with norm_fx)
284  //TODO...figure out why it is done this way
285  if(fNormFXMode)
286  {
287  out_index[i] = fOutputDimensionSize[i] - in_index[i];
288  if(in_index[i] == 0)
289  {
290  out_index[i] = fOutputDimensionSize[i] / 2;
291  }
292  }
293  }
294  else
295  {
296  out_index[i] = in_index[i];
297  }
298  }
299  std::size_t out_loc =
300  MHO_NDArrayMath::OffsetFromRowMajorIndex< XArgType::rank::value >(fOutputDimensionSize, out_index);
301  (*(out))[out_loc] = *in_iter;
302  ++in_iter;
303  }
304  }
305 
306  IfTableTransformAxis(in, out);
307  //successful
308  return true;
309  }
310  else
311  {
312  //error
313  msg_error("operators", "Array dimensions are not valid or intialization failed. Aborting zero padding." << eom);
314  return false;
315  }
316  }
317 
318  private:
319  //default...does nothing
327  template< typename XCheckType = XArgType >
328  typename std::enable_if< !std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
329  IfTableTransformAxis(const XArgType* , XArgType* ){};
330 
331  //use SFINAE to generate specialization for MHO_TableContainer types
332  template< typename XCheckType = XArgType >
333  typename std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
334  IfTableTransformAxis(const XArgType* in, XArgType* out)
335  {
336  for(size_t i = 0; i < XArgType::rank::value; i++) //apply to all axes
337  {
338  TransformAxis axis_transformer(fAxesToXForm[i], fFlipped, fCopyTags);
339  apply_at2< typename XArgType::axis_pack_tuple_type, TransformAxis >(*in, *out, i, axis_transformer);
340  }
341  out->CopyTags(*in); //make sure the table tags get copied
342  }
343 
344  class TransformAxis
345  {
346  public:
347  TransformAxis(bool modify, bool flipped, bool copy_tags)
348  : fModify(modify), fFlipped(flipped), fCopyTags(copy_tags){};
349 
350  ~TransformAxis(){};
351 
352  //generic axis, do nothing
353  template< typename XAxisType > void operator()(const XAxisType& axis1, XAxisType& axis2)
354  {
355  if(!fCopyTags)
356  {
357  CopyLabelsWithoutTags(axis1, axis2);
358  }
359  else
360  {
361  axis2.Copy(axis1);
362  }
363  if(!fModify)
364  {
365  return;
366  } //just copy this axis
367  };
368 
369  void operator()(const MHO_Axis< double >& axis1, MHO_Axis< double >& axis2)
370  {
371  std::size_t ax1_size = axis1.GetSize();
372  std::size_t ax2_size = axis2.GetSize();
373  if(!fCopyTags)
374  {
375  CopyLabelsWithoutTags(axis1, axis2);
376  }
377  else
378  {
379  axis2.Copy(axis1);
380  }
381  if(!fModify)
382  {
383  return;
384  } //just copy this axis
385  axis2.Resize(ax2_size);
386  //assumes uniform labeling, probably ok as we only need this for FFTs
387  double delta = axis1(1) - axis1(0);
388  if(!fFlipped)
389  {
390  for(std::size_t i = 0; i < ax1_size; i++)
391  {
392  axis2(i) = axis1(i);
393  }
394  for(std::size_t i = ax1_size; i < ax2_size; i++)
395  {
396  axis2(i) = axis1(ax1_size - 1) + (i - (ax1_size - 1)) * delta;
397  }
398  }
399  else
400  {
401  for(std::size_t i = 0; i < ax1_size; i++)
402  {
403  axis2(i) = axis1(ax1_size - 1 - i);
404  }
405  for(std::size_t i = ax1_size; i < ax2_size; i++)
406  {
407  axis2(i) = axis1(0) - (i - (ax1_size - 1)) * delta;
408  }
409  }
410  }
411 
412  void operator()(const MHO_Axis< float >& axis1, MHO_Axis< float >& axis2)
413  {
414  std::size_t ax1_size = axis1.GetSize();
415  std::size_t ax2_size = axis2.GetSize();
416  if(!fCopyTags)
417  {
418  CopyLabelsWithoutTags(axis1, axis2);
419  }
420  else
421  {
422  axis2.Copy(axis1);
423  }
424  if(!fModify)
425  {
426  return;
427  } //just copy this axis
428  axis2.Resize(ax2_size);
429  //assumes uniform labeling, probably ok as we only need this for FFTs
430  double delta = axis1(1) - axis1(0);
431  if(!fFlipped)
432  {
433  for(std::size_t i = 0; i < ax1_size; i++)
434  {
435  axis2(i) = axis1(i);
436  }
437  for(std::size_t i = ax1_size; i < ax2_size; i++)
438  {
439  axis2(i) = axis1(ax1_size - 1) + (i - (ax1_size - 1)) * delta;
440  }
441  }
442  else
443  {
444  for(std::size_t i = 0; i < ax1_size; i++)
445  {
446  axis2(i) = axis1(ax1_size - 1 - i);
447  }
448  for(std::size_t i = ax1_size; i < ax2_size; i++)
449  {
450  axis2(i) = axis1(0) - (i - (ax1_size - 1)) * delta;
451  }
452  }
453  }
454 
455  private:
456  template< typename XAxisType > void CopyLabelsWithoutTags(const XAxisType& axis1, XAxisType& axis2)
457  {
458  //just copy axis labels
459  std::size_t ax1_size = axis1.GetSize();
460  std::size_t ax2_size = axis2.GetSize();
461  std::size_t s = std::min(ax1_size, ax2_size);
462  for(std::size_t i = 0; i < s; i++)
463  {
464  axis2(i) = axis1(i);
465  }
466  }
467 
468  bool fModify;
469  bool fFlipped;
470  bool fCopyTags;
471  };
472 
473  void ConditionallyResizeOutput(const std::array< std::size_t, XArgType::rank::value >& dims, XArgType* out)
474  {
475  auto out_dim = out->GetDimensionArray();
476  bool have_to_resize = false;
477  for(std::size_t i = 0; i < XArgType::rank::value; i++)
478  {
479  if(fAxesToXForm[i])
480  {
481  if(dims[i] * fPaddingFactor != out_dim[i])
482  {
483  have_to_resize = true;
484  out_dim[i] = dims[i] * fPaddingFactor;
485  }
486  if(fPaddingFactor == 1)
487  {
488  if(dims[i] != fPaddedSize)
489  {
490  have_to_resize = true;
491  out_dim[i] = fPaddedSize;
492  }
493  }
494  }
495  else
496  {
497  if(dims[i] != out_dim[i])
498  {
499  have_to_resize = true;
500  out_dim[i] = dims[i];
501  }
502  }
503  }
504  if(have_to_resize)
505  {
506  out->Resize(&(out_dim[0]));
507  }
508  out->GetDimensions(fOutputDimensionSize);
509  }
510 
511  bool fIsValid;
512  bool fInitialized;
513  bool fFlipped;
514  bool fNormFXMode;
515  bool fPreserveWorkspace;
516  bool fCopyTags;
517 
518  std::size_t fPaddingFactor;
519  std::size_t fPaddedSize;
520  std::size_t fInputDimensionSize[XArgType::rank::value];
521  std::size_t fOutputDimensionSize[XArgType::rank::value];
522  bool fAxesToXForm[XArgType::rank::value];
523 
524  XArgType* fTmpWorkspace;
525 };
526 
527 } // namespace hops
528 
529 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:238
#define profiler_scope()
Definition: MHO_Profiler.hh:237
virtual void Copy(const MHO_Axis &rhs)
Expensive copy for MHO_Axis that handles special treatment of index/interval labels.
Definition: MHO_Axis.hh:200
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:142
virtual void DoNotPreserveWorkspace()
Sets preserve workspace flag to false, delete memory after execution.
Definition: MHO_EndZeroPadder.hh:112
virtual ~MHO_EndZeroPadder()
Definition: MHO_EndZeroPadder.hh:51
virtual void EnableTagCopy()
Enables copying of tags.
Definition: MHO_EndZeroPadder.hh:124
virtual bool ExecuteOutOfPlace(const XArgType *in, XArgType *out) override
Function ExecuteOutOfPlace.
Definition: MHO_EndZeroPadder.hh:239
void SelectAllAxes()
Selects all axes for transformation. sometimes we may want to select/deselect particular dimensions o...
Definition: MHO_EndZeroPadder.hh:131
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 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
virtual bool InitializeInPlace(XArgType *in) override
Initializes in-place by creating a temporary workspace and calling InitializeOutOfPlace.
Definition: MHO_EndZeroPadder.hh:176
virtual bool ExecuteInPlace(XArgType *in) override
Executes operation in-place by copying temporary workspace back to input object.
Definition: MHO_EndZeroPadder.hh:192
void SelectAxis(std::size_t axis_index)
Selects an axis for transformation if its index is within the array rank.
Definition: MHO_EndZeroPadder.hh:155
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
virtual bool InitializeOutOfPlace(const XArgType *in, XArgType *out) override
Initializes out-of-place processing for input and output arrays.
Definition: MHO_EndZeroPadder.hh:213
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:99
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_AdhocFlagging.hh:18