Wayverb
range.h
1 #pragma once
2 
3 #include <algorithm>
4 #include <cmath>
5 #include <numeric>
6 #include <stdexcept>
7 #include <type_traits>
8 
9 namespace util {
10 
11 template <typename t>
12 class range final {
13 public:
14  using value_type = t;
15 
17 
18  constexpr range()
19  : min_{0}
20  , max_{0} {}
21 
22  constexpr range(value_type a, value_type b)
23  : min_{std::move(a)}
24  , max_{std::move(b)} {
25  maintain_invariant();
26  }
27 
28  template <typename V>
29  constexpr range(const range<V>& r)
30  : min_{r.get_min()}
31  , max_{r.get_max()} {}
32 
33  template <typename V>
34  constexpr range(range<V>&& r) noexcept
35  : min_{std::move(r.min_)}
36  , max_{std::move(r.max_)} {}
37 
38  constexpr auto get_min() const { return min_; }
39  constexpr auto get_max() const { return max_; }
40 
42 
43  template <typename V>
44  constexpr range& operator+=(const V& v) {
45  min_ += v;
46  max_ += v;
47  return *this;
48  }
49 
50  template <typename V>
51  constexpr range& operator-=(const V& v) {
52  min_ -= v;
53  max_ -= v;
54  return *this;
55  }
56 
57  template <typename V>
58  constexpr range& operator*=(const V& v) {
59  min_ *= v;
60  max_ *= v;
61  maintain_invariant();
62  return *this;
63  }
64 
65  template <typename V>
66  constexpr range& operator/=(const V& v) {
67  min_ /= v;
68  max_ /= v;
69  maintain_invariant();
70  return *this;
71  }
72 
73  template <typename V>
74  constexpr range& pad(const V& v) {
75  min_ -= v;
76  max_ += v;
77  maintain_invariant();
78  return *this;
79  }
80 
81 private:
82  constexpr void maintain_invariant() {
83  const auto a = min_;
84  const auto b = max_;
85 
86  using std::min;
87  using std::max;
88 
89  min_ = min(a, b);
90  max_ = max(a, b);
91  }
92 
93  value_type min_;
94  value_type max_;
95 };
96 
97 template <typename t>
98 constexpr range<t> make_range(const t& a, const t& b) {
99  return range<t>{a, b};
100 }
101 
103 
104 template <typename A, typename B>
105 constexpr bool operator==(const range<A>& a, const range<B>& b) {
106  return std::make_tuple(a.get_min(), a.get_max()) ==
107  std::make_tuple(b.get_min(), b.get_max());
108 }
109 
110 template <typename A, typename B>
111 constexpr bool operator!=(const range<A>& a, const range<B>& b) {
112  return !(a == b);
113 }
114 
115 template <typename A, typename B>
116 constexpr auto operator+(const range<A>& a, const B& b) {
118  return ret += b;
119 }
120 
121 template <typename A, typename B>
122 constexpr auto operator-(const range<A>& a, const B& b) {
124  return ret -= b;
125 }
126 
127 template <typename A, typename B>
128 constexpr auto operator*(const range<A>& a, const B& b) {
130  return ret *= b;
131 }
132 
133 template <typename A, typename B>
134 constexpr auto operator/(const range<A>& a, const B& b) {
136  return ret /= b;
137 }
138 
140 
141 template <typename A, typename B>
142 constexpr auto padded(const range<A>& a, const B& b) {
144  return ret.pad(b);
145 }
146 
147 template <typename t>
148 constexpr auto centre(const range<t>& a) {
149  return (a.get_min() + a.get_max()) * t{0.5};
150 }
151 
152 template <typename t>
153 constexpr auto dimensions(const range<t>& a) {
154  return a.get_max() - a.get_min();
155 }
156 
157 template <typename T, typename U, typename V>
158 constexpr auto map(T x, range<U> in, range<V> out) {
159  return (((x - in.get_min()) * dimensions(out)) / dimensions(in)) +
160  out.get_min();
161 }
162 
163 template <typename T, typename U>
164 constexpr auto inside(const T& t, const range<U>& r) {
165  return r.get_min() <= t && t < r.get_max();
166 }
167 
168 template <typename T, typename U>
169 constexpr auto clamp(const T& t, const range<U>& r) {
170  using std::min;
171  using std::max;
172  return max(r.get_min(), min(r.get_max(), t));
173 }
174 
176 
177 template <typename It, typename T>
178 constexpr auto accumulate_min(It begin, It end, T starting_value) {
179  return std::accumulate(
180  begin, end, starting_value, [](const auto& a, const auto& b) {
181  return min(a, b);
182  });
183 }
184 
185 template <typename It, typename T>
186 constexpr auto accumulate_max(It begin, It end, T starting_value) {
187  return std::accumulate(
188  begin, end, starting_value, [](const auto& a, const auto& b) {
189  return max(a, b);
190  });
191 }
192 
193 template <typename It>
194 constexpr auto enclosing_range(It begin, It end) {
195  if (begin == end) {
196  throw std::runtime_error("Can't minmax empty range.");
197  }
198  return make_range(accumulate_min(begin + 1, end, *begin),
199  accumulate_max(begin + 1, end, *begin));
200 }
201 
202 } // namespace util
Definition: allocator.h:6
Definition: range.h:12
constexpr range()
setters/getters
Definition: range.h:18
constexpr range & operator+=(const V &v)
mutators
Definition: range.h:44