echelon  0.8.0
array_slice.hpp
1 // Copyright (c) 2015 Christopher Hinz
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef ECHELON_HDF5_ARRAY_SLICE_HPP
7 #define ECHELON_HDF5_ARRAY_SLICE_HPP
8 
9 #include <echelon/hdf5/range.hpp>
10 #include <echelon/hdf5/container_adaption.hpp>
11 
12 #include <vector>
13 #include <utility>
14 
15 namespace echelon
16 {
17 namespace hdf5
18 {
19 
20 template <typename T>
21 class array_slice
22 {
23 public:
24  array_slice(T* data_, std::vector<hsize_t> original_shape_, std::vector<hsize_t> offset_,
25  std::vector<hsize_t> shape_, std::vector<hsize_t> stride_)
26  : data_(std::move(data_)), original_shape_(std::move(original_shape_)),
27  offset_(std::move(offset_)), shape_(std::move(shape_)), stride_(std::move(stride_))
28  {
29  }
30 
31  template <typename... Indices>
32  T operator()(Indices... indices) const
33  {
34  std::vector<hsize_t> indices_({static_cast<hsize_t>(indices)...});
35 
36  hsize_t linear_index = 0;
37 
38  for (std::size_t i = indices_.size(); i-- > 0;)
39  {
40  linear_index =
41  linear_index * original_shape_[i] + (offset_[i] + indices_[i] * stride_[i]);
42  }
43 
44  return data_[linear_index];
45  }
46 
47  T* data() const
48  {
49  return data_;
50  }
51 
52  const std::vector<hsize_t>& original_shape() const
53  {
54  return original_shape_;
55  }
56 
57  const std::vector<hsize_t>& offset() const
58  {
59  return offset_;
60  }
61 
62  const std::vector<hsize_t>& shape() const
63  {
64  return shape_;
65  }
66 
67  const std::vector<hsize_t>& stride() const
68  {
69  return stride_;
70  }
71 
72 private:
73  T* data_;
74  std::vector<hsize_t> original_shape_;
75  std::vector<hsize_t> offset_;
76  std::vector<hsize_t> shape_;
77  std::vector<hsize_t> stride_;
78 };
79 
88 template <typename C, typename... Args>
89 array_slice<typename container_trait<C>::value_type> make_slice(C&& container, Args... args)
90 {
91  static_assert(is_container<C>(), "C does not fulfill the Container requirements.");
92 
93  using value_type = typename container_trait<C>::value_type;
94 
95  std::vector<hsize_t> shape_;
96 
97  auto shape = echelon::hdf5::shape_adl(container);
98 
99  for (auto extent : shape)
100  {
101  shape_.push_back(extent);
102  }
103 
104  std::vector<totally_bound_range_t> slice_boundaries;
105 
106  detail::calculate_slice_boundaries<0, Args...>::eval(shape_, slice_boundaries, args...);
107 
108  std::vector<hsize_t> offset;
109  std::vector<hsize_t> slice_shape;
110  std::vector<hsize_t> stride;
111 
112  for (auto bounds : slice_boundaries)
113  {
114  auto base = bounds.base();
115 
116  offset.push_back(base);
117  slice_shape.push_back(bounds.bound() - base);
118  stride.push_back(bounds.stride());
119  }
120 
121  return array_slice<value_type>(echelon::hdf5::data_adl(container), std::move(shape_),
122  std::move(offset), std::move(slice_shape), std::move(stride));
123 }
124 }
125 }
126 
127 #endif
echelon&#39;s core namespace
Definition: attribute.cpp:10
array_slice< typename container_trait< C >::value_type > make_slice(C &&container, Args...args)
Slice a container.
Definition: array_slice.hpp:89