Home | History | Annotate | Download | only in debase
      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 
     28 #include <math.h>
     29 #include <float.h>
     30 
     31 DE_BEGIN_EXTERN_C
     32 
     33 /* Mathematical constants. */
     34 
     35 #define DE_PI			3.14159265358979324f	/*!< Pi.					*/
     36 #define DE_LOG_2		0.69314718056f			/*!< log_e(2.0)				*/
     37 #define DE_INV_LOG_2	1.44269504089f			/*!< 1.0 / log_e(2.0)		*/
     38 #define DE_E			2.71828182845904523536f	/*!< e.						*/
     39 #define DE_LOG2_E		1.44269504088896340736f	/*!< log_2(e).				*/
     40 #define DE_INV_LOG2_E	0.69314718055994530942f	/*!< 1.0 / log_2(e).		*/
     41 
     42 #define DE_PI_DOUBLE	3.14159265358979323846	/*!< Pi as a double.		*/
     43 #define DE_PI_16BIT		0x4248					/*!< Pi. as a float16b		*/
     44 
     45 /* Rounding mode control. */
     46 
     47 typedef enum deRoundingMode_e
     48 {
     49 	DE_ROUNDINGMODE_TO_NEAREST_EVEN = 0,
     50 	DE_ROUNDINGMODE_TO_ZERO,
     51 	DE_ROUNDINGMODE_TO_POSITIVE_INF,
     52 	DE_ROUNDINGMODE_TO_NEGATIVE_INF,
     53 
     54 	DE_ROUNDINGMODE_LAST
     55 } deRoundingMode;
     56 
     57 deRoundingMode		deGetRoundingMode	(void);
     58 deBool				deSetRoundingMode	(deRoundingMode mode);
     59 
     60 void				deMath_selfTest		(void);
     61 
     62 /* Float properties */
     63 
     64 /* \note The NaN test probably won't work with -ffast-math */
     65 
     66 DE_INLINE int		deFloatIsInf		(float x)		{ return (x > FLT_MAX) - (x < -FLT_MAX); }
     67 DE_INLINE deBool	deFloatIsNaN		(float x)		{ return (x != x); }
     68 
     69 DE_INLINE int		deIsInf				(double x)		{ return (x > DBL_MAX) - (x < -DBL_MAX); }
     70 DE_INLINE deBool	deIsNaN				(double x)		{ return (x != x); }
     71 
     72 /* Basic utilities. */
     73 
     74 DE_INLINE float		deFloatAbs			(float x)						{ return (x >= 0.0f) ? x : -x; }
     75 DE_INLINE float		deFloatMin			(float a, float b)				{ return (a <= b) ? a : b; }
     76 DE_INLINE float		deFloatMax			(float a, float b)				{ return (a >= b) ? a : b; }
     77 DE_INLINE float		deFloatClamp		(float x, float mn, float mx)	{ return (x <= mn) ? mn : ((x >= mx) ? mx : x); }
     78 
     79 DE_INLINE double	deAbs				(double x)							{ return (x >= 0.0) ? x : -x; }
     80 DE_INLINE double	deMin				(double a, double b)				{ return (a <= b) ? a : b; }
     81 DE_INLINE double	deMax				(double a, double b)				{ return (a >= b) ? a : b; }
     82 DE_INLINE double	deClamp				(double x, double mn, double mx)	{ return (x <= mn) ? mn : ((x >= mx) ? mx : x); }
     83 
     84 /* Utility functions. */
     85 
     86 DE_INLINE float		deFloatSign			(float a)					{ return (a == 0.0f) ? 0.0f : ((a > 0.0f) ? +1.0f : -1.0f); }
     87 DE_INLINE int		deFloatIntSign		(float a)					{ return (a == 0.0f) ? 0 : ((a > 0.0f) ? +1 : -1); }
     88 DE_INLINE float		deFloatFloor		(float a)					{ return (float)floor(a); }
     89 DE_INLINE float		deFloatCeil			(float a)					{ return (float)ceil(a); }
     90 DE_INLINE float		deFloatRound		(float a)					{ return deFloatFloor(a + 0.5f); }
     91 DE_INLINE float		deFloatFrac			(float a)					{ return a - deFloatFloor(a); }
     92 DE_INLINE float		deFloatMod			(float a, float b)			{ return (float)fmod(a, b); }
     93 DE_INLINE float		deFloatModf			(float x, float* i)			{ double j = 0; double ret = modf(x, &j); *i = (float)j; return (float)ret; }
     94 DE_INLINE float		deFloatMadd			(float a, float b, float c)	{ return (a*b) + c; }
     95 DE_INLINE float		deFloatTrunc		(float a)					{ return deFloatSign(a) * deFloatFloor(deFloatAbs(a)); }
     96 DE_INLINE float		deFloatLdExp		(float a, int exponent)		{ return (float)ldexp(a, exponent); }
     97 DE_INLINE float		deFloatFrExp		(float x, int* exponent)	{ return (float)frexp(x, exponent); }
     98 float				deFloatFractExp		(float x, int* exponent);
     99 
    100 DE_INLINE double	deSign				(double x)						{ return deIsNaN(x) ? x : (double)((x > 0.0) - (x < 0.0)); }
    101 DE_INLINE int		deIntSign			(double x)						{ return (x > 0.0) - (x < 0.0); }
    102 DE_INLINE double	deFloor				(double a)						{ return floor(a); }
    103 DE_INLINE double	deCeil				(double a)						{ return ceil(a); }
    104 DE_INLINE double	deRound				(double a)						{ return floor(a + 0.5); }
    105 DE_INLINE double	deFrac				(double a)						{ return a - deFloor(a); }
    106 DE_INLINE double	deMod				(double a, double b)			{ return fmod(a, b); }
    107 DE_INLINE double	deModf				(double x, double* i)			{ return modf(x, i); }
    108 DE_INLINE double	deMadd				(double a, double b, double c)	{ return (a*b) + c; }
    109 DE_INLINE double	deTrunc				(double a)						{ return deSign(a) * floor(fabs(a)); }
    110 DE_INLINE double	deLdExp				(double a, int exponent)		{ return ldexp(a, exponent); }
    111 double				deRoundEven			(double a);
    112 DE_INLINE double	deFrExp				(double x, int* exponent)		{ return frexp(x, exponent); }
    113 /* Like frexp, except the returned fraction is in range [1.0, 2.0) */
    114 double				deFractExp			(double x, int* exponent);
    115 
    116 /* Exponential functions. */
    117 
    118 DE_INLINE float		deFloatPow			(float a, float b)			{ return (float)pow(a, b); }
    119 DE_INLINE float		deFloatExp			(float a)					{ return (float)exp(a); }
    120 DE_INLINE float		deFloatLog			(float a)					{ return (float)log(a); }
    121 DE_INLINE float		deFloatExp2			(float a)					{ return (float)exp(a * DE_LOG_2); }
    122 DE_INLINE float		deFloatLog2			(float a)					{ return (float)log(a) * DE_INV_LOG_2; }
    123 DE_INLINE float		deFloatSqrt			(float a)					{ return (float)sqrt(a); }
    124 DE_INLINE float		deFloatRcp			(float a)					{ return (1.0f / a); }
    125 DE_INLINE float		deFloatRsq			(float a)					{ float s = (float)sqrt(a); return (s == 0.0f) ? 0.0f : (1.0f / s); }
    126 
    127 DE_INLINE double	dePow				(double a, double b)		{ return pow(a, b); }
    128 DE_INLINE double	deExp				(double a)					{ return exp(a); }
    129 DE_INLINE double	deLog				(double a)					{ return log(a); }
    130 DE_INLINE double	deExp2				(double a)					{ return exp(a * log(2.0)); }
    131 DE_INLINE double	deLog2				(double a)					{ return log(a) / log(2.0); }
    132 DE_INLINE double	deSqrt				(double a)					{ return sqrt(a); }
    133 DE_INLINE double	deCbrt				(double a)					{ return deSign(a) * dePow(deAbs(a), 1.0 / 3.0); }
    134 
    135 /* Geometric functions. */
    136 
    137 DE_INLINE float		deFloatRadians		(float a)					{ return a * (DE_PI / 180.0f); }
    138 DE_INLINE float		deFloatDegrees		(float a)					{ return a * (180.0f / DE_PI); }
    139 DE_INLINE float		deFloatSin			(float a)					{ return (float)sin(a); }
    140 DE_INLINE float		deFloatCos			(float a)					{ return (float)cos(a); }
    141 DE_INLINE float		deFloatTan			(float a)					{ return (float)tan(a); }
    142 DE_INLINE float		deFloatAsin			(float a)					{ return (float)asin(a); }
    143 DE_INLINE float		deFloatAcos			(float a)					{ return (float)acos(a); }
    144 DE_INLINE float		deFloatAtan2		(float y, float x)			{ return (float)atan2(y, x); }
    145 DE_INLINE float		deFloatAtanOver		(float yOverX)				{ return (float)atan(yOverX); }
    146 DE_INLINE float		deFloatSinh			(float a)					{ return (float)sinh(a); }
    147 DE_INLINE float		deFloatCosh			(float a)					{ return (float)cosh(a); }
    148 DE_INLINE float		deFloatTanh			(float a)					{ return (float)tanh(a); }
    149 DE_INLINE float		deFloatAsinh		(float a)					{ return deFloatLog(a + deFloatSqrt(a*a + 1)); }
    150 DE_INLINE float		deFloatAcosh		(float a)					{ return deFloatLog(a + deFloatSqrt(a*a - 1)); }
    151 DE_INLINE float		deFloatAtanh		(float a)					{ return 0.5f*deFloatLog((1.0f+a)/(1.0f-a)); }
    152 
    153 DE_INLINE double	deSin			(double a)						{ return sin(a); }
    154 DE_INLINE double	deCos			(double a)						{ return cos(a); }
    155 DE_INLINE double	deTan			(double a)						{ return tan(a); }
    156 DE_INLINE double	deAsin			(double a)						{ return asin(a); }
    157 DE_INLINE double	deAcos			(double a)						{ return acos(a); }
    158 DE_INLINE double	deAtan2			(double y, double x)			{ return atan2(y, x); }
    159 DE_INLINE double	deAtanOver		(double yOverX)					{ return atan(yOverX); }
    160 DE_INLINE double	deSinh			(double a)						{ return sinh(a); }
    161 DE_INLINE double	deCosh			(double a)						{ return cosh(a); }
    162 DE_INLINE double	deTanh			(double a)						{ return tanh(a); }
    163 DE_INLINE double	deAsinh			(double a)						{ return deLog(a + deSqrt(a*a + 1)); }
    164 DE_INLINE double	deAcosh			(double a)						{ return deLog(a + deSqrt(a*a - 1)); }
    165 DE_INLINE double	deAtanh			(double a)						{ return 0.5*deLog((1.0+a)/(1.0-a)); }
    166 
    167 /* Interpolation. */
    168 
    169 DE_INLINE float		deFloatMix			(float a, float b, float t)	{ return a*(1.0f-t) + b*t; }
    170 DE_INLINE float		deFloatStep			(float limit, float val)	{ return (val < limit) ? 0.0f : 1.0f; }
    171 DE_INLINE float		deFloatSmoothStep	(float e0, float e1, float v)
    172 {
    173 	float t;
    174 	if (v <= e0) return 0.0f;
    175 	if (v >= e1) return 1.0f;
    176 	t = (v - e0) / (e1 - e0);
    177 	return t * t * (3.0f - 2.0f * t);
    178 }
    179 
    180 DE_INLINE double	deMix				(double a, double b, double t)	{ return a*(1.0-t) + b*t; }
    181 DE_INLINE double	deStep				(double limit, double val)		{ return (val < limit) ? 0.0 : 1.0; }
    182 
    183 /* Comparison functions. */
    184 
    185 DE_INLINE deBool	deFloatCmpEQ		(float a, float b)			{ return (a == b); }
    186 DE_INLINE deBool	deFloatCmpNE		(float a, float b)			{ return (a != b); }
    187 DE_INLINE deBool	deFloatCmpLT		(float a, float b)			{ return (a < b);  }
    188 DE_INLINE deBool	deFloatCmpLE		(float a, float b)			{ return (a <= b); }
    189 DE_INLINE deBool	deFloatCmpGT		(float a, float b)			{ return (a > b);  }
    190 DE_INLINE deBool	deFloatCmpGE		(float a, float b)			{ return (a >= b); }
    191 
    192 /* Convert int to float. If the value cannot be represented exactly in native single precision format, return
    193  * either the nearest lower or the nearest higher representable value, chosen in an implementation-defined manner.
    194  *
    195  * \note Choosing either nearest lower or nearest higher means that implementation could for example consistently
    196  *       choose the lower value, i.e. this function does not round towards nearest.
    197  * \note Value returned is in native single precision format. For example with x86 extended precision, the value
    198  *       returned might not be representable in IEEE single precision float.
    199  */
    200 DE_INLINE float		deInt32ToFloat				(deInt32 x)					{ return (float)x; }
    201 
    202 /* Convert to float. If the value cannot be represented exactly in IEEE single precision floating point format,
    203  * return the nearest lower (round towards negative inf). */
    204 float				deInt32ToFloatRoundToNegInf	(deInt32 x);
    205 
    206 /* Convert to float. If the value cannot be represented exactly IEEE single precision floating point format,
    207  * return the nearest higher (round towards positive inf). */
    208 float				deInt32ToFloatRoundToPosInf	(deInt32 x);
    209 
    210 /* Conversion to integer. */
    211 
    212 DE_INLINE deInt32	deChopFloatToInt32		(float x)				{ return (deInt32)x; }
    213 DE_INLINE deInt32	deFloorFloatToInt32		(float x)				{ return (deInt32)(deFloatFloor(x)); }
    214 DE_INLINE deInt32	deCeilFloatToInt32		(float x)				{ return (deInt32)(deFloatCeil(x)); }
    215 
    216 DE_INLINE deInt32	deChopToInt32			(double x)				{ return (deInt32)x; }
    217 DE_INLINE deInt32	deFloorToInt32			(double x)				{ return (deInt32)(deFloor(x)); }
    218 DE_INLINE deInt32	deCeilToInt32			(double x)				{ return (deInt32)(deCeil(x)); }
    219 
    220 /* Arithmetic round */
    221 DE_INLINE deInt16	deRoundFloatToInt16		(float x)				{ if(x >= 0.0f) return (deInt16)(x + 0.5f); else return (deInt16)(x - 0.5f); }
    222 DE_INLINE deInt32	deRoundFloatToInt32		(float x)				{ if(x >= 0.0f) return (deInt32)(x + 0.5f); else return (deInt32)(x - 0.5f); }
    223 DE_INLINE deInt64	deRoundFloatToInt64		(float x)				{ if(x >= 0.0f) return (deInt64)(x + 0.5f); else return (deInt64)(x - 0.5f); }
    224 
    225 DE_INLINE deInt16	deRoundToInt16			(double x)				{ if(x >= 0.0) return (deInt16)(x + 0.5); else return (deInt16)(x - 0.5); }
    226 DE_INLINE deInt32	deRoundToInt32			(double x)				{ if(x >= 0.0) return (deInt32)(x + 0.5); else return (deInt32)(x - 0.5); }
    227 DE_INLINE deInt64	deRoundToInt64			(double x)				{ if(x >= 0.0) return (deInt64)(x + 0.5); else return (deInt64)(x - 0.5); }
    228 
    229 DE_END_EXTERN_C
    230 
    231 #endif /* _DEMATH_H */
    232