OSSIA
Open Scenario System for Interactive Application
math.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <ossia/detail/config.hpp>
3 
4 #include <ossia/detail/ssize.hpp>
5 
6 #include <cmath>
7 
8 #include <algorithm>
9 #include <cinttypes>
10 #include <utility>
17 namespace ossia
18 {
19 #if defined(__ANDROID_API__)
20 using ::asinh;
21 using ::exp2;
22 using ::fma;
23 using ::llround;
24 using ::log1p;
25 using ::remainder;
26 #else
27 using std::asinh;
28 using std::exp2;
29 using std::fma;
30 using std::llround;
31 using std::log1p;
32 using std::remainder;
33 #endif
34 const constexpr auto pi = 3.141592653589793238462643383279502884;
35 const constexpr auto two_pi = 6.283185307179586476925286766559005768;
36 const constexpr auto half_pi = 1.570796326794896619231321691639751442;
37 const constexpr auto rad_to_deg = 5.729577951308232087679815481410517033e+01;
38 const constexpr auto deg_to_rad = 1.745329251994329576923690768488612713e-02;
39 const constexpr auto ln_2 = 6.931471805599453094172321214581765680e-01;
40 const constexpr auto sqrt_2 = 1.414213562373095048801688724209698078e+00;
41 
42 template <typename T>
43 T ipow(T x, int N) noexcept
44 {
45  T res = x;
46  for(int i = 1; i < N; i++)
47  {
48  res *= x;
49  }
50  return res;
51 }
52 
53 template <typename T>
54 auto norm(T x, T y) noexcept
55 {
56  return std::sqrt(ipow(x, 2) + ipow(y, 2));
57 }
58 
59 template <typename T>
60 auto norm(T x, T y, T z) noexcept
61 {
62  return std::sqrt(ipow(x, 2) + ipow(y, 2) + ipow(z, 2));
63 }
64 
65 inline constexpr size_t constexpr_log2(size_t n) noexcept
66 {
67  return ((n < 2) ? 0 : 1 + constexpr_log2(n / 2));
68 }
69 
70 template <typename T>
71 inline constexpr size_t constexpr_abs(T n) noexcept
72 {
73  return n < 0 ? -n : n;
74 }
75 
76 // https://github.com/a2flo/floor/blob/master/constexpr/const_math.hpp#L251
77 template <typename T>
78 inline constexpr int64_t constexpr_floor(T val) noexcept
79 {
80  const auto val_int = (int64_t)val;
81  const T fval_int = (T)val_int;
82  return (val >= (T)0 ? fval_int : (val == fval_int ? val : fval_int - 1));
83 }
84 
85 template <typename T>
86 inline constexpr int64_t constexpr_ceil(T f)
87 {
88  const int64_t i = f;
89  return f > i ? i + 1 : i;
90 }
91 
95 template <class T, class U>
96 OSSIA_INLINE constexpr auto max(const T a, const U b) noexcept ->
97  typename std::conditional<(sizeof(T) > sizeof(U)), T, U>::type
98 {
99  static_assert(std::is_integral_v<T> && std::is_integral_v<U>);
100  static_assert(std::is_signed_v<T> == std::is_signed_v<U>);
101  return a < b ? b : a;
102 }
103 
104 static OSSIA_INLINE constexpr float max(float a, const float b) noexcept
105 {
106  return a < b ? b : a;
107 }
108 static OSSIA_INLINE constexpr double max(double a, const double b) noexcept
109 {
110  return a < b ? b : a;
111 }
112 static OSSIA_INLINE constexpr double max(float a, const double b) noexcept
113 {
114  return a < b ? b : a;
115 }
116 static OSSIA_INLINE constexpr double max(double a, const float b) noexcept
117 {
118  return a < b ? b : a;
119 }
120 
124 template <class T, class U>
125 OSSIA_INLINE constexpr auto min(const T a, const U b) noexcept ->
126  typename std::conditional<(sizeof(T) > sizeof(U)), T, U>::type
127 {
128  static_assert(std::is_integral_v<T> && std::is_integral_v<U>);
129  static_assert(std::is_signed_v<T> == std::is_signed_v<U>);
130  return a > b ? b : a;
131 }
132 
133 static OSSIA_INLINE constexpr float min(float a, const float b) noexcept
134 {
135  return a > b ? b : a;
136 }
137 static OSSIA_INLINE constexpr double min(double a, const double b) noexcept
138 {
139  return a > b ? b : a;
140 }
141 static OSSIA_INLINE constexpr double min(float a, const double b) noexcept
142 {
143  return a > b ? b : a;
144 }
145 static OSSIA_INLINE constexpr double min(double a, const float b) noexcept
146 {
147  return a > b ? b : a;
148 }
149 
153 template <class T>
154 OSSIA_INLINE constexpr T clamp(T d, const T min, const T max) noexcept
155 {
156  return ossia::max(ossia::min(d, max), min);
157 }
158 
159 static OSSIA_INLINE constexpr int64_t
160 clamp(int64_t d, const int64_t min, const int64_t max) noexcept
161 {
162  return ossia::max(ossia::min(d, max), min);
163 }
164 static OSSIA_INLINE constexpr int64_t
165 clamp(int64_t d, const int32_t min, const int64_t max) noexcept
166 {
167  return ossia::max(ossia::min(d, max), min);
168 }
169 static OSSIA_INLINE constexpr int64_t
170 clamp(int64_t d, const int32_t min, const int32_t max) noexcept
171 {
172  return ossia::max(ossia::min(d, max), min);
173 }
174 static OSSIA_INLINE constexpr int64_t
175 clamp(int64_t d, const int64_t min, const int32_t max) noexcept
176 {
177  return ossia::max(ossia::min(d, max), min);
178 }
179 static OSSIA_INLINE constexpr int32_t
180 clamp(int32_t d, const int32_t min, const int32_t max) noexcept
181 {
182  return ossia::max(ossia::min(d, max), min);
183 }
184 static OSSIA_INLINE constexpr int64_t
185 clamp(int32_t d, const int64_t min, const int64_t max) noexcept
186 {
187  return ossia::max(ossia::min(d, max), min);
188 }
189 static OSSIA_INLINE constexpr int64_t
190 clamp(int32_t d, const int32_t min, const int64_t max) noexcept
191 {
192  return ossia::max(ossia::min(d, max), min);
193 }
194 static OSSIA_INLINE constexpr int64_t
195 clamp(int32_t d, const int64_t min, const int32_t max) noexcept
196 {
197  return ossia::max(ossia::min(d, max), min);
198 }
199 
200 static OSSIA_INLINE constexpr uint64_t
201 clamp(uint64_t d, const uint64_t min, const uint64_t max) noexcept
202 {
203  return ossia::max(ossia::min(d, max), min);
204 }
205 static OSSIA_INLINE constexpr uint64_t
206 clamp(uint64_t d, const uint32_t min, const uint64_t max) noexcept
207 {
208  return ossia::max(ossia::min(d, max), min);
209 }
210 static OSSIA_INLINE constexpr uint64_t
211 clamp(uint64_t d, const uint32_t min, const uint32_t max) noexcept
212 {
213  return ossia::max(ossia::min(d, max), min);
214 }
215 static OSSIA_INLINE constexpr uint64_t
216 clamp(uint64_t d, const uint64_t min, const uint32_t max) noexcept
217 {
218  return ossia::max(ossia::min(d, max), min);
219 }
220 static OSSIA_INLINE constexpr uint32_t
221 clamp(uint32_t d, const uint32_t min, const uint32_t max) noexcept
222 {
223  return ossia::max(ossia::min(d, max), min);
224 }
225 static OSSIA_INLINE constexpr uint64_t
226 clamp(uint32_t d, const uint64_t min, const uint64_t max) noexcept
227 {
228  return ossia::max(ossia::min(d, max), min);
229 }
230 static OSSIA_INLINE constexpr uint64_t
231 clamp(uint32_t d, const uint32_t min, const uint64_t max) noexcept
232 {
233  return ossia::max(ossia::min(d, max), min);
234 }
235 static OSSIA_INLINE constexpr uint64_t
236 clamp(uint32_t d, const uint64_t min, const uint32_t max) noexcept
237 {
238  return ossia::max(ossia::min(d, max), min);
239 }
240 
241 static OSSIA_INLINE constexpr double
242 clamp(double d, const double min, const double max) noexcept
243 {
244  return ossia::max(ossia::min(d, max), min);
245 }
246 static OSSIA_INLINE constexpr double
247 clamp(double d, const float min, const double max) noexcept
248 {
249  return ossia::max(ossia::min(d, max), min);
250 }
251 static OSSIA_INLINE constexpr double
252 clamp(double d, const float min, const float max) noexcept
253 {
254  return ossia::max(ossia::min(d, max), min);
255 }
256 static OSSIA_INLINE constexpr double
257 clamp(double d, const double min, const float max) noexcept
258 {
259  return ossia::max(ossia::min(d, max), min);
260 }
261 static OSSIA_INLINE constexpr float
262 clamp(float d, const float min, const float max) noexcept
263 {
264  return ossia::max(ossia::min(d, max), min);
265 }
266 static OSSIA_INLINE constexpr double
267 clamp(float d, const double min, const double max) noexcept
268 {
269  return ossia::max(ossia::min(d, max), min);
270 }
271 static OSSIA_INLINE constexpr double
272 clamp(float d, const float min, const double max) noexcept
273 {
274  return ossia::max(ossia::min(d, max), min);
275 }
276 static OSSIA_INLINE constexpr double
277 clamp(float d, const double min, const float max) noexcept
278 {
279  return ossia::max(ossia::min(d, max), min);
280 }
281 
282 // Wrap & Fold code taken from Jamoma TTLimits.h.
283 // Credits : Nils Peters, Nov. 2008
284 template <class T>
285 OSSIA_INLINE constexpr T wrap(const T val, const T low, const T high) noexcept
286 {
287  if((val >= low) && (val < high))
288  return val;
289  else if(val >= low)
290  return low + std::fmod(val - low, std::fabs(low - high));
291  else
292  return high - std::fmod(low - val, std::fabs(low - high));
293 }
294 
295 template <class T>
296 OSSIA_INLINE constexpr T fold(const T val, const T low, const T high) noexcept
297 {
298  if((val >= low) && (val <= high))
299  return val;
300  else
301  {
302  return low + std::fabs(ossia::remainder(val - low, 2. * std::fabs(low - high)));
303  }
304 }
305 
306 template <class T>
307 OSSIA_INLINE constexpr std::pair<T, T> div(T num, T denom) noexcept
308 {
309  return {num / denom, num % denom};
310 }
311 
312 // normalized means x in [min, min + range] => f(x) in [0; 1] with log increase
313 OSSIA_INLINE float log_to_normalized(float min, float range, float val) noexcept
314 {
315  return val <= min ? 0.f : std::log1pf(val - min) / std::log1pf(range);
316 }
317 OSSIA_INLINE float normalized_to_log(float min, float range, float val) noexcept
318 {
319  const float res = std::expm1f(val * std::log1pf(range)) + min;
320  return std::min(res, min + range);
321 }
322 
323 template <typename T, typename R>
324 constexpr OSSIA_INLINE bool valid_index(T idx, const R& range) noexcept
325 {
326  using range_size_type = typename R::size_type;
327  if constexpr(std::is_signed_v<T>)
328  {
329  if constexpr(std::is_signed_v<range_size_type>)
330  return idx >= 0 && idx < range.size();
331  else
332  return idx >= 0 && idx < std::ssize(range);
333  }
334  else
335  {
336  if constexpr(std::is_signed_v<range_size_type>)
337  return idx < static_cast<std::size_t>(range.size());
338  else
339  return idx < range.size();
340  }
341 }
342 
343 }
Definition: git_info.h:7
constexpr OSSIA_INLINE T clamp(T d, const T min, const T max) noexcept
clamp Returns the value bounded by a min and a max
Definition: math.hpp:154
constexpr OSSIA_INLINE auto min(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
min function tailored for values
Definition: math.hpp:125
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96