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:
62 
70  virtual bool InitializeInPlace(XArrayType* in) override { return InitializeOutOfPlace(in, &fWorkspace); }
71 
79  virtual bool ExecuteInPlace(XArrayType* in) override
80  {
81  bool status = ExecuteOutOfPlace(in, &fWorkspace);
82  //"in-place" execution requires a copy from the workspace back to the object we are modifying
83  in->Copy(fWorkspace);
84 
85  // auto workspace_dim = fWorkspace.GetDimensionArray();
86  // for(std::size_t i=0; i<workspace_dim.size(); i++){workspace_dim[i] = 0;}
87  // fWorkspace.Resize(&(workspace_dim[0]));
88 
89  return status;
90  }
91 
100  virtual bool InitializeOutOfPlace(const XArrayType* in, XArrayType* out) override
101  {
102  if(in != nullptr && out != nullptr)
103  {
104  //check that the dimension we are sub-sampling is divisable by the stride
105  if(in->GetDimension(fDimIndex) % fStride != 0)
106  {
107  msg_error("operators", "dimension to sub-sample must be divisable by stride." << eom);
108  return false;
109  }
110  auto dims = DetermineOutputDimensions(in);
111  ConditionallyResizeOutput(dims, out);
112  fInitialized = true;
113  }
114  return true;
115  }
116 
125  virtual bool ExecuteOutOfPlace(const XArrayType* in, XArrayType* out) override
126  {
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:
194 
201  std::array< std::size_t, XArrayType::rank::value > DetermineOutputDimensions(const XArrayType* in)
202  {
203  auto in_dim = in->GetDimensionArray();
204  in_dim[fDimIndex] /= fStride;
205  return in_dim;
206  }
207 
214  void ConditionallyResizeOutput(const std::array< std::size_t, XArrayType::rank::value >& dims, XArrayType* out)
215  {
216  auto out_dim = out->GetDimensionArray();
217  bool have_to_resize = false;
218  for(std::size_t i = 0; i < XArrayType::rank::value; i++)
219  {
220  if(out_dim[i] != dims[i])
221  {
222  have_to_resize = true;
223  }
224  }
225  if(have_to_resize)
226  {
227  out->Resize(&(dims[0]));
228  }
229  }
230 
231  //default...does nothing
239  template< typename XCheckType = XArrayType >
240  typename std::enable_if< !std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
241  IfTableSubSampleAxis(const XArrayType* , XArrayType* ){};
242 
251  template< typename XCheckType = XArrayType >
252  typename std::enable_if< std::is_base_of< MHO_TableContainerBase, XCheckType >::value, void >::type
253  IfTableSubSampleAxis(const XArrayType* in, XArrayType* out)
254  {
255  for(size_t i = 0; i < XArrayType::rank::value; i++) //apply to all axes
256  {
257  std::size_t stride = 1; //non-sub-sampled axis are just copied directly (stride of 1)
258  if(i == fDimIndex)
259  {
260  stride = fStride;
261  }
262  SubSampleAxis axis_sub_sampler(stride);
263  apply_at2< typename XArrayType::axis_pack_tuple_type, SubSampleAxis >(*in, *out, i, axis_sub_sampler);
264  }
265  out->CopyTags(*in); //make sure the table tags get copied
266  }
267 
271  class SubSampleAxis
272  {
273  public:
274  SubSampleAxis(std::size_t stride): fStride(stride){};
275  ~SubSampleAxis(){};
276 
277  template< typename XAxisType > void operator()(const XAxisType& axis1, XAxisType& axis2)
278  {
279  if(fStride == 1)
280  {
281  axis2.Copy(axis1);
282  }
283  else
284  {
285  TODO_FIXME_MSG("ensure that only the proper index tags are selected/copied here.")
286  axis2.CopyTags(axis1); //copy the axis tags
287  //at this point axis2 should already be re-sized appropriately
288  auto it1 = axis1.cstride_begin(fStride);
289  auto end1 = axis1.cstride_end(fStride);
290  auto it2 = axis2.begin();
291  auto end2 = axis2.end();
292  while(it1 != end1 && it2 != end2)
293  {
294  *it2++ = *it1++;
295  }
296  }
297  }
298 
299  private:
300  std::size_t fStride;
301  };
302 
303  bool fInitialized;
304  std::size_t fDimIndex;
305  std::size_t fStride;
306  XArrayType fWorkspace;
307 };
308 
309 }; // namespace hops
310 
311 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:244
#define TODO_FIXME_MSG(x)
Definition: MHO_Message.hh:35
template meta-programming helper functions, mostly tuple access/modification
static void RowMajorIndexFromOffset(std::size_t offset, const std::size_t *DimSize, std::size_t *Index)
Function RowMajorIndexFromOffset.
Definition: MHO_NDArrayMath.hh:121
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:100
virtual bool ExecuteInPlace(XArrayType *in) override
Executes operation in-place and updates input array from workspace.
Definition: MHO_SubSample.hh:79
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:70
virtual bool ExecuteOutOfPlace(const XArrayType *in, XArrayType *out) override
Function ExecuteOutOfPlace.
Definition: MHO_SubSample.hh:125
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_ChannelLabeler.hh:17