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 "type_traits.hpp"
11#include "../macros.hpp"
12#include "assert.hpp"
13#include "cast.hpp"
14#include "terminate.hpp"
15#include "exception.hpp"
16#include <complex>
17#include <cmath>
18#include <limits>
19#include <span>
20#include <tuple>
21#include <numeric>
22#include <iterator>
23#include <bit>
24#include <concepts>
25#include <algorithm>
26#include <numbers>
27
28#if HI_COMPILER == HI_CC_MSVC
29#include <intrin.h>
30#endif
31#if HI_PROCESSOR == HI_CPU_X86_64
32#include <immintrin.h>
33#endif
34
35hi_export_module(hikogui.utility.math);
36
37hi_export namespace hi::inline v1 {
38
39template<typename Iterator>
40[[nodiscard]] auto mean(Iterator first, Iterator last)
41{
42 auto const init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
43
44 auto const sum = std::reduce(first, last, init);
45 auto const count = static_cast<decltype(sum)>(std::distance(first, last));
46
47 return count > 0.0 ? sum / count : sum;
48}
49
50template<typename Iterator, typename T>
51[[nodiscard]] auto stddev(Iterator first, Iterator last, T mean)
52{
53 auto const init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
54
55 auto const sum = std::accumulate(first, last, init, [=](auto const& acc, auto const& value) {
56 auto const tmp = value - mean;
57 return acc + tmp * tmp;
58 });
59
60 auto const count = static_cast<decltype(sum)>(std::distance(first, last));
61 return count > 0.0 ? sum / count : sum;
62}
63
64template<typename T>
65constexpr bool inplace_max(T& a, T const& b) noexcept
66{
67 using std::max;
68 a = max(a, b);
69 return a == b;
70}
71
72template<typename T>
73constexpr bool inplace_min(T& a, T const& b) noexcept
74{
75 using std::min;
76 a = min(a, b);
77 return a == b;
78}
79
80template<typename T>
81constexpr void inplace_clamp(T& a, T const& lo, T const& hi) noexcept
82{
83 hi_axiom(lo <= hi);
84
85 using std::clamp;
86 a = clamp(a, lo, hi);
87}
88
89template<typename T>
90[[nodiscard]] constexpr T abs(T a) noexcept
91{
92 return a < T{} ? -a : a;
93}
94
95template<std::floating_point T>
96[[nodiscard]] constexpr bool almost_equal(T a, T b) noexcept
97{
98 auto e = (a + b) * std::numeric_limits<T>::epsilon();
99 return std::abs(a - b) <= e;
100}
101
107template<std::floating_point T>
108[[nodiscard]] constexpr T to_radian(T degree) noexcept
109{
110 return degree * (std::numbers::pi_v<T> / T{180.0});
111}
112
118template<std::unsigned_integral T>
119[[nodiscard]] constexpr T floor(T value, T alignment) noexcept
120{
121 return (value / alignment) * alignment;
122}
123
129template<std::unsigned_integral T>
130[[nodiscard]] constexpr T ceil(T value, T alignment) noexcept
131{
132 return floor(value + (alignment - 1), alignment);
133}
134
135template<std::floating_point T>
136[[nodiscard]] constexpr bool isnan(T value) noexcept
137{
138 return not (value == value);
139}
140
141constexpr unsigned long long pow10_table[20] = {
142 1ULL,
143 10ULL,
144 100ULL,
145 1'000ULL,
146 10'000ULL,
147 100'000ULL,
148 1'000'000ULL,
149 10'000'000ULL,
150 100'000'000ULL,
151 1'000'000'000ULL,
152 10'000'000'000ULL,
153 100'000'000'000ULL,
154 1'000'000'000'000ULL,
155 10'000'000'000'000ULL,
156 100'000'000'000'000ULL,
157 1'000'000'000'000'000ULL,
158 10'000'000'000'000'000ULL,
159 100'000'000'000'000'000ULL,
160 1'000'000'000'000'000'000ULL,
161};
162
163[[nodiscard]] constexpr uint64_t pow10(unsigned int x) noexcept
164{
165 hi_axiom_bounds(x, 20);
166 return pow10_table[x];
167}
168
169template<std::unsigned_integral T>
170[[nodiscard]] constexpr unsigned int decimal_width(T x)
171{
172 // clang-format off
173 constexpr uint8_t guess_table[] = {
174 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4,
175 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9,
176 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14,
177 14, 14, 15, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18
178 };
179 // clang-format on
180
181 auto const num_bits = std::bit_width(x);
182 hi_axiom_bounds(num_bits, guess_table);
183 auto const guess = guess_table[num_bits];
184 return guess + wide_cast<unsigned int>(x >= pow10(guess));
185}
186
187template<std::signed_integral T>
188[[nodiscard]] constexpr unsigned int decimal_width(T x)
189{
190 return decimal_width(narrow_cast<std::make_unsigned_t<T>>(abs(x)));
191}
192
193} // namespace hi::inline v1
Utilities to assert and bound check.
Functions for casting values between types savely.
Utilities for throwing exceptions and terminating the application.
The HikoGUI namespace.
Definition array_generic.hpp:20
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
constexpr T to_radian(T degree) noexcept
Convert degree to radian.
Definition math.hpp:108
T accumulate(T... args)
T count(T... args)
T distance(T... args)
T max(T... args)
T min(T... args)