Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezMath is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #include <type_traits>
30 : : #include <cmath>
31 : : #include <string>
32 : : #include <sstream>
33 : : #include <iomanip>
34 : : #include <cstdint>
35 : : #include <limits>
36 : :
37 : : ////////////////////////////////////////////////////////////////////////////
38 : : ////////////////////////////////////////////////////////////////////////////
39 : : ////////////////////////////////////////////////////////////////////////////
40 : :
41 : : #ifdef _MSC_VER
42 : : #pragma warning(push)
43 : : #pragma warning(disable : 4244) // Conversion from 'double' to 'float', possible loss of data
44 : : #pragma warning(disable : 4305) // Truncation from 'double' to 'float'
45 : : #elif defined(__GNUC__) || defined(__clang__)
46 : : #pragma GCC diagnostic push
47 : : #pragma GCC diagnostic ignored "-Wconversion"
48 : : #pragma GCC diagnostic ignored "-Wfloat-conversion"
49 : : #endif
50 : :
51 : : ////////////////////////////////////////////////////////////////////////////
52 : : ////////////////////////////////////////////////////////////////////////////
53 : : ////////////////////////////////////////////////////////////////////////////
54 : :
55 : : namespace ez {
56 : :
57 : : #ifndef M_PI
58 : : #define M_PI 3.1415926535897932384626433832795
59 : : #endif
60 : :
61 : : #ifndef M_E
62 : : #define M_E 2.7182818284590452353602874713527
63 : : #endif
64 : :
65 : : // This function rounds a floating-point number to 'n' decimal places.
66 : : // Only floating-point types (float, double, long double) are allowed.
67 : : template <typename T>
68 : 12 : inline std::string round_n(T vValue, int n) {
69 : 12 : static_assert(std::is_floating_point<T>::value, "round_n is only valid for floating point types");
70 : 12 : std::stringstream tmp;
71 : 12 : tmp << std::setprecision(n) << std::fixed << vValue;
72 : 12 : return tmp.str();
73 : 12 : }
74 : :
75 : : /// This function is used to ensure that a floating point number is not a NaN or infinity.
76 : 5 : inline bool floatIsValid(float x) {
77 : 5 : const union {
78 : 5 : float f;
79 : 5 : int32_t i;
80 : 5 : } v = {x};
81 : 5 : return (v.i & 0x7f800000) != 0x7f800000;
82 : 5 : }
83 : :
84 : : // Checks if two numbers are different according to epsilon precision.
85 : : template <typename T>
86 : 26 : inline bool isDifferent(T vA, T vB) {
87 : 26 : return vA != vB;
88 : 26 : }
89 : :
90 : : template <>
91 : 58 : inline bool isDifferent(float vA, float vB) {
92 : 58 : return std::fabs(vA - vB) > std::numeric_limits<float>::epsilon();
93 : 58 : }
94 : :
95 : : template <>
96 : 58 : inline bool isDifferent(double vA, double vB) {
97 : 58 : return std::abs(vA - vB) > std::numeric_limits<double>::epsilon();
98 : 58 : }
99 : :
100 : : // Checks if two numbers are equal according to epsilon precision.
101 : : template <typename T>
102 : 353 : inline bool isEqual(T vA, T vB) {
103 : 353 : return vA == vB;
104 : 353 : }
105 : :
106 : : template <>
107 : 110 : inline bool isEqual(float vA, float vB) {
108 : 110 : return std::fabs(vA - vB) < std::numeric_limits<float>::epsilon();
109 : 110 : }
110 : :
111 : : template <>
112 : 97 : inline bool isEqual(double vA, double vB) {
113 : 97 : return std::abs(vA - vB) < std::numeric_limits<double>::epsilon();
114 : 97 : }
115 : :
116 : : // Rounds a floating-point number to the nearest integer.
117 : : // Only floating-point types (float, double, long double) are allowed.
118 : : template <typename T>
119 : 6 : inline T round(T v) {
120 : 6 : static_assert(std::is_floating_point<T>::value, "round is only valid for floating point types");
121 : 6 : return static_cast<T>(std::round(v));
122 : 6 : }
123 : :
124 : : // Returns the largest integer less than or equal to the floating-point number.
125 : : // Only floating-point types (float, double, long double) are allowed.
126 : : template <typename T>
127 : 493 : inline T floor(T v) {
128 : 493 : static_assert(std::is_floating_point<T>::value, "floor is only valid for floating point types");
129 : 493 : return static_cast<T>(std::floor(v));
130 : 493 : }
131 : :
132 : : // Returns the smallest integer greater than or equal to the floating-point number.
133 : : // Only floating-point types (float, double, long double) are allowed.
134 : : template <typename T>
135 : 10 : inline T ceil(T v) {
136 : 10 : static_assert(std::is_floating_point<T>::value, "ceil is only valid for floating point types");
137 : 10 : return static_cast<T>(std::ceil(v));
138 : 10 : }
139 : :
140 : : // Returns the fractional part of a floating-point number.
141 : : // Only floating-point types (float, double, long double) are allowed.
142 : : template <typename T>
143 : 10 : inline T fract(T v) {
144 : 10 : static_assert(std::is_floating_point<T>::value, "fract is only valid for floating point types");
145 : 10 : return v - floor(v);
146 : 10 : }
147 : :
148 : : // Computes the cosine of a floating-point number.
149 : : // Only floating-point types (float, double, long double) are allowed.
150 : : template <typename T>
151 : 8 : inline T cos(T v) {
152 : 8 : static_assert(std::is_floating_point<T>::value, "cos is only valid for floating point types");
153 : 8 : return std::cos(v);
154 : 8 : }
155 : :
156 : : // Computes the arc cosine of a floating-point number.
157 : : // Only floating-point types (float, double, long double) are allowed.
158 : : template <typename T>
159 : 4 : inline T acos(T v) {
160 : 4 : static_assert(std::is_floating_point<T>::value, "acos is only valid for floating point types");
161 : 4 : return std::acos(v);
162 : 4 : }
163 : :
164 : : // Computes the sine of a floating-point number.
165 : : // Only floating-point types (float, double, long double) are allowed.
166 : : template <typename T>
167 : 8 : inline T sin(T v) {
168 : 8 : static_assert(std::is_floating_point<T>::value, "sin is only valid for floating point types");
169 : 8 : return std::sin(v);
170 : 8 : }
171 : :
172 : : // Computes the arc sine of a floating-point number.
173 : : // Only floating-point types (float, double, long double) are allowed.
174 : : template <typename T>
175 : 4 : inline T asin(T v) {
176 : 4 : static_assert(std::is_floating_point<T>::value, "asin is only valid for floating point types");
177 : 4 : return std::asin(v);
178 : 4 : }
179 : :
180 : : // Computes the tangent of a floating-point number.
181 : : // Only floating-point types (float, double, long double) are allowed.
182 : : template <typename T>
183 : 6 : inline T tan(T v) {
184 : 6 : static_assert(std::is_floating_point<T>::value, "tan is only valid for floating point types");
185 : 6 : return std::tan(v);
186 : 6 : }
187 : :
188 : : // Computes the arc tangent of a floating-point number.
189 : : // Only floating-point types (float, double, long double) are allowed.
190 : : template <typename T>
191 : 8 : inline T atan(T v) {
192 : 8 : static_assert(std::is_floating_point<T>::value, "atan is only valid for floating point types");
193 : 8 : return std::atan(v);
194 : 8 : }
195 : :
196 : : // Computes the sqrt of a floating-point number.
197 : : // Only floating-point types (float, double, long double) are allowed.
198 : : template <typename T>
199 : 24 : inline T sqrt(T v) {
200 : 24 : static_assert(std::is_floating_point<T>::value, "sqrt is only valid for floating point types");
201 : 24 : return std::sqrt(v);
202 : 24 : }
203 : :
204 : : // Returns the smaller of two values.
205 : : // Works with both integral and floating-point types.
206 : : template <typename T>
207 : 27946158 : inline T mini(T a, T b) {
208 [ + + ][ + + ]: 27946158 : return a < b ? a : b;
[ + + ][ + + ]
[ + + ][ + + ]
209 : 27946158 : }
210 : :
211 : : // Returns the larger of two values.
212 : : // Works with both integral and floating-point types.
213 : : template <typename T>
214 : 19373109 : inline T maxi(T a, T b) {
215 [ + + ][ + + ]: 19373109 : return a > b ? a : b;
[ + + ][ + + ]
[ + + ][ + + ]
216 : 19373109 : }
217 : :
218 : : // Clamps a value between 0 and 1.
219 : : // Works with both integral and floating-point types.
220 : : template <typename T>
221 : : inline T clamp(T n) {
222 : : return n >= static_cast<T>(0) && n <= static_cast<T>(1) ? n : static_cast<T>(n > static_cast<T>(0));
223 : : }
224 : :
225 : : // Clamps a value between 0 and b.
226 : : // Works with both integral and floating-point types.
227 : : template <typename T>
228 : : inline T clamp(T n, T b) {
229 : : return n >= static_cast<T>(0) && n <= b ? n : static_cast<T>(n > static_cast<T>(0)) * b;
230 : : }
231 : :
232 : : // Clamps a value between a and b.
233 : : // Works with both integral and floating-point types.
234 : : template <typename T>
235 : 26 : inline T clamp(T n, T a, T b) {
236 [ + + ][ + + ]: 26 : return n >= a && n <= b ? n : n < a ? a : b;
[ + + ][ + + ]
[ + + ][ + + ]
[ - + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
237 : 26 : }
238 : :
239 : : // Computes the absolute value of a number.
240 : : // Works with both integral and floating-point types.
241 : : template <typename T>
242 : 37 : inline T abs(T a) {
243 : 37 : static_assert(std::is_arithmetic<T>::value, "abs is only valid for arithmetic types");
244 [ + + ][ + + ]: 37 : return (a < 0) ? a * static_cast<T>(-1) : a;
[ + + ][ + + ]
245 : 37 : }
246 : :
247 : : // Determines the sign of a number (-1 for negative, 1 for positive).
248 : : // Works with both integral and floating-point types.
249 : : template <typename T>
250 : 24 : inline T sign(T a) {
251 : 24 : static_assert(std::is_signed<T>::value, "sign is only valid for signed types");
252 [ + + ][ + + ]: 24 : if (a < 0) {
[ + + ][ + + ]
253 : 4 : return static_cast<T>(-1);
254 [ + + ][ + + ]: 20 : } else if (a > 0) {
[ + + ][ + + ]
255 : 12 : return static_cast<T>(1);
256 : 12 : }
257 : 8 : return static_cast<T>(0);
258 : 24 : }
259 : :
260 : : // Returns 0 if b < a, otherwise returns 1.
261 : : // Works with both integral and floating-point types.
262 : : template <typename T>
263 : 4 : inline T step(T a, T b) {
264 : 4 : static_assert(std::is_arithmetic<T>::value, "step is only valid for arithmetic types");
265 [ + + ][ + + ]: 4 : return (b < a) ? static_cast<T>(0) : static_cast<T>(1);
266 : 4 : }
267 : :
268 : : // Computes the floating-point remainder of the division operation.
269 : : // Only floating-point types (float, double, long double) are allowed.
270 : : template <typename T>
271 : 68 : inline T mod(T v, T l) {
272 : 68 : static_assert(std::is_floating_point<T>::value, "mod is only valid for floating point types");
273 : 68 : return std::fmod(v, l);
274 : 68 : }
275 : :
276 : : // Linearly interpolates between a and b by t.
277 : : // Only floating-point types (float, double, long double) are allowed.
278 : : template <typename T>
279 : 8 : inline T lerp(T a, T b, T t) {
280 : 8 : static_assert(std::is_arithmetic<T>::value, "lerp is only valid for arithmetic types");
281 : 8 : return a * (static_cast<T>(1.0) - t) + b * t;
282 : 8 : }
283 : :
284 : : // Computes the linear normalisation value of t from range [a:b] to range [0:1]
285 : : // Works with both integral and floating-point types.
286 : : template <typename T>
287 : 5 : inline T invLerp(T a, T b, T t) {
288 : 5 : static_assert(std::is_arithmetic<T>::value, "invLerp is only valid for arithmetic types");
289 : 5 : return (t - a) / (b - a);
290 : 5 : }
291 : :
292 : : // Performs linear interpolation (lerp) between a and b by t.
293 : : // Only floating-point types (float, double, long double) are allowed.
294 : : template <typename T>
295 : 4 : inline T mix(T a, T b, T t) {
296 : 4 : static_assert(std::is_arithmetic<T>::value, "mix is only valid for arithmetic types");
297 : 4 : return lerp(a, b, t);
298 : 4 : }
299 : :
300 : : // Computes the linear normalisation value of t from range [a:b] to range [0:1]
301 : : // compute normalisation of t from range [a:b] to range [0:1]
302 : : // Only floating-point types (float, double, long double) are allowed.
303 : : template <typename T>
304 : 2 : inline T invMix(T a, T b, T t) {
305 : 2 : static_assert(std::is_arithmetic<T>::value, "invMix is only valid for arithmetic types");
306 : 2 : return invLerp(a, b, t);
307 : 2 : }
308 : :
309 : : // Computes the linear normalisation value of t from range [a:b] to range [0:1]
310 : : // compute normalisation of t from range [a:b] to range [0:1]
311 : : // Only floating-point types (float, double, long double) are allowed.
312 : : template <typename T>
313 : : inline T norm(T min, T max, T v) {
314 : : static_assert(std::is_arithmetic<T>::value, "norm is only valid for arithmetic types");
315 : : return invLerp(min, max, v);
316 : : }
317 : :
318 : : // Exponentially interpolates between a and b by t.
319 : : // Only floating-point types (float, double, long double) are allowed.
320 : : template <typename T>
321 : 4 : inline T eerp(T a, T b, T t) {
322 : 4 : static_assert(std::is_floating_point<T>::value, "eerp is only valid for floating point types");
323 [ + + ][ + + ]: 4 : if (a == static_cast<T>(0)) {
324 : 2 : return static_cast<T>(0);
325 : 2 : }
326 : 2 : return std::pow(a * (b / a), t);
327 : 4 : }
328 : :
329 : : // Say if the string is an integer
330 : 5 : inline bool isInteger(const std::string& vStr, const int vBase = 10) {
331 : 5 : char* end;
332 : 5 : std::strtol(vStr.c_str(), &end, vBase);
333 : 5 : return *end == '\0'; // end is on the end if all is number
334 : 5 : }
335 : :
336 : : template <typename TTYPE>
337 : : struct range {
338 : : TTYPE rMin{};
339 : : TTYPE rMax{};
340 : 20 : range() = default;
341 : : explicit range(TTYPE vMin, TTYPE vMax) : rMin(vMin), rMax(vMax) {}
342 : : // compute normalisation of value from range [min:max] to range [0:1]
343 : 1 : double norm(TTYPE vValue) const { return invLerp<double>(rMin, rMax, vValue); }
344 : : // move min et max according to vValue
345 : 40 : void combine(TTYPE vValue) {
346 [ + + ]: 40 : if (rMin > vValue) {
347 : 7 : rMin = vValue;
348 : 7 : }
349 [ + + ]: 40 : if (rMax < vValue) {
350 : 20 : rMax = vValue;
351 : 20 : }
352 : 40 : }
353 : : void combine(range<TTYPE> vRange) {
354 : : combine(vRange.rMin);
355 : : combine(vRange.rMax);
356 : : }
357 : : };
358 : :
359 : : } // namespace ez
360 : :
361 : : #include "ezStr.hpp"
362 : : #include "ezVec2.hpp"
363 : : #include "ezVec3.hpp"
364 : : #include "ezVec4.hpp"
365 : : #include "ezMat2.hpp"
366 : : #include "ezMat3.hpp"
367 : : #include "ezMat4.hpp"
368 : : #include "ezAABB.hpp"
369 : : #include "ezQuat.hpp"
370 : : #include "ezPlane.hpp"
371 : : #include "ezAABBCC.hpp"
372 : : #include "ezScreen.hpp"
373 : :
374 : : ////////////////////////////////////////////////////////////////////////////
375 : : ////////////////////////////////////////////////////////////////////////////
376 : : ////////////////////////////////////////////////////////////////////////////
377 : :
378 : : #ifdef _MSC_VER
379 : : #pragma warning(pop)
380 : : #elif defined(__GNUC__) || defined(__clang__)
381 : : #pragma GCC diagnostic pop
382 : : #endif
383 : :
384 : : ////////////////////////////////////////////////////////////////////////////
385 : : ////////////////////////////////////////////////////////////////////////////
386 : : ////////////////////////////////////////////////////////////////////////////
|