HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SYS_Math.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: SYS_Math.h (SYS Library, C++)
7  *
8  * COMMENTS: Houdini math interface.
9  * statements like: a = sin(x); b = sinf(y);
10  * we use: a = SYSsin(x); b = SYSsin(y);
11  *
12  * Functions defined here:
13  * SYSmin(a,b) - Returns the minimum of a or b
14  * SYSmin(a,b,c) - Returns the minimum of a, b or c
15  * SYSmin(a,b,c,d) - Returns minimum of a, b, c or d
16  * SYSargmin(a,b) - Returns index of minimum number
17  * SYSargmin(a,b,c) - Returns index of minimum number
18  * SYSargmin(a,b,c,d) - Returns index of minimum number
19  * SYSmax(a,b) - Returns the maximum of a or b
20  * SYSmax(a,b,c) - Returns the maximum of a, b or c
21  * SYSmax(a,b,c,d) - Returns maximum of a, b, c or d
22  * SYSsort(a, b) - Sorts so a < b
23  * SYSsort(a, b, c) - Sorts so a < b < c
24  * SYSargmax(a,b) - Returns index of largest number
25  * SYSargmax(a,b,c) - Returns index of largest number
26  * SYSargmax(a,b,c,d) - Returns index of largest number
27  * SYSabs(x) - Works for all types (including fpreal)
28  * SYSavg(a,b,c) - Return average value of 3 values
29  * SYSavg(a,b,c,d) - Return average value of 4 values
30  *
31  * SYSminmax(a,b,&min.&max) - Find min and max of 2 values
32  * SYSminmax(a,b,c,&min.&max) - Find min and max of 3 values
33  * SYSminmax(a,b,c,d,&min.&max) - Find min and max of 4 values
34  *
35  * SYSwrapmod(a, b) - Returns [0..b) interval for +ve b.
36  *
37  * SYSsignum(a) - Numerically robust Sign function:
38  * -1, if a is negative
39  * 1, if a is positive
40  * 0, otherwise:
41  *
42  * Comparison:
43  * SYSequalZero(a, [tol]) - Is a equal to zero
44  * SYSisEqual(a, b, tol) -
45  * SYSalmostEqual(a, b, ulps, tol) - Almost equal given units in last place
46  *
47  * Interpolation/Range:
48  * SYSclamp(a, min, max) - Clamp value between min and max
49  * SYSsmooth(min, max, a) - Ease-in ease-out curve
50  * SYSsmooth(min, max, a, roll) - Ease-in ease-out curve (with rolloff)
51  * SYSsmoother(min, max, a) - Ease-in ease-out curve (2nd order)
52  * SYSlerp(v1, v2, bias) - Linear interpolation
53  * SYSinvlerp(a, min, max) - Bias required to return a when
54  * lerping min and max.
55  * SYSfit(v, omin,omax, nmin,nmax) - Map v in (omin,omax) to (nmin,nmax),
56  * clamping to (nmin, nmax)
57  * SYSefit(v, omin,omax, nmin,nmax)- Map as in SYSfit() without clamping
58  * to (nmin,nmax). (ie, extrapolate)
59  *
60  * The bilerp function expects:
61  * u0v1--u1v1
62  * | |
63  * u0v0--u1v0
64  * Where u is horizontal and v is vertical in the diagram above.
65  * SYSbilerp(u0v0, u1v0, u0v1, u1v1, u, v)
66  *
67  * Standard math (single/double precision signatures):
68  *
69  * Name | Equation | Domain
70  * --------------------+------------------------------------+-------------
71  * SYSsin(x) | sin(x) | (-inf, +inf)
72  * SYScos(x) | cos(x) | (-inf, +inf)
73  * SYStan(x) | tan(x) | (-inf, +inf)
74  * --------------------+------------------------------------+-------------
75  * SYSasinUnsafe(x) | asin(x) | [ -1, +1 ]
76  * SYSasin(x) | asin(x), -1 if x < -1, +1 if x > 1 | (-inf, +inf)
77  * SYSacosUnsafe(x) | acos(x) | [ -1, +1 ]
78  * SYSacos(x) | acos(x), -1 if x < -1, +1 if x > 1 | (-inf, +inf)
79  * SYSatan(x) | atan(x) | (-inf, +inf)
80  * SYSatan2(y, x) | atan(y, x) |
81  * --------------------+------------------------------------+-------------
82  * SYSsinh(x) | sinh(x) | (-inf, +inf)
83  * SYScosh(x) | cosh(x) | (-inf, +inf)
84  * SYStanh(x) | tanh(x) | (-inf, +inf)
85  * SYSasinh(x) | asinh(x) | (-inf, +inf)
86  * SYSacoshUnsafe(x) | acosh(x) | [ 1, +inf)
87  * SYSacosh(x) | acosh(x), 0 if x < 1 | (-inf, +inf)
88  * SYSatanhUnsafe(x) | atanh(x) | ( -1, +1 )
89  * SYSatanh(x) | atanh(x), x clamped in (-1, 1) | (-inf, +inf)
90  * --------------------+------------------------------------+-------------
91  * SYSsinpi(x) | sin(x * pi) | (-inf, +inf)
92  * SYScospi(x) | cos(x * pi) | (-inf, +inf)
93  * SYStanpi(x) | tan(x * pi) | (-inf, +inf)
94  * --------------------+------------------------------------+-------------
95  * SYSasinpiUnsafe(x) | asin(x) / pi | [ -1, +1 ]
96  * SYSasinpi(x) | asin(x) / pi, | (-inf, +inf)
97  * | -1/2 if x < -1, +1/2 if x > 1 |
98  * SYSacospiUnsafe(x) | acos(x) / pi | [ -1, +1 ]
99  * SYSacospi(x) | acos(x) / pi, | (-inf, +inf)
100  * | -1 if x < -1, +1 if x > 1 |
101  * SYSatanpi(x) | atan(x) / pi | (-inf, +inf)
102  * SYSatan2pi(y, x) | atan(y, x) / pi |
103  * --------------------+------------------------------------+-------------
104  * SYSsincos(x, s, c) | s = sin(x), c = cos(x) | (-inf, +inf)
105  * --------------------+------------------------------------+-------------
106  * SYScbrt(x) | x^(1/3) | (-inf, +inf) Use #include <SYS/SYS_MathCbrt.h>
107  * SYSrecip(x) | 1 / x | (-inf, +inf)
108  * SYSsaferecip(x) | 1 / x, 0 if x = 0 | (-inf, +inf)
109  * SYSrsqrtUnsafe(x) | 1 / sqrt(x) | ( 0, +inf)
110  * SYSrsqrt(x) | 1 / sqrt(x), 0 if x <= 0 | (-inf, +inf)
111  * SYSsqrt(x) | sqrt(x) | [ 0, +inf)
112  * SYSsafesqrt(x) | sqrt(x), 0 if x <= 0 | (-inf, +inf)
113  * --------------------+------------------------------------+-------------
114  * SYSlogUnsafe(x) | ln(x) | ( 0, +inf)
115  * SYSlog(x) | ln(x), 0 if x <= 0 | (-inf, +inf)
116  * SYSlog1pUnsafe(x) | ln(1 + x) | ( -1, +inf)
117  * SYSlog1p(x) | ln(1 + x), 0 if x <= -1 | (-inf, +inf)
118  * SYSlog2Unsafe(x) | log2(x) | ( 0, +inf)
119  * SYSlog2(x) | log2(x), 0 if x <= 0 | (-inf, +inf)
120  * SYSlog2p1Unsafe(x) | log2(x + 1) | ( -1, +inf)
121  * SYSlog2p1(x) | log2(x + 1), 0 if x <= -1 | (-inf, +inf)
122  * SYSlog10Unsafe(x) | log10(x) | ( 0, +inf)
123  * SYSlog10(x) | log10(x), 0 if x <= 0 | (-inf, +inf)
124  * SYSlog10p1Unsafe(x) | log10(x + 1) | ( -1, +inf)
125  * SYSlog10p1(x) | log10(x + 1), 0 if x <= -1 | (-inf, +inf)
126  * --------------------+------------------------------------+-------------
127  * SYSexp(x) | e^x | (-inf, +inf)
128  * SYSexpm1(x) | e^x - 1 | (-inf, +inf)
129  * SYSexp2(x) | 2^x | (-inf, +inf)
130  * SYSexp2m1(x) | 2^x - 1 | (-inf, +inf)
131  * SYSexp10(x) | 10^x | (-inf, +inf)
132  * SYSexp10m1(x) | 10^x - 1 | (-inf, +inf)
133  * --------------------+------------------------------------+-------------
134  * SYSerf(x) | erf(x) | (-inf, +inf)
135  * SYSerfc(x) | 1 - erf(x) | (-inf, +inf)
136  * SYStgamma(x) | tgamma(x) | ( 0, +inf)
137  * SYShypot(x, y) | sqrt(x*x + y*y) | (-inf, +inf)
138  * SYSpow(x, y) | x^y |
139  * SYSsafepow(x, y) | x^y, 1 if y = 0 |
140  * SYSfmod(x) | x % y | (-inf, +inf)
141  * SYSsafefmod(x, y) | x % y, 0 if y = 0 | (-inf, +inf)
142  * SYScopysign(x, y) | sign(y) * x | (-inf, +inf)
143  * --------------------+------------------------------------+-------------
144  * SYSfabs(x) | abs(x) | (-inf, +inf)
145  * SYStrunc(x) | trunc(x) | (-inf, +inf)
146  * SYSfloor(x) | floor(x) | (-inf, +inf)
147  * SYSceil(x) | ceil(x) | (-inf, +inf)
148  * SYSsafediv(x, y) | x / y, 0 if y = 0 | (-inf, +inf)
149  *
150  * Random:
151  * SYSwang_inthash - 32-bit Integer hashing function
152  * SYSwang_inthash64 - 64-bit Integer hashing function
153  * SYSwang2_inthash - Newer 32-bit Integer hashing function
154  * SYSwang2_inthash64 - Newer 64-bit Integer hashing function
155  * SYSreal_hash - Generate a hash for a real number
156  * SYSreal_hashseed - Generate a hash for a real number
157  * SYSvector_hash - Generate a hash for a real vector
158  * SYSfastRandom - Really fast random number generator (0,1)
159  * SYSrandom - Fast random number (fewer artifacts) (0,1)
160  * SYSfastRandomZero - Really fast random number generator (-.5, .5)
161  * SYSrandomZero - Fast random number (fewer artifacts) (-.5, .5)
162  *
163  * Rounding:
164  * SYSroundDownToMultipleOf -
165  * SYSroundUpToMultipleOf -
166  * SYSroundAngle -
167  *
168  * Misc:
169  * SYSisNan - Is this a valid floating-point number?
170  * SYSisFinite - Is not a NAN or Infinity
171  * SYSisInf - Is an Infinity
172  * SYSisNormal - Is a normalized floating point number
173  * SYSisInt - Is the string an integer
174  * SYSisFloat - Is the string a float
175  * SYSisPrime - Is it a prime?
176  * SYSsameSign(a,b) - Do the non-zero numbers have the same sign?
177  * (Note: does not work if either number is zero)
178  * SYSmakePrime - Make it a prime
179  * SYSnextPrime - Next prime
180  * SYSsincosDeg - sin/cos from degrees, multiples of 90 are accurate
181  * SYSgetSinCosFromSlope - Compute sin/cos given a slope
182  * SYShexCharToInt - map '0'-'9,'a'-'z' to 0-15, or -1
183  * SYSintToHexChar - map 0-15 to '0'-'9,'a'-'z'
184  * SYSdivMod(n,d,q,r) - q = n/d; r = n%d; The compiler should make
185  * just one DIV or IDIV instruction.
186  *
187  * For information on almostEqual, please see:
188  * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
189  *
190  */
191 
192 #ifndef __SYS_Math__
193 #define __SYS_Math__
194 
195 #include "SYS_API.h"
196 #include "SYS_Types.h"
197 #include "SYS_MathLib.h"
198 
199 /*
200  * System dependent includes
201  */
202 #if defined(SYS_MATHLIB_OPENLIBM)
203 # include "SYS_FastMath.h"
204 #endif
205 
206 #include <float.h>
207 #include <limits>
208 #include <math.h>
209 #include <stdio.h>
210 #include <stdlib.h>
211 
212 // We do not want to use the built-ins for srand48 or drand48 as they
213 // are not threadsafe. This version uses thread local storage to
214 // avoid that.
215 SYS_API void SYSsrand48(long seed);
216 SYS_API double SYSdrand48();
217 
218 #if !defined(SESI_ALLOW_DRAND48)
219 
220 // These macros are to aggressively prevent anyone from accidentally
221 // using thread unsafe functions
222 #undef srand48
223 #undef drand48
224 #define srand48(X) static_assert(0, "Use SYSsrand48() instead")
225 #define drand48(X) 0; { static_assert(0, "Use SYSdrand48() instead"); }
226 
227 #endif
228 
229 // It would be useful to disable rand() and srand() as well, but
230 // they are used by std::rand :<
231 
232 template< typename F >
233 constexpr inline int
234 SYSsignum(const F a) noexcept
235 {
236  return int(F(0) < a) - int(a < F(0));
237 }
238 
239 // Determine whether f is not-a-number (NAN) for any floating point type f
240 template< typename F >
241 constexpr inline bool
242 SYSisNan(const F f)
243 {
244  return(f != f);
245 }
246 
247 template <>
248 inline bool
250 {
251  return f.isNan();
252 }
253 
254 #include <cmath>
255 
256 /// Check whether a number is finite. That is, not Nan and not infinity.
257 /// @see SYSisNan()
258 /// @{
259 inline bool SYSisFinite(fpreal64 f) { return std::isfinite(f); }
260 inline bool SYSisFinite(fpreal32 f) { return std::isfinite(f); }
261 inline bool SYSisFinite(fpreal16 f) { return f.isFinite(); }
262 constexpr inline bool SYSisFinite(int32 f) { return true; }
263 constexpr inline bool SYSisFinite(int64 f) { return true; }
264 /// @}
265 
266 /// Check whether a number is an infinity.
267 /// @{
268 inline bool SYSisInf(fpreal64 f) { return std::isinf(f); }
269 inline bool SYSisInf(fpreal32 f) { return std::isinf(f); }
270 inline bool SYSisInf(fpreal16 f) { return f.isInfinity(); }
271 constexpr inline bool SYSisInf(int32 f) { return false; }
272 constexpr inline bool SYSisInf(int64 f) { return false; }
273 /// @}
274 
275 /// SYSisNormal() checks whether the string represents a non-finite number
276 /// @{
277 inline bool SYSisNormal(fpreal64 f) { return std::isnormal(f); }
278 inline bool SYSisNormal(fpreal32 f) { return std::isnormal(f); }
279 inline bool SYSisNormal(fpreal16 f) { return f.isNormalized(); }
280 constexpr inline bool SYSisNormal(int32 f) { return true; }
281 constexpr inline bool SYSisNormal(int64 f) { return true; }
282 /// @}
283 
284 /// SYSisNan() checks whether the string represents a non-finite number
285 SYS_API bool SYSisNan(const char *number);
286 SYS_API bool SYSisInt(const char *str);
287 SYS_API bool SYSisFloat(const char *str);
292 SYS_API bool SYSisPrime(uint num);
293 SYS_API bool SYSisPrime(uint64 num);
296 
297 #if defined(__cplusplus)
298 
299 // NOTE:
300 // These have been carefully written so that in the case of equality
301 // we always return the first parameter. This is so that NANs in
302 // in the second parameter are suppressed.
303 #define h_min(a, b) (((a) > (b)) ? (b) : (a))
304 #define h_argmin(a, b) (((a) > (b)) ? 1 : 0)
305 #define h_max(a, b) (((a) < (b)) ? (b) : (a))
306 #define h_argmax(a, b) (((a) < (b)) ? 1 : 0)
307 // DO NOT CHANGE THE ABOVE WITHOUT READING THE COMMENT
308 #define h_abs(a) (((a) > 0) ? (a) : -(a))
309 #define h_sgn(a) (((a) > 0) ? 1 : (((a) < 0) ? -1 : 0))
310 
311 #define SYS_DEF_MINMAX_FUNC1(NAME, RETTYPE, ATYPE) \
312  static inline RETTYPE SYS##NAME(ATYPE a) { return h_##NAME(a); }
313 
314 #define SYS_DEF_MINMAX_FUNC2(NAME, RETTYPE, ATYPE, BTYPE) \
315  static inline RETTYPE SYS##NAME(ATYPE a, BTYPE b) { return h_##NAME(a,b); }
316 
317 #define SYS_MIN(RETTYPE, ATYPE, BTYPE) SYS_DEF_MINMAX_FUNC2(min, RETTYPE, ATYPE, BTYPE)
318 #define SYS_MAX(RETTYPE, ATYPE, BTYPE) SYS_DEF_MINMAX_FUNC2(max, RETTYPE, ATYPE, BTYPE)
319 #define SYS_ABS(RETTYPE, ATYPE) SYS_DEF_MINMAX_FUNC1(abs, RETTYPE, ATYPE)
320 #define SYS_SGN(RETTYPE, ATYPE) SYS_DEF_MINMAX_FUNC1(sgn, RETTYPE, ATYPE)
321 #define SYS_ARGMIN(RETTYPE, ATYPE, BTYPE) SYS_DEF_MINMAX_FUNC2(argmin, RETTYPE, ATYPE, BTYPE)
322 #define SYS_ARGMAX(RETTYPE, ATYPE, BTYPE) SYS_DEF_MINMAX_FUNC2(argmax, RETTYPE, ATYPE, BTYPE)
323 
324 // (Return Type) (Type of Argument A) (Type of Argument B)
325 // \_________ \ _______/
326 // \ \ /
327 constexpr SYS_MIN ( int16, int16, int16 )
328 constexpr SYS_MAX ( int16, int16, int16 )
329 constexpr SYS_ABS ( int16, int16 )
330 constexpr SYS_SGN ( int16, int16 )
331 constexpr SYS_ARGMIN ( int, int16, int16 )
332 constexpr SYS_ARGMAX ( int, int16, int16 )
333 constexpr SYS_MIN ( int32, int32, int32 )
334 constexpr SYS_MAX ( int32, int32, int32 )
335 constexpr SYS_ABS ( int32, int32 )
336 constexpr SYS_SGN ( int32, int32 )
337 constexpr SYS_ARGMIN ( int, int32, int32 )
338 constexpr SYS_ARGMAX ( int, int32, int32 )
339 constexpr SYS_MIN ( int64, int64, int64 )
340 constexpr SYS_MAX ( int64, int64, int64 )
341 constexpr SYS_MIN ( int64, int32, int64 )
342 constexpr SYS_MAX ( int64, int32, int64 )
343 constexpr SYS_MIN ( int64, int64, int32 )
344 constexpr SYS_MAX ( int64, int64, int32 )
345 constexpr SYS_ABS ( int64, int64 )
346 constexpr SYS_SGN ( int64, int64 )
347 constexpr SYS_ARGMIN ( int, int64, int64 )
348 constexpr SYS_ARGMAX ( int, int64, int64 )
349 constexpr SYS_MIN ( uint16, uint16, uint16 )
350 constexpr SYS_MAX ( uint16, uint16, uint16 )
351 constexpr SYS_ARGMIN ( int, uint16, uint16 )
352 constexpr SYS_ARGMAX ( int, uint16, uint16 )
353 constexpr SYS_MIN ( uint32, uint32, uint32 )
354 constexpr SYS_MAX ( uint32, uint32, uint32 )
355 constexpr SYS_ARGMIN ( int, uint32, uint32 )
356 constexpr SYS_ARGMAX ( int, uint32, uint32 )
357 constexpr SYS_MIN ( uint64, uint64, uint64 )
358 constexpr SYS_MAX ( uint64, uint64, uint64 )
359 constexpr SYS_ARGMIN ( int, uint64, uint64 )
360 constexpr SYS_ARGMAX ( int, uint64, uint64 )
361 constexpr SYS_MIN ( fpreal32, fpreal32, fpreal32 )
362 constexpr SYS_MAX ( fpreal32, fpreal32, fpreal32 )
363 constexpr SYS_SGN ( fpreal32, fpreal32 )
364 constexpr SYS_ARGMIN ( int, fpreal32, fpreal32 )
365 constexpr SYS_ARGMAX ( int, fpreal32, fpreal32 )
366 constexpr SYS_MIN ( fpreal64, fpreal64, fpreal64 )
367 constexpr SYS_MAX ( fpreal64, fpreal64, fpreal64 )
368 constexpr SYS_SGN ( fpreal64, fpreal64 )
369 constexpr SYS_ARGMIN ( int, fpreal64, fpreal64 )
370 constexpr SYS_ARGMAX ( int, fpreal64, fpreal64 )
371  SYS_MIN ( fpreal16, fpreal16, fpreal16 )
372  SYS_MAX ( fpreal16, fpreal16, fpreal16 )
373  SYS_SGN ( fpreal16, fpreal16 )
374  SYS_ARGMIN ( int, fpreal16, fpreal16 )
375  SYS_ARGMAX ( int, fpreal16, fpreal16 )
376 
377 // Some systems have size_t as a seperate type from uint. Some don't.
378 #if defined(MBSD)
379 constexpr SYS_MIN ( size_t, size_t, size_t )
380 constexpr SYS_MAX ( size_t, size_t, size_t )
381 constexpr SYS_ARGMIN ( int, size_t, size_t )
382 constexpr SYS_ARGMAX ( int, size_t, size_t )
383 constexpr SYS_MIN ( size_t, long, long )
384 constexpr SYS_MAX ( size_t, long, long )
385 constexpr SYS_ARGMIN ( int, long, long )
386 constexpr SYS_ARGMAX ( int, long, long )
387 #endif
388 
389 #undef SYS_MIN
390 #undef SYS_MAX
391 #undef SYS_ABS
392 #undef SYS_SGN
393 #undef SYS_ARGMIN
394 #undef SYS_ARGMAX
395 
396 #undef SYS_DEF_MINMAX_FUNC1
397 #undef SYS_DEF_MINMAX_FUNC2
398 
399 #undef h_min
400 #undef h_max
401 #undef h_abs
402 #undef h_sgn
403 
404 #define h_clamp(val, min, max, tol) \
405  ((val <= min+tol) ? min : ((val >= max-tol) ? max : val))
406 
407  static constexpr inline int
408  SYSclamp(int v, int min, int max)
409  { return h_clamp(v, min, max, 0); }
410 
411  static constexpr inline uint
413  { return h_clamp(v, min, max, 0); }
414 
415  static constexpr inline int64
416  SYSclamp(int64 v, int64 min, int64 max)
417  { return h_clamp(v, min, max, CONST_INT64(0)); }
418 
419  static constexpr inline uint64
420  SYSclamp(uint64 v, uint64 min, uint64 max)
421  { return h_clamp(v, min, max, CONST_UINT64(0)); }
422 
423  static constexpr inline fpreal32
424  SYSclamp(fpreal32 v, fpreal32 min, fpreal32 max, fpreal32 tol=(fpreal32)0)
425  { return h_clamp(v, min, max, tol); }
426 
427  static constexpr inline fpreal64
428  SYSclamp(fpreal64 v, fpreal64 min, fpreal64 max, fpreal64 tol=(fpreal64)0)
429  { return h_clamp(v, min, max, tol); }
430 
431 #undef h_clamp
432 
433 // clamp float to [0, 1]
434 static constexpr inline float SYSclamp01(float v)
435  { return SYSclamp(v, 0.f, 1.f); }
436 static constexpr inline double SYSclamp01(double v)
437  { return SYSclamp(v, 0.0, 1.0); }
438 
439 // clamp float to [0, 1)
440 static constexpr inline float SYSclamp01_excl1(float v)
441  { return SYSclamp(v, 0.f, 1.f - FLT_EPSILON/FLT_RADIX); }
442 static constexpr inline double SYSclamp01_excl1(double v)
443  { return SYSclamp(v, 0.0, 1.0 - DBL_EPSILON/FLT_RADIX); }
444 
445 /// This converts from one integer type to another by clamping
446 /// the range, instead of the usual wrapping.
447 template<typename OUTTYPE,typename INTYPE>
448 constexpr OUTTYPE SYSclampInt(INTYPE value)
449 {
450  value = SYSclamp(value, (INTYPE)std::numeric_limits<OUTTYPE>::min(),
452  return OUTTYPE(value);
453 }
454 
455 // Wrapper for libm math function calls
456 #if defined(SYS_MATHLIB_COREMATH)
457  #define SYS_MF(X) ::cr_##X
458 #elif defined(SYS_MATHLIB_SYSTEM)
459  #define SYS_MF(X) ::X
460 #elif defined(SYS_MATHLIB_OPENLIBM)
461  #define SYS_MF(X) SYS_FastMath::X
462 #else
463  #error Unknown math library
464 #endif
465 
466 #define SYS_MF_STDLIB(X) ::X
467 
468 #if defined(SYS_MATHLIB_COREMATH)
469 extern "C"
470 {
471  #define DECLARE_COREMATH_UNARY_FUNCTIONS(FUNC) \
472  float cr_##FUNC##f(float x); \
473  double cr_##FUNC(double x);
474  #define DECLARE_COREMATH_BINARY_FUNCTIONS(FUNC, ARG_A, ARG_B) \
475  float cr_##FUNC##f(float ARG_A, float ARG_B); \
476  double cr_##FUNC(double ARG_A, double ARG_B);
477 
478  DECLARE_COREMATH_UNARY_FUNCTIONS(acos);
479  DECLARE_COREMATH_UNARY_FUNCTIONS(acosh);
480  DECLARE_COREMATH_UNARY_FUNCTIONS(acospi);
481  DECLARE_COREMATH_UNARY_FUNCTIONS(asin);
482  DECLARE_COREMATH_UNARY_FUNCTIONS(asinh);
483  DECLARE_COREMATH_UNARY_FUNCTIONS(asinpi);
484  DECLARE_COREMATH_UNARY_FUNCTIONS(atan);
485  DECLARE_COREMATH_UNARY_FUNCTIONS(atanh);
486  DECLARE_COREMATH_UNARY_FUNCTIONS(atanpi);
487  DECLARE_COREMATH_UNARY_FUNCTIONS(cbrt);
488  DECLARE_COREMATH_UNARY_FUNCTIONS(cos);
489  DECLARE_COREMATH_UNARY_FUNCTIONS(cosh);
490  DECLARE_COREMATH_UNARY_FUNCTIONS(cospi);
491  DECLARE_COREMATH_UNARY_FUNCTIONS(erf);
492  DECLARE_COREMATH_UNARY_FUNCTIONS(erfc);
493  DECLARE_COREMATH_UNARY_FUNCTIONS(exp);
494  DECLARE_COREMATH_UNARY_FUNCTIONS(exp10);
495  DECLARE_COREMATH_UNARY_FUNCTIONS(exp10m1);
496  DECLARE_COREMATH_UNARY_FUNCTIONS(exp2);
497  DECLARE_COREMATH_UNARY_FUNCTIONS(exp2m1);
498  DECLARE_COREMATH_UNARY_FUNCTIONS(expm1);
499  DECLARE_COREMATH_UNARY_FUNCTIONS(log);
500  DECLARE_COREMATH_UNARY_FUNCTIONS(log10);
501  DECLARE_COREMATH_UNARY_FUNCTIONS(log10p1);
502  DECLARE_COREMATH_UNARY_FUNCTIONS(log1p);
503  DECLARE_COREMATH_UNARY_FUNCTIONS(log2);
504  DECLARE_COREMATH_UNARY_FUNCTIONS(log2p1);
505  DECLARE_COREMATH_UNARY_FUNCTIONS(rsqrt);
506  DECLARE_COREMATH_UNARY_FUNCTIONS(sin);
507  DECLARE_COREMATH_UNARY_FUNCTIONS(sinh);
508  DECLARE_COREMATH_UNARY_FUNCTIONS(sinpi);
509  DECLARE_COREMATH_UNARY_FUNCTIONS(tan);
510  DECLARE_COREMATH_UNARY_FUNCTIONS(tanh);
511  DECLARE_COREMATH_UNARY_FUNCTIONS(tanpi);
512  DECLARE_COREMATH_UNARY_FUNCTIONS(tgamma);
513 
514  DECLARE_COREMATH_BINARY_FUNCTIONS(atan2, y, x);
515  DECLARE_COREMATH_BINARY_FUNCTIONS(atan2pi, y, x);
516  DECLARE_COREMATH_BINARY_FUNCTIONS(hypot, x, y);
517  DECLARE_COREMATH_BINARY_FUNCTIONS(pow, x, y);
518 
519  extern void cr_sincosf(float x, float *s, float *c);
520  extern void cr_sincos(double x, double *s, double *c);
521 
522  #undef DECLARE_COREMATH_UNARY_FUNCTIONS
523  #undef DECLARE_COREMATH_BINARY_FUNCTIONS
524 }
525 
526  #if defined(SYS_MATH_BUILDING_SHARED_LIB)
527  #define SYS_MATH_API SYS_API
528  #elif defined(SESI_INTERNAL)
529  #define SYS_MATH_API static inline
530  #else
531  #define SYS_MATH_API
532  #endif
533 #else
534  #define SYS_MATH_API static inline
535 #endif
536 
537 #define SYS_MATH_UNARY_IMPL(func) \
538  SYS_MATH_API fpreal64 SYS##func(fpreal64 x) \
539  { return SYS_MF(func)(x); } \
540  SYS_MATH_API fpreal32 SYS##func(fpreal32 x) \
541  { return SYS_MF(func##f)(x); } \
542  SYS_MATH_API fpreal64 SYS##func(int64 x) \
543  { return SYS_MF(func)((fpreal64)x); } \
544  SYS_MATH_API fpreal64 SYS##func(int32 x) \
545  { return SYS_MF(func)((fpreal64)x); }
546 #define SYS_MATH_BINARY_IMPL(func, VARA, VARB) \
547  SYS_MATH_API fpreal32 SYS##func(fpreal32 VARA, fpreal32 VARB) \
548  { return SYS_MF(func##f)(VARA, VARB); } \
549  SYS_MATH_API fpreal64 SYS##func(fpreal64 VARA, fpreal64 VARB) \
550  { return SYS_MF(func)(VARA, VARB); }
551 
552 #define SYS_MATH_UNARY_DEFN(func) \
553  SYS_MATH_API fpreal64 SYS##func(fpreal64 x); \
554  SYS_MATH_API fpreal32 SYS##func(fpreal32 x); \
555  SYS_MATH_API fpreal64 SYS##func(int64 x); \
556  SYS_MATH_API fpreal64 SYS##func(int32 x);
557 #define SYS_MATH_BINARY_DEFN(func, VARA, VARB) \
558  SYS_MATH_API fpreal32 SYS##func(fpreal32 VARA, fpreal32 VARB); \
559  SYS_MATH_API fpreal64 SYS##func(fpreal64 VARA, fpreal64 VARB);
560 
561 #if defined(SESI_INTERNAL) && !defined(SYS_MATH_BUILDING_SHARED_LIB)
562  #define SYS_MATH_UNARY(func) SYS_MATH_UNARY_IMPL(func)
563  #define SYS_MATH_BINARY(func, VARA, VARB) SYS_MATH_BINARY_IMPL(func, VARA, VARB)
564 #else
565  #define SYS_MATH_UNARY(func) SYS_MATH_UNARY_DEFN(func)
566  #define SYS_MATH_BINARY(func, VARA, VARB) SYS_MATH_BINARY_DEFN(func, VARA, VARB)
567 #endif
568 
569 #define SYS_MATH_UNARY_STDLIB(func) \
570  static inline fpreal32 SYS##func(fpreal32 x) \
571  { return SYS_MF_STDLIB(func##f)(x); } \
572  static inline fpreal64 SYS##func(fpreal64 x) \
573  { return SYS_MF_STDLIB(func)(x); } \
574  static inline fpreal64 SYS##func(int32 x) \
575  { return SYS_MF_STDLIB(func)((fpreal64)x); } \
576  static inline fpreal64 SYS##func(int64 x) \
577  { return SYS_MF_STDLIB(func)((fpreal64)x); }
578 #define SYS_MATH_BINARY_STDLIB(func, VARA, VARB) \
579  static inline fpreal32 SYS##func(fpreal32 VARA, fpreal32 VARB) \
580  { return SYS_MF_STDLIB(func##f)(VARA, VARB); } \
581  static inline fpreal64 SYS##func(fpreal64 VARA, fpreal64 VARB) \
582  { return SYS_MF_STDLIB(func)(VARA, VARB); }
583 
584 #define SYS_MATH_UNARY_SUFFIX_WRAPPER_IMPL(FUNC, SUFFIX, WRAPPER) \
585  SYS_MATH_API fpreal32 SYS##FUNC##SUFFIX(fpreal32 x) \
586  { return WRAPPER(FUNC##f)(x); } \
587  SYS_MATH_API fpreal64 SYS##FUNC##SUFFIX(fpreal64 x) \
588  { return WRAPPER(FUNC) (x); }
589 #define SYS_MATH_BINARY_SUFFIX_WRAPPER_IMPL(FUNC, SUFFIX, WRAPPER, VARA, VARB) \
590  SYS_MATH_API fpreal32 SYS##FUNC##SUFFIX(fpreal32 VARA, fpreal32 VARB) \
591  { return WRAPPER(FUNC##f)(VARA, VARB); } \
592  SYS_MATH_API fpreal64 SYS##FUNC##SUFFIX(fpreal64 VARA, fpreal64 VARB) \
593  { return WRAPPER(FUNC) (VARA, VARB); }
594 
595 #define SYS_MATH_UNARY_SUFFIX_WRAPPER_DEFN(FUNC, SUFFIX, WRAPPER) \
596  SYS_MATH_API fpreal32 SYS##FUNC##SUFFIX(fpreal32 x); \
597  SYS_MATH_API fpreal64 SYS##FUNC##SUFFIX(fpreal64 x);
598 #define SYS_MATH_BINARY_SUFFIX_WRAPPER_DEFN(FUNC, SUFFIX, WRAPPER, VARA, VARB) \
599  SYS_MATH_API fpreal32 SYS##FUNC##SUFFIX(fpreal32 VARA, fpreal32 VARB); \
600  SYS_MATH_API fpreal64 SYS##FUNC##SUFFIX(fpreal64 VARA, fpreal64 VARB);
601 
602 #if defined(SESI_INTERNAL) && !defined(SYS_MATH_BUILDING_SHARED_LIB)
603  #define SYS_MATH_UNARY_SUFFIX_WRAPPER(FUNC, SUFFIX, WRAPPER) \
604  SYS_MATH_UNARY_SUFFIX_WRAPPER_IMPL(FUNC, SUFFIX, WRAPPER)
605  #define SYS_MATH_BINARY_SUFFIX_WRAPPER(FUNC, SUFFIX, WRAPPER, VARA, VARB) \
606  SYS_MATH_BINARY_SUFFIX_WRAPPER_IMPL(FUNC, SUFFIX, WRAPPER, VARA, VARB)
607 #else
608  #define SYS_MATH_UNARY_SUFFIX_WRAPPER(FUNC, SUFFIX, WRAPPER) \
609  SYS_MATH_UNARY_SUFFIX_WRAPPER_DEFN(FUNC, SUFFIX, WRAPPER)
610  #define SYS_MATH_BINARY_SUFFIX_WRAPPER(FUNC, SUFFIX, WRAPPER, VARA, VARB) \
611  SYS_MATH_BINARY_SUFFIX_WRAPPER_DEFN(FUNC, SUFFIX, WRAPPER, VARA, VARB)
612 #endif
613 
614 #define SYS_MATH_UNSAFE_UNARY(FUNC) \
615  SYS_MATH_UNARY_SUFFIX_WRAPPER(FUNC, Unsafe, SYS_MF)
616 #define SYS_MATH_SAFE_UNARY(FUNC) \
617  SYS_MATH_UNARY_SUFFIX_WRAPPER(FUNC, , SYS_MF)
618 #define SYS_MATH_UNSAFE_UNARY_STDLIB(FUNC) \
619  SYS_MATH_UNARY_SUFFIX_WRAPPER_IMPL(FUNC, Unsafe, SYS_MF_STDLIB)
620 #define SYS_MATH_SAFE_UNARY_STDLIB(FUNC) \
621  SYS_MATH_UNARY_SUFFIX_WRAPPER_IMPL(FUNC, , SYS_MF_STDLIB)
622 #define SYS_MATH_UNSAFE_BINARY(FUNC, VARA, VARB) \
623  SYS_MATH_BINARY_SUFFIX_WRAPPER(FUNC, Unsafe, SYS_MF, VARA, VARB)
624 #define SYS_MATH_SAFE_BINARY(FUNC, VARA, VARB) \
625  SYS_MATH_BINARY_SUFFIX_WRAPPER(FUNC, , SYS_MF, VARA, VARB);
626 
627 #define SYS_MATH_UNARY_PI_IMPL(FUNC) \
628  SYS_MATH_API fpreal32 SYS##FUNC##pi(fpreal32 x) { return SYS_MF(FUNC##pi##f)(x); } \
629  SYS_MATH_API fpreal64 SYS##FUNC##pi(fpreal64 x) { return SYS_MF(FUNC##pi) (x); } \
630  SYS_MATH_API fpreal32 SYS##FUNC##pi(int32 x) { return SYS_MF(FUNC##pi) (x); } \
631  SYS_MATH_API fpreal64 SYS##FUNC##pi(int64 x) { return SYS_MF(FUNC##pi) (x); }
632 
633 #define SYS_MATH_UNARY_PI_DEFN(FUNC) \
634  SYS_MATH_API fpreal32 SYS##FUNC##pi(fpreal32 x); \
635  SYS_MATH_API fpreal64 SYS##FUNC##pi(fpreal64 x); \
636  SYS_MATH_API fpreal32 SYS##FUNC##pi(int32 x); \
637  SYS_MATH_API fpreal64 SYS##FUNC##pi(int64 x);
638 
639 #if defined(SESI_INTERNAL) && !defined(SYS_MATH_BUILDING_SHARED_LIB)
640  #if defined(SYS_MATHLIB_COREMATH)
641  #define SYS_MATH_UNARY_PI(FUNC) SYS_MATH_UNARY_PI_IMPL(FUNC)
642  #else
643  #define SYS_MATH_UNARY_PI(FUNC) \
644  SYS_MATH_API fpreal32 SYS##FUNC##pi(fpreal32 x) { return SYS##FUNC(SYSfmod(x, 2.0f) * M_PI); } \
645  SYS_MATH_API fpreal64 SYS##FUNC##pi(fpreal64 x) { return SYS##FUNC(SYSfmod(x, 2.0 ) * M_PI); } \
646  SYS_MATH_API fpreal32 SYS##FUNC##pi(int32 x) { return SYS##FUNC((x % 2) * M_PI); } \
647  SYS_MATH_API fpreal64 SYS##FUNC##pi(int64 x) { return SYS##FUNC((x % 2) * M_PI); }
648  #endif
649 #else
650  #define SYS_MATH_UNARY_PI(FUNC) SYS_MATH_UNARY_PI_DEFN(FUNC)
651 #endif
652 
653  SYS_MATH_UNARY(sin)
654  SYS_MATH_UNARY(cos)
655  SYS_MATH_UNARY(tan)
656  SYS_MATH_UNARY(sinh)
657  SYS_MATH_UNARY(cosh)
658  SYS_MATH_UNARY(tanh)
659  SYS_MATH_UNARY(asinh)
660  SYS_MATH_UNARY(exp)
661  SYS_MATH_BINARY(pow, x, y)
662  SYS_MATH_BINARY(atan2, y, x)
663  SYS_MATH_BINARY(hypot, x, y)
664 
665  SYS_MATH_UNARY_STDLIB(sqrt)
666  SYS_MATH_UNARY_STDLIB(trunc)
667  SYS_MATH_BINARY_STDLIB(fmod, x, y)
668  SYS_MATH_BINARY_STDLIB(copysign, x, y)
669 
670 #if defined(SYS_MATHLIB_COREMATH)
671  SYS_MATH_UNSAFE_UNARY(rsqrt); // SYSrsqrtUnsafe
672 #else
673  static inline fpreal32 SYSrsqrtUnsafe(fpreal32 x) { return 1.0f / SYS_MF(sqrtf)(x); }
674  static inline fpreal64 SYSrsqrtUnsafe(fpreal64 x) { return 1.0 / SYS_MF(sqrt) (x); }
675 #endif
676 
677  static inline fpreal32 SYSrsqrt(fpreal32 x) { return x > 0 ? SYSrsqrtUnsafe(x) : 0.0f; }
678  static inline fpreal64 SYSrsqrt(fpreal64 x) { return x > 0 ? SYSrsqrtUnsafe(x) : 0.0; }
679 
680  SYS_MATH_UNSAFE_UNARY(asin); // SYSasinUnsafe
681  static inline fpreal32 SYSasin(fpreal32 x) { return SYSasinUnsafe(SYSclamp(x, -1.0f, 1.0f)); }
682  static inline fpreal64 SYSasin(fpreal64 x) { return SYSasinUnsafe(SYSclamp(x, -1.0, 1.0)); }
683 
684  SYS_MATH_UNSAFE_UNARY(acos); // SYSacosUnsafe
685  static inline fpreal32 SYSacos(fpreal32 x) { return SYSacosUnsafe(SYSclamp(x, -1.0f, 1.0f)); }
686  static inline fpreal64 SYSacos(fpreal64 x) { return SYSacosUnsafe(SYSclamp(x, -1.0, 1.0)); }
687 
688  // The domain of atan is infinite, so there's no unsafe version
689  SYS_MATH_SAFE_UNARY(atan); // SYSatan
690 #if defined(SESI_INTERNAL) && !defined(SYS_MATH_BUILDING_SHARED_LIB)
691  SYS_MATH_API fpreal32 SYSatan(fpreal32 y, fpreal32 x) { return SYS_MF(atan2f)(y, x); }
692  SYS_MATH_API fpreal64 SYSatan(fpreal64 y, fpreal64 x) { return SYS_MF(atan2) (y, x); }
693 #else
694  SYS_MATH_API fpreal32 SYSatan(fpreal32 y, fpreal32 x);
695  SYS_MATH_API fpreal64 SYSatan(fpreal64 y, fpreal64 x);
696 #endif
697 
698  SYS_MATH_UNSAFE_UNARY(acosh); // SYSacoshUnsafe
699  static inline fpreal32 SYSacosh(fpreal32 x) { return x < 1.0f ? 0.0f : SYSacoshUnsafe(x); }
700  static inline fpreal64 SYSacosh(fpreal64 x) { return x < 1.0f ? 0.0 : SYSacoshUnsafe(x); }
701 
702  SYS_MATH_UNSAFE_UNARY(atanh); // SYSatanhUnsafe
703  static inline fpreal32 SYSatanh(fpreal32 x) { return SYSatanhUnsafe(SYSclamp(x, -1.0f + FLT_EPSILON/FLT_RADIX, 1.0f - FLT_EPSILON/FLT_RADIX)); }
704  static inline fpreal64 SYSatanh(fpreal64 x) { return SYSatanhUnsafe(SYSclamp(x, -1.0 + DBL_EPSILON/FLT_RADIX, 1.0 - DBL_EPSILON/FLT_RADIX)); }
705 
706 #if defined(SYS_MATHLIB_COREMATH)
707  SYS_MATH_SAFE_BINARY(atan2pi, y, x); // SYSatan2pi
708  SYS_MATH_UNSAFE_UNARY(asinpi); // SYSsinpiUnsafe
709  SYS_MATH_UNSAFE_UNARY(acospi); // SYSacospiUnsafe
710  SYS_MATH_SAFE_UNARY(atanpi); // SYSatanpi
711 #else
712  static inline fpreal32 SYSatan2pi(fpreal32 y, fpreal32 x) { return SYSatan(y, x) / (fpreal32)M_PI; }
713  static inline fpreal64 SYSatan2pi(fpreal64 y, fpreal64 x) { return SYSatan(y, x) / M_PI; }
714 
715  static inline fpreal32 SYSasinpiUnsafe(fpreal32 x) { return SYSasinUnsafe(x) / (fpreal32)M_PI; }
716  static inline fpreal64 SYSasinpiUnsafe(fpreal64 x) { return SYSasinUnsafe(x) / M_PI; }
717 
718  static inline fpreal32 SYSacospiUnsafe(fpreal32 x) { return SYSacosUnsafe(x) / (fpreal32)M_PI; }
719  static inline fpreal64 SYSacospiUnsafe(fpreal64 x) { return SYSacosUnsafe(x) / M_PI; }
720 
721  static inline fpreal32 SYSatanpi(fpreal32 x) { return SYSatan(x) / (fpreal32)M_PI; }
722  static inline fpreal64 SYSatanpi(fpreal64 x) { return SYSatan(x) / M_PI; }
723 #endif
724 
725  static inline fpreal32 SYSasinpi(fpreal32 x) { return SYSasinpiUnsafe(SYSclamp(x, -1.0f, 1.0f)); }
726  static inline fpreal64 SYSasinpi(fpreal64 x) { return SYSasinpiUnsafe(SYSclamp(x, -1.0, 1.0 )); }
727 
728  static inline fpreal32 SYSacospi(fpreal32 x) { return SYSacospiUnsafe(SYSclamp(x, -1.0f, 1.0f)); }
729  static inline fpreal64 SYSacospi(fpreal64 x) { return SYSacospiUnsafe(SYSclamp(x, -1.0, 1.0 )); }
730 
731  SYS_MATH_UNARY_PI(sin); // SYSsinpi
732  SYS_MATH_UNARY_PI(cos); // SYScospi
733  SYS_MATH_UNARY_PI(tan); // SYStanpi
734 
735  SYS_MATH_UNSAFE_UNARY(log);
736  static inline fpreal32 SYSlog(fpreal32 x) { return x > 0.0f ? SYSlogUnsafe(x) : 0.0f; }
737  static inline fpreal64 SYSlog(fpreal64 x) { return x > 0.0 ? SYSlogUnsafe(x) : 0.0; }
738 
739 #if defined(SYS_MATHLIB_COREMATH)
740  SYS_MATH_UNSAFE_UNARY(log2); // SYSlog2Unsafe
741 #else
742  SYS_MATH_UNSAFE_UNARY_STDLIB(log2); // OpenLibm doesn't have log2
743 #endif
744  static inline fpreal32 SYSlog2(fpreal32 x) { return x > 0.0f ? SYSlog2Unsafe(x) : 0.0f; }
745  static inline fpreal64 SYSlog2(fpreal64 x) { return x > 0.0 ? SYSlog2Unsafe(x) : 0.0; }
746 
747  SYS_MATH_UNSAFE_UNARY(log10); // SYSlog10Unsafe
748  static inline fpreal32 SYSlog10(fpreal32 x) { return x > 0.0f ? SYSlog10Unsafe(x) : 0.0f; }
749  static inline fpreal64 SYSlog10(fpreal64 x) { return x > 0.0 ? SYSlog10Unsafe(x) : 0.0; }
750 
751  SYS_MATH_UNSAFE_UNARY(log1p); // SYSlog1pUnsafe
752  static inline fpreal32 SYSlog1p(fpreal32 x) { return x > -1.0f ? SYSlog1pUnsafe(x) : 0.0f; }
753  static inline fpreal64 SYSlog1p(fpreal64 x) { return x > -1.0 ? SYSlog1pUnsafe(x) : 0.0; }
754 
755 #if defined(SYS_MATHLIB_COREMATH)
756  SYS_MATH_SAFE_UNARY(exp2) // SYSexp2
757  SYS_MATH_SAFE_UNARY(erf) // SYSerf
758  SYS_MATH_SAFE_UNARY(erfc) // SYSerfc
759  SYS_MATH_SAFE_UNARY(tgamma) // SYStgamma
760 #else
761  // OpenLibm doesn't have the following functions
762  SYS_MATH_SAFE_UNARY_STDLIB(exp2)
763  SYS_MATH_SAFE_UNARY_STDLIB(erf)
764  SYS_MATH_SAFE_UNARY_STDLIB(erfc)
765  SYS_MATH_SAFE_UNARY_STDLIB(tgamma)
766 #endif
767 
768  SYS_MATH_UNARY(expm1)
769 
770 #if defined(SYS_MATHLIB_COREMATH)
771  SYS_MATH_SAFE_UNARY(exp2m1); // SYSexp2m1
772  SYS_MATH_SAFE_UNARY(exp10); // SYSexp10
773  SYS_MATH_SAFE_UNARY(exp10m1); // SYSexp10m1
774 
775  SYS_MATH_UNSAFE_UNARY(log2p1); // SYSlog2p1
776  SYS_MATH_UNSAFE_UNARY(log10p1); // SYSlog10p1
777 #else
778  static inline fpreal32 SYSexp2m1(fpreal32 x) { return SYSpow(2.0f, x) - 1.0f; }
779  static inline fpreal64 SYSexp2m1(fpreal64 x) { return SYSpow(2.0, x) - 1.0; }
780 
781  static inline fpreal32 SYSexp10(fpreal32 x) { return SYSpow(10.0f, x); }
782  static inline fpreal64 SYSexp10(fpreal64 x) { return SYSpow(10.0, x); }
783 
784  static inline fpreal32 SYSexp10m1(fpreal32 x) { return SYSpow(10.0f, x) - 1.0f; }
785  static inline fpreal64 SYSexp10m1(fpreal64 x) { return SYSpow(10.0, x) - 1.0; }
786 
787  static inline fpreal32 SYSlog2p1Unsafe(fpreal32 x) { return SYSlog2Unsafe(x + 1.0f); }
788  static inline fpreal64 SYSlog2p1Unsafe(fpreal64 x) { return SYSlog2Unsafe(x + 1.0 ); }
789 
790  static inline fpreal32 SYSlog10p1Unsafe(fpreal32 x) { return SYSlog10Unsafe(x + 1.0f); }
791  static inline fpreal64 SYSlog10p1Unsafe(fpreal64 x) { return SYSlog10Unsafe(x + 1.0 ); }
792 #endif
793 
794  static inline fpreal32 SYSlog2p1(fpreal32 x) { return x > -1.0f ? SYSlog2p1Unsafe(x) : 0.0f; }
795  static inline fpreal64 SYSlog2p1(fpreal64 x) { return x > -1.0 ? SYSlog2p1Unsafe(x) : 0.0; }
796 
797  static inline fpreal32 SYSlog10p1(fpreal32 x) { return x > -1.0f ? SYSlog10p1Unsafe(x) : 0.0f; }
798  static inline fpreal64 SYSlog10p1(fpreal64 x) { return x > -1.0 ? SYSlog10p1Unsafe(x) : 0.0; }
799 
800  static constexpr inline fpreal32 SYSsafediv(fpreal32 x, fpreal32 y)
801  { return x/(y != 0 ? y : SYS_Types<fpreal32>::infinity()); }
802  static constexpr inline fpreal64 SYSsafediv(fpreal64 x, fpreal64 y)
803  { return x/(y != 0 ? y : SYS_Types<fpreal64>::infinity()); }
804  static constexpr inline fpreal32 SYSsafesqrt(fpreal32 x)
805  { return x > 0 ? SYSsqrt(x) : 0; }
806  static constexpr inline fpreal64 SYSsafesqrt(fpreal64 x)
807  { return x > 0 ? SYSsqrt(x) : 0; }
808  static constexpr inline fpreal32 SYSsafefmod(fpreal32 x, fpreal32 y)
809  { return y != 0 ? SYSfmod(x, y) : 0; }
810  static constexpr inline fpreal64 SYSsafefmod(fpreal64 x, fpreal64 y)
811  { return y != 0 ? SYSfmod(x, y) : 0; }
812 
813 #if defined(SYS_MATHLIB_COREMATH)
814 # if defined(SESI_INTERNAL) && !defined(SYS_MATH_BUILDING_SHARED_LIB)
815  SYS_MATH_API void SYSsincos(fpreal32 x, fpreal32 *s, fpreal32 *c)
816  { SYS_MF(sincosf)(x,s,c); }
817  SYS_MATH_API void SYSsincos(fpreal64 x, fpreal64 *s, fpreal64 *c)
818  { SYS_MF(sincos)(x,s,c); }
819  SYS_MATH_API void SYSsincos(fpreal32 x, fpreal16 *s, fpreal16 *c)
820  {
821  fpreal32 s32, c32;
822  SYS_MF(sincosf)(x,&s32,&c32);
823  *s = (fpreal16)s32;
824  *c = (fpreal16)c32;
825  }
826 # else
827  SYS_MATH_API void SYSsincos(fpreal32 x, fpreal32 *s, fpreal32 *c);
828  SYS_MATH_API void SYSsincos(fpreal64 x, fpreal64 *s, fpreal64 *c);
829  SYS_MATH_API void SYSsincos(fpreal32 x, fpreal16 *s, fpreal16 *c);
830 # endif
831 #else
832 # if defined(WIN32)
833  // Windows doesn't have sincos
834  static inline void SYSsincos(fpreal32 x, fpreal32 *s, fpreal32 *c)
835  { *s = SYS_MF(sinf)(x); *c = SYS_MF(cosf)(x); }
836  static inline void SYSsincos(fpreal64 x, fpreal64 *s, fpreal64 *c)
837  { *s = SYS_MF(sin)(x); *c = SYS_MF(cos)(x); }
838  static inline void SYSsincos(fpreal32 x, fpreal16 *s, fpreal16 *c)
839  {
840  fpreal s32 = SYS_MF(sinf)(x);
841  fpreal c32 = SYS_MF(cosf)(x);
842  *s = (fpreal16)s32;
843  *c = (fpreal16)c32;
844  }
845 # elif defined(MBSD)
846  static inline void SYSsincos(fpreal32 x, fpreal32 *s, fpreal32 *c)
847  { __sincosf(x,s,c); }
848  static inline void SYSsincos(fpreal64 x, fpreal64 *s, fpreal64 *c)
849  { __sincos(x,s,c); }
850  static inline void SYSsincos(fpreal32 x, fpreal16 *s, fpreal16 *c)
851  {
852  fpreal32 s32, c32;
853  __sincosf(x,&s32,&c32);
854  *s = (fpreal16)s32;
855  *c = (fpreal16)c32;
856  }
857 # else
858  static inline void SYSsincos(fpreal32 x, fpreal32 *s, fpreal32 *c)
859  { SYS_MF(sincosf)(x,s,c); }
860  static inline void SYSsincos(fpreal64 x, fpreal64 *s, fpreal64 *c)
861  { SYS_MF(sincos)(x,s,c); }
862  static inline void SYSsincos(fpreal32 x, fpreal16 *s, fpreal16 *c)
863  {
864  fpreal32 s32, c32;
865  SYS_MF(sincosf)(x,&s32,&c32);
866  *s = (fpreal16)s32;
867  *c = (fpreal16)c32;
868  }
869 # endif
870 #endif
871 
872  // integer log2 (incorrect for 0, gives -1)
873  static inline int32 SYSlog2Int(uint32 x)
874  {
875  // branchless integer log2, https://web.archive.org/web/20220917111023/http://guihaire.com/code/?p=414
876  if (x == 0)
877  return -1;
878  uint32 r = (x > 0xFFFFu) << 4; x >>= r;
879  uint32 shift = (x > 0xFFu ) << 3; x >>= shift; r |= shift;
880  shift = (x > 0xFu ) << 2; x >>= shift; r |= shift;
881  shift = (x > 0x3u ) << 1;
882  return r | shift | (x >> (shift+1));
883  }
884 
885 #undef SYS_MATH_BINARY
886 #undef SYS_MATH_BINARY_DEFN
887 #undef SYS_MATH_BINARY_IMPL
888 #undef SYS_MATH_BINARY_STDLIB
889 #undef SYS_MATH_BINARY_SUFFIX_WRAPPER
890 #undef SYS_MATH_BINARY_SUFFIX_WRAPPER_DEFN
891 #undef SYS_MATH_BINARY_SUFFIX_WRAPPER_IMPL
892 #undef SYS_MATH_SAFE_BINARY
893 #undef SYS_MATH_SAFE_UNARY
894 #undef SYS_MATH_SAFE_UNARY_STDLIB
895 #undef SYS_MATH_UNARY
896 #undef SYS_MATH_UNARY_DEFN
897 #undef SYS_MATH_UNARY_IMPL
898 #undef SYS_MATH_UNARY_PI
899 #undef SYS_MATH_UNARY_PI_DEFN
900 #undef SYS_MATH_UNARY_PI_IMPL
901 #undef SYS_MATH_UNARY_STDLIB
902 #undef SYS_MATH_UNARY_SUFFIX_WRAPPER
903 #undef SYS_MATH_UNARY_SUFFIX_WRAPPER_DEFN
904 #undef SYS_MATH_UNARY_SUFFIX_WRAPPER_IMPL
905 #undef SYS_MATH_UNSAFE_BINARY
906 #undef SYS_MATH_UNSAFE_UNARY
907 #undef SYS_MATH_UNSAFE_UNARY_STDLIB
908 
909 static inline fpreal32 SYSabs (fpreal32 x) { return SYS_MF_STDLIB(fabsf)(x); }
910 static inline fpreal64 SYSabs (fpreal64 x) { return SYS_MF_STDLIB(fabs) (x); }
911 static inline fpreal32 SYSfabs(fpreal32 x) { return SYS_MF_STDLIB(fabsf)(x); }
912 static inline fpreal64 SYSfabs(fpreal64 x) { return SYS_MF_STDLIB(fabs) (x); }
913 
914 #include "SYS_Floor.h"
915 
916 static inline fpreal32 SYSsafepow(fpreal32 x, fpreal32 y) { return x > 0 ? SYSpow(x, y) : x < 0 ? SYSpow(x, SYSrint(y)) : y == 0 ? 1 : 0; }
917 static inline fpreal64 SYSsafepow(fpreal64 x, fpreal64 y) { return x > 0 ? SYSpow(x, y) : x < 0 ? SYSpow(x, SYSrint(y)) : y == 0 ? 1 : 0; }
918 
919 static constexpr inline fpreal32 SYSrecip(fpreal32 x) { return 1.0f / x; }
920 static constexpr inline fpreal64 SYSrecip(fpreal64 x) { return 1.0 / x; }
921 static constexpr inline fpreal32 SYSrecip(int32 x) { return 1.0f / (fpreal32)x; }
922 static constexpr inline fpreal64 SYSrecip(int64 x) { return 1.0 / (fpreal64)x; }
923 
924 static constexpr inline fpreal32 SYSsaferecip(fpreal32 x) { return SYSsafediv(1.0f, x); }
925 static constexpr inline fpreal64 SYSsaferecip(fpreal64 x) { return SYSsafediv(1.0, x); }
926 static constexpr inline fpreal32 SYSsaferecip(int32 x) { return SYSsafediv(1.0f, (fpreal32)x); }
927 static constexpr inline fpreal64 SYSsaferecip(int64 x) { return SYSsafediv(1.0, (fpreal64)x); }
928 
929 static constexpr inline fpreal32 SYSdegToRad(fpreal32 x) { return x*(fpreal32)(M_PI/180.0); }
930 static constexpr inline fpreal64 SYSdegToRad(fpreal64 x) { return x*(fpreal64)(M_PI/180.0); }
931 static constexpr inline fpreal64 SYSdegToRad(int32 x) { return x*(fpreal64)(M_PI/180.0); }
932 static constexpr inline fpreal64 SYSdegToRad(int64 x) { return x*(fpreal64)(M_PI/180.0); }
933 
934 static constexpr inline fpreal32 SYSradToDeg(fpreal32 x) { return x*(fpreal32)(180.0/M_PI); }
935 static constexpr inline fpreal64 SYSradToDeg(fpreal64 x) { return x*(fpreal64)(180.0/M_PI); }
936 static constexpr inline fpreal64 SYSradToDeg(int32 x) { return x*(fpreal64)(180.0/M_PI); }
937 static constexpr inline fpreal64 SYSradToDeg(int64 x) { return x*(fpreal64)(180.0/M_PI); }
938 
939 static constexpr inline fpreal32 SYSpow2(fpreal32 x) { return x*x; }
940 static constexpr inline fpreal64 SYSpow2(fpreal64 x) { return x*x; }
941 static constexpr inline fpreal32 SYSpow3(fpreal32 x) { return x*x*x; }
942 static constexpr inline fpreal64 SYSpow3(fpreal64 x) { return x*x*x; }
943 static constexpr inline fpreal32 SYSpow4(fpreal32 x) { return SYSpow2(SYSpow2(x)); }
944 static constexpr inline fpreal64 SYSpow4(fpreal64 x) { return SYSpow2(SYSpow2(x)); }
945 static constexpr inline fpreal32 SYSpow5(fpreal32 x) { return SYSpow4(x) * x; }
946 static constexpr inline fpreal64 SYSpow5(fpreal64 x) { return SYSpow4(x) * x; }
947 
948 #define h_compare(func, code) \
949  static inline bool func(fpreal32 a, fpreal32 b, \
950  fpreal32 tol=SYS_FTOLERANCE) \
951  { return code; } \
952  static inline bool func(fpreal64 a, fpreal64 b, \
953  fpreal64 tol=SYS_FTOLERANCE_D) \
954  { return code; }
955 #define h_compare_ce(func, code) \
956  static constexpr inline bool func(fpreal32 a, fpreal32 b, \
957  fpreal32 tol=SYS_FTOLERANCE) \
958  { return code; } \
959  static constexpr inline bool func(fpreal64 a, fpreal64 b, \
960  fpreal64 tol=SYS_FTOLERANCE_D) \
961  { return code; }
962 
963  static constexpr inline bool
964  SYSequalZero(fpreal32 a, fpreal32 tol=SYS_FTOLERANCE)
965  { return a >= -tol && a <= tol; }
966 
967  static constexpr inline bool
968  SYSequalZero(fpreal64 a, fpreal64 tol=SYS_FTOLERANCE_D)
969  { return a >= -tol && a <= tol; }
970 
971  static constexpr inline bool
972  SYSequalZero(int32 a, fpreal64 tol=SYS_FTOLERANCE_D)
973  { return a >= -tol && a <= tol; }
974 
975  static constexpr inline bool
976  SYSequalZero(int64 a, fpreal64 tol=SYS_FTOLERANCE_D)
977  { return a >= -tol && a <= tol; }
978 
979  h_compare(SYSisEqual, SYSabs(a-b)<=tol)
980  h_compare_ce(SYSisGreater, (a-b) > tol)
981  h_compare_ce(SYSisGreaterOrEqual, (a-b) >= -tol)
982  h_compare_ce(SYSisLess, (a-b) < -tol)
983  h_compare_ce(SYSisLessOrEqual, (a-b) <= tol)
984 #undef h_compare
985 #undef h_compare_ce
986 
987 constexpr inline bool SYSisEqual(int32 a, int32 b) { return a == b; }
988 constexpr inline bool SYSisEqual(int64 a, int64 b) { return a == b; }
989 constexpr inline bool SYSisGreater(int32 a, int32 b) { return a > b; }
990 constexpr inline bool SYSisGreater(int64 a, int64 b) { return a > b; }
991 constexpr inline bool SYSisGreaterOrEqual(int32 a, int32 b) { return a >= b; }
992 constexpr inline bool SYSisGreaterOrEqual(int64 a, int64 b) { return a >= b; }
993 constexpr inline bool SYSisLess(int32 a, int32 b) { return a < b; }
994 constexpr inline bool SYSisLess(int64 a, int64 b) { return a < b; }
995 constexpr inline bool SYSisLessOrEqual(int32 a, int32 b) { return a <= b; }
996 constexpr inline bool SYSisLessOrEqual(int64 a, int64 b) { return a <= b; }
997 
998 static inline bool
999 SYSalmostEqual(fpreal32 a, fpreal32 b, int ulps=50, fpreal32 tol = 1e-6)
1000 {
1001  // check if they are absolutely close together (only possible near zero)
1002  if (SYSfabs(a - b) <= tol)
1003  return true;
1004 
1005  // we keep the following check in to allow points that are within 1e-15 of
1006  // zero to be "equal" for backwards compatibility (so 6e-16 and -6e-16 are
1007  // "equal" even though they may not be within 1e-15, for example):
1008  // If both double-precision floats are very close to zero, we consider them
1009  // equal.
1010  if((SYSabs(a) < 1e-6) && (SYSabs(b) < 1e-6))
1011  return true;
1012 
1013  // if they have different signs they are not equal (since they must be at
1014  // least tol distance apart by this point, there is no trickiness with +-0)
1015  if ((a < 0) != (b < 0))
1016  return false;
1017 
1018  SYS_FPRealUnionF ai, bi;
1019  ai.fval = a;
1020  bi.fval = b;
1021 
1022  // find the difference in ulps
1023  // We're very careful to avoid signed integer overflow here.
1024  if ((ai.uval > bi.uval ? ai.uval - bi.uval : bi.uval - ai.uval) <= ulps)
1025  return true;
1026 
1027  return false;
1028 }
1029 
1030 // adapted from AlmostEqualUlpsAndAbs from:
1031 // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
1032 static inline bool
1033 SYSalmostEqual(fpreal64 a, fpreal64 b, int64 ulps, fpreal64 tol = 1e-15)
1034 {
1035  // check if they are absolutely close together (only possible near zero)
1036  if (SYSfabs(a - b) <= tol)
1037  return true;
1038 
1039  // we keep the following check in to allow points that are within 1e-15 of
1040  // zero to be "equal" for backwards compatibility (so 6e-16 and -6e-16 are
1041  // "equal" even though they may not be within 1e-15, for example):
1042  // If both double-precision floats are very close to zero, we consider them
1043  // equal.
1044  if((SYSabs(a) < 1e-15) && (SYSabs(b) < 1e-15))
1045  return true;
1046 
1047  // if they have different signs they are not equal (since they must be at
1048  // least tol distance apart by this point, there is no trickiness with +-0)
1049  if ((a < 0) != (b < 0))
1050  return false;
1051 
1052  SYS_FPRealUnionD ai, bi;
1053  ai.fval = a;
1054  bi.fval = b;
1055 
1056  // find the difference in ulps
1057  // We're very careful to avoid signed integer overflow here.
1058  if ((ai.uval > bi.uval ? ai.uval - bi.uval : bi.uval - ai.uval) <= ulps)
1059  return true;
1060 
1061  return false;
1062 }
1063 
1064 static inline bool
1065 SYSalmostEqual(fpreal64 a, fpreal64 b, int32 ulps=50, fpreal64 tol = 1e-15)
1066 {
1067  return SYSalmostEqual(a, b, (int64)ulps, tol);
1068 }
1069 
1070 static inline bool SYSisInteger(fpreal32 val)
1071  { return SYSisEqual(val, SYSfloor(val)) || SYSisEqual(val, SYSceil(val)); }
1072 static inline bool SYSisInteger(fpreal64 val)
1073  { return SYSisEqual(val, SYSfloor(val)) || SYSisEqual(val, SYSceil(val)); }
1074 
1075 #define h_max3(type) \
1076  static constexpr inline type \
1077  SYSmax(type v0, type v1, type v2) { \
1078  return SYSmax(v2, SYSmax(v0, v1)); \
1079  }
1080 #define h_max4(type) \
1081  static constexpr inline type \
1082  SYSmax(type v0, type v1, type v2, type v3) { \
1083  return SYSmax(SYSmax(v0, v1), SYSmax(v2, v3)); \
1084  }
1085 #define h_argmax3(type) \
1086  static constexpr inline int \
1087  SYSargmax(type v0, type v1, type v2) { \
1088  return v2 > SYSmax(v0, v1) ? 2 : SYSargmax(v0, v1); \
1089  }
1090 #define h_argmax4(type) \
1091  static constexpr inline int \
1092  SYSargmax(type v0, type v1, type v2, type v3) { \
1093  return SYSmax(v0, v1) < SYSmax(v2, v3) ? \
1094  (SYSargmax(v2, v3) + 2) : SYSargmax(v0, v1); \
1095  }
1096 #define h_min3(type) \
1097  static constexpr inline type \
1098  SYSmin(type v0, type v1, type v2) { \
1099  return SYSmin(v2, SYSmin(v0, v1)); \
1100  }
1101 #define h_min4(type) \
1102  static constexpr inline type \
1103  SYSmin(type v0, type v1, type v2, type v3) { \
1104  return SYSmin(SYSmin(v0, v1), SYSmin(v2, v3)); \
1105  }
1106 #define h_argmin3(type) \
1107  static constexpr inline int \
1108  SYSargmin(type v0, type v1, type v2) { \
1109  return v2 < SYSmin(v0, v1) ? 2 : SYSargmin(v0, v1); \
1110  }
1111 #define h_argmin4(type) \
1112  static constexpr inline int \
1113  SYSargmin(type v0, type v1, type v2, type v3) { \
1114  return SYSmin(v0, v1) > SYSmin(v2, v3) ? \
1115  (SYSargmin(v2, v3) + 2) : SYSargmin(v0, v1); \
1116  }
1117 
1118 
1119 #define h_max(type) h_min3(type) h_min4(type) h_max3(type) h_max4(type) \
1120  h_argmin3(type) h_argmin4(type) \
1121  h_argmax3(type) h_argmax4(type)
1122 
1123 #define h_avg3(type) \
1124  static constexpr inline type \
1125  SYSavg(type v0, type v1, type v2) { \
1126  return (v0+v1+v2) * ((type)(1.0/3.0)); \
1127  }
1128 #define h_avg4(type) \
1129  static constexpr inline type \
1130  SYSavg(type v0, type v1, type v2, type v3) { \
1131  return (v0+v1+v2+v3) * ((type)0.25); \
1132  }
1133 
1134 #define h_avg(type) h_avg3(type) h_avg4(type)
1135 
1136 h_max(int8)
1137 h_max(uint8)
1138 h_max(int16)
1139 h_max(uint16)
1140 h_max(int32)
1141 h_max(uint32)
1142 h_max(int64)
1143 h_max(uint64)
1144 h_max(fpreal32) h_avg(fpreal32)
1145 h_max(fpreal64) h_avg(fpreal64)
1146 
1147 static constexpr inline int32
1148 SYSavg(int32 a, int32 b, int32 c)
1149 { return (a + b + c + 1) / 3; }
1150 static constexpr inline int32
1151 SYSavg(int32 a, int32 b, int32 c, int32 d)
1152 { return (a + b + c + d + 2) / 4; }
1153 
1154 static constexpr inline int64
1155 SYSavg(int64 a, int64 b, int64 c)
1156 { return (a + b + c + 1) / 3; }
1157 static constexpr inline int64
1158 SYSavg(int64 a, int64 b, int64 c, int64 d)
1159 { return (a + b + c + d + 2) / 4; }
1160 
1161 // Some systems have size_t as a seperate type from uint. Some don't.
1162 #if defined(MBSD)
1163 h_max(size_t)
1164 #endif
1165 
1166 #undef h_min3
1167 #undef h_min4
1168 #undef h_max3
1169 #undef h_max4
1170 #undef h_argmin3
1171 #undef h_argmin4
1172 #undef h_argmax3
1173 #undef h_argmax4
1174 #undef h_avg3
1175 #undef h_avg4
1176 #undef h_max
1177 #undef h_avg
1178 
1179 /// @{
1180 /// Linear interpolation between v0 and v1.
1181 static constexpr inline fpreal32
1182 SYSlerp(fpreal32 v1, fpreal32 v2, fpreal32 t)
1183 {
1184  return v1 + (v2 - v1)*t;
1185 }
1186 
1187 static constexpr inline fpreal64
1188 SYSlerp(fpreal64 v1, fpreal64 v2, fpreal64 t)
1189 {
1190  return v1 + (v2 - v1)*t;
1191 }
1192 /// @}
1193 
1194 /// @{
1195 /// Bilinear interpolation over a quadrilateral: @code
1196 /// (u=0,v=1) u0v1 u1v1 (u=1,v=1)
1197 /// +--------+
1198 /// | |
1199 /// | |
1200 /// +--------+
1201 /// (u=0,v=0) u0v0 u1v0 (u=1,v=0)
1202 /// @endcode
1203 static constexpr inline fpreal32
1204 SYSbilerp(fpreal32 u0v0, fpreal32 u1v0, fpreal32 u0v1, fpreal32 u1v1,
1205  fpreal32 u, fpreal32 v)
1206 {
1207  return SYSlerp(SYSlerp(u0v0, u0v1, v), SYSlerp(u1v0, u1v1, v), u);
1208 }
1209 
1210 static constexpr inline fpreal64
1211 SYSbilerp(fpreal64 u0v0, fpreal64 u1v0, fpreal64 u0v1, fpreal64 u1v1,
1212  fpreal64 u, fpreal64 v)
1213 {
1214  return SYSlerp(SYSlerp(u0v0, u0v1, v), SYSlerp(u1v0, u1v1, v), u);
1215 }
1216 /// @}
1217 
1218 /// @{
1219 /// Barycentric coordinates do interpolation over the triangle specified by the
1220 /// three vertices (v0, v1, v2): @code
1221 /// | (u=0,v=1) |
1222 /// | v2 |
1223 /// | / \ |
1224 /// | / \ |
1225 /// | / \ |
1226 /// | (u=0,v=0) v0------v1 (u=1,v=0) |
1227 /// @endcode
1228 static constexpr inline fpreal32
1229 SYSbarycentric(fpreal32 v0, fpreal32 v1, fpreal32 v2, fpreal32 u, fpreal32 v)
1230 {
1231  return v0*(1-u-v) + v1*u + v2*v;
1232 }
1233 
1234 static constexpr inline fpreal64
1235 SYSbarycentric(fpreal64 v0, fpreal64 v1, fpreal64 v2, fpreal64 u, fpreal64 v)
1236 {
1237  return v0*(1-u-v) + v1*u + v2*v;
1238 }
1239 /// @}
1240 
1241 /// @{
1242 /// Wrap mod is like mod, but returns [0..b) interval thereby
1243 /// usually giving a more useful result.
1244 /// This is always defined as safe!
1245 /// @}
1246 static constexpr inline fpreal32
1247 SYSwrapmod(fpreal32 a, fpreal32 b)
1248 {
1249  fpreal32 r = SYSsafefmod(a, b);
1250  return ((a < 0) ^ (b < 0) && r != 0.0f) ? r+b : r;
1251 }
1252 
1253 static constexpr inline fpreal64
1254 SYSwrapmod(fpreal64 a, fpreal64 b)
1255 {
1256  fpreal64 r = SYSsafefmod(a, b);
1257  return ((a < 0) ^ (b < 0) && r != 0.0) ? r+b : r;
1258 }
1259 
1260 static constexpr inline int32
1261 SYSwrapmod(int32 a, int32 b)
1262 {
1263  if (b == 0)
1264  return 0;
1265  int32 r = a % b;
1266  return ((a < 0) ^ (b < 0) && r) ? r+b : r;
1267 }
1268 
1269 static constexpr inline int64
1270 SYSwrapmod(int64 a, int64 b)
1271 {
1272  if (b == 0)
1273  return 0;
1274  int64 r = a % b;
1275  return ((a < 0) ^ (b < 0) && r) ? r+b : r;
1276 }
1277 
1278 static constexpr inline fpreal32
1279 SYSsmooth(fpreal32 min, fpreal32 max, fpreal32 val)
1280 {
1281  if (val <= min) return 0;
1282  if (val >= max) return 1;
1283  fpreal32 t = max - min;
1284  if (SYSequalZero(t, (fpreal32)1e-8)) return (fpreal32).5;
1285  t = (val - min) / t;
1286  return t*t*((fpreal32)3.0 - (fpreal32)2.0*t);
1287 }
1288 
1289 static constexpr inline fpreal64
1290 SYSsmooth(fpreal64 min, fpreal64 max, fpreal64 val)
1291 {
1292  if (val <= min) return 0;
1293  if (val >= max) return 1;
1294  fpreal64 t = max - min;
1295  if (SYSequalZero(t, (fpreal64)1e-18)) return (fpreal64).5;
1296  t = (val - min) / t;
1297  return t*t*((fpreal64)3.0 - (fpreal64)2.0*t);
1298 }
1299 
1300 static constexpr inline fpreal32
1301 SYSsmooth(fpreal32 min, fpreal32 max, fpreal32 value, fpreal32 roll)
1302 {
1303  if (roll > 0)
1304  {
1305  fpreal32 f = SYSsmooth(min, max, value);
1306  return roll < (fpreal32)1 ? (fpreal32)1-SYSpow((fpreal32)1-f,
1307  (fpreal32)1/roll) : SYSpow(f, roll);
1308  }
1309  return (fpreal32)1;
1310 }
1311 
1312 static constexpr inline fpreal64
1313 SYSsmooth(fpreal64 min, fpreal64 max, fpreal64 value, fpreal64 roll)
1314 {
1315  if (roll > 0)
1316  {
1317  fpreal64 f = SYSsmooth(min, max, value);
1318  return roll < (fpreal64)1 ? (fpreal64)1-SYSpow((fpreal64)1-f,
1319  (fpreal64)1/roll) : SYSpow(f, roll);
1320  }
1321  return (fpreal64)1;
1322 }
1323 
1324 static constexpr inline fpreal32
1325 SYSsmoother(fpreal32 min, fpreal32 max, fpreal32 val)
1326 {
1327  if (val <= min) return 0;
1328  if (val >= max) return 1;
1329  fpreal32 t = max - min;
1330  if (SYSequalZero(t, (fpreal32)1e-8)) return (fpreal32).5;
1331  t = (val - min) / t;
1332  return t*t*t*(t * ((fpreal32)6.0 * t - (fpreal32)15.0) + (fpreal32)10.0);
1333 }
1334 
1335 static constexpr inline fpreal64
1336 SYSsmoother(fpreal64 min, fpreal64 max, fpreal64 val)
1337 {
1338  if (val <= min) return 0;
1339  if (val >= max) return 1;
1340  fpreal64 t = max - min;
1341  if (SYSequalZero(t, (fpreal64)1e-18)) return (fpreal64).5;
1342  t = (val - min) / t;
1343  return t*t*t*(t * ((fpreal64)6.0 * t - (fpreal64)15.0) + (fpreal64)10.0);
1344 }
1345 
1346 static constexpr inline fpreal32
1347 SYSfit(fpreal32 val, fpreal32 omin, fpreal32 omax, fpreal32 nmin, fpreal32 nmax)
1348 {
1349  fpreal32 d = omax - omin;
1350  fpreal32 tmp = (d == 0) ? 0.5f * (nmin+nmax) : SYSlerp(nmin, nmax, (val-omin)/d);
1351  return (d >= 0) ? (val < omin ? nmin : (val > omax ? nmax : tmp))
1352  : (val < omax ? nmax : (val > omin ? nmin : tmp));
1353 }
1354 
1355 static constexpr inline fpreal64
1356 SYSfit(fpreal64 val, fpreal64 omin, fpreal64 omax, fpreal64 nmin, fpreal64 nmax)
1357 {
1358  fpreal64 d = omax - omin;
1359  fpreal64 tmp = (d == 0) ? 0.5 * (nmin+nmax) : SYSlerp(nmin, nmax, (val-omin)/d);
1360  return (d >= 0) ? (val < omin ? nmin : (val > omax ? nmax : tmp))
1361  : (val < omax ? nmax : (val > omin ? nmin : tmp));
1362 }
1363 
1364 /// SYSefit() will not clamp the values to the range
1365 static constexpr inline fpreal32
1366 SYSefit(fpreal32 v, fpreal32 omin, fpreal32 omax, fpreal32 nmin, fpreal32 nmax)
1367 {
1368  fpreal32 d = omax - omin;
1369  return (d == 0) ? 0.5f * (nmin+nmax) : SYSlerp(nmin, nmax, (v-omin)/d);
1370 }
1371 
1372 static constexpr inline fpreal64
1373 SYSefit(fpreal64 v, fpreal64 omin, fpreal64 omax, fpreal64 nmin, fpreal64 nmax)
1374 {
1375  fpreal64 d = omax - omin;
1376  return (d == 0) ? 0.5 * (nmin+nmax) : SYSlerp(nmin, nmax, (v-omin)/d);
1377 }
1378 
1379 static constexpr inline fpreal32
1380 SYSfit01(fpreal32 val, fpreal32 nmin, fpreal32 nmax)
1381 {
1382  if (val < 0) return nmin;
1383  if (val > 1) return nmax;
1384  return SYSlerp(nmin, nmax, val);
1385 }
1386 
1387 static constexpr inline fpreal64
1388 SYSfit01(fpreal64 val, fpreal64 nmin, fpreal64 nmax)
1389 {
1390  if (val < 0) return nmin;
1391  if (val > 1) return nmax;
1392  return SYSlerp(nmin, nmax, val);
1393 }
1394 
1395 /// SYSinvlerp() will produce the bias needed for lerp, but avoid
1396 /// zeros. Essentially built on efit.
1397 static constexpr inline fpreal32
1398 SYSinvlerp(fpreal32 v, fpreal32 omin, fpreal32 omax)
1399 {
1400  return SYSefit(v, omin, omax, 0.0f, 1.0f);
1401 }
1402 
1403 static constexpr inline fpreal64
1404 SYSinvlerp(fpreal64 v, fpreal64 omin, fpreal64 omax)
1405 {
1406  return SYSefit(v, omin, omax, 0.0, 1.0);
1407 }
1408 
1409 // Linear hat function over kernel width dx.
1410 static inline fpreal32
1411 SYShat(fpreal32 x, fpreal32 dx)
1412 {
1413  const fpreal32 ax = SYSabs(x);
1414  return (ax > dx ? 0 : 1 - ax / dx);
1415 }
1416 
1417 static inline fpreal64
1418 SYShat(fpreal64 x, fpreal64 dx)
1419 {
1420  const fpreal64 ax = SYSabs(x);
1421  return (ax > dx ? 0 : 1 - ax / dx);
1422 }
1423 
1424 // Derivative of the linear hat function over kernel width dx.
1425 static constexpr inline fpreal32
1426 SYSdhat(fpreal32 x, fpreal32 dx)
1427 {
1428  return (x < -dx || x > dx ? 0 : -SYSsgn(x) / dx);
1429 }
1430 
1431 static constexpr inline fpreal64
1432 SYSdhat(fpreal64 x, fpreal64 dx)
1433 {
1434  return (x < -dx || x > dx ? 0 : -SYSsgn(x) / dx);
1435 }
1436 
1437 
1438 // For integer types.
1439 template<typename T>
1440 constexpr inline T
1441 SYSroundDownToMultipleOf(T val, T multiple)
1442 {
1443  // Only handle multiples of 2 and up.
1444  if (multiple <= 1)
1445  return val;
1446 
1447  int rem = val % multiple;
1448  if (rem == 0)
1449  return val;
1450 
1451  if (val < 0)
1452  return val - multiple - rem;
1453  else
1454  return val - rem;
1455 }
1456 
1457 template<>
1458 inline fpreal32
1459 SYSroundDownToMultipleOf<fpreal32>(fpreal32 val, fpreal32 multiple)
1460 {
1461  if (SYSequalZero(multiple))
1462  return val;
1463  fpreal32 modulus = SYSfmod(val, multiple);
1464  if (SYSequalZero(modulus) || SYSequalZero(modulus-multiple))
1465  return val;
1466  fpreal32 retval = val - modulus;
1467  if( val < (fpreal32)0 && modulus!=(fpreal32)0 )
1468  retval -= multiple;
1469  return retval;
1470 }
1471 
1472 template<>
1473 inline fpreal64
1474 SYSroundDownToMultipleOf<fpreal64>(fpreal64 val, fpreal64 multiple)
1475 {
1476  if (SYSequalZero(multiple))
1477  return val;
1478  fpreal64 modulus = SYSfmod(val, multiple);
1479  if (SYSequalZero(modulus) || SYSequalZero(modulus-multiple))
1480  return val;
1481  fpreal64 retval = val - modulus;
1482  if( val < (fpreal64)0 && modulus!=(fpreal64)0 )
1483  retval -= multiple;
1484  return retval;
1485 }
1486 
1487 template<typename T>
1488 constexpr inline T
1489 SYSroundUpToMultipleOf(T val, T multiple)
1490 {
1491  // Only handle multiples of 2 and up.
1492  if (multiple <= 1)
1493  return val;
1494 
1495  int rem = val % multiple;
1496  if (rem == 0)
1497  return val;
1498 
1499  if (val < 0)
1500  return val - rem;
1501  else
1502  return val + multiple - rem;
1503 }
1504 
1505 template<>
1506 inline fpreal32
1507 SYSroundUpToMultipleOf<fpreal32>(fpreal32 val, fpreal32 multiple)
1508 {
1509  fpreal32 modulus;
1510  if (SYSequalZero(multiple))
1511  return val;
1512  modulus = SYSfmod(val, multiple);
1513  if (SYSequalZero(modulus) || SYSequalZero(modulus-multiple))
1514  return val;
1515  if (val > (fpreal32)0)
1516  val += multiple;
1517  return val - modulus;
1518 }
1519 
1520 template<>
1521 inline fpreal64
1522 SYSroundUpToMultipleOf<fpreal64>(fpreal64 val, fpreal64 multiple)
1523 {
1524  fpreal64 modulus;
1525  if (SYSequalZero(multiple))
1526  return val;
1527  modulus = SYSfmod(val, multiple);
1528  if (SYSequalZero(modulus) || SYSequalZero(modulus-multiple))
1529  return val;
1530  if (val > (fpreal64)0)
1531  val += multiple;
1532  return val - modulus;
1533 }
1534 
1535 inline constexpr uint32
1536 SYSroundUpPow2(uint32 val)
1537 {
1538  // From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
1539  uint32 v = val;
1540 
1541  v--;
1542  v |= v >> 1;
1543  v |= v >> 2;
1544  v |= v >> 4;
1545  v |= v >> 8;
1546  v |= v >> 16;
1547  v++;
1548 
1549  return v;
1550 }
1551 
1552 static constexpr inline uint32
1553 SYSwang_inthash(uint32 key)
1554 {
1555  // From http://www.concentric.net/~Ttwang/tech/inthash.htm
1556  key += ~(key << 16);
1557  key ^= (key >> 5);
1558  key += (key << 3);
1559  key ^= (key >> 13);
1560  key += ~(key << 9);
1561  key ^= (key >> 17);
1562  return key;
1563 }
1564 
1565 
1566 static constexpr inline uint32
1567 SYSmultiplicative_inthash(uint32 key)
1568 {
1569  // Multiply by the golden mean of 2^32 (Knuth's multiplicative method) to
1570  // get a uniformly distributed hash value. Do a google search for
1571  // 2654435761 for more information.
1572  return key * 2654435761u;
1573 }
1574 
1575 static constexpr inline uint64
1576 SYSmultiplicative_inthash64(uint64 key)
1577 {
1578  // Same as the 32-bit version above, but using the golden mean of 2^64.
1579  return key * 11400714819323198485llu;
1580 }
1581 
1582 static constexpr inline uint64
1583 SYSwang_inthash64(uint64 key)
1584 {
1585  // From http://www.concentric.net/~Ttwang/tech/inthash.htm
1586  key += ~(key << 32ULL);
1587  key ^= (key >> 22);
1588  key += ~(key << 13);
1589  key ^= (key >> 8);
1590  key += (key << 3);
1591  key ^= (key >> 15);
1592  key += ~(key << 27);
1593  key ^= (key >> 31);
1594  return key;
1595 }
1596 
1597 static constexpr inline uint32
1598 SYSsharpe_inthash(uint32 key)
1599 {
1600  // Based on https://github.com/skeeto/hash-prospector, but with
1601  // modifications such that:
1602  // - bias value of 0.1406800449
1603  // - minimum cycle of 17 (the original algorithm had f(0) == 0)
1604  // - improved dieharder results
1605  key ^= (key >> 16);
1606  key *= 0xdbfb352dU;
1607  key ^= ~(key >> 15);
1608  key *= 0x6c2ca68bU;
1609  key ^= (key >> 16);
1610  return key;
1611 }
1612 
1613 static constexpr inline uint32
1614 SYSwang2_inthash(uint32 key)
1615 {
1616  // From https://web.archive.org/web/20120626084524/http://www.concentric.net/~ttwang/tech/inthash.htm
1617  // Updated integer hashing (2007)
1618  constexpr uint c2=0x27d4eb2d; // a prime or an odd constant
1619  key = (key ^ 61) ^ (key >> 16);
1620  key = key + (key << 3);
1621  key = key ^ (key >> 4);
1622  key = key * c2;
1623  key = key ^ (key >> 15);
1624  return key;
1625 }
1626 
1627 static constexpr inline uint64
1628 SYSwang2_inthash(uint64 key)
1629 {
1630  // From https://web.archive.org/web/20120626084524/http://www.concentric.net/~ttwang/tech/inthash.htm
1631  // Updated integer hashing (2007)
1632  key = (~key) + (key << 21); // key = (key<<21) - key - 1;
1633  key = key ^ (key >> 24);
1634  key = (key + (key << 3)) + (key << 8); // key * 265
1635  key = key ^ (key >> 14);
1636  key = (key + (key << 2)) + (key << 4); // key * 21
1637  key = key ^ (key >> 28);
1638  key = key + (key << 31);
1639  return key;
1640 }
1641 
1642 static inline uint
1643 SYSreal_hash(fpreal16 a, int lowmask=0x3)
1644 {
1645  return SYSwang_inthash(a.bits() & (~lowmask));
1646 }
1647 
1648 static inline uint
1649 SYSreal_hashseed(fpreal16 a, uint seed, int lowmask=0x3)
1650 {
1651  return SYSwang_inthash(seed + (a.bits() & (~lowmask)));
1652 }
1653 
1654 static inline uint
1655 SYSreal_hash(fpreal32 a, int lowmask=0xf)
1656 {
1657  SYS_FPRealUnionF ai;
1658  ai.fval = a;
1659  return SYSwang_inthash(ai.uval & (~lowmask));
1660 }
1661 
1662 static inline uint
1663 SYSreal_hashseed(fpreal32 a, uint seed, int lowmask=0xf)
1664 {
1665  SYS_FPRealUnionF ai;
1666  ai.fval = a;
1667  return SYSwang_inthash(seed + (ai.uval & (~lowmask)));
1668 }
1669 
1670 static inline uint
1671 SYSreal_hash(fpreal64 a, int lowmask=0xf)
1672 {
1673  SYS_FPRealUnionD ai;
1674  ai.fval = a;
1675  return SYSwang_inthash64(ai.uval & (~lowmask));
1676 }
1677 
1678 static inline uint
1679 SYSreal_hashseed(fpreal64 a, uint seed, int64 lowmask=0xf)
1680 {
1681  SYS_FPRealUnionD ai;
1682  ai.fval = a;
1683  return SYSwang_inthash64(seed + (ai.uval & (~lowmask)));
1684 }
1685 
1686 static constexpr inline uint
1687 SYSvector_hash(const uint8 *vector, int size)
1688 {
1689  uint hash = 0;
1690  for (int i = 0; i < size; ++i)
1691  hash = SYSwang_inthash(hash + vector[i]);
1692  return hash;
1693 }
1694 
1695 static constexpr inline uint
1696 SYSvector_hash(const int8 *vector, int size)
1697 {
1698  uint hash = 0;
1699  for (int i = 0; i < size; ++i)
1700  hash = SYSwang_inthash(hash + vector[i]);
1701  return hash;
1702 }
1703 
1704 static constexpr inline uint
1705 SYSvector_hash(const int16 *vector, int size)
1706 {
1707  uint hash = 0;
1708  for (int i = 0; i < size; ++i)
1709  hash = SYSwang_inthash(hash + vector[i]);
1710  return hash;
1711 }
1712 
1713 static constexpr inline uint
1714 SYSvector_hash(const int32 *vector, int size)
1715 {
1716  uint hash = 0;
1717  for (int i = 0; i < size; ++i)
1718  hash = SYSwang_inthash(hash + vector[i]);
1719  return hash;
1720 }
1721 
1722 static constexpr inline uint
1723 SYSvector_hash(const int64 *vector, int size)
1724 {
1725  uint hash = 0;
1726  for (int i = 0; i < size; ++i)
1727  hash = (uint)SYSwang_inthash64(hash + vector[i]);
1728  return hash;
1729 }
1730 
1731 static inline uint
1732 SYSvector_hash(const fpreal16 *vector, int size)
1733 {
1734  uint hash = 0;
1735  for (int i = 0; i < size; ++i)
1736  hash = SYSreal_hashseed(vector[i], hash);
1737  return hash;
1738 }
1739 
1740 static inline uint
1741 SYSvector_hash(const fpreal32 *vector, int size)
1742 {
1743  uint hash = 0;
1744  for (int i = 0; i < size; ++i)
1745  hash = SYSreal_hashseed(vector[i], hash);
1746  return hash;
1747 }
1748 
1749 static inline uint
1750 SYSvector_hash(const fpreal64 *vector, int size)
1751 {
1752  uint hash = 0;
1753  for (int i = 0; i < size; ++i)
1754  hash = SYSreal_hashseed(vector[i], hash);
1755  return hash;
1756 }
1757 
1758 // Spatial hashing function for 3-vectors
1759 // Reference:
1760 // "Optimized Spatial Hashing for Collision Detection of Deformable Objects"
1761 //
1762 template<class P>
1763 static inline size_t
1764 SYSvector3_hash(const P &vector)
1765 {
1766  static constexpr size_t p1 = 73856093;
1767  static constexpr size_t p2 = 19349663;
1768  static constexpr size_t p3 = 83492791;
1769 
1770  return size_t(vector.x()*p1) ^ size_t(vector.y()*p2) ^ size_t(vector.z()*p3);
1771 }
1772 
1773 // Convert a uniform random bit pattern to a random float in the range [0, 1)
1774 inline static fpreal32
1775 SYShashToFloat01(uint hash)
1776 {
1777  SYS_FPRealUnionF tmp;
1778  tmp.uval = 0x3f800000 | (0x007fffff & hash);
1779  return tmp.fval-1.0F;
1780 }
1781 
1782 // Generate a random number in range [0, 1)
1783 static inline fpreal32
1784 SYSfastRandom(uint &seed)
1785 {
1786  seed = seed*1664525 + 1013904223;
1787  return SYShashToFloat01(seed);
1788 }
1789 
1790 inline static fpreal32
1791 SYSrandom(uint &seed)
1792 {
1793  seed = seed*1664525 + 1013904223;
1794  return SYShashToFloat01(SYSwang_inthash(seed));
1795 }
1796 
1797 static constexpr uint
1798 SYSfastRandomInt(uint &seed)
1799 {
1800  seed = seed*1664525 + 1013904223;
1801  return SYSwang_inthash(seed);
1802 }
1803 
1804 inline static fpreal32
1805 SYSfastRandomZero(uint &seed)
1806 {
1807  return SYSfastRandom(seed) - 0.5F;
1808 }
1809 
1810 inline static fpreal32
1811 SYSrandomZero(uint &seed)
1812 {
1813  return SYSrandom(seed) - 0.5F;
1814 }
1815 
1816 template <typename T>
1817 static constexpr inline void
1818 SYSminmax(T v0, T v1, T v2, T v3, T &min, T &max)
1819 {
1820  min = SYSmin(v0, v1, v2, v3);
1821  max = SYSmax(v0, v1, v2, v3);
1822 }
1823 
1824 template <typename T>
1825 static constexpr inline void
1826 SYSminmax(T v0, T v1, T v2, T &min, T &max)
1827 {
1828  min = SYSmin(v0, v1, v2);
1829  max = SYSmax(v0, v1, v2);
1830 }
1831 
1832 template <typename T>
1833 static constexpr inline void
1834 SYSminmax(T v0, T v1, T &min, T &max)
1835 {
1836  min = SYSmin(v0, v1);
1837  max = SYSmax(v0, v1);
1838 }
1839 
1840 SYS_API void SYSsincosDeg(fpreal64 degrees, fpreal64 *s, fpreal64 *c);
1841 SYS_API void SYSsincosDeg(fpreal32 degrees, fpreal32 *s, fpreal32 *c);
1842 
1843 inline static void
1844 SYSgetSinCosFromSlope(fpreal32 slope, fpreal32 &sintheta, fpreal32 &costheta)
1845 {
1846  fpreal32 one_over_m;
1847  sintheta = slope / SYSsqrt(slope*slope + (fpreal32)1);
1848  if ((slope = SYSabs(slope)) > (fpreal32)1)
1849  {
1850  one_over_m = (fpreal32)1 / slope;
1851  costheta = one_over_m / SYSsqrt(one_over_m*one_over_m + 1);
1852  }
1853  else
1854  costheta = SYSsqrt((fpreal32)1 - sintheta*sintheta);
1855 }
1856 
1857 inline static void
1858 SYSgetSinCosFromSlope(fpreal64 slope, fpreal64 &sintheta, fpreal64 &costheta)
1859 {
1860  fpreal64 one_over_m;
1861  sintheta = slope / SYSsqrt(slope*slope + (fpreal64)1);
1862  if ((slope = SYSabs(slope)) > (fpreal64)1)
1863  {
1864  one_over_m = (fpreal64)1 / slope;
1865  costheta = one_over_m / SYSsqrt(one_over_m*one_over_m + 1);
1866  }
1867  else
1868  costheta = SYSsqrt((fpreal64)1 - sintheta*sintheta);
1869 }
1870 
1871 inline constexpr static bool
1872 SYSsameSign( fpreal32 v0, fpreal32 v1 )
1873 {
1874  return (v0*v1)>0;
1875 }
1876 
1877 inline constexpr static bool
1878 SYSsameSign( fpreal64 v0, fpreal64 v1 )
1879 {
1880  return (v0*v1)>0;
1881 }
1882 
1883 inline constexpr static bool
1884 SYSsameSign( int32 v0, int32 v1 )
1885 {
1886  return (v0 ^ v1) >= 0;
1887 }
1888 
1889 inline constexpr static bool
1890 SYSsameSign( int64 v0, int64 v1 )
1891 {
1892  return (v0 ^ v1) >= 0;
1893 }
1894 
1895 static inline uint
1896 SYSnextPrime(uint num)
1897 {
1898  return SYSmakePrime(num+1);
1899 }
1900 
1901 static constexpr inline int
1902 SYShexCharToInt(char c)
1903 {
1904  // Given a hexidecimal character, return it's corresponding value between
1905  // 0 and 15, or -1 if it's not a hexidecimal character.
1906  if (c >= '0' && c <= '9')
1907  return c - '0';
1908  if (c >= 'a' && c <= 'f')
1909  return c - 'a' + 10;
1910  if (c >= 'A' && c <= 'F')
1911  return c - 'A' + 10;
1912  return -1;
1913 }
1914 
1915 static constexpr inline char
1916 SYSintToHexChar(int value)
1917 {
1918  // The value must be from 0-15 for this function to return a valid result.
1919  return value < 10 ? '0' + value : 'a' + value - 10;
1920 }
1921 
1922 SYS_API void SYSsort(int &a, int &b);
1923 SYS_API void SYSsort(int &a, int &b, int &c);
1924 SYS_API void SYSsort(int64 &a, int64 &b);
1925 SYS_API void SYSsort(int64 &a, int64 &b, int64 &c);
1926 SYS_API void SYSsort(float &a, float &b);
1927 SYS_API void SYSsort(float &a, float &b, float &c);
1928 SYS_API void SYSsort(double &a, double &b);
1929 SYS_API void SYSsort(double &a, double &b, double &c);
1930 
1931 // Compute both integer division and integer modulus
1932 // They are compiled into a single instruction
1933 static constexpr inline void
1934 SYSdivMod(int numerator, int denominator, int &quotient, int &remainder)
1935 {
1936  quotient = numerator / denominator;
1937  remainder = numerator % denominator;
1938 }
1939 
1940 static constexpr inline void
1941 SYSdivMod(int64 numerator, int64 denominator, int64 &quotient, int64 &remainder)
1942 {
1943  quotient = numerator / denominator;
1944  remainder = numerator % denominator;
1945 }
1946 
1947 // Include permutations of fpreal32/fpreal64
1948 #include "SYS_MathPermute.h"
1949 #include "SYS_MathRestrictive.h"
1950 
1951 #else /* cplusplus */
1952 #define SYSmax(a,b) ((a) > (b) ? (a) : (b))
1953 #define SYSmin(a,b) ((a) < (b) ? (a) : (b))
1954 #define SYSabs(a) ((a) < 0 ? (a) : -(a))
1955 #endif
1956 
1957 #endif
bool SYSisNormal(fpreal64 f)
Definition: SYS_Math.h:277
#define SYSmax(a, b)
Definition: SYS_Math.h:1952
bool SYSisEqual(const UT_Vector2T< T > &a, const UT_Vector2T< T > &b, S tol)
Componentwise equality.
Definition: UT_Vector2.h:677
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
unsigned short uint16
Definition: SYS_Types.h:38
UT_Vector3T< T > SYSrecip(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1085
int int32
Definition: SYS_Types.h:39
SYS_API fpreal32 SYSceil(const fpreal32 val)
const GLdouble * v
Definition: glcorearb.h:837
#define M_PI
Definition: fmath.h:98
SYS_API void SYSsrand48(long seed)
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool SYSisFinite(fpreal64 f)
Definition: SYS_Math.h:259
bool SYSisInf(fpreal64 f)
Definition: SYS_Math.h:268
#define CONST_INT64(x)
Definition: SYS_Types.h:326
bool SYSisInteger(const UT_Vector2T< T > &v1)
Componentwise integer test.
Definition: UT_Vector2.h:96
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7694
OIIO_HOSTDEVICE void sincos(float x, float *sine, float *cosine)
Definition: fmath.h:711
constexpr bool SYSisNan(const F f)
Definition: SYS_Math.h:242
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
#define SYSabs(a)
Definition: SYS_Math.h:1954
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
UT_Matrix2T< T > SYSbilerp(const UT_Matrix2T< T > &u0v0, const UT_Matrix2T< T > &u1v0, const UT_Matrix2T< T > &u0v1, const UT_Matrix2T< T > &u1v1, S u, S v)
Bilinear interpolation.
Definition: UT_Matrix2.h:72
GLint y
Definition: glcorearb.h:103
#define SYS_FTOLERANCE_D
Definition: SYS_Types.h:209
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:818
UT_Matrix2T< T > SYSlerp(const UT_Matrix2T< T > &v1, const UT_Matrix2T< T > &v2, S t)
Definition: UT_Matrix2.h:675
unsigned long long uint64
Definition: SYS_Types.h:117
GLfloat GLfloat GLfloat GLfloat v3
Definition: glcorearb.h:819
UT_Matrix2T< T > SYSbarycentric(const UT_Matrix2T< T > &v0, const UT_Matrix2T< T > &v1, const UT_Matrix2T< T > &v2, S u, S v)
Barycentric interpolation.
Definition: UT_Matrix2.h:79
float fpreal32
Definition: SYS_Types.h:200
double fpreal64
Definition: SYS_Types.h:201
ImageBuf OIIO_API pow(const ImageBuf &A, cspan< float > B, ROI roi={}, int nthreads=0)
unsigned char uint8
Definition: SYS_Types.h:36
GLfloat f
Definition: glcorearb.h:1926
IMATH_HOSTDEVICE constexpr int trunc(T x) IMATH_NOEXCEPT
Definition: ImathFun.h:126
SYS_API fpreal32 SYSroundAngle(fpreal32 base, fpreal32 source)
UT_Vector3T< T > SYSclamp(const UT_Vector3T< T > &v, const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
Definition: UT_Vector3.h:1059
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
SYS_API bool SYSisPrime(uint num)
SYS_API fpreal32 SYSfloor(const fpreal32 val)
constexpr int SYSsignum(const F a) noexcept
Definition: SYS_Math.h:234
bool isFinite() const
Definition: fpreal16.h:671
long long int64
Definition: SYS_Types.h:116
SYS_API double SYSdrand48()
UT_Vector2T< T > SYSinvlerp(const UT_Vector2T< T > &a, const UT_Vector2T< T > &v1, const UT_Vector2T< T > &v2)
Componentwise inverse linear interpolation.
Definition: UT_Vector2.h:693
signed char int8
Definition: SYS_Types.h:35
SYS_API bool SYSisInt(const char *str)
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLint GLenum GLint x
Definition: glcorearb.h:409
bool isInfinity() const
Definition: fpreal16.h:712
GLdouble t
Definition: glad.h:2397
GLfloat v0
Definition: glcorearb.h:816
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1071
SYS_API uint SYSmakePrime(uint num)
GLsizeiptr size
Definition: glcorearb.h:664
short int16
Definition: SYS_Types.h:37
fpreal64 fpreal
Definition: SYS_Types.h:283
GLfloat GLfloat v1
Definition: glcorearb.h:817
GLuint GLfloat * val
Definition: glcorearb.h:1608
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
double cbrt(double x)
bool isNan() const
Definition: fpreal16.h:703
unsigned int uint32
Definition: SYS_Types.h:40
fpreal32 SYSrint(const fpreal32 val)
Definition: SYS_Floor.h:164
#define SYS_FTOLERANCE
Definition: SYS_Types.h:208
#define SYS_API
Definition: SYS_API.h:11
#define CONST_UINT64(x)
Definition: SYS_Types.h:327
GLboolean r
Definition: glcorearb.h:1222
unsigned short bits() const
Definition: fpreal16.h:764
OIIO_FORCEINLINE T log(const T &v)
Definition: simd.h:7905
vfloat4 rsqrt(const vfloat4 &a)
Fully accurate 1/sqrt.
Definition: simd.h:7706
#define SYSmin(a, b)
Definition: SYS_Math.h:1953
SYS_API bool SYSisFloat(const char *str)
unsigned int uint
Definition: SYS_Types.h:45
bool isNormalized() const
Definition: fpreal16.h:679
OIIO_FORCEINLINE OIIO_HOSTDEVICE T degrees(T rad)
Convert radians to degrees.
Definition: fmath.h:681