HOPS
HOPS class reference
MHO_SubSample.hh
Go to the documentation of this file.
1 #ifndef MHO_SubSample_HH__
2 #define MHO_SubSample_HH__
3 
4 #include <algorithm>
5 #include <cstdint>
6 
7 #include "MHO_Message.hh"
8 #include "MHO_Meta.hh"
9 #include "MHO_NDArrayWrapper.hh"
10 #include "MHO_TableContainer.hh"
11 #include "MHO_UnaryOperator.hh"
12 
13 namespace hops
14 {
15 
29 template< class XArrayType > class MHO_SubSample: public MHO_UnaryOperator< XArrayType >
30 {
31  public:
33  {
34  fInitialized = false;
35  fDimIndex = 0;
36  fStride = 1;
37  };
38 
39  virtual ~MHO_SubSample(){};
40 
47  void SetDimensionAndStride(std::size_t dimension_index, std::size_t stride)
48  {
49  if(dimension_index < XArrayType::rank::value)
50  {
51  fDimIndex = dimension_index;
52  fStride = stride;
53  }
54  else
55  {
56  msg_error("operators", "error, cannot select dimension: " << dimension_index << ", exceeds array rank." << eom);
57  }
58  fInitialized = false;
59  }
60 
61  protected:
69  virtual bool InitializeInPlace(XArrayType* in) override { return InitializeOutOfPlace(in, &fWorkspace); }
70 
78  virtual bool ExecuteInPlace(XArrayType* in) override
79  {
80  bool status = ExecuteOutOfPlace(in, &fWorkspace);
81  //"in-place" execution requires a copy from the workspace back to the object we are modifying
82  in->Copy(fWorkspace);
83 
84  // auto workspace_dim = fWorkspace.GetDimensionArray();
85  // for(std::size_t i=0; i<workspace_dim.size(); i++){workspace_dim[i] = 0;}
86  // fWorkspace.Resize(&(workspace_dim[0]));
87 
88  return status;
89  }
90 
99  virtual bool InitializeOutOfPlace(const XArrayType* in, XArrayType* out) override
100  {
101  if(in != nullptr && out != nullptr)
102  {
103  //check that the dimension we are sub-sampling is divisable by the stride
104  if(in->GetDimension(fDimIndex) % fStride != 0)
105  {
106  msg_error("operators", "dimension to sub-sample must be divisable by stride." << eom);
107  return false;
108  }
109  auto dims = DetermineOutputDimensions(in);
110  ConditionallyResizeOutput(dims, out);
111  fInitialized = true;
112  }
113  return true;
114  }
115 
124  virtual bool ExecuteOutOfPlace(const XArrayType* in, XArrayType* out) override
125  {
126  profiler_scope();
127  size_t index[XArrayType::rank::value];
128  size_t non_active_dimension_size[XArrayType::rank::value - 1];
129  size_t non_active_dimension_value[XArrayType::rank::value - 1];
130  size_t non_active_dimension_index[XArrayType::rank::value - 1];
131 
132  std::size_t d = fDimIndex;
133  //now we loop over all dimensions not specified by d
134  //first compute the number of arrays we need to sub-sample
135  size_t n_srow = 1;
136  size_t count = 0;
137  size_t in_stride = in->GetStride(d);
138  for(size_t i = 0; i < XArrayType::rank::value; i++)
139  {
140  if(i != d)
141  {
142  n_srow *= in->GetDimension(i);
143  non_active_dimension_index[count] = i;
144  non_active_dimension_size[count] = in->GetDimension(i);
145  count++;
146  }
147  }
148 
149  //loop over the number of rows we need to sub-sample
150  for(size_t n = 0; n < n_srow; n++)
151  {
152  //invert place in list to obtain indices of block in array
153  MHO_NDArrayMath::RowMajorIndexFromOffset< XArrayType::rank::value - 1 >(n, non_active_dimension_size,
154  non_active_dimension_value);
155 
156  //copy the value of the non-active dimensions in to index
157  for(size_t i = 0; i < XArrayType::rank::value - 1; i++)
158  {
159  index[non_active_dimension_index[i]] = non_active_dimension_value[i];
160  }
161  index[d] = 0; //always at start of row, for dim we are sampling
162 
163  //locate the start of this row
164  size_t in_data_location;
165  in_data_location =
166  MHO_NDArrayMath::OffsetFromRowMajorIndex< XArrayType::rank::value >(in->GetDimensions(), index);
167 
168  //locate the start of this row
169  size_t out_data_location;
170  out_data_location =
171  MHO_NDArrayMath::OffsetFromRowMajorIndex< XArrayType::rank::value >(out->GetDimensions(), index);
172 
173  //now sample the array by the specified amount
174  auto in_iter = in->cstride_iterator_at(in_data_location, fStride * in_stride);
175  auto out_iter = out->stride_iterator_at(out_data_location, out->GetStride(d));
176  auto in_end = in_iter + in->GetDimension(d);
177  auto out_end = out_iter + out->GetDimension(d);
178 
179  do
180  {
181  *out_iter = *in_iter;
182  ++in_iter;
183  ++out_iter;
184  }
185  while(in_iter != in_end && out_iter != out_end);
186  }
187 
188  IfTableSubSampleAxis(in, out);
189 
190  return true;
191  }
192 
193  private:
200  std::array< std::size_t, XArrayType::rank::value > DetermineOutputDimensions(const XArrayType* in)
201  {
202  auto in_dim = in->GetDimensionArray();
203  in_dim[fDimIndex] /= fStride;
204  return in_dim;
205  }
206 
213  void ConditionallyResizeOutput(const std::array< std::size_t, XArrayType::rank::value >& dims, XArrayType* out)
214  {
215  auto out_dim = out->GetDimensionArray();
216  bool have_to_resize = false;
217  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
218  {
219  if(out_dim[i] != dims[i])
220  {
221  have_to_resize = true;
222  }
223  }
224  if(have_to_resize)
225  {
226  out->Resize(&(dims[0]));
227  }
228  }
229 
230  //default...does nothing
238  template< typename XCheckType = XArrayType >
239  typename std::enable_if< !std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
240  IfTableSubSampleAxis(const XArrayType* , XArrayType* ){};
241 
250  template< typename XCheckType = XArrayType >
251  typename std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
252  IfTableSubSampleAxis(const XArrayType* in, XArrayType* out)
253  {
254  for(size_t i = 0; i < XArrayType::rank::value; i++) //apply to all axes
255  {
256  std::size_t stride = 1; //non-sub-sampled axis are just copied directly (stride of 1)
257  if(i == fDimIndex)
258  {
259  stride = fStride;
260  }
261  SubSampleAxis axis_sub_sampler(stride);
262  apply_at2< typename XArrayType::axis_pack_tuple_type, SubSampleAxis >(*in, *out, i, axis_sub_sampler);
263  }
264  out->CopyTags(*in); //make sure the table tags get copied
265  }
266 
270  class SubSampleAxis
271  {
272  public:
273  SubSampleAxis(std::size_t stride): fStride(stride){};
274  ~SubSampleAxis(){};
275 
276  template< typename XAxisType > void operator()(const XAxisType& axis1, XAxisType& axis2)
277  {
278  if(fStride == 1)
279  {
280  axis2.Copy(axis1);
281  }
282  else
283  {
284  TODO_FIXME_MSG("ensure that only the proper index tags are selected/copied here.")
285  axis2.CopyTags(axis1); //copy the axis tags
286  //at this point axis2 should already be re-sized appropriately
287  auto it1 = axis1.cstride_begin(fStride);
288  auto end1 = axis1.cstride_end(fStride);
289  auto it2 = axis2.begin();
290  auto end2 = axis2.end();
291  while(it1 != end1 && it2 != end2)
292  {
293  *it2++ = *it1++;
294  }
295  }
296  }
297 
298  private:
299  std::size_t fStride;
300  };
301 
302  bool fInitialized;
303  std::size_t fDimIndex;
304  std::size_t fStride;
305  XArrayType fWorkspace;
306 };
307 
308 }; // namespace hops
309 
310 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:238
#define TODO_FIXME_MSG(x)
Definition: MHO_Message.hh:35
template meta-programming helper functions, mostly tuple access/modification
#define profiler_scope()
Definition: MHO_Profiler.hh:237
static void RowMajorIndexFromOffset(std::size_t offset, const std::size_t *DimSize, std::size_t *Index)
Function RowMajorIndexFromOffset.
Definition: MHO_NDArrayMath.hh:117
Class MHO_SubSample.
Definition: MHO_SubSample.hh:30
virtual bool InitializeOutOfPlace(const XArrayType *in, XArrayType *out) override
Initializes output array out-of-place using input array in.
Definition: MHO_SubSample.hh:99
virtual bool ExecuteInPlace(XArrayType *in) override
Executes operation in-place and updates input array from workspace.
Definition: MHO_SubSample.hh:78
MHO_SubSample()
Definition: MHO_SubSample.hh:32
virtual bool InitializeInPlace(XArrayType *in) override
Initializes in-place execution by calling InitializeOutOfPlace with workspace and returning its resul...
Definition: MHO_SubSample.hh:69
virtual bool ExecuteOutOfPlace(const XArrayType *in, XArrayType *out) override
Function ExecuteOutOfPlace.
Definition: MHO_SubSample.hh:124
void SetDimensionAndStride(std::size_t dimension_index, std::size_t stride)
set the axis to sub sample, and the stride at which samples are selected
Definition: MHO_SubSample.hh:47
virtual ~MHO_SubSample()
Definition: MHO_SubSample.hh:39
Class MHO_UnaryOperator.
Definition: MHO_UnaryOperator.hh:24
struct type_status status
Definition: fourfit3.c:53
Definition: MHO_AdhocFlagging.hh:18