libpnicore
array_selection.hpp
1 //
2 // (c) Copyright 2011 DESY, Eugen Wintersberger <eugen.wintersberger@desy.de>
3 //
4 // This file is part of libpnicore.
5 //
6 // libpnicore is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // libpnicore is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with libpnicore. If not, see <http://www.gnu.org/licenses/>.
18 //
19 // ============================================================================
20 //
21 // Created on: Jun 1, 2012
22 // Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
23 //
24 #pragma once
25 
26 #include <vector>
27 #include <algorithm>
28 
29 #ifdef NOFOREACH
30 #include <boost/foreach.hpp>
31 #endif
32 
33 #include "../utilities/container_utils.hpp"
34 #include "../error/exception_utils.hpp"
35 #include "../algorithms.hpp"
36 #include "slice.hpp"
37 
38 namespace pni{
39 namespace core{
40 
41 
73  {
74  private:
76  typedef std::vector<size_t> index_type;
77 
78  //member variables describing the selection in the original array
79  //all of these containers have the same size which is equal to the
80  //rank of the original array
82  index_type _oshape;
84  index_type _offset;
86  index_type _stride;
87 
88  public:
89  //===================constructors and destructor====================
101  template<template<typename ...> class CTYPE,typename ...OTS>
102  explicit array_selection(const CTYPE<OTS...> &oshape,
103  const CTYPE<OTS...> &ooffset,
104  const CTYPE<OTS...> &ostride):
105  _oshape(oshape.size()),
106  _offset(ooffset.size()),
107  _stride(ostride.size())
108  {
109  std::copy(oshape.begin(),oshape.end(),_oshape.begin());
110  std::copy(ooffset.begin(),ooffset.end(),_offset.begin());
111  std::copy(ostride.begin(),ostride.end(),_stride.begin());
112  }
113 
114  //------------------------------------------------------------------
118  explicit array_selection(): _oshape(0), _offset(0), _stride(0)
119  {}
120 
121  //-----------------------------------------------------------------
131  explicit array_selection(index_type &&oshape,index_type &ooffset,
132  index_type &&ostride):
133  _oshape(std::move(oshape)),
134  _offset(std::move(ooffset)),
135  _stride(std::move(ostride))
136  {
137  }
138 
139  //-----------------------------------------------------------------
148  explicit array_selection(const index_type &oshape,
149  const index_type &ooffset,
150  const index_type &ostride):
151  _oshape(oshape),
152  _offset(ooffset),
153  _stride(ostride)
154  {
155  }
156 
157  //-----------------------------------------------------------------
161  explicit array_selection(const array_selection &s):
162  _oshape(s._oshape),
163  _offset(s._offset),
164  _stride(s._stride)
165  { }
166 
167  //-----------------------------------------------------------------
172  _oshape(std::move(s._oshape)),
173  _offset(std::move(s._offset)),
174  _stride(std::move(s._stride))
175  { }
176 
177  //-----------------------------------------------------------------
182  {
183  if(this == &s) return *this;
184 
185  _oshape = s._oshape;
186  _offset = s._offset;
187  _stride = s._stride;
188 
189  return *this;
190  }
191 
192  //-----------------------------------------------------------------
197  {
198  if(this == &s) return *this;
199 
200  _oshape = std::move(s._oshape);
201  _offset = std::move(s._offset);
202  _stride = std::move(s._stride);
203 
204  return *this;
205  }
206 
207 
208  //-----------------------------------------------------------------
210  template<typename CTYPE,
211  typename = typename std::enable_if<
212  std::is_same<typename CTYPE::value_type,pni::core::slice>::value
213  >::type
214  >
215  static array_selection create(const CTYPE &s)
216  {
217  typedef container_utils<index_type> cutils_type;
218  auto shape = cutils_type::create(s.size());
219  auto offset = cutils_type::create(s.size());
220  auto stride = cutils_type::create(s.size());
221 
222  size_t index = 0;
223 #ifdef NOFOREACH
224  BOOST_FOREACH(auto sl,s)
225 #else
226  for(auto sl: s)
227 #endif
228  {
229  offset[index] = sl.first();
230  stride[index] = sl.stride();
231  shape[index] = pni::core::size(sl);
232  index++;
233  }
234 
235  return array_selection(std::move(shape),
236  std::move(offset),
237  std::move(stride));
238  }
239 
240 
241  //=================inquery methods=================================
252  size_t rank() const
253  {
254  return _oshape.size() - std::count(_oshape.begin(),_oshape.end(),1);
255  }
256 
257  //-----------------------------------------------------------------
268  template<typename CTYPE> CTYPE shape() const
269  {
270  typedef container_utils<CTYPE> cutils_type;
271  auto c = cutils_type::create(rank());
272 
273  //now we have to copy only those values from the original shape
274  //that are not equal 1
275  std::copy_if(_oshape.begin(),_oshape.end(),c.begin(),
276  [](size_t i){ return i!=1; });
277  return c;
278  }
279 
280  //-----------------------------------------------------------------
290  size_t size() const
291  {
292  typedef typename index_type::value_type value_type;
293  if(_oshape.empty()) return 0; //not initialized
294 
295  if(rank() == 0) return 1; //scalar element selected
296 
297  //compute the size and return it
298  return std::accumulate(_oshape.begin(),_oshape.end(),
299  value_type(1),
300  std::multiplies<value_type>());
301  }
302 
303  //=========methods to retrieve full selection information==========
312  const index_type &full_shape() const { return _oshape; }
313 
314  //-----------------------------------------------------------------
324  template<typename CTYPE> CTYPE full_shape() const
325  {
326  typedef container_utils<CTYPE> cutils_type;
327  auto c = cutils_type::create(_oshape.size());
328  std::copy(_oshape.begin(),_oshape.end(),c.begin());
329  return c;
330  }
331 
332  //-----------------------------------------------------------------
341  const index_type &offset() const { return _offset; }
342 
343  //-----------------------------------------------------------------
351  template<typename CTYPE> CTYPE offset() const
352  {
353  typedef container_utils<CTYPE> cutils_type;
354  auto c = cutils_type::create(_offset.size());
355  std::copy(_offset.begin(),_offset.end(),c.begin());
356  return c;
357  }
358 
359  //-----------------------------------------------------------------
366  const index_type &stride() const { return _stride; }
367 
368  //-----------------------------------------------------------------
377  template<typename CTYPE> CTYPE stride() const
378  {
379  typedef container_utils<CTYPE> cutils_type;
380  auto c = cutils_type::create(_stride.size());
381 
382  std::copy(_stride.begin(),_stride.end(),c.begin());
383  return c;
384  }
385 
386  //================get indices======================================
392 
413  template<
425  typename ITYPE,
426  typename OITYPE
427  >
428  void index(const ITYPE &sindex,OITYPE &oindex) const
429  {
430 #ifdef DEBUG
431  //check here if the size (rank) of the original shape of the
432  //selection matches that of the original index.
433  check_equal_size(_oshape,oindex,EXCEPTION_RECORD);
434  //check if the size of the selection index container matches the
435  //effective rank of the selection
436  check_equal_size(shape<ITYPE>(),sindex,EXCEPTION_RECORD);
437 #endif
438 
439  //now we have to add index*stride from the selection index too
440  //the appropriate locations
441  auto os_iter = _oshape.begin(); //iter. over original shape
442  auto st_iter = _stride.begin(); //iter. over selection strides
443  auto si_iter = sindex.begin(); //iter. over selection index
444  auto of_iter = _offset.begin(); //iter. over the offset
445 
446  //loop over output index
447  for(auto &oi: oindex)
448  {
449  size_t index = *of_iter++;
450  //oi = *of_iter++;
451  if(*os_iter++ != 1) index += (*st_iter)*(*si_iter++);
452  ++st_iter; //need to increment this guy in any case
453  oi = index;
454  }
455  }
456 
457  //-----------------------------------------------------------------
472  template<
473  typename OITYPE,
474  typename ITYPE
475  >
476  OITYPE index(const ITYPE &sindex) const
477  {
478  typedef container_utils<OITYPE> cutils_type;
479  auto oindex = cutils_type::create(_oshape.size());
480 
481  try{ index(sindex,oindex); }
483 
484  return oindex;
485  }
486  };
487 
488 
489  //-------------------------------------------------------------------------
506  template<
507  typename MAPT,
508  typename CTYPE
509  >
510  size_t offset(const MAPT &map,const array_selection &s,
511  const CTYPE &index)
512  {
513  //compute the original index of the selection index
514  auto orig_index = container_utils<CTYPE>::create(map.rank());
515  s.index(index,orig_index);
516 
517  return map.offset(orig_index);
518  }
519 
520  //-------------------------------------------------------------------------
534  template<typename MAPT>
535  size_t start_offset(const MAPT &map,const array_selection &s)
536  {
537  typedef std::vector<size_t> index_type;
538 
539  auto index = s.template shape<index_type>();
540  //set all elements to zero
541  std::fill(index.begin(),index.end(),size_t(0));
542 
543  return offset(map,s,index);
544  }
545 
546  //-------------------------------------------------------------------------
560  template<typename MAPT>
561  size_t last_offset(const MAPT &map,const array_selection &s)
562  {
563  typedef std::vector<size_t> index_type;
564 
565  auto index = s.template shape<index_type>();
566  std::transform(index.begin(),index.end(),index.begin(),
567  [](const size_t &i){ return i-size_t(1); });
568 
569  return offset(map,s,index);
570 
571  }
572 
573  //-------------------------------------------------------------------------
586  template<typename MAPT>
587  bool is_contiguous(const MAPT &map,const array_selection &s)
588  {
589 
590  size_t orig_first_offset = start_offset(map,s);
591  size_t orig_last_offset = last_offset(map,s);
592 
593  //check if the size of the selection matches the offset-difference in
594  //the original array - in this case we have a contiguous selection.
595  if( (orig_last_offset - orig_first_offset + 1) == s.size())
596  return true;
597 
598  return false;
599  }
600 
601 
602 //end of namespace
603 }
604 }
index_type _offset
offset in the original array
Definition: array_selection.hpp:84
static container_type create(size_t n, value_type default_value=value_type())
create container of given size
Definition: container_utils.hpp:85
array_selection(array_selection &&s)
move constructor
Definition: array_selection.hpp:171
CTYPE full_shape() const
get full shape
Definition: array_selection.hpp:324
Size mismatch error.
Definition: exceptions.hpp:399
size_t size() const
get selection size
Definition: array_selection.hpp:290
OITYPE index(const ITYPE &sindex) const
compute the original index
Definition: array_selection.hpp:476
array_selection(const index_type &oshape, const index_type &ooffset, const index_type &ostride)
constructor
Definition: array_selection.hpp:148
array_selection & operator=(const array_selection &s)
copy assignment operator
Definition: array_selection.hpp:181
index_type _oshape
shape of the selection in the original array
Definition: array_selection.hpp:82
#define EXCEPTION_RECORD
macro creating an instance of ExceptionRecord
Definition: exceptions.hpp:48
STL namespace.
size_t rank() const
get effective rank
Definition: array_selection.hpp:252
size_t last_offset(const MAPT &map, const array_selection &s)
compute last element offset
Definition: array_selection.hpp:561
array_selection()
default constructor
Definition: array_selection.hpp:118
container utility
Definition: container_utils.hpp:59
selection from a multidimensional array
Definition: array_selection.hpp:72
size_t start_offset(const MAPT &map, const array_selection &s)
compute first element offset
Definition: array_selection.hpp:535
index_type _stride
stride in the original array
Definition: array_selection.hpp:86
Definition: add_op.hpp:29
array_selection(const CTYPE< OTS...> &oshape, const CTYPE< OTS...> &ooffset, const CTYPE< OTS...> &ostride)
constructor
Definition: array_selection.hpp:102
invoke< std::enable_if< C::value >> enable_if
shortcut for std::enable_if
Definition: sfinae_macros.hpp:108
const index_type & full_shape() const
get full shape reference
Definition: array_selection.hpp:312
#define EXCEPTION_FORWARD(ETYPE)
forward an exception
Definition: exceptions.hpp:67
array_selection(const array_selection &s)
copy constructor
Definition: array_selection.hpp:161
const index_type & offset() const
get reference to offset
Definition: array_selection.hpp:341
bool check_equal_size(const A &a, const B &b)
check if two container have equal size
Definition: exception_utils.hpp:77
array_selection(index_type &&oshape, index_type &ooffset, index_type &&ostride)
constructor
Definition: array_selection.hpp:131
const index_type & stride() const
get reference to stride
Definition: array_selection.hpp:366
void index(const ITYPE &sindex, OITYPE &oindex) const
compute original index
Definition: array_selection.hpp:428
CTYPE offset() const
get offset
Definition: array_selection.hpp:351
std::vector< size_t > index_type
private index type
Definition: array_selection.hpp:76
CTYPE stride() const
get stride
Definition: array_selection.hpp:377
CTYPE shape() const
get effective shape
Definition: array_selection.hpp:268
array_selection & operator=(array_selection &&s)
move asignment operator
Definition: array_selection.hpp:196
size_t offset(const MAPT &map, const array_selection &s, const CTYPE &index)
compute offset
Definition: array_selection.hpp:510
size_t size(const slice &s)
compute slice size
bool is_contiguous(const MAPT &map, const array_selection &s)
check continuity of a selection
Definition: array_selection.hpp:587
static array_selection create(const CTYPE &s)
static creation function
Definition: array_selection.hpp:215