Scanframe Modular Application 0.1.0
Loading...
Searching...
No Matches
misc/gen/math.h
Go to the documentation of this file.
1#pragma once
2#include <array>
3#include <cmath>
4#include <misc/global.h>
5#include <random>
6
7namespace sf
8{
9
10namespace numbers
11{
12
13#if __cplusplus <= 201703L
14
15template<typename T>
16inline constexpr T pi_v = static_cast<T>(3.141592653589793238462643383279502884L);
17
18#else
19
20template<typename T>
21inline constexpr T pi_v = ::std::numbers::pi_v<T>;
22
23#endif
24}// namespace numbers
25
29template<typename T>
30T round(T value, T rnd)
31{
32 // Prevent non-integer and non-float types from implementing this template.
33 static_assert(std::is_arithmetic_v<T>, "Type T must be an arithmetic type.");
34 if constexpr (std::is_integral_v<T>)
35 {
36 return (value + rnd / T(2)) / rnd * rnd;
37 }
38 if constexpr (std::is_floating_point_v<T>)
39 {
40 // Function 'std::floor' has al float types implemented.
41 return std::floor(value / rnd + T(0.5)) * rnd;
42 }
43 return value;
44}
45
49template<typename T, typename S>
50S calculateOffset(T value, T min, T max, S len, bool clip)
51{
52 max -= min;
53 value -= min;
54 S temp = max && value ? (std::is_floating_point_v<T> ? len * (value / max) : len * value / max) : 0;
55 // Clip when required.
56 if (clip)
57 {
58 // When the len is a negative value.
59 if (len < 0)
60 {
61 return temp < len ? len : temp > S(0) ? S(0) : temp;
62 }
63 return temp > len ? len : temp < S(0) ? S(0) : temp;
64 }
65 return temp;
66}
67
76template<typename T>
77T clip(const T value, const T lower_lim, const T upper_lim)
78{
79 return value < lower_lim ? lower_lim : value > upper_lim ? upper_lim : value;
80}
81
85template<typename T>
86T random(T start, T stop)
87{
88 static std::default_random_engine generator{};// NOLINT(cert-msc32-c,cert-msc51-cpp)
89 std::uniform_int_distribution<T> distribution(start, stop);
90 return distribution(generator);
91}
92
100template<typename T>
101T modulo(T k, T n)
102{
103 // Only implementations of arithmetic values are allowed.
104 static_assert(std::is_arithmetic_v<T>, "Type T must be an arithmetic type.");
105 // Distinguish between floats and integers.
106 if constexpr (std::is_floating_point_v<T>)
107 {
108 // Function fmod has implementations for any floating point.
109 T r = std::fmod(k, n);
110 //if the r is less than zero, add n to put it in the [0, n-1] range if n is positive
111 //if the r is greater than zero, add n to put it in the [n-1, 0] range if n is negative
112 return (n > 0 && r < 0) || (n < 0 && r > 0) ? r + n : r;
113 }
114 else
115 {
116 T r = k % n;
117 //if the r is less than zero, add n to put it in the [0, n-1] range if n is positive
118 //if the r is greater than zero, add n to put it in the [n-1, 0] range if n is negative
119 return (n > 0 && r < 0) || (n < 0 && r > 0) ? r + n : r;
120 }
121}
122
129template<typename T>
130T toAbs(T v)
131{
132 static_assert(std::is_arithmetic_v<T>, "Type T must be an arithmetic type.");
133 if constexpr (std::is_same<T, long double>())
134 {
135 return fabsl(v);
136 }
137 if constexpr (std::is_same<T, double>())
138 {
139 return fabs(v);
140 }
141 if constexpr (std::is_same<T, float>())
142 {
143 return fabsf(v);
144 }
145 if constexpr (std::is_integral_v<T>)
146 {
147 if constexpr (std::numeric_limits<T>::is_signed)
148 {
149 if constexpr (std::is_same<T, long long int>())
150 {
151 return std::llabs(v);
152 }
153 if constexpr (std::is_same<T, long int>())
154 {
155 return std::labs(v);
156 }
157 if constexpr (std::is_same<T, int>())
158 {
159 return std::abs(v);
160 }
161 // Smaller integers are handled here.
162 return static_cast<T>(std::abs(v));
163 }
164 }
165 // Not a signed value return it as is.
166 return v;
167}
168
176template<typename T>
177T ipow(T base, int exponent)
178{
179 // Prevent non-integer types from implementing this template.
180 static_assert(std::is_integral_v<T>, "Type T must be an integer type.");
181 // Initialize the integer.
182 T rv{1};
183 for (;;)
184 {
185 // Check if the first bit is set.
186 if (exponent & 1)
187 {
188 rv *= base;
189 }
190 // Shift the bits right.
191 exponent >>= 1;
192 // When no bits are standing of the exponent done break th loop.
193 if (!exponent)
194 {
195 break;
196 }
197 // Squaring the values so far.
198 base *= base;
199 }
200 return rv;
201}
202
206template<typename T>
207constexpr T toRadians(T degrees)
208{
209 // Only implemented for floating point values.
210 static_assert(std::is_floating_point_v<T>, "Type T must be a floating point type.");
211 return degrees * (numbers::pi_v<T> / 180);
212}
213
217template<typename T>
218constexpr T toDegrees(T radians)
219{
220 // Only implemented for floating point values.
221 static_assert(std::is_floating_point_v<T>, "Type T must be a floating point type.");
222 return radians / numbers::pi_v<T> * 180;
223}
224
233template<typename T>
234bool isEqual(T a, T b, T epsilon = std::numeric_limits<T>::epsilon())
235{
236 // Only implemented for floating point values.
237 static_assert(std::is_floating_point_v<T>, "Type T must be a floating point type.");
238 return std::abs(a - b) <= epsilon;
239}
240
244template<typename T>
245bool isZero(T value, T epsilon = std::numeric_limits<T>::epsilon())
246{
247 static_assert(std::is_arithmetic_v<T>, "Type T must be an arithmetic type.");
248 if constexpr (std::is_integral_v<T>)
249 {
250 return value == std::numeric_limits<T>::denorm_min();
251 }
252 if constexpr (std::is_floating_point_v<T>)
253 {
254 return std::fabs(value) < epsilon;
255 }
256 return false;
257}
258
262template<typename T>
263bool isValidValue(T value)
264{
265 static_assert(std::is_floating_point_v<T>, "Type T must be an floating point type.");
266 return !std::isinf(value) && !std::isnan(value);
267}
268
272template<typename T, typename... Args>
273size_t maxArgumentIndex(T first, Args... args)
274{
275 T largest = first;
276 size_t idx = 0;
277 size_t idx_cur = 0;
278 // Lambda to find the largest value and its index
279 auto compare = [&largest, &idx, &idx_cur](T value) {
280 if (value > largest)
281 {
282 largest = value;
283 idx = idx_cur;
284 }
285 ++idx_cur;
286 };
287 (compare(first), ..., compare(args));// Apply to all arguments
288 return idx;
289}
290
294template<typename T, typename... Args>
295size_t minArgumentIndex(T first, Args... args)
296{
297 T largest = first;
298 size_t idx = 0;
299 size_t idx_cur = 0;
300 // Lambda to find the largest value and its index
301 auto compare = [&largest, &idx, &idx_cur](T value) {
302 if (value < largest)
303 {
304 largest = value;
305 idx = idx_cur;
306 }
307 ++idx_cur;
308 };
309 (compare(first), ..., compare(args));// Apply to all arguments
310 return idx;
311}
312
320template<typename T, size_t N>
321size_t maxArrayIndex(const std::array<T, N>& arr)
322{
323 T cur = arr[0];
324 size_t index = 0;
325 for (size_t i = 1; i < arr.size(); ++i)
326 {
327 if (arr[i] > cur)
328 {
329 cur = arr[i];
330 index = i;
331 }
332 }
333 return index;
334}
335
343template<typename T, size_t N>
344size_t minArrayIndex(const std::array<T, N>& arr)
345{
346 T cur = arr[0];
347 size_t index = 0;
348 for (size_t i = 1; i < arr.size(); ++i)
349 {
350 if (arr[i] < cur)
351 {
352 cur = arr[i];
353 index = i;
354 }
355 }
356 return index;
357}
358
367_MISC_FUNC int precision(double value);
368
376_MISC_FUNC int digits(double value);
377
384template<typename T>
385std::pair<T, int> getMantissaExponent(T value)
386{
387 // Allow only floating point values.
388 static_assert(std::is_floating_point_v<T>, "Type T must be a floating point type.");
389 // Return zero for value zero.
390 if (isZero(value))
391 return {0, 0};
392 auto exponent = std::floor(std::log10(std::abs(value)));
393 auto mantissa = value / std::pow(10, exponent);
394 // Adjust mantissa and exponent to ensure |mantissa| is between 0.1 and 1.0
395 if (std::abs(mantissa) < 0.1)
396 {
397 mantissa *= 10;
398 exponent -= 1;
399 }
400 else if (abs(mantissa) >= 1.0)
401 {
402 mantissa /= 10;
403 exponent += 1;
404 }
405 return {mantissa, exponent};
406}
407
415template<typename T>
416int magnitude(T value)
417{
418 return getMantissaExponent(value).second;
419}
420
429
440_MISC_FUNC int requiredDigits(double round_val, double min_val, double max_val);
441
442}// namespace sf
#define _MISC_FUNC
Definition misc/global.h:39
constexpr T pi_v
Definition misc/gen/math.h:16
Definition Application.h:10
size_t minArgumentIndex(T first, Args... args)
Finds the index of the smallest element passed as an argument.
Definition misc/gen/math.h:295
T ipow(T base, int exponent)
Fast integer power-of function.
Definition misc/gen/math.h:177
size_t minArrayIndex(const std::array< T, N > &arr)
Finds the largest element index of the passed array.
Definition misc/gen/math.h:344
int magnitude(T value)
Gets the order of magnitude of the passed floating point value. Examples: magnitude(0....
Definition misc/gen/math.h:416
T modulo(T k, T n)
Modulo template function.
Definition misc/gen/math.h:101
constexpr T toRadians(T degrees)
Converts degrees to radians.
Definition misc/gen/math.h:207
T clip(const T value, const T lower_lim, const T upper_lim)
Template function clipping the given value between an upper and lower limit.
Definition misc/gen/math.h:77
size_t maxArgumentIndex(T first, Args... args)
Finds the index of the largest element passed as an argument.
Definition misc/gen/math.h:273
bool isEqual(T a, T b, T epsilon=std::numeric_limits< T >::epsilon())
Compares 2 floating point values of the same type with a given epsilon.
Definition misc/gen/math.h:234
constexpr T toDegrees(T radians)
Converts radians to degrees.
Definition misc/gen/math.h:218
size_t maxArrayIndex(const std::array< T, N > &arr)
Finds the largest element index of the passed array.
Definition misc/gen/math.h:321
_MISC_FUNC int precision(double value)
Returns the precision of the passed floating point value. This is the amount of characters after the ...
std::pair< T, int > getMantissaExponent(T value)
Gets the mantissa and exponent part of a floating point value.
Definition misc/gen/math.h:385
_MISC_FUNC int magnitudeObsolete(double value)
Gets the order of magnitude of the passed double value. Examples: magnitude(0.001234) => -2 magnitude...
bool isZero(T value, T epsilon=std::numeric_limits< T >::epsilon())
Check if the passed value is zero or near zero according the given epsilon.
Definition misc/gen/math.h:245
T random(T start, T stop)
Generates random numbers within a specified integer range.
Definition misc/gen/math.h:86
T round(T value, T rnd)
Rounds the passed value to a multiple of the rnd value.
Definition misc/gen/math.h:30
_MISC_FUNC int digits(double value)
Returns the amount of digits which are significant for the value. When the value is 12300....
S calculateOffset(T value, T min, T max, S len, bool clip)
Calculates the offset for a given range and set point.
Definition misc/gen/math.h:50
bool isValidValue(T value)
Check if the passed value is not NaN or infinity.
Definition misc/gen/math.h:263
T toAbs(T v)
Gets the absolute value of a passed scalar value.
Definition misc/gen/math.h:130
_MISC_FUNC int requiredDigits(double round_val, double min_val, double max_val)
Gets the amount of required digits needed when drawing a scale.