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