Project Alice
Loading...
Searching...
No Matches
math_fns.hpp
Go to the documentation of this file.
1#pragma once
2#include <cmath>
3
4namespace math {
5
6// TODO: all this functions need to be defined in terms of
7// basic floating point operations (+, -, *, /)
8
9inline constexpr float pi = 3.14159265358979323846f;
10
11inline constexpr float internal_check(float x, float err, float lower, float upper) noexcept {
12 assert(err >= 0.f); // error must be positive
13 assert(lower <= upper); // conflicting definitions
14 assert(x + err >= lower && x - err <= upper); // unreasonable
15 return (x < lower) ? lower : ((x > upper) ? upper : x);
16}
17
18inline float sin(float x) noexcept {
19 // based on
20 // https://web.archive.org/web/20200628195036/http://mooooo.ooo/chebyshev-sine-approximation/
21 assert(x >= -2.f * pi && x <= 2.f * pi);
22 if(x < -pi) {
23 x += 2.f * pi;
24 } else if(x > pi) {
25 x -= 2.f * pi;
26 }
27 static const float coeffs[] = {
28 -0.10132118f, // x
29 0.0066208798f, // x^3
30 -0.00017350505f, // x^5
31 0.0000025222919f, // x^7
32 -0.000000023317787f, // x^9
33 0.00000000013291342f, // x^11
34 };
35 float pi_major = 3.1415927f;
36 float pi_minor = -0.00000008742278f;
37 float x2 = x * x;
38 float p11 = coeffs[5];
39 float p9 = p11 * x2 + coeffs[4];
40 float p7 = p9 * x2 + coeffs[3];
41 float p5 = p7 * x2 + coeffs[2];
42 float p3 = p5 * x2 + coeffs[1];
43 float p1 = p3 * x2 + coeffs[0];
44 float r = (x - pi_major - pi_minor) * (x + pi_major + pi_minor) * p1 * x;
45 return internal_check(r, 0.0016f, -1.f, 1.f);
46}
47
48inline float cos(float x) noexcept {
49 float r = math::sin(pi / 2.f - x);
50 return internal_check(r, 0.0016f, -1.f, 1.f);
51}
52
53inline float acos(float x) noexcept {
54 // Lagrange polynomial - https://stackoverflow.com/questions/3380628/fast-arc-cos-algorithm
55 // Maximum absolute error of 0.017
56 constexpr float acos_input_err = 0.001f;
57 assert(x >= -1.f - acos_input_err && x <= 1.f + acos_input_err);
58 if(x >= 1.f) { // clamp max
59 assert(x <= 1.f + acos_input_err);
60 return 0.f;
61 } else if(x <= -1.f) { // clamp min
62 assert(x >= -1.f - acos_input_err);
63 return pi;
64 }
65 float r = ((0.4643653210307f * x * x * x + 0.921784152891457f * x * x - 2.0178302343512f * x - 0.939115566365855f) * x + 1.5707963267949f) / ((0.295624144969963f * x * x - 1.28459062446908f) * (x * x) + 1.f);
66 assert((x >= 1.f) ? r == 0.f : r > 0.f); //we need not to give 0 on distances
67 return internal_check(r, 0.017f, 0.f, pi);
68}
69
70inline float sqrt(float x) noexcept {
71 union {
72 float f;
73 int i;
74 } u = {x};
75 u.i = 0x5f375a86 - (u.i >> 1);
76 u.f = u.f * (1.5f - (0.5f * x) * u.f * u.f);
77 u.f = u.f * (1.5f - (0.5f * x) * u.f * u.f);
78 return u.f * x;
79}
80
81}
#define assert(condition)
Definition: debug.h:74
Definition: math_fns.hpp:4
constexpr float pi
Definition: math_fns.hpp:9
float cos(float x) noexcept
Definition: math_fns.hpp:48
float sin(float x) noexcept
Definition: math_fns.hpp:18
constexpr float internal_check(float x, float err, float lower, float upper) noexcept
Definition: math_fns.hpp:11
float sqrt(float x) noexcept
Definition: math_fns.hpp:70
float acos(float x) noexcept
Definition: math_fns.hpp:53