Initial commit
This commit is contained in:
946
deps/g3dlite/include/G3D/g3dmath.h
vendored
Normal file
946
deps/g3dlite/include/G3D/g3dmath.h
vendored
Normal file
@@ -0,0 +1,946 @@
|
||||
/**
|
||||
@file g3dmath.h
|
||||
|
||||
Math util class.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite highestBit by Jukka Liimatta
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2013-01-27
|
||||
|
||||
Copyright 2000-2013, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_g3dmath_h
|
||||
#define G3D_g3dmath_h
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable : 4127)
|
||||
// disable: "C++ exception handler used"
|
||||
# pragma warning (disable : 4530)
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1000)
|
||||
// Visual Studio is missing inttypes.h
|
||||
# ifndef PRId64
|
||||
# define PRId64 "I64d"
|
||||
# endif
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/*These defines enable functionality introduced with the 1999 ISO C
|
||||
**standard. They must be defined before the inclusion of math.h to
|
||||
**engage them. If optimisation is enabled, these functions will be
|
||||
**inlined. With optimisation switched off, you have to link in the
|
||||
**maths library using -lm.
|
||||
*/
|
||||
|
||||
#define _ISOC9X_SOURCE1
|
||||
#define _ISOC99_SOURCE1
|
||||
#define __USE_ISOC9X1
|
||||
#define __USE_ISOC991
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "G3D/debug.h"
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
/**
|
||||
\def G3D_DECLARE_SYMBOL(s)
|
||||
Defines SYMBOL_s as a static const std::string with the value s.
|
||||
Useful for avoiding heap allocation from C-string constants being
|
||||
converted at runtime.
|
||||
*/
|
||||
#define G3D_DECLARE_SYMBOL(s) \
|
||||
static const std::string SYMBOL_##s = #s
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
inline double __fastcall drand48() {
|
||||
return ::rand() / double(RAND_MAX);
|
||||
}
|
||||
|
||||
# ifdef _M_IX86
|
||||
// 32-bit
|
||||
/**
|
||||
Win32 implementation of the C99 fast rounding routines.
|
||||
|
||||
@cite routines are
|
||||
Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this file for any
|
||||
purpose is hereby granted without fee, provided that the above copyright
|
||||
and this permission notice appear in all copies. No representations are
|
||||
made about the suitability of this software for any purpose. It is
|
||||
provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
__inline long int lrint (double flt) {
|
||||
int intgr;
|
||||
|
||||
_asm {
|
||||
fld flt
|
||||
fistp intgr
|
||||
};
|
||||
|
||||
return intgr;
|
||||
}
|
||||
|
||||
__inline long int lrintf(float flt) {
|
||||
int intgr;
|
||||
|
||||
_asm {
|
||||
fld flt
|
||||
fistp intgr
|
||||
};
|
||||
|
||||
return intgr;
|
||||
}
|
||||
# else
|
||||
// 64-bit
|
||||
|
||||
__inline long int lrintf(float flt) {
|
||||
return (long int)(flt + 0.5f);
|
||||
}
|
||||
|
||||
__inline long int lrint (double flt) {
|
||||
return (long int)(flt + 0.5);
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#define fuzzyEpsilon64 (0.0000005)
|
||||
#define fuzzyEpsilon32 (0.00001f)
|
||||
|
||||
/**
|
||||
This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
double inf();
|
||||
|
||||
/** This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
double nan();
|
||||
|
||||
float finf();
|
||||
|
||||
float fnan();
|
||||
|
||||
inline double pi() {
|
||||
return 3.1415926535898;
|
||||
}
|
||||
|
||||
inline float pif() {
|
||||
return 3.1415926535898f;
|
||||
}
|
||||
|
||||
inline double halfPi() {
|
||||
return 1.57079633;
|
||||
}
|
||||
|
||||
inline double twoPi() {
|
||||
return 6.28318531;
|
||||
}
|
||||
|
||||
typedef int8_t int8;
|
||||
typedef uint8_t uint8;
|
||||
typedef int16_t int16;
|
||||
typedef uint16_t uint16;
|
||||
typedef int32_t int32;
|
||||
typedef uint32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
int iAbs(int iValue);
|
||||
int iCeil(double fValue);
|
||||
|
||||
/**
|
||||
Clamps the value to the range [low, hi] (inclusive)
|
||||
*/
|
||||
int iClamp(int val, int low, int hi);
|
||||
int16 iClamp(int16 val, int16 low, int16 hi);
|
||||
double clamp(double val, double low, double hi);
|
||||
float clamp(float val, float low, float hi);
|
||||
|
||||
/**
|
||||
Returns a + (b - a) * f;
|
||||
*/
|
||||
inline double lerp(double a, double b, double f) {
|
||||
return a + (b - a) * f;
|
||||
}
|
||||
|
||||
inline float lerp(float a, float b, float f) {
|
||||
return a + (b - a) * f;
|
||||
}
|
||||
|
||||
/**
|
||||
Wraps the value to the range [0, hi) (exclusive
|
||||
on the high end). This is like the clock arithmetic
|
||||
produced by % (modulo) except the result is guaranteed
|
||||
to be positive.
|
||||
*/
|
||||
int iWrap(int val, int hi);
|
||||
|
||||
int iFloor(double fValue);
|
||||
|
||||
int iSign(int iValue);
|
||||
int iSign(double fValue);
|
||||
|
||||
inline int iSign(float f) {
|
||||
return iSign((double)f);
|
||||
}
|
||||
|
||||
inline double round(double f) {
|
||||
return floor(f + 0.5f);
|
||||
}
|
||||
|
||||
inline float round(float f) {
|
||||
return floor(f + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
Fast round to integer using the lrint routine.
|
||||
Typically 6x faster than casting to integer.
|
||||
*/
|
||||
inline int iRound(double fValue) {
|
||||
return lrint(fValue);
|
||||
}
|
||||
|
||||
/**
|
||||
Fast round to integer using the lrint routine.
|
||||
Typically 6x faster than casting to integer.
|
||||
*/
|
||||
inline int iRound(float f) {
|
||||
return lrintf(f);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a random number uniformly at random between low and hi
|
||||
(inclusive).
|
||||
@deprecated Use Random::integer
|
||||
*/
|
||||
int iRandom(int low, int hi);
|
||||
|
||||
double abs (double fValue);
|
||||
double aCos (double fValue);
|
||||
double aSin (double fValue);
|
||||
double aTan (double fValue);
|
||||
double aTan2 (double fY, double fX);
|
||||
double sign (double fValue);
|
||||
double square (double fValue);
|
||||
|
||||
/**
|
||||
Returns true if the argument is a finite real number.
|
||||
*/
|
||||
bool isFinite(double x);
|
||||
|
||||
/**
|
||||
Returns true if the argument is NaN (not a number).
|
||||
You can't use x == nan to test this because all
|
||||
comparisons against nan return false.
|
||||
*/
|
||||
bool isNaN(double x);
|
||||
bool isNaN(float x);
|
||||
inline bool isNaN(int x) {
|
||||
(void)x;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isNaN(uint64 x) {
|
||||
(void)x;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Computes x % 3.
|
||||
*/
|
||||
int iMod3(int x);
|
||||
|
||||
/**
|
||||
Uniform random number between low and hi, inclusive. [low, hi]
|
||||
@deprecated
|
||||
@sa Random::uniform
|
||||
*/
|
||||
float uniformRandom(float low = 0.0f, float hi = 1.0f);
|
||||
|
||||
/**
|
||||
Normally distributed random number.
|
||||
|
||||
@deprecated
|
||||
@sa Random::gaussian
|
||||
*/
|
||||
float gaussRandom(float mean = 0.0f, float stdev = 1.0f);
|
||||
|
||||
|
||||
/** Returns x<sup>5</sup> */
|
||||
template <class T>
|
||||
inline T pow5(T x) {
|
||||
const T y = x * x;
|
||||
return y * y * x;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline T min(const T& x, const T& y) {
|
||||
return std::min<T>(x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T min(const T& x, const T& y, const T& z) {
|
||||
return std::min<T>(std::min<T>(x, y), z);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T min(const T& x, const T& y, const T& z, const T& w) {
|
||||
return std::min<T>(std::min<T>(x, y), std::min<T>(z, w));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T max(const T& x, const T& y) {
|
||||
return std::max<T>(x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T max(const T& x, const T& y, const T& z) {
|
||||
return std::max<T>(std::max<T>(x, y), z);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T max(const T& x, const T& y, const T& z, const T& w) {
|
||||
return std::max<T>(std::max<T>(x, y), std::max<T>(z, w));
|
||||
}
|
||||
|
||||
int iMin(int x, int y);
|
||||
int iMax(int x, int y);
|
||||
|
||||
double square(double x);
|
||||
double sumSquares(double x, double y);
|
||||
double sumSquares(double x, double y, double z);
|
||||
double distance(double x, double y);
|
||||
double distance(double x, double y, double z);
|
||||
|
||||
/**
|
||||
Returnes the 0-based index of the highest 1 bit from
|
||||
the left. -1 means the number was 0.
|
||||
|
||||
@cite Based on code by jukka@liimatta.org
|
||||
*/
|
||||
int highestBit(uint32 x);
|
||||
|
||||
/**
|
||||
Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply
|
||||
fuzzyEq(a, c), although that will be the case on some
|
||||
occasions.
|
||||
*/
|
||||
bool fuzzyEq(double a, double b);
|
||||
|
||||
|
||||
/** True if a is definitely not equal to b.
|
||||
Guaranteed false if a == b.
|
||||
Possibly false when a != b.*/
|
||||
bool fuzzyNe(double a, double b);
|
||||
|
||||
/** Is a strictly greater than b? (Guaranteed false if a <= b).
|
||||
(Possibly false if a > b) */
|
||||
bool fuzzyGt(double a, double b);
|
||||
|
||||
/** Is a near or greater than b? */
|
||||
bool fuzzyGe(double a, double b);
|
||||
|
||||
/** Is a strictly less than b? (Guaranteed false if a >= b)*/
|
||||
bool fuzzyLt(double a, double b);
|
||||
|
||||
/** Is a near or less than b? */
|
||||
bool fuzzyLe(double a, double b);
|
||||
|
||||
/**
|
||||
Computes 1 / sqrt(x).
|
||||
*/
|
||||
inline float rsq(float x) {
|
||||
return 1.0f / sqrtf(x);
|
||||
}
|
||||
|
||||
/**
|
||||
Return the next power of 2 higher than the input
|
||||
If the input is already a power of 2, the output will be the same
|
||||
as the input.
|
||||
*/
|
||||
int ceilPow2(unsigned int in);
|
||||
|
||||
/** Returns 2^x */
|
||||
inline int pow2(unsigned int x) {
|
||||
return 1 << x;
|
||||
}
|
||||
|
||||
inline double log2(double x) {
|
||||
return ::log(x) * 1.442695;
|
||||
}
|
||||
|
||||
inline float log2(float x) {
|
||||
return ::logf(x) * 1.442695f;
|
||||
}
|
||||
|
||||
inline double log2(int x) {
|
||||
return log2((double)x);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* True if num is a power of two.
|
||||
*/
|
||||
bool isPow2(int num);
|
||||
bool isPow2(uint64 num);
|
||||
|
||||
bool isOdd(int num);
|
||||
bool isEven(int num);
|
||||
|
||||
double toRadians(double deg);
|
||||
double toDegrees(double rad);
|
||||
|
||||
/**
|
||||
Returns true if x is not exactly equal to 0.0f.
|
||||
*/
|
||||
inline bool any(float x) {
|
||||
return x != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if x is not exactly equal to 0.0f.
|
||||
*/
|
||||
inline bool all(float x) {
|
||||
return x != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
v / v (for DirectX/Cg support)
|
||||
*/
|
||||
inline float normalize(float v) {
|
||||
return v / v;
|
||||
}
|
||||
|
||||
/**
|
||||
a * b (for DirectX/Cg support)
|
||||
*/
|
||||
inline float dot(float a, float b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
a * b (for DirectX/Cg support)
|
||||
*/
|
||||
inline float mul(float a, float b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
/**
|
||||
2^x
|
||||
*/
|
||||
inline double exp2(double x) {
|
||||
return pow(2.0, x);
|
||||
}
|
||||
|
||||
inline float exp2(float x) {
|
||||
return powf(2.0f, x);
|
||||
}
|
||||
|
||||
/** @deprecated Use rsq */
|
||||
inline double rsqrt(double x) {
|
||||
return 1.0 / sqrt(x);
|
||||
}
|
||||
|
||||
/** @deprecated Use rsq */
|
||||
inline float rsqrt(float x) {
|
||||
// TODO: default this to using the SSE2 instruction
|
||||
return 1.0f / sqrtf(x);
|
||||
}
|
||||
|
||||
/**
|
||||
sin(x)/x
|
||||
*/
|
||||
inline double sinc(double x) {
|
||||
double r = sin(x) / x;
|
||||
|
||||
if (isNaN(r)) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Computes a floating point modulo; the result is t wrapped to the range [lo, hi).
|
||||
*/
|
||||
inline float wrap(float t, float lo, float hi) {
|
||||
if ((t >= lo) && (t < hi)) {
|
||||
return t;
|
||||
}
|
||||
|
||||
debugAssert(hi > lo);
|
||||
|
||||
float interval = hi - lo;
|
||||
|
||||
return t - interval * iFloor((t - lo) / interval);
|
||||
}
|
||||
|
||||
|
||||
inline double wrap(double t, double lo, double hi) {
|
||||
if ((t >= lo) && (t < hi)) {
|
||||
return t;
|
||||
}
|
||||
|
||||
debugAssert(hi > lo);
|
||||
|
||||
double interval = hi - lo;
|
||||
|
||||
return t - interval * iFloor((t - lo) / interval);
|
||||
}
|
||||
|
||||
inline double wrap(double t, double hi) {
|
||||
return wrap(t, 0.0, hi);
|
||||
}
|
||||
|
||||
|
||||
inline bool isFinite(double x) {
|
||||
return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf());
|
||||
}
|
||||
|
||||
inline bool isFinite(float x) {
|
||||
return ! isNaN(x) && (x < G3D::finf()) && (x > -G3D::finf());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iAbs (int iValue) {
|
||||
return ( iValue >= 0 ? iValue : -iValue );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iCeil (double fValue) {
|
||||
return int(::ceil(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline int iClamp(int val, int low, int hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline int16 iClamp(int16 val, int16 low, int16 hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline double clamp(double val, double low, double hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
inline float clamp(float val, float low, float hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline int iWrap(int val, int hi) {
|
||||
if (val < 0) {
|
||||
return ((val % hi) + hi) % hi;
|
||||
} else {
|
||||
return val % hi;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iFloor (double fValue) {
|
||||
return int(::floor(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iSign (int iValue) {
|
||||
return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) );
|
||||
}
|
||||
|
||||
inline int iSign (double fValue) {
|
||||
return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double abs (double fValue) {
|
||||
return double(::fabs(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aCos (double fValue) {
|
||||
if ( -1.0 < fValue ) {
|
||||
if ( fValue < 1.0 )
|
||||
return double(::acos(fValue));
|
||||
else
|
||||
return 0.0;
|
||||
} else {
|
||||
return pi();
|
||||
}
|
||||
}
|
||||
|
||||
inline float acos (float fValue) {
|
||||
if ( -1.0f < fValue ) {
|
||||
if ( fValue < 1.0f ) {
|
||||
return ::acos(fValue);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
} else {
|
||||
return pif();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aSin (double fValue) {
|
||||
if ( -1.0 < fValue ) {
|
||||
if ( fValue < 1.0 ) {
|
||||
return double(::asin(fValue));
|
||||
} else {
|
||||
return -halfPi();
|
||||
}
|
||||
} else {
|
||||
return halfPi();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aTan (double fValue) {
|
||||
return double(::atan(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aTan2 (double fY, double fX) {
|
||||
return double(::atan2(fY, fX));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double sign (double fValue) {
|
||||
if (fValue > 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (fValue < 0.0) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
inline float sign (float fValue) {
|
||||
if (fValue > 0.0f) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (fValue < 0.0f) {
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
inline float uniformRandom(float low, float hi) {
|
||||
return (hi - low) * float(::rand()) / float(RAND_MAX) + low;
|
||||
}
|
||||
|
||||
inline double square(double x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
inline float square(float x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
inline int square(int x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double sumSquares(double x, double y) {
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float sumSquares(float x, float y) {
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double sumSquares(double x, double y, double z) {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float sumSquares(float x, float y, float z) {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double distance(double x, double y) {
|
||||
return sqrt(sumSquares(x, y));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float distance(float x, float y) {
|
||||
return sqrt(sumSquares(x, y));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double distance(double x, double y, double z) {
|
||||
return sqrt(sumSquares(x, y, z));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float distance(float x, float y, float z) {
|
||||
return sqrt(sumSquares(x, y, z));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/** @deprecated use G3D::min */
|
||||
inline int iMin(int x, int y) {
|
||||
return (x >= y) ? y : x;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** @deprecated use G3D::min */
|
||||
inline int iMax(int x, int y) {
|
||||
return (x >= y) ? x : y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int ceilPow2(unsigned int in) {
|
||||
in -= 1;
|
||||
|
||||
in |= in >> 16;
|
||||
in |= in >> 8;
|
||||
in |= in >> 4;
|
||||
in |= in >> 2;
|
||||
in |= in >> 1;
|
||||
|
||||
return in + 1;
|
||||
}
|
||||
|
||||
inline bool isPow2(int num) {
|
||||
return ((num & -num) == num);
|
||||
}
|
||||
|
||||
inline bool isPow2(uint64 x) {
|
||||
// See http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/, method #9
|
||||
return ((x != 0) && !(x & (x - 1)));
|
||||
}
|
||||
|
||||
inline bool isPow2(uint32 x) {
|
||||
// See http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/, method #9
|
||||
return ((x != 0) && !(x & (x - 1)));
|
||||
}
|
||||
|
||||
inline bool isOdd(int num) {
|
||||
return (num & 1) == 1;
|
||||
}
|
||||
|
||||
inline bool isEven(int num) {
|
||||
return (num & 1) == 0;
|
||||
}
|
||||
|
||||
inline double toRadians(double deg) {
|
||||
return deg * pi() / 180.0;
|
||||
}
|
||||
|
||||
inline double toDegrees(double rad) {
|
||||
return rad * 180.0 / pi();
|
||||
}
|
||||
|
||||
inline float toRadians(float deg) {
|
||||
return deg * (float)pi() / 180.0f;
|
||||
}
|
||||
|
||||
inline float toDegrees(float rad) {
|
||||
return rad * 180.0f / (float)pi();
|
||||
}
|
||||
|
||||
inline float toRadians(int deg) {
|
||||
return deg * (float)pi() / 180.0f;
|
||||
}
|
||||
|
||||
inline float toDegrees(int rad) {
|
||||
return rad * 180.0f / (float)pi();
|
||||
}
|
||||
/**
|
||||
Computes an appropriate epsilon for comparing a and b.
|
||||
*/
|
||||
inline double eps(double a, double b) {
|
||||
// For a and b to be nearly equal, they must have nearly
|
||||
// the same magnitude. This means that we can ignore b
|
||||
// since it either has the same magnitude or the comparison
|
||||
// will fail anyway.
|
||||
(void)b;
|
||||
const double aa = abs(a) + 1.0;
|
||||
if (aa == inf()) {
|
||||
return fuzzyEpsilon64;
|
||||
} else {
|
||||
return fuzzyEpsilon64 * aa;
|
||||
}
|
||||
}
|
||||
|
||||
inline float eps(float a, float b) {
|
||||
// For a and b to be nearly equal, they must have nearly
|
||||
// the same magnitude. This means that we can ignore b
|
||||
// since it either has the same magnitude or the comparison
|
||||
// will fail anyway.
|
||||
(void)b;
|
||||
const float aa = (float)abs(a) + 1.0f;
|
||||
if (aa == inf()) {
|
||||
return fuzzyEpsilon32;
|
||||
} else {
|
||||
return fuzzyEpsilon32 * aa;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool fuzzyEq(float a, float b) {
|
||||
return (a == b) || (abs(a - b) <= eps(a, b));
|
||||
}
|
||||
|
||||
inline bool fuzzyEq(double a, double b) {
|
||||
return (a == b) || (abs(a - b) <= eps(a, b));
|
||||
}
|
||||
|
||||
inline bool fuzzyNe(double a, double b) {
|
||||
return ! fuzzyEq(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyGt(double a, double b) {
|
||||
return a > b + eps(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyGe(double a, double b) {
|
||||
return a > b - eps(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyLt(double a, double b) {
|
||||
return a < b - eps(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyLe(double a, double b) {
|
||||
return a < b + eps(a, b);
|
||||
}
|
||||
|
||||
inline int iMod3(int x) {
|
||||
return x % 3;
|
||||
}
|
||||
|
||||
/**
|
||||
Given a 32-bit integer, returns the integer with the bytes in the opposite order.
|
||||
*/
|
||||
inline uint32 flipEndian32(const uint32 x) {
|
||||
return (x << 24) | ((x & 0xFF00) << 8) |
|
||||
((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
/**
|
||||
Given a 16-bit integer, returns the integer with the bytes in the opposite order.
|
||||
*/
|
||||
inline uint16 flipEndian16(const uint16 x) {
|
||||
return (x << 8) | ((x & 0xFF00) >> 8);
|
||||
}
|
||||
|
||||
/** The GLSL smoothstep function */
|
||||
inline float smoothstep(float edge0, float edge1, float x) {
|
||||
// Scale, bias and saturate x to 0..1 range
|
||||
x = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
||||
|
||||
// Evaluate polynomial
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
|
||||
/** Perlin's C2 continous variation on smoothstep() */
|
||||
inline float smootherstep(float edge0, float edge1, float x) {
|
||||
|
||||
// Scale, and saturate x to 0..1 range
|
||||
x = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
||||
|
||||
// Evaluate polynomial
|
||||
return x * x * x * (x * (x * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
|
||||
/** Computes |b|^e * sign(b) */
|
||||
inline float signedPow(float b, float e) {
|
||||
return sign(b) * powf(fabsf(b), e);
|
||||
}
|
||||
|
||||
|
||||
/** Computes |b|^e * sign(b) */
|
||||
inline double signedPow(double b, double e) {
|
||||
return sign(b) * pow(abs(b), e);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace std {
|
||||
inline int pow(int a, int b) {
|
||||
return (int)::pow(double(a), double(b));
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user