HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2019-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
8#pragma once
9
10#include "utility.hpp"
11#include "cast.hpp"
12#include "type_traits.hpp"
13#include "assert.hpp"
14#include <complex>
15#include <cmath>
16#include <limits>
17#include <span>
18#include <tuple>
19#include <numeric>
20#include <iterator>
21#include <bit>
22#include <concepts>
23#include <algorithm>
24#include <numbers>
25
26#if HI_COMPILER == HI_CC_MSVC
27#include <intrin.h>
28#endif
29#if HI_PROCESSOR == HI_CPU_X64
30#include <immintrin.h>
31#endif
32
33namespace hi::inline v1 {
34
35
36template<typename Iterator>
37[[nodiscard]] auto mean(Iterator first, Iterator last)
38{
39 hilet init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
40
41 hilet sum = std::reduce(first, last, init);
42 hilet count = static_cast<decltype(sum)>(std::distance(first, last));
43
44 return count > 0.0 ? sum / count : sum;
45}
46
47template<typename Iterator, typename T>
48[[nodiscard]] auto stddev(Iterator first, Iterator last, T mean)
49{
50 hilet init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
51
52 hilet sum = std::accumulate(first, last, init, [=](hilet& acc, hilet& value) {
53 hilet tmp = value - mean;
54 return acc + tmp * tmp;
55 });
56
57 hilet count = static_cast<decltype(sum)>(std::distance(first, last));
58 return count > 0.0 ? sum / count : sum;
59}
60
61template<typename T>
62constexpr bool inplace_max(T& a, T const& b) noexcept
63{
64 using std::max;
65 a = max(a, b);
66 return a == b;
67}
68
69template<typename T>
70constexpr bool inplace_min(T& a, T const& b) noexcept
71{
72 using std::min;
73 a = min(a, b);
74 return a == b;
75}
76
77template<typename T>
78constexpr void inplace_clamp(T& a, T const& lo, T const& hi) noexcept
79{
80 hi_axiom(lo <= hi);
81
82 using std::clamp;
83 a = clamp(a, lo, hi);
84}
85
86template<typename T>
87[[nodiscard]] constexpr T abs(T a) noexcept
88{
89 return a < T{} ? -a : a;
90}
91
92template<std::floating_point T>
93[[nodiscard]] constexpr bool almost_equal(T a, T b) noexcept
94{
95 auto e = (a + b) * std::numeric_limits<T>::epsilon();
96 return std::abs(a - b) <= e;
97}
98
104template<std::floating_point T>
105[[nodiscard]] constexpr T to_radian(T degree) noexcept
106{
107 return degree * (std::numbers::pi_v<T> / T{180.0});
108}
109
115template<std::unsigned_integral T>
116[[nodiscard]] constexpr T floor(T value, T alignment) noexcept
117{
118 return (value / alignment) * alignment;
119}
120
126template<std::unsigned_integral T>
127[[nodiscard]] constexpr T ceil(T value, T alignment) noexcept
128{
129 return floor(value + (alignment - 1), alignment);
130}
131
132template<std::floating_point T>
133[[nodiscard]] constexpr bool isnan(T value) noexcept
134{
135 return not (value == value);
136}
137
138constexpr unsigned long long pow10_table[20] = {
139 1ULL,
140 10ULL,
141 100ULL,
142 1'000ULL,
143 10'000ULL,
144 100'000ULL,
145 1'000'000ULL,
146 10'000'000ULL,
147 100'000'000ULL,
148 1'000'000'000ULL,
149 10'000'000'000ULL,
150 100'000'000'000ULL,
151 1'000'000'000'000ULL,
152 10'000'000'000'000ULL,
153 100'000'000'000'000ULL,
154 1'000'000'000'000'000ULL,
155 10'000'000'000'000'000ULL,
156 100'000'000'000'000'000ULL,
157 1'000'000'000'000'000'000ULL,
158};
159
160[[nodiscard]] constexpr uint64_t pow10(unsigned int x) noexcept
161{
162 hi_axiom_bounds(x, 20);
163 return pow10_table[x];
164}
165
166template<std::unsigned_integral T>
167[[nodiscard]] constexpr unsigned int decimal_width(T x)
168{
169 // clang-format off
170 constexpr uint8_t guess_table[] = {
171 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4,
172 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9,
173 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14,
174 14, 14, 15, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18
175 };
176 // clang-format on
177
178 hilet num_bits = std::bit_width(x);
179 hi_axiom_bounds(num_bits, guess_table);
180 hilet guess = guess_table[num_bits];
181 return guess + wide_cast<unsigned int>(x >= pow10(guess));
182}
183
184template<std::signed_integral T>
185[[nodiscard]] constexpr unsigned int decimal_width(T x)
186{
187 return decimal_width(narrow_cast<std::make_unsigned_t<T>>(abs(x)));
188}
189
190} // namespace hi::inline v1
Utilities to assert and bound check.
#define hi_axiom_bounds(x,...)
Specify an axiom that the value is within bounds.
Definition assert.hpp:264
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Functions for casting values between types savely.
DOXYGEN BUG.
Definition algorithm.hpp:13
constexpr T to_radian(T degree) noexcept
Convert degree to radian.
Definition math.hpp:105
geometry/margins.hpp
Definition cache.hpp:11
Horizontal/Vertical alignment combination.
Definition alignment.hpp:238
T accumulate(T... args)
T count(T... args)
T distance(T... args)
T max(T... args)
T min(T... args)