1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef BASE_MATH_H
4#define BASE_MATH_H
5
6#include <algorithm>
7#include <cmath>
8#include <cstdlib>
9
10using std::clamp;
11
12constexpr float pi = 3.1415926535897932384626433f;
13
14constexpr inline int round_to_int(float f)
15{
16 return f > 0 ? (int)(f + 0.5f) : (int)(f - 0.5f);
17}
18
19constexpr inline int round_truncate(float f)
20{
21 return (int)f;
22}
23
24template<typename T, typename TB>
25constexpr inline T mix(const T a, const T b, TB amount)
26{
27 return a + (b - a) * amount;
28}
29
30template<typename T, typename TB>
31inline T bezier(const T p0, const T p1, const T p2, const T p3, TB amount)
32{
33 // De-Casteljau Algorithm
34 const T c10 = mix(p0, p1, amount);
35 const T c11 = mix(p1, p2, amount);
36 const T c12 = mix(p2, p3, amount);
37
38 const T c20 = mix(c10, c11, amount);
39 const T c21 = mix(c11, c12, amount);
40
41 return mix(c20, c21, amount); // c30
42}
43
44inline float random_float()
45{
46 return rand() / (float)(RAND_MAX);
47}
48
49inline float random_float(float min, float max)
50{
51 return min + random_float() * (max - min);
52}
53
54inline float random_float(float max)
55{
56 return random_float(min: 0.0f, max);
57}
58
59inline float random_angle()
60{
61 return 2.0f * pi * (rand() / std::nextafter(x: (float)RAND_MAX, y: std::numeric_limits<float>::max()));
62}
63
64constexpr int fxpscale = 1 << 10;
65
66// float to fixed
67constexpr inline int f2fx(float v)
68{
69 return round_to_int(f: v * fxpscale);
70}
71constexpr inline float fx2f(int v)
72{
73 return v / (float)fxpscale;
74}
75
76// int to fixed
77constexpr inline int i2fx(int v)
78{
79 return v * fxpscale;
80}
81constexpr inline int fx2i(int v)
82{
83 return v / fxpscale;
84}
85
86class fxp
87{
88 int value;
89
90public:
91 void set(int v)
92 {
93 value = v;
94 }
95 int get() const
96 {
97 return value;
98 }
99 fxp &operator=(int v)
100 {
101 value = i2fx(v);
102 return *this;
103 }
104 fxp &operator=(float v)
105 {
106 value = f2fx(v);
107 return *this;
108 }
109 operator int() const
110 {
111 return fx2i(v: value);
112 }
113 operator float() const
114 {
115 return fx2f(v: value);
116 }
117};
118
119template<typename T>
120constexpr inline T minimum(T a, T b)
121{
122 return std::min(a, b);
123}
124template<typename T>
125constexpr inline T minimum(T a, T b, T c)
126{
127 return std::min(std::min(a, b), c);
128}
129template<typename T>
130constexpr inline T maximum(T a, T b)
131{
132 return std::max(a, b);
133}
134template<typename T>
135constexpr inline T maximum(T a, T b, T c)
136{
137 return std::max(std::max(a, b), c);
138}
139template<typename T>
140constexpr inline T absolute(T a)
141{
142 return a < T(0) ? -a : a;
143}
144
145template<typename T>
146constexpr inline T in_range(T a, T lower, T upper)
147{
148 return lower <= a && a <= upper;
149}
150template<typename T>
151constexpr inline T in_range(T a, T upper)
152{
153 return in_range(a, 0, upper);
154}
155
156#endif // BASE_MATH_H
157