Iros
 
Loading...
Searching...
No Matches
functions.h
Go to the documentation of this file.
1#pragma once
2
4#include "di/math/abs.h"
5#include "di/math/constants.h"
6#include "di/meta/language.h"
7#include "di/types/byte.h"
8#include "di/types/floats.h"
9#include "di/util/bit_cast.h"
11
12namespace di::math::detail {
13struct Signbit {
14 template<concepts::FloatingPoint T>
15 constexpr static auto operator()(T x) -> T {
16 auto as_bytes = di::bit_cast<di::Array<byte, sizeof(T)>>(x);
17 auto msb = [&] {
18 if constexpr (Endian::Little == Endian::Native) {
19 return as_bytes[sizeof(T) - 1];
20 } else {
21 return as_bytes[0];
22 }
23 }();
24 return (msb & byte(0b1000'0000)) != byte(0);
25 }
26
27 template<concepts::Integral T>
28 constexpr static auto operator()(T x) -> bool {
29 return Signbit::operator()(f64(x));
30 }
31};
32}
33
34namespace di {
35constexpr inline auto signbit = math::detail::Signbit {};
36}
37
38namespace di::math::detail {
39struct Copysign {
40 template<concepts::FloatingPoint T>
41 constexpr static auto operator()(T x, T y) -> T {
42 auto sign = signbit(y);
43
44 auto as_bytes = di::bit_cast<di::Array<byte, sizeof(T)>>(x);
45 auto& msb = [&] -> byte& {
46 if constexpr (Endian::Little == Endian::Native) {
47 return as_bytes[sizeof(T) - 1];
48 } else {
49 return as_bytes[0];
50 }
51 }();
52
53 msb &= ~(byte(1) << 7);
54 msb |= (byte(sign) << 7);
55
56 return di::bit_cast<T>(as_bytes);
57 }
58
59 template<concepts::Integral T>
60 constexpr static auto operator()(T x, T y) -> f64 {
61 return Copysign::operator()(f64(x), f64(y));
62 }
63};
64}
65
66namespace di {
67constexpr inline auto copysign = math::detail::Copysign {};
68}
69
70namespace di::math::detail {
71struct Round {
72 template<concepts::FloatingPoint T>
73 constexpr static auto operator()(T x) -> T {
74 // FIXME: this is not sufficently precise.
75 if (x < 0) {
76 return -Round::operator()(-x);
77 }
78 // NOLINTNEXTLINE(bugprone-incorrect-roundings)
79 return T(i64(x + 0.5));
80 }
81
82 template<concepts::Integral T>
83 constexpr static auto operator()(T x) -> f64 {
84 return Round::operator()(f64(x));
85 }
86};
87}
88
89namespace di {
90constexpr inline auto round = math::detail::Round {};
91}
92
93namespace di::math::detail {
94struct Remainder {
95 template<concepts::FloatingPoint T>
96 constexpr static auto operator()(T x, T y) -> T {
97 // NOTE: this probably isn't a sufficently precise implemenation.
98 auto quotient = round(x / y);
99 return x - quotient * y;
100 }
101
102 template<concepts::Integral T>
103 constexpr static auto operator()(T x, T y) -> f64 {
104 return Remainder::operator()(f64(x), f64(y));
105 }
106};
107}
108
109namespace di {
110constexpr inline auto remainder = math::detail::Remainder {};
111}
112
113namespace di::math::detail {
114struct Fmod {
115 template<concepts::FloatingPoint T>
116 constexpr static auto operator()(T x, T y) -> T {
117 y = abs(y);
118 auto result = remainder(abs(x), y);
119 if (signbit(result)) {
120 result += y;
121 }
122 return copysign(result, x);
123 }
124
125 template<concepts::Integral T>
126 constexpr static auto operator()(T x, T y) -> f64 {
127 return Fmod::operator()(f64(x), f64(y));
128 }
129};
130}
131
132namespace di {
133constexpr inline auto fmod = math::detail::Fmod {};
134}
135
136namespace di::math::detail {
137struct Cos {
138 template<concepts::FloatingPoint T>
139 constexpr static auto operator()(T x) -> T;
140
141 template<concepts::Integral T>
142 constexpr static auto operator()(T x) -> f64 {
143 return Cos::operator()(f64(x));
144 }
145};
146
147struct Sin {
148 template<concepts::FloatingPoint T>
149 constexpr static auto operator()(T x) -> T;
150
151 template<concepts::Integral T>
152 constexpr static auto operator()(T x) -> f64 {
153 return Sin::operator()(f64(x));
154 }
155};
156
157template<concepts::FloatingPoint T>
158constexpr auto Cos::operator()(T x) -> T {
159 // cos(x) is an even function.
160 x = abs(x);
161
162 // cos(x) is periodic with T = 2 pi
163 x = fmod(x, 2 * numbers::pi_v<T>);
164 if (x >= 3 * numbers::pi_v<T> / 2) {
165 x -= 2 * numbers::pi_v<T>;
166 }
167
168 // cos(x) = -cos(x - pi)
169 if (x > numbers::pi_v<T> / 2) {
171 }
172
173 // cos(x) is an even function.
174 x = abs(x);
175
176 // x is now in the interval [0, pi / 2]
177 // Compute -sin(x - pi/2) if x > pi/4, for increased accuracy.
178 if (x > numbers::pi_v<T> / 4) {
179 return -Sin::operator()(x - numbers::pi_v<T> / 2);
180 }
181
182 // Use a 4 term Taylor series to compute cos(x).
183 return T(1.0) - x * x / T(2.0) + x * x * x * x / T(24.0) - x * x * x * x * x * x / T(720.0);
184}
185
186template<concepts::FloatingPoint T>
187constexpr auto Sin::operator()(T x) -> T {
188 // sin(x) is a odd function.
189 if (x < 0) {
190 return -Sin::operator()(-x);
191 }
192
193 // sin(x) is periodic with T = 2 pi
194 x = fmod(x, 2 * numbers::pi_v<T>);
195
196 // sin(x) = -sin(x - pi)
197 if (x > numbers::pi_v<T>) {
199 }
200
201 // sin(x) = sin(pi - x)
202 if (x > numbers::pi_v<T> / 2) {
203 x = numbers::pi_v<T> - x;
204 }
205
206 // x is now in the interval [0, pi / 2]
207 // Compute cos(x - pi/2) if x > pi/4, for increased accuracy.
208 if (x > numbers::pi_v<T> / 4) {
209 return Cos::operator()(x - numbers::pi_v<T> / 2);
210 }
211
212 // Use a 3 term Taylor series to compute sin(x).
213 return x - x * x * x / T(6.0) + x * x * x * x * x / T(120.0);
214}
215}
216
217namespace di {
218constexpr inline auto cos = math::detail::Cos {};
219constexpr inline auto sin = math::detail::Sin {};
220}
221
222namespace di::math::detail {
224 template<concepts::FloatingPoint T>
225 constexpr static auto operator()(T x, T y, T epsilon = 0.0001) {
226 return x >= y - epsilon && x <= y + epsilon;
227 }
228};
229}
230
231namespace di {
233}
Definition abs.h:11
constexpr auto abs
Definition abs.h:39
constexpr auto pi_v
Definition constants.h:21
std::byte byte
Definition byte.h:64
double f64
Definition floats.h:5
__INT64_TYPE__ i64
Definition integers.h:17
Definition zstring_parser.h:9
constexpr auto sin
Definition functions.h:219
constexpr auto signbit
Definition functions.h:35
constexpr auto approximately_equal
Definition functions.h:232
constexpr auto as_bytes
Definition as_bytes.h:16
constexpr auto remainder
Definition functions.h:110
constexpr auto fmod
Definition functions.h:133
constexpr auto round
Definition functions.h:90
constexpr auto copysign
Definition functions.h:67
constexpr auto cos
Definition functions.h:218
Definition functions.h:223
static constexpr auto operator()(T x, T y, T epsilon=0.0001)
Definition functions.h:225
Definition functions.h:39
static constexpr auto operator()(T x, T y) -> f64
Definition functions.h:60
static constexpr auto operator()(T x, T y) -> T
Definition functions.h:41
Definition functions.h:137
static constexpr auto operator()(T x) -> f64
Definition functions.h:142
static constexpr auto operator()(T x) -> T
Definition functions.h:158
Definition functions.h:114
static constexpr auto operator()(T x, T y) -> T
Definition functions.h:116
static constexpr auto operator()(T x, T y) -> f64
Definition functions.h:126
Definition functions.h:94
static constexpr auto operator()(T x, T y) -> T
Definition functions.h:96
static constexpr auto operator()(T x, T y) -> f64
Definition functions.h:103
Definition functions.h:71
static constexpr auto operator()(T x) -> T
Definition functions.h:73
static constexpr auto operator()(T x) -> f64
Definition functions.h:83
Definition functions.h:13
static constexpr auto operator()(T x) -> T
Definition functions.h:15
static constexpr auto operator()(T x) -> bool
Definition functions.h:28
Definition functions.h:147
static constexpr auto operator()(T x) -> f64
Definition functions.h:152
static constexpr auto operator()(T x) -> T
Definition functions.h:187
Definition span_fixed_size.h:37