HOPS
HOPS class reference
MHO_Reducer.hh
Go to the documentation of this file.
1 #ifndef MHO_Reducer_HH__
2 #define MHO_Reducer_HH__
3 
4 #include <algorithm>
5 
6 #include "MHO_CompoundReductions.hh" //for operator type definitions
7 #include "MHO_Message.hh"
8 #include "MHO_NDArrayWrapper.hh"
9 #include "MHO_TableContainer.hh"
10 #include "MHO_UnaryOperator.hh"
11 
12 namespace hops
13 {
14 
29 template< typename XArrayType, template< typename > class XFunctorType >
30 class MHO_Reducer: public MHO_UnaryOperator< XArrayType >
31 {
32  public:
33  using XItemType = typename XArrayType::value_type;
34 
36  {
37  fInitialized = false;
38  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
39  {
40  fAxesToReduce[i] = 0;
41  }
42  }
43 
44  virtual ~MHO_Reducer(){};
45 
56  void ReduceAxis(std::size_t axis_index)
57  {
58  fInitialized = false;
59  if(axis_index < XArrayType::rank::value)
60  {
61  fAxesToReduce[axis_index] = 1;
62  }
63  else
64  {
65  msg_error("operators", "Cannot reduce axis with index: " << axis_index << "for array with rank: "
66  << XArrayType::rank::value << eom);
67  }
68  }
69 
70  //de-select all axes
75  {
76  fInitialized = false;
77  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
78  {
79  fAxesToReduce[i] = 0;
80  }
81  }
82 
83  protected:
91  virtual bool InitializeInPlace(XArrayType* in) override { return InitializeOutOfPlace(in, &fWorkspace); }
92 
100  virtual bool ExecuteInPlace(XArrayType* in) override
101  {
102  bool status = ExecuteOutOfPlace(in, &fWorkspace);
103  //"in-place" execution requires a copy from the workspace back to the object we are modifying
104  in->Copy(fWorkspace);
105  return status;
106  }
107 
116  virtual bool InitializeOutOfPlace(const XArrayType* in, XArrayType* out) override
117  {
118  if(in != nullptr && out != nullptr)
119  {
120  std::size_t in_dim[XArrayType::rank::value];
121  std::size_t out_dim[XArrayType::rank::value];
122  std::size_t current_out_dim[XArrayType::rank::value];
123  in->GetDimensions(in_dim);
124  out->GetDimensions(current_out_dim);
125 
126  //first figure out what the remaining dim sizes are to be
127  //after the array is contracted along the specified dimensions
128  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
129  {
130  if(fAxesToReduce[i])
131  {
132  out_dim[i] = 1;
133  }
134  else
135  {
136  out_dim[i] = in_dim[i];
137  }
138  }
139 
140  bool have_to_resize = false;
141  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
142  {
143  if(out_dim[i] != current_out_dim[i])
144  {
145  have_to_resize = true;
146  break;
147  }
148  }
149 
150  if(have_to_resize)
151  {
152  out->Resize(out_dim);
153  }
154 
155  //must set the entire output array to the identity of the currently
156  //templated
157  out->SetArray(this->fReductionFunctor.identity);
158  fInitialized = true;
159  }
160  return fInitialized;
161  }
162 
171  virtual bool ExecuteOutOfPlace(const XArrayType* in, XArrayType* out) override
172  {
173  if(fInitialized)
174  {
175  std::size_t in_dim[XArrayType::rank::value];
176  std::size_t out_dim[XArrayType::rank::value];
177  in->GetDimensions(in_dim);
178  out->GetDimensions(out_dim);
179 
180  std::size_t offset;
181  std::size_t in_loc[XArrayType::rank::value];
182  std::size_t out_loc[XArrayType::rank::value];
183  auto iter_begin = in->cbegin();
184  auto iter_end = in->cend();
185  for(auto iter = iter_begin; iter != iter_end; ++iter)
186  {
187  //get the input indices for each dimension
188  offset = iter.GetOffset();
189  MHO_NDArrayMath::RowMajorIndexFromOffset< XArrayType::rank::value >(offset, in->GetDimensions(),
190  &(in_loc[0]));
191 
192  //set the output indices to collapse each index of the dimensions under reduction
193  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
194  {
195  out_loc[i] = std::min(in_loc[i], out_dim[i] - 1);
196  }
197  //find offset to location in output array
198  std::size_t m = MHO_NDArrayMath::OffsetFromRowMajorIndex< XArrayType::rank::value >(out_dim, out_loc);
199  //execute the reduction operator += or *= or user-defined
200  fReductionFunctor((*(out))[m], *iter);
201  }
202 
203  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
204  {
205  // if(fAxesToReduce[i] == 1){IfTableReduceAxis(in, out, i);}
206  IfTableReduceAxis(in, out, i);
207  }
208 
209  return true;
210  }
211  return false;
212  }
213 
214  private:
218  class AxisReducer
219  {
220  public:
221  AxisReducer(std::size_t reduce_ax): fReduce(false)
222  {
223  if(reduce_ax)
224  {
225  fReduce = true;
226  }
227  };
228 
229  ~AxisReducer(){};
230 
231  template< typename XAxisType > void operator()(const XAxisType& axis1, XAxisType& axis2)
232  {
233  if(fReduce)
234  {
235  //all we do is set the axis label to the start value of the
236  //original axis, perhaps we ought to enable an option to use
237  //the mean value as well/instead?
238  auto it1 = axis1.cbegin();
239  auto it2 = axis2.begin();
240  *it2 = *it1;
241  axis2.CopyTags(axis1); //copy the axis tags
242  }
243  else
244  {
245  //copy the axis
246  axis2.Copy(axis1);
247  }
248  }
249 
250  private:
251  bool fReduce;
252  };
253 
254  //default...does nothing
263  template< typename XCheckType = XArrayType >
264  typename std::enable_if< !std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
265  IfTableReduceAxis(const XArrayType* , XArrayType* , std::size_t ){};
266 
267  //use SFINAE to generate specialization for MHO_TableContainer types
276  template< typename XCheckType = XArrayType >
277  typename std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
278  IfTableReduceAxis(const XArrayType* in, XArrayType* out, std::size_t ax_index)
279  {
280  AxisReducer axis_reducer(fAxesToReduce[ax_index]);
281  apply_at2< typename XArrayType::axis_pack_tuple_type, AxisReducer >(*in, *out, ax_index, axis_reducer);
282  if(ax_index == 0)
283  {
284  out->CopyTags(*in);
285  } //make sure the table tags get copied, just once
286  }
287 
288  bool fInitialized;
289  std::size_t fAxesToReduce[XArrayType::rank::value];
290  XFunctorType< XItemType > fReductionFunctor;
291  XArrayType fWorkspace;
292 };
293 
294 } // namespace hops
295 
296 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:238
Class MHO_Reducer.
Definition: MHO_Reducer.hh:31
void ClearAxisSelection()
De-selects all axes by setting internal flags and arrays to default values (no reduction)
Definition: MHO_Reducer.hh:74
typename XArrayType::value_type XItemType
Definition: MHO_Reducer.hh:33
MHO_Reducer()
Definition: MHO_Reducer.hh:35
void ReduceAxis(std::size_t axis_index)
Sets axis index for reduction operation.
Definition: MHO_Reducer.hh:56
virtual ~MHO_Reducer()
Definition: MHO_Reducer.hh:44
virtual bool ExecuteInPlace(XArrayType *in) override
Executes operation in-place by calling ExecuteOutOfPlace and copying result back to input.
Definition: MHO_Reducer.hh:100
virtual bool InitializeOutOfPlace(const XArrayType *in, XArrayType *out) override
Initializes out-of-place operation using input array and workspace.
Definition: MHO_Reducer.hh:116
virtual bool InitializeInPlace(XArrayType *in) override
Initializes XArrayType in-place by calling InitializeOutOfPlace with given workspace.
Definition: MHO_Reducer.hh:91
virtual bool ExecuteOutOfPlace(const XArrayType *in, XArrayType *out) override
Function ExecuteOutOfPlace - carries out the array reduction.
Definition: MHO_Reducer.hh:171
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