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