HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
math.hpp
1// Copyright Take Vos 2019-2020.
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
5#pragma once
6
7#include "required.hpp"
8#include "cast.hpp"
9#include "type_traits.hpp"
10#include <complex>
11#include <cmath>
12#include <limits>
13#include <span>
14#include <tuple>
15#include <numeric>
16#include <iterator>
17#include <bit>
18
19#if TT_COMPILER == TT_CC_MSVC
20#include <intrin.h>
21#endif
22#if TT_PROCESSOR == TT_CPU_X64
23#include <immintrin.h>
24#endif
25
26namespace tt {
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_axiom(x >= 0 && x <= 18);
52 return pow10_table[x];
53}
54
58template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>,int> = 0>
59constexpr int bsr(T x) noexcept
60{
61 return static_cast<int>(sizeof(T) * 8 - std::countr_zero(x)) - 1;
62}
63
66template<typename T>
67constexpr T make_mask(T x)
68{
69 ttlet x_ = static_cast<unsigned long long>(x) + 1;
70 ttlet p2 = std::bit_ceil(x_);
71 return static_cast<T>(p2 - 1);
72}
73
74
75template<typename T>
76constexpr T median(T a, T b, T c) noexcept {
77 return std::clamp(c, std::min(a, b), std::max(a, b));
78}
79
84constexpr bool almost_equal(float a, float b) noexcept {
85 constexpr int32_t epsilon = 5;
86
87 ttlet a_ = std::bit_cast<int32_t>(a);
88 ttlet b_ = std::bit_cast<int32_t>(b);
89
90 // Strip the sign bit, and extend to not overflow when calculating the delta.
91 ttlet a_abs = static_cast<int64_t>(a_ & 0x7ffffff);
92 ttlet b_abs = static_cast<int64_t>(b_ & 0x7ffffff);
93
94 // If both floats have the same size, we can subtract to get the delta.
95 // If they have a different sign then we need to add.
96 ttlet delta = (a_ < 0) == (b_ < 0) ? a_abs - b_abs : a_abs + b_abs;
97
98 // Check if the delta is with epsilon.
99 return delta < epsilon && delta > -epsilon;
100}
101
102template<typename Iterator>
103auto mean(Iterator first, Iterator last)
104{
105 ttlet init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
106
107 ttlet sum = std::reduce(first, last, init);
108 ttlet count = static_cast<decltype(sum)>(std::distance(first, last));
109
110 return count > 0.0 ? sum / count : sum;
111}
112
113template<typename Iterator, typename T>
114auto stddev(Iterator first, Iterator last, T mean)
115{
116 ttlet init = static_cast<typename std::iterator_traits<Iterator>::value_type>(0);
117
118 ttlet sum = std::accumulate(first, last, init, [=](ttlet &acc, ttlet &value) {
119 ttlet tmp = value - mean;
120 return acc + tmp*tmp;
121 });
122
123 ttlet count = static_cast<decltype(sum)>(std::distance(first, last));
124 return count > 0.0 ? sum / count : sum;
125}
126
127}
T accumulate(T... args)
T count(T... args)
T distance(T... args)
T max(T... args)
T min(T... args)