Merge pull request #276 from Ella-0/master
[platform/upstream/VK-GL-CTS.git] / framework / delibs / debase / deMath.h
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 deBool                          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
67 DE_INLINE int           deFloatIsInf            (float x)               { return (x > FLT_MAX) - (x < -FLT_MAX); }
68 DE_INLINE deBool        deFloatIsNaN            (float x)               { return (x != x); }
69
70 DE_INLINE int           deIsInf                         (double x)              { return (x > DBL_MAX) - (x < -DBL_MAX); }
71 DE_INLINE deBool        deIsNaN                         (double x)              { return (x != x); }
72
73 DE_INLINE deUint32 deFloatBitsToUint32(float x)
74 {
75         deUint32 bits;
76         deMemcpy((void *)&bits, (void *)&x, 4);
77         return bits;
78 }
79
80 DE_INLINE deUint64 deDoubleBitsToUint64(double x)
81 {
82         deUint64 bits;
83         deMemcpy((void *)&bits, (void *)&x, 8);
84         return bits;
85 }
86
87 DE_INLINE deBool deFloatIsPositiveZero(float x)
88 {
89         return x == 0 && (deFloatBitsToUint32(x) >> 31) == 0;
90 }
91
92 DE_INLINE deBool deDoubleIsPositiveZero(double x)
93 {
94         return x == 0 && (deDoubleBitsToUint64(x) >> 63) == 0;
95 }
96
97 DE_INLINE deBool deFloatIsNegativeZero(float x)
98 {
99         return x == 0 && (deFloatBitsToUint32(x) >> 31) != 0;
100 }
101
102 DE_INLINE deBool deDoubleIsNegativeZero(double x)
103 {
104         return x == 0 && (deDoubleBitsToUint64(x) >> 63) != 0;
105 }
106
107 DE_INLINE deBool deFloatIsIEEENaN(float x)
108 {
109         deUint32 e = (deFloatBitsToUint32(x) & 0x7f800000u) >> 23;
110         deUint32 m = (deFloatBitsToUint32(x) & 0x007fffffu);
111         return e == 0xff && m != 0;
112 }
113
114 DE_INLINE deBool deDoubleIsIEEENaN(double x)
115 {
116         deUint64 e = (deDoubleBitsToUint64(x) & 0x7ff0000000000000ull) >> 52;
117         deUint64 m = (deDoubleBitsToUint64(x) & 0x000fffffffffffffull);
118         return e == 0x7ff && m != 0;
119 }
120
121 /* \note The definition used for signaling NaN here is valid for ARM and
122  * x86 but possibly not for other platforms.
123  *
124  * These are defined as overloads so that they can be used in templated
125  * code without risking a type conversion which would triggern an exception
126  * on a signaling NaN.  We don't use deIsNan in these helpers because they
127  * do a comparison operation which may also trigger exceptions.
128  */
129 DE_INLINE deBool deFloatIsSignalingNaN(float x)
130 {
131         return deFloatIsIEEENaN(x) && (deFloatBitsToUint32(x) & (1u << 22)) == 0;
132 }
133
134 DE_INLINE deBool deDoubleIsSignalingNaN(double x)
135 {
136         return deDoubleIsIEEENaN(x) && (deDoubleBitsToUint64(x) & (1ull << 51)) == 0;
137 }
138
139 DE_INLINE deBool deFloatIsQuietNaN(float x)
140 {
141         return deFloatIsIEEENaN(x) && (deFloatBitsToUint32(x) & (1u << 22)) != 0;
142 }
143
144 DE_INLINE deBool deDoubleIsQuietNaN(double x)
145 {
146         return deDoubleIsIEEENaN(x) && (deDoubleBitsToUint64(x) & (1ull << 51)) != 0;
147 }
148
149 /* Basic utilities. */
150
151 DE_INLINE float         deFloatAbs                      (float x)                                               { return (x >= 0.0f) ? x : -x; }
152 DE_INLINE float         deFloatMin                      (float a, float b)                              { return (a <= b) ? a : b; }
153 DE_INLINE float         deFloatMax                      (float a, float b)                              { return (a >= b) ? a : b; }
154 DE_INLINE float         deFloatClamp            (float x, float mn, float mx)   { return (x <= mn) ? mn : ((x >= mx) ? mx : x); }
155
156 DE_INLINE double        deAbs                           (double x)                                                      { return (x >= 0.0) ? x : -x; }
157 DE_INLINE double        deMin                           (double a, double b)                            { return (a <= b) ? a : b; }
158 DE_INLINE double        deMax                           (double a, double b)                            { return (a >= b) ? a : b; }
159 DE_INLINE double        deClamp                         (double x, double mn, double mx)        { return (x <= mn) ? mn : ((x >= mx) ? mx : x); }
160
161 /* Utility functions. */
162
163 DE_INLINE float         deFloatSign                     (float a)                                       { return (a == 0.0f) ? 0.0f : ((a > 0.0f) ? +1.0f : -1.0f); }
164 DE_INLINE int           deFloatIntSign          (float a)                                       { return (a == 0.0f) ? 0 : ((a > 0.0f) ? +1 : -1); }
165 DE_INLINE float         deFloatFloor            (float a)                                       { return (float)floor(a); }
166 DE_INLINE float         deFloatCeil                     (float a)                                       { return (float)ceil(a); }
167 DE_INLINE float         deFloatRound            (float a)                                       { return deFloatFloor(a + 0.5f); }
168 DE_INLINE float         deFloatFrac                     (float a)                                       { return a - deFloatFloor(a); }
169 DE_INLINE float         deFloatMod                      (float a, float b)                      { return (float)fmod(a, b); }
170 DE_INLINE float         deFloatModf                     (float x, float* i)                     { double j = 0; double ret = modf(x, &j); *i = (float)j; return (float)ret; }
171 DE_INLINE float         deFloatMadd                     (float a, float b, float c)     { return (a*b) + c; }
172 DE_INLINE float         deFloatTrunc            (float a)                                       { return deFloatSign(a) * deFloatFloor(deFloatAbs(a)); }
173 DE_INLINE float         deFloatLdExp            (float a, int exponent)         { return (float)ldexp(a, exponent); }
174 DE_INLINE float         deFloatFrExp            (float x, int* exponent)        { return (float)frexp(x, exponent); }
175 float                           deFloatFractExp         (float x, int* exponent);
176
177 DE_INLINE double        deSign                          (double x)                                              { return deIsNaN(x) ? x : (double)((x > 0.0) - (x < 0.0)); }
178 DE_INLINE int           deIntSign                       (double x)                                              { return (x > 0.0) - (x < 0.0); }
179 DE_INLINE double        deFloor                         (double a)                                              { return floor(a); }
180 DE_INLINE double        deCeil                          (double a)                                              { return ceil(a); }
181 DE_INLINE double        deRound                         (double a)                                              { return floor(a + 0.5); }
182 DE_INLINE double        deFrac                          (double a)                                              { return a - deFloor(a); }
183 DE_INLINE double        deMod                           (double a, double b)                    { return fmod(a, b); }
184 DE_INLINE double        deModf                          (double x, double* i)                   { return modf(x, i); }
185 DE_INLINE double        deMadd                          (double a, double b, double c)  { return (a*b) + c; }
186 DE_INLINE double        deTrunc                         (double a)                                              { return deSign(a) * floor(fabs(a)); }
187 DE_INLINE double        deLdExp                         (double a, int exponent)                { return ldexp(a, exponent); }
188 double                          deRoundEven                     (double a);
189 DE_INLINE double        deFrExp                         (double x, int* exponent)               { return frexp(x, exponent); }
190 /* Like frexp, except the returned fraction is in range [1.0, 2.0) */
191 double                          deFractExp                      (double x, int* exponent);
192
193 /* Exponential functions. */
194
195 DE_INLINE float         deFloatPow                      (float a, float b)                      { return (float)pow(a, b); }
196 DE_INLINE float         deFloatExp                      (float a)                                       { return (float)exp(a); }
197 DE_INLINE float         deFloatLog                      (float a)                                       { return (float)log(a); }
198 DE_INLINE float         deFloatExp2                     (float a)                                       { return (float)exp(a * DE_LOG_2); }
199 DE_INLINE float         deFloatLog2                     (float a)                                       { return (float)log(a) * DE_INV_LOG_2; }
200 DE_INLINE float         deFloatSqrt                     (float a)                                       { return (float)sqrt(a); }
201 DE_INLINE float         deFloatRcp                      (float a)                                       { return (1.0f / a); }
202 DE_INLINE float         deFloatRsq                      (float a)                                       { float s = (float)sqrt(a); return (s == 0.0f) ? 0.0f : (1.0f / s); }
203
204 DE_INLINE double        dePow                           (double a, double b)            { return pow(a, b); }
205 DE_INLINE double        deExp                           (double a)                                      { return exp(a); }
206 DE_INLINE double        deLog                           (double a)                                      { return log(a); }
207 DE_INLINE double        deExp2                          (double a)                                      { return exp(a * log(2.0)); }
208 DE_INLINE double        deLog2                          (double a)                                      { return log(a) / log(2.0); }
209 DE_INLINE double        deSqrt                          (double a)                                      { return sqrt(a); }
210 DE_INLINE double        deCbrt                          (double a)                                      { return deSign(a) * dePow(deAbs(a), 1.0 / 3.0); }
211
212 /* Geometric functions. */
213
214 DE_INLINE float         deFloatRadians          (float a)                                       { return a * (DE_PI / 180.0f); }
215 DE_INLINE float         deFloatDegrees          (float a)                                       { return a * (180.0f / DE_PI); }
216 DE_INLINE float         deFloatSin                      (float a)                                       { return (float)sin(a); }
217 DE_INLINE float         deFloatCos                      (float a)                                       { return (float)cos(a); }
218 DE_INLINE float         deFloatTan                      (float a)                                       { return (float)tan(a); }
219 DE_INLINE float         deFloatAsin                     (float a)                                       { return (float)asin(a); }
220 DE_INLINE float         deFloatAcos                     (float a)                                       { return (float)acos(a); }
221 DE_INLINE float         deFloatAtan2            (float y, float x)                      { return (float)atan2(y, x); }
222 DE_INLINE float         deFloatAtanOver         (float yOverX)                          { return (float)atan(yOverX); }
223 DE_INLINE float         deFloatSinh                     (float a)                                       { return (float)sinh(a); }
224 DE_INLINE float         deFloatCosh                     (float a)                                       { return (float)cosh(a); }
225 DE_INLINE float         deFloatTanh                     (float a)                                       { return (float)tanh(a); }
226 DE_INLINE float         deFloatAsinh            (float a)                                       { return deFloatLog(a + deFloatSqrt(a*a + 1)); }
227 DE_INLINE float         deFloatAcosh            (float a)                                       { return deFloatLog(a + deFloatSqrt(a*a - 1)); }
228 DE_INLINE float         deFloatAtanh            (float a)                                       { return 0.5f*deFloatLog((1.0f+a)/(1.0f-a)); }
229
230 DE_INLINE double        deSin                   (double a)                                              { return sin(a); }
231 DE_INLINE double        deCos                   (double a)                                              { return cos(a); }
232 DE_INLINE double        deTan                   (double a)                                              { return tan(a); }
233 DE_INLINE double        deAsin                  (double a)                                              { return asin(a); }
234 DE_INLINE double        deAcos                  (double a)                                              { return acos(a); }
235 DE_INLINE double        deAtan2                 (double y, double x)                    { return atan2(y, x); }
236 DE_INLINE double        deAtanOver              (double yOverX)                                 { return atan(yOverX); }
237 DE_INLINE double        deSinh                  (double a)                                              { return sinh(a); }
238 DE_INLINE double        deCosh                  (double a)                                              { return cosh(a); }
239 DE_INLINE double        deTanh                  (double a)                                              { return tanh(a); }
240 DE_INLINE double        deAsinh                 (double a)                                              { return deLog(a + deSqrt(a*a + 1)); }
241 DE_INLINE double        deAcosh                 (double a)                                              { return deLog(a + deSqrt(a*a - 1)); }
242 DE_INLINE double        deAtanh                 (double a)                                              { return 0.5*deLog((1.0+a)/(1.0-a)); }
243
244 /* Interpolation. */
245
246 DE_INLINE float         deFloatMix                      (float a, float b, float t)     { return a*(1.0f-t) + b*t; }
247 DE_INLINE float         deFloatStep                     (float limit, float val)        { return (val < limit) ? 0.0f : 1.0f; }
248 DE_INLINE float         deFloatSmoothStep       (float e0, float e1, float v)
249 {
250         float t;
251         if (v <= e0) return 0.0f;
252         if (v >= e1) return 1.0f;
253         t = (v - e0) / (e1 - e0);
254         return t * t * (3.0f - 2.0f * t);
255 }
256
257 DE_INLINE double        deMix                           (double a, double b, double t)  { return a*(1.0-t) + b*t; }
258 DE_INLINE double        deStep                          (double limit, double val)              { return (val < limit) ? 0.0 : 1.0; }
259
260 /* Comparison functions. */
261
262 DE_INLINE deBool        deFloatCmpEQ            (float a, float b)                      { return (a == b); }
263 DE_INLINE deBool        deFloatCmpNE            (float a, float b)                      { return (a != b); }
264 DE_INLINE deBool        deFloatCmpLT            (float a, float b)                      { return (a < b);  }
265 DE_INLINE deBool        deFloatCmpLE            (float a, float b)                      { return (a <= b); }
266 DE_INLINE deBool        deFloatCmpGT            (float a, float b)                      { return (a > b);  }
267 DE_INLINE deBool        deFloatCmpGE            (float a, float b)                      { return (a >= b); }
268
269 /* Convert int to float. If the value cannot be represented exactly in native single precision format, return
270  * either the nearest lower or the nearest higher representable value, chosen in an implementation-defined manner.
271  *
272  * \note Choosing either nearest lower or nearest higher means that implementation could for example consistently
273  *       choose the lower value, i.e. this function does not round towards nearest.
274  * \note Value returned is in native single precision format. For example with x86 extended precision, the value
275  *       returned might not be representable in IEEE single precision float.
276  */
277 DE_INLINE float         deInt32ToFloat                          (deInt32 x)                                     { return (float)x; }
278
279 /* Convert to float. If the value cannot be represented exactly in IEEE single precision floating point format,
280  * return the nearest lower (round towards negative inf). */
281 float                           deInt32ToFloatRoundToNegInf     (deInt32 x);
282
283 /* Convert to float. If the value cannot be represented exactly IEEE single precision floating point format,
284  * return the nearest higher (round towards positive inf). */
285 float                           deInt32ToFloatRoundToPosInf     (deInt32 x);
286
287 /* Conversion to integer. */
288
289 DE_INLINE deInt32       deChopFloatToInt32              (float x)                               { return (deInt32)x; }
290 DE_INLINE deInt32       deFloorFloatToInt32             (float x)                               { return (deInt32)(deFloatFloor(x)); }
291 DE_INLINE deInt32       deCeilFloatToInt32              (float x)                               { return (deInt32)(deFloatCeil(x)); }
292
293 DE_INLINE deInt32       deChopToInt32                   (double x)                              { return (deInt32)x; }
294 DE_INLINE deInt32       deFloorToInt32                  (double x)                              { return (deInt32)(deFloor(x)); }
295 DE_INLINE deInt32       deCeilToInt32                   (double x)                              { return (deInt32)(deCeil(x)); }
296
297 /* Arithmetic round */
298 DE_INLINE deInt16       deRoundFloatToInt16             (float x)                               { if(x >= 0.0f) return (deInt16)(x + 0.5f); else return (deInt16)(x - 0.5f); }
299 DE_INLINE deInt32       deRoundFloatToInt32             (float x)                               { if(x >= 0.0f) return (deInt32)(x + 0.5f); else return (deInt32)(x - 0.5f); }
300 DE_INLINE deInt64       deRoundFloatToInt64             (float x)                               { if(x >= 0.0f) return (deInt64)(x + 0.5f); else return (deInt64)(x - 0.5f); }
301
302 DE_INLINE deInt16       deRoundToInt16                  (double x)                              { if(x >= 0.0) return (deInt16)(x + 0.5); else return (deInt16)(x - 0.5); }
303 DE_INLINE deInt32       deRoundToInt32                  (double x)                              { if(x >= 0.0) return (deInt32)(x + 0.5); else return (deInt32)(x - 0.5); }
304 DE_INLINE deInt64       deRoundToInt64                  (double x)                              { if(x >= 0.0) return (deInt64)(x + 0.5); else return (deInt64)(x - 0.5); }
305
306 DE_END_EXTERN_C
307
308 #endif /* _DEMATH_H */