xref: /aosp_15_r20/external/deqp/framework/delibs/debase/deMath.h (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _DEMATH_H
2 #define _DEMATH_H
3 /*-------------------------------------------------------------------------
4  * drawElements Base Portability Library
5  * -------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Basic mathematical operations.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "deDefs.h"
27 #include "deMemory.h"
28 
29 #include <math.h>
30 #include <float.h>
31 
32 DE_BEGIN_EXTERN_C
33 
34 /* Mathematical constants. */
35 
36 #define DE_PI 3.14159265358979324f            /*!< Pi.                    */
37 #define DE_LOG_2 0.69314718056f               /*!< log_e(2.0)                */
38 #define DE_INV_LOG_2 1.44269504089f           /*!< 1.0 / log_e(2.0)        */
39 #define DE_E 2.71828182845904523536f          /*!< e.                        */
40 #define DE_LOG2_E 1.44269504088896340736f     /*!< log_2(e).                */
41 #define DE_INV_LOG2_E 0.69314718055994530942f /*!< 1.0 / log_2(e).        */
42 
43 #define DE_PI_DOUBLE 3.14159265358979323846 /*!< Pi as a double.        */
44 #define DE_PI_16BIT 0x4248                  /*!< Pi. as a float16b        */
45 
46 /* Rounding mode control. */
47 
48 typedef enum deRoundingMode_e
49 {
50     DE_ROUNDINGMODE_TO_NEAREST_EVEN = 0,
51     DE_ROUNDINGMODE_TO_ZERO,
52     DE_ROUNDINGMODE_TO_POSITIVE_INF,
53     DE_ROUNDINGMODE_TO_NEGATIVE_INF,
54 
55     DE_ROUNDINGMODE_LAST
56 } deRoundingMode;
57 
58 deRoundingMode deGetRoundingMode(void);
59 bool deSetRoundingMode(deRoundingMode mode);
60 
61 void deMath_selfTest(void);
62 
63 /* Float properties */
64 
65 /* \note The NaN test probably won't work with -ffast-math */
66 
deFloatIsInf(float x)67 DE_INLINE int deFloatIsInf(float x)
68 {
69     return (x > FLT_MAX) - (x < -FLT_MAX);
70 }
deFloatIsNaN(float x)71 DE_INLINE bool deFloatIsNaN(float x)
72 {
73     return (x != x);
74 }
75 
deIsInf(double x)76 DE_INLINE int deIsInf(double x)
77 {
78     return (x > DBL_MAX) - (x < -DBL_MAX);
79 }
deIsNaN(double x)80 DE_INLINE bool deIsNaN(double x)
81 {
82     return (x != x);
83 }
84 
deFloatBitsToUint32(float x)85 DE_INLINE uint32_t deFloatBitsToUint32(float x)
86 {
87     uint32_t bits;
88     deMemcpy((void *)&bits, (void *)&x, 4);
89     return bits;
90 }
91 
deDoubleBitsToUint64(double x)92 DE_INLINE uint64_t deDoubleBitsToUint64(double x)
93 {
94     uint64_t bits;
95     deMemcpy((void *)&bits, (void *)&x, 8);
96     return bits;
97 }
98 
deFloatIsPositiveZero(float x)99 DE_INLINE bool deFloatIsPositiveZero(float x)
100 {
101     return x == 0 && (deFloatBitsToUint32(x) >> 31) == 0;
102 }
103 
deDoubleIsPositiveZero(double x)104 DE_INLINE bool deDoubleIsPositiveZero(double x)
105 {
106     return x == 0 && (deDoubleBitsToUint64(x) >> 63) == 0;
107 }
108 
deFloatIsNegativeZero(float x)109 DE_INLINE bool deFloatIsNegativeZero(float x)
110 {
111     return x == 0 && (deFloatBitsToUint32(x) >> 31) != 0;
112 }
113 
deDoubleIsNegativeZero(double x)114 DE_INLINE bool deDoubleIsNegativeZero(double x)
115 {
116     return x == 0 && (deDoubleBitsToUint64(x) >> 63) != 0;
117 }
118 
deFloatIsIEEENaN(float x)119 DE_INLINE bool deFloatIsIEEENaN(float x)
120 {
121     uint32_t e = (deFloatBitsToUint32(x) & 0x7f800000u) >> 23;
122     uint32_t m = (deFloatBitsToUint32(x) & 0x007fffffu);
123     return e == 0xff && m != 0;
124 }
125 
deDoubleIsIEEENaN(double x)126 DE_INLINE bool deDoubleIsIEEENaN(double x)
127 {
128     uint64_t e = (deDoubleBitsToUint64(x) & 0x7ff0000000000000ull) >> 52;
129     uint64_t m = (deDoubleBitsToUint64(x) & 0x000fffffffffffffull);
130     return e == 0x7ff && m != 0;
131 }
132 
133 /* \note The definition used for signaling NaN here is valid for ARM and
134  * x86 but possibly not for other platforms.
135  *
136  * These are defined as overloads so that they can be used in templated
137  * code without risking a type conversion which would triggern an exception
138  * on a signaling NaN.  We don't use deIsNan in these helpers because they
139  * do a comparison operation which may also trigger exceptions.
140  */
deFloatIsSignalingNaN(float x)141 DE_INLINE bool deFloatIsSignalingNaN(float x)
142 {
143     return deFloatIsIEEENaN(x) && (deFloatBitsToUint32(x) & (1u << 22)) == 0;
144 }
145 
deDoubleIsSignalingNaN(double x)146 DE_INLINE bool deDoubleIsSignalingNaN(double x)
147 {
148     return deDoubleIsIEEENaN(x) && (deDoubleBitsToUint64(x) & (1ull << 51)) == 0;
149 }
150 
deFloatIsQuietNaN(float x)151 DE_INLINE bool deFloatIsQuietNaN(float x)
152 {
153     return deFloatIsIEEENaN(x) && (deFloatBitsToUint32(x) & (1u << 22)) != 0;
154 }
155 
deDoubleIsQuietNaN(double x)156 DE_INLINE bool deDoubleIsQuietNaN(double x)
157 {
158     return deDoubleIsIEEENaN(x) && (deDoubleBitsToUint64(x) & (1ull << 51)) != 0;
159 }
160 
161 /* Basic utilities. */
162 
deFloatAbs(float x)163 DE_INLINE float deFloatAbs(float x)
164 {
165     return (x >= 0.0f) ? x : -x;
166 }
deFloatMin(float a,float b)167 DE_INLINE float deFloatMin(float a, float b)
168 {
169     return (a <= b) ? a : b;
170 }
deFloatMax(float a,float b)171 DE_INLINE float deFloatMax(float a, float b)
172 {
173     return (a >= b) ? a : b;
174 }
deFloatClamp(float x,float mn,float mx)175 DE_INLINE float deFloatClamp(float x, float mn, float mx)
176 {
177     return (x <= mn) ? mn : ((x >= mx) ? mx : x);
178 }
179 
deAbs(double x)180 DE_INLINE double deAbs(double x)
181 {
182     return (x >= 0.0) ? x : -x;
183 }
deMin(double a,double b)184 DE_INLINE double deMin(double a, double b)
185 {
186     return (a <= b) ? a : b;
187 }
deMax(double a,double b)188 DE_INLINE double deMax(double a, double b)
189 {
190     return (a >= b) ? a : b;
191 }
deClamp(double x,double mn,double mx)192 DE_INLINE double deClamp(double x, double mn, double mx)
193 {
194     return (x <= mn) ? mn : ((x >= mx) ? mx : x);
195 }
196 
197 /* Utility functions. */
198 
deFloatSign(float a)199 DE_INLINE float deFloatSign(float a)
200 {
201     return (a == 0.0f) ? 0.0f : ((a > 0.0f) ? +1.0f : -1.0f);
202 }
deFloatIntSign(float a)203 DE_INLINE int deFloatIntSign(float a)
204 {
205     return (a == 0.0f) ? 0 : ((a > 0.0f) ? +1 : -1);
206 }
deFloatFloor(float a)207 DE_INLINE float deFloatFloor(float a)
208 {
209     return (float)floor(a);
210 }
deFloatCeil(float a)211 DE_INLINE float deFloatCeil(float a)
212 {
213     return (float)ceil(a);
214 }
deFloatRound(float a)215 DE_INLINE float deFloatRound(float a)
216 {
217     return deFloatFloor(a + 0.5f);
218 }
deFloatFrac(float a)219 DE_INLINE float deFloatFrac(float a)
220 {
221     return a - deFloatFloor(a);
222 }
deFloatMod(float a,float b)223 DE_INLINE float deFloatMod(float a, float b)
224 {
225     return (float)fmod(a, b);
226 }
deFloatModf(float x,float * i)227 DE_INLINE float deFloatModf(float x, float *i)
228 {
229     double j   = 0;
230     double ret = modf(x, &j);
231     *i         = (float)j;
232     return (float)ret;
233 }
deFloatMadd(float a,float b,float c)234 DE_INLINE float deFloatMadd(float a, float b, float c)
235 {
236     return (a * b) + c;
237 }
deFloatTrunc(float a)238 DE_INLINE float deFloatTrunc(float a)
239 {
240     return deFloatSign(a) * deFloatFloor(deFloatAbs(a));
241 }
deFloatLdExp(float a,int exponent)242 DE_INLINE float deFloatLdExp(float a, int exponent)
243 {
244     return (float)ldexp(a, exponent);
245 }
deFloatFrExp(float x,int * exponent)246 DE_INLINE float deFloatFrExp(float x, int *exponent)
247 {
248     return (float)frexp(x, exponent);
249 }
250 float deFloatFractExp(float x, int *exponent);
251 
deSign(double x)252 DE_INLINE double deSign(double x)
253 {
254     return deDoubleIsIEEENaN(x) ? x : (double)((x > 0.0) - (x < 0.0));
255 }
deIntSign(double x)256 DE_INLINE int deIntSign(double x)
257 {
258     return (x > 0.0) - (x < 0.0);
259 }
deFloor(double a)260 DE_INLINE double deFloor(double a)
261 {
262     return floor(a);
263 }
deCeil(double a)264 DE_INLINE double deCeil(double a)
265 {
266     return ceil(a);
267 }
deRound(double a)268 DE_INLINE double deRound(double a)
269 {
270     return floor(a + 0.5);
271 }
deFrac(double a)272 DE_INLINE double deFrac(double a)
273 {
274     return a - deFloor(a);
275 }
deMod(double a,double b)276 DE_INLINE double deMod(double a, double b)
277 {
278     return fmod(a, b);
279 }
deModf(double x,double * i)280 DE_INLINE double deModf(double x, double *i)
281 {
282     return modf(x, i);
283 }
deMadd(double a,double b,double c)284 DE_INLINE double deMadd(double a, double b, double c)
285 {
286     return (a * b) + c;
287 }
deTrunc(double a)288 DE_INLINE double deTrunc(double a)
289 {
290     return deSign(a) * floor(fabs(a));
291 }
deLdExp(double a,int exponent)292 DE_INLINE double deLdExp(double a, int exponent)
293 {
294     return ldexp(a, exponent);
295 }
296 double deRoundEven(double a);
deFrExp(double x,int * exponent)297 DE_INLINE double deFrExp(double x, int *exponent)
298 {
299     return frexp(x, exponent);
300 }
301 /* Like frexp, except the returned fraction is in range [1.0, 2.0) */
302 double deFractExp(double x, int *exponent);
303 
304 /* Exponential functions. */
305 
deFloatPow(float a,float b)306 DE_INLINE float deFloatPow(float a, float b)
307 {
308     return (float)pow(a, b);
309 }
deFloatExp(float a)310 DE_INLINE float deFloatExp(float a)
311 {
312     return (float)exp(a);
313 }
deFloatLog(float a)314 DE_INLINE float deFloatLog(float a)
315 {
316     return (float)log(a);
317 }
deFloatExp2(float a)318 DE_INLINE float deFloatExp2(float a)
319 {
320     return (float)exp(a * DE_LOG_2);
321 }
deFloatLog2(float a)322 DE_INLINE float deFloatLog2(float a)
323 {
324     return (float)log(a) * DE_INV_LOG_2;
325 }
deFloatSqrt(float a)326 DE_INLINE float deFloatSqrt(float a)
327 {
328     return (float)sqrt(a);
329 }
deFloatRcp(float a)330 DE_INLINE float deFloatRcp(float a)
331 {
332     return (1.0f / a);
333 }
deFloatRsq(float a)334 DE_INLINE float deFloatRsq(float a)
335 {
336     float s = (float)sqrt(a);
337     return (s == 0.0f) ? 0.0f : (1.0f / s);
338 }
339 
dePow(double a,double b)340 DE_INLINE double dePow(double a, double b)
341 {
342     return pow(a, b);
343 }
deExp(double a)344 DE_INLINE double deExp(double a)
345 {
346     return exp(a);
347 }
deLog(double a)348 DE_INLINE double deLog(double a)
349 {
350     return log(a);
351 }
deExp2(double a)352 DE_INLINE double deExp2(double a)
353 {
354     return exp(a * log(2.0));
355 }
deLog2(double a)356 DE_INLINE double deLog2(double a)
357 {
358     return log(a) / log(2.0);
359 }
deSqrt(double a)360 DE_INLINE double deSqrt(double a)
361 {
362     return sqrt(a);
363 }
deCbrt(double a)364 DE_INLINE double deCbrt(double a)
365 {
366     return deSign(a) * dePow(deAbs(a), 1.0 / 3.0);
367 }
368 
369 /* Geometric functions. */
370 
deFloatRadians(float a)371 DE_INLINE float deFloatRadians(float a)
372 {
373     return a * (DE_PI / 180.0f);
374 }
deFloatDegrees(float a)375 DE_INLINE float deFloatDegrees(float a)
376 {
377     return a * (180.0f / DE_PI);
378 }
deFloatSin(float a)379 DE_INLINE float deFloatSin(float a)
380 {
381     return (float)sin(a);
382 }
deFloatCos(float a)383 DE_INLINE float deFloatCos(float a)
384 {
385     return (float)cos(a);
386 }
deFloatTan(float a)387 DE_INLINE float deFloatTan(float a)
388 {
389     return (float)tan(a);
390 }
deFloatAsin(float a)391 DE_INLINE float deFloatAsin(float a)
392 {
393     return (float)asin(a);
394 }
deFloatAcos(float a)395 DE_INLINE float deFloatAcos(float a)
396 {
397     return (float)acos(a);
398 }
deFloatAtan2(float y,float x)399 DE_INLINE float deFloatAtan2(float y, float x)
400 {
401     return (float)atan2(y, x);
402 }
deFloatAtanOver(float yOverX)403 DE_INLINE float deFloatAtanOver(float yOverX)
404 {
405     return (float)atan(yOverX);
406 }
deFloatSinh(float a)407 DE_INLINE float deFloatSinh(float a)
408 {
409     return (float)sinh(a);
410 }
deFloatCosh(float a)411 DE_INLINE float deFloatCosh(float a)
412 {
413     return (float)cosh(a);
414 }
deFloatTanh(float a)415 DE_INLINE float deFloatTanh(float a)
416 {
417     return (float)tanh(a);
418 }
deFloatAsinh(float a)419 DE_INLINE float deFloatAsinh(float a)
420 {
421     return deFloatLog(a + deFloatSqrt(a * a + 1));
422 }
deFloatAcosh(float a)423 DE_INLINE float deFloatAcosh(float a)
424 {
425     return deFloatLog(a + deFloatSqrt(a * a - 1));
426 }
deFloatAtanh(float a)427 DE_INLINE float deFloatAtanh(float a)
428 {
429     return 0.5f * deFloatLog((1.0f + a) / (1.0f - a));
430 }
431 
deSin(double a)432 DE_INLINE double deSin(double a)
433 {
434     return sin(a);
435 }
deCos(double a)436 DE_INLINE double deCos(double a)
437 {
438     return cos(a);
439 }
deTan(double a)440 DE_INLINE double deTan(double a)
441 {
442     return tan(a);
443 }
deAsin(double a)444 DE_INLINE double deAsin(double a)
445 {
446     return asin(a);
447 }
deAcos(double a)448 DE_INLINE double deAcos(double a)
449 {
450     return acos(a);
451 }
deAtan2(double y,double x)452 DE_INLINE double deAtan2(double y, double x)
453 {
454     return atan2(y, x);
455 }
deAtanOver(double yOverX)456 DE_INLINE double deAtanOver(double yOverX)
457 {
458     return atan(yOverX);
459 }
deSinh(double a)460 DE_INLINE double deSinh(double a)
461 {
462     return sinh(a);
463 }
deCosh(double a)464 DE_INLINE double deCosh(double a)
465 {
466     return cosh(a);
467 }
deTanh(double a)468 DE_INLINE double deTanh(double a)
469 {
470     return tanh(a);
471 }
deAsinh(double a)472 DE_INLINE double deAsinh(double a)
473 {
474     return deLog(a + deSqrt(a * a + 1));
475 }
deAcosh(double a)476 DE_INLINE double deAcosh(double a)
477 {
478     return deLog(a + deSqrt(a * a - 1));
479 }
deAtanh(double a)480 DE_INLINE double deAtanh(double a)
481 {
482     return 0.5 * deLog((1.0 + a) / (1.0 - a));
483 }
484 
485 /* Interpolation. */
486 
deFloatMix(float a,float b,float t)487 DE_INLINE float deFloatMix(float a, float b, float t)
488 {
489     return a * (1.0f - t) + b * t;
490 }
deFloatStep(float limit,float val)491 DE_INLINE float deFloatStep(float limit, float val)
492 {
493     return (val < limit) ? 0.0f : 1.0f;
494 }
deFloatSmoothStep(float e0,float e1,float v)495 DE_INLINE float deFloatSmoothStep(float e0, float e1, float v)
496 {
497     float t;
498     if (v <= e0)
499         return 0.0f;
500     if (v >= e1)
501         return 1.0f;
502     t = (v - e0) / (e1 - e0);
503     return t * t * (3.0f - 2.0f * t);
504 }
505 
deMix(double a,double b,double t)506 DE_INLINE double deMix(double a, double b, double t)
507 {
508     return a * (1.0 - t) + b * t;
509 }
deStep(double limit,double val)510 DE_INLINE double deStep(double limit, double val)
511 {
512     return (val < limit) ? 0.0 : 1.0;
513 }
514 
515 /* Convert int to float. If the value cannot be represented exactly in native single precision format, return
516  * either the nearest lower or the nearest higher representable value, chosen in an implementation-defined manner.
517  *
518  * \note Choosing either nearest lower or nearest higher means that implementation could for example consistently
519  *       choose the lower value, i.e. this function does not round towards nearest.
520  * \note Value returned is in native single precision format. For example with x86 extended precision, the value
521  *       returned might not be representable in IEEE single precision float.
522  */
deInt32ToFloat(int32_t x)523 DE_INLINE float deInt32ToFloat(int32_t x)
524 {
525     return (float)x;
526 }
527 
528 /* Convert to float. If the value cannot be represented exactly in IEEE single precision floating point format,
529  * return the nearest lower (round towards negative inf). */
530 float deInt32ToFloatRoundToNegInf(int32_t x);
531 
532 /* Convert to float. If the value cannot be represented exactly IEEE single precision floating point format,
533  * return the nearest higher (round towards positive inf). */
534 float deInt32ToFloatRoundToPosInf(int32_t x);
535 
536 /* Conversion to integer. */
537 
deChopFloatToInt32(float x)538 DE_INLINE int32_t deChopFloatToInt32(float x)
539 {
540     return (int32_t)x;
541 }
deFloorFloatToInt32(float x)542 DE_INLINE int32_t deFloorFloatToInt32(float x)
543 {
544     return (int32_t)(deFloatFloor(x));
545 }
deCeilFloatToInt32(float x)546 DE_INLINE int32_t deCeilFloatToInt32(float x)
547 {
548     return (int32_t)(deFloatCeil(x));
549 }
550 
deChopToInt32(double x)551 DE_INLINE int32_t deChopToInt32(double x)
552 {
553     return (int32_t)x;
554 }
deFloorToInt32(double x)555 DE_INLINE int32_t deFloorToInt32(double x)
556 {
557     return (int32_t)(deFloor(x));
558 }
deCeilToInt32(double x)559 DE_INLINE int32_t deCeilToInt32(double x)
560 {
561     return (int32_t)(deCeil(x));
562 }
563 
564 /* Arithmetic round */
deRoundFloatToInt16(float x)565 DE_INLINE int16_t deRoundFloatToInt16(float x)
566 {
567     if (x >= 0.0f)
568         return (int16_t)(x + 0.5f);
569     else
570         return (int16_t)(x - 0.5f);
571 }
deRoundFloatToInt32(float x)572 DE_INLINE int32_t deRoundFloatToInt32(float x)
573 {
574     if (x >= 0.0f)
575         return (int32_t)(x + 0.5f);
576     else
577         return (int32_t)(x - 0.5f);
578 }
deRoundFloatToInt64(float x)579 DE_INLINE int64_t deRoundFloatToInt64(float x)
580 {
581     if (x >= 0.0f)
582         return (int64_t)(x + 0.5f);
583     else
584         return (int64_t)(x - 0.5f);
585 }
586 
deRoundToInt16(double x)587 DE_INLINE int16_t deRoundToInt16(double x)
588 {
589     if (x >= 0.0)
590         return (int16_t)(x + 0.5);
591     else
592         return (int16_t)(x - 0.5);
593 }
deRoundToInt32(double x)594 DE_INLINE int32_t deRoundToInt32(double x)
595 {
596     if (x >= 0.0)
597         return (int32_t)(x + 0.5);
598     else
599         return (int32_t)(x - 0.5);
600 }
deRoundToInt64(double x)601 DE_INLINE int64_t deRoundToInt64(double x)
602 {
603     if (x >= 0.0)
604         return (int64_t)(x + 0.5);
605     else
606         return (int64_t)(x - 0.5);
607 }
608 
609 DE_END_EXTERN_C
610 
611 #endif /* _DEMATH_H */
612