echelon  0.8.0
hdf5/range.hpp
1 // Copyright (c) 2012-2014 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_RANGE_HPP
7 #define ECHELON_HDF5_RANGE_HPP
8 
9 #include <echelon/utility/macros.hpp>
10 
11 #include <hdf5.h>
12 #include <type_traits>
13 
14 namespace echelon
15 {
16 namespace hdf5
17 {
18 template <typename Base, typename Bound>
19 class range_t
20 {
21 public:
22  range_t(Base base_, Bound bound_, hsize_t stride_ = 1)
23  : base_(base_), bound_(bound_), stride_(stride_)
24  {
25  }
26 
27  template <typename OtherBase, typename OtherBound,
28  typename Dummy = typename std::enable_if<std::is_convertible<
29  Base, OtherBase>::value&& std::is_convertible<Bound, OtherBound>::value>::type>
30  range_t(range_t<OtherBase, OtherBound> other)
31  : base_(other.base()), bound_(other.bound()), stride_(other.stride())
32  {
33  }
34 
35  Base base() const
36  {
37  return base_;
38  }
39 
40  Bound bound() const
41  {
42  return bound_;
43  }
44 
45  hsize_t stride() const
46  {
47  return stride_;
48  }
49 
50 private:
51  Base base_;
52  Bound bound_;
53  hsize_t stride_;
54 };
55 
62 template <typename Base, typename Bound>
63 inline range_t<Base, Bound> range(Base base, Bound bound, hsize_t stride = 1)
64 {
65  return range_t<Base, Bound>{base, bound, stride};
66 }
67 
68 typedef range_t<hsize_t, hsize_t> totally_bound_range_t;
69 
70 struct unbound_t
71 {
72 };
73 
74 static const unbound_t _ = {};
75 
76 namespace detail
77 {
78 
79 template <std::size_t I, typename... Args>
80 struct calculate_slice_boundaries;
81 
82 template <std::size_t I>
83 struct calculate_slice_boundaries<I>
84 {
85  static void eval(const std::vector<hsize_t>&, std::vector<totally_bound_range_t>&)
86  {
87  }
88 };
89 
90 template <std::size_t I, typename Front, typename... Tail>
91 struct calculate_slice_boundaries<I, Front, Tail...>
92 {
93  static void eval(const std::vector<hsize_t>& current_shape,
94  std::vector<totally_bound_range_t>& boundaries, Front front, Tail... tail)
95  {
96  boundaries.push_back(get_boundaries(current_shape[I], front));
97 
98  calculate_slice_boundaries<I + 1, Tail...>::eval(current_shape, boundaries, tail...);
99  }
100 
101 private:
102  static totally_bound_range_t get_boundaries(hsize_t extend, unbound_t)
103  {
104  return range(0, extend);
105  }
106 
107  template <typename Base>
108  static totally_bound_range_t get_boundaries(hsize_t extend, range_t<Base, unbound_t> r)
109  {
110  // FIXME: add a bound check
111 
112  return range(r.base(), extend);
113  }
114 
115  template <typename Bound>
116  static totally_bound_range_t get_boundaries(hsize_t, range_t<unbound_t, Bound> r)
117  {
118  // FIXME: add a bound check
119 
120  return range(0, r.bound());
121  }
122 
123  template <typename Base, typename Bound>
124  static totally_bound_range_t get_boundaries(hsize_t, range_t<Base, Bound> r)
125  {
126  static_assert(std::is_integral<Base>::value && std::is_integral<Bound>::value,
127  "only integral values are allowed in slicing expressions");
128 
129  // FIXME: add a bound check
130 
131  return r;
132  }
133 
134  template <typename T>
135  static totally_bound_range_t get_boundaries(hsize_t ECHELON_UNUSED_RELEASE(extend), T value)
136  {
137  static_assert(std::is_integral<T>::value,
138  "only integral values are allowed in slicing expressions");
139 
140  assert(value < extend);
141 
142  return range(value, value + 1);
143  }
144 };
145 }
146 
147 
148 
149 }
150 }
151 
152 #endif
echelon&#39;s core namespace
Definition: attribute.cpp:10
range_t< Base, Bound > range(Base base, Bound bound, hsize_t stride=1)
Constructs an index range.
Definition: hdf5/range.hpp:63