HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
math.hpp
1// Copyright 2019 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/required.hpp"
7#include "TTauri/Foundation/numeric_cast.hpp"
8#include "TTauri/Foundation/type_traits.hpp"
9#include <complex>
10#include <cmath>
11#include <limits>
12#include <nonstd/span>
13#include <tuple>
14#include <numeric>
15#include <iterator>
16
17#if TT_COMPILER == TT_CC_MSVC
18#include <intrin.h>
19#endif
20#if TT_PROCESSOR == TT_CPU_X64
21#include <immintrin.h>
22#endif
23
24namespace tt {
25
26constexpr long double pi = 3.141592653589793238462643383279502884L;
27
28constexpr long long pow10_table[20] {
29 1LL,
30 10LL,
31 100LL,
32 1'000LL,
33 10'000LL,
34 100'000LL,
35 1'000'000LL,
36 10'000'000LL,
37 100'000'000LL,
38 1'000'000'000LL,
39 10'000'000'000LL,
40 100'000'000'000LL,
41 1'000'000'000'000LL,
42 10'000'000'000'000LL,
43 100'000'000'000'000LL,
44 1'000'000'000'000'000LL,
45 10'000'000'000'000'000LL,
46 100'000'000'000'000'000LL,
47 1'000'000'000'000'000'000LL,
48};
49
50constexpr long long pow10ll(int x) noexcept {
51 tt_assume(x >= 0 && x <= 18);
52 return pow10_table[x];
53}
54
55template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>,int> = 0>
56constexpr int bsr(T x) noexcept
57{
58#if TT_COMPILER == TT_CC_MSVC
59 if constexpr (sizeof(T) == 4) {
60 unsigned long index;
61 auto found = _BitScanReverse(&index, x);
62 return found ? index : -1;
63
64 } else if constexpr (sizeof(T) == 8) {
65 unsigned long index;
66 auto found = _BitScanReverse64(&index, x);
67 return found ? index : -1;
68
69 } else {
70 tt_not_implemented;
71 }
72#elif TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
73 if constexpr (std::is_same_v<T,unsigned int>) {
74 auto tmp = __builtin_clz(x);
75 return x == 0 ? -1 : ssizeof(T) * 8 - tmp - 1;
76
77 } else if constexpr (std::is_same_v<T,unsigned long>) {
78 auto tmp = __builtin_clzl(x);
79 return x == 0 ? -1 : ssizeof(T) * 8 - tmp - 1;
80
81 } else if constexpr (std::is_same_v<T,unsigned long long>) {
82 auto tmp = __builtin_clzll(x);
83 return x == 0 ? -1 : ssizeof(T) * 8 - tmp - 1;
84
85 } else {
86 tt_not_implemented;
87 }
88#else
89#error "Not implemented"
90#endif
91}
92
93template<typename T>
94constexpr auto next_power_of_two(T rhs)
95{
96 make_larger_t<T> x = rhs;
97
98 --x;
99 x |= x >> 1;
100 x |= x >> 2;
101 x |= x >> 4;
102 if constexpr (sizeof(T) >= 2) {
103 x |= x >> 8;
104 }
105 if constexpr (sizeof(T) >= 4) {
106 x |= x >> 16;
107 }
108 if constexpr (sizeof(T) >= 8) {
109 x |= x >> 32;
110 }
111 ++x;
112 x += (x == 0);
113 return x;
114}
115
118template<typename T>
119constexpr T make_mask(T x)
120{
121 ttlet p2 = next_power_of_two(x);
122 return static_cast<T>(p2 - 1);
123}
124
129template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>,int> = 0>
130constexpr int popcount(T x) noexcept
131{
132#if TT_COMPILER == TT_CC_MSVC
133 if constexpr (sizeof(T) == sizeof(unsigned __int64)) {
134 return __popcnt64(x);
135 } else if constexpr (sizeof(T) == sizeof(unsigned int)) {
136 return __popcnt(x);
137 } else if constexpr (sizeof(T) == sizeof(unsigned short)) {
138 return __popcnt16(x);
139 } else {
140 return __popcnt64(static_cast<unsigned __int64>(x));
141 }
142#elif TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
143 if constexpr (std::is_same_v<T,unsigned int>) {
144 return __builtin_popcount(x);
145
146 } else if constexpr (std::is_same_v<T,unsigned long>) {
147 return __builtin_popcountl(x);
148
149 } else if constexpr (std::is_same_v<T,unsigned long long>) {
150 return __builtin_popcountll(x);
151
152 } else {
153 tt_not_implemented;
154 }
155#else
156#error "Not implemented"
157#endif
158}
159
160template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>,int> = 0>
161constexpr T rotl(T x, unsigned int count) noexcept
162{
163#if TT_COMPILER == TT_CC_MSVC
164 if constexpr (sizeof(T) == 1) {
165 return _rotl8(x, count);
166 } else if constexpr (sizeof(T) == 2) {
167 return _rotl16(x, count);
168 } else if constexpr (sizeof(T) == 4) {
169 return _rotl(x, count);
170 } else if constexpr (sizeof(T) == 8) {
171 return _rotl64(x, count);
172 } else {
173 constexpr unsigned int mask = (8 * sizeof(T)) - 1;
174 return x << count | x >> (-count & mask);
175 }
176#else
177 constexpr unsigned int mask = (8 * sizeof(T)) - 1;
178 return x << count | x >> (-count & mask);
179#endif
180}
181
182template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>,int> = 0>
183constexpr T rotr(T x, unsigned int count) noexcept
184{
185#if TT_COMPILER == TT_CC_MSVC
186 if constexpr (sizeof(T) == 1) {
187 return _rotr8(x, count);
188 } else if constexpr (sizeof(T) == 2) {
189 return _rotr16(x, count);
190 } else if constexpr (sizeof(T) == 4) {
191 return _rotr(x, count);
192 } else if constexpr (sizeof(T) == 8) {
193 return _rotr64(x, count);
194 } else {
195 constexpr unsigned int mask = (8 * sizeof(T)) - 1;
196 return x >> count | x << (-count & mask);
197 }
198#else
199 constexpr unsigned int mask = (8 * sizeof(T)) - 1;
200 return x >> count | x << (-count & mask);
201#endif
202}
203
204template<typename T>
205constexpr T median(T a, T b, T c) noexcept {
206 return std::clamp(c, std::min(a, b), std::max(a, b));
207}
208
209inline bool almost_equal(float a, float b) noexcept {
210 uint32_t a_;
211 uint32_t b_;
212
213 std::memcpy(&a_, &a, sizeof(a_));
214 std::memcpy(&b_, &b, sizeof(b_));
215
216 auto a__ = static_cast<int>(a_ & 0x7ffffff);
217 auto b__ = static_cast<int>(b_ & 0x7ffffff);
218
219 if ((a_ < 0) == (b_ < 0)) {
220 return std::abs(a__ - b__) < 10;
221 } else {
222 return std::abs(a__ + b__) < 10;
223 }
224}
225
226template<typename Iterator>
227auto mean(Iterator first, Iterator last)
228{
229 ttlet init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
230
231 ttlet sum = std::reduce(first, last, init);
232 ttlet count = static_cast<decltype(sum)>(std::distance(first, last));
233
234 return count > 0.0 ? sum / count : sum;
235}
236
237template<typename Iterator, typename T>
238auto stddev(Iterator first, Iterator last, T mean)
239{
240 ttlet init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
241
242 ttlet sum = std::accumulate(first, last, init, [=](ttlet &acc, ttlet &value) {
243 ttlet tmp = value - mean;
244 return acc + tmp*tmp;
245 });
246
247 ttlet count = static_cast<decltype(sum)>(std::distance(first, last));
248 return count > 0.0 ? sum / count : sum;
249}
250
251}
T accumulate(T... args)
T count(T... args)
T distance(T... args)
T max(T... args)
T memcpy(T... args)
T min(T... args)