aboutsummaryrefslogtreecommitdiff
path: root/dep/include/g3dlite/G3D/g3dmath.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/include/g3dlite/G3D/g3dmath.h')
-rw-r--r--dep/include/g3dlite/G3D/g3dmath.h525
1 files changed, 525 insertions, 0 deletions
diff --git a/dep/include/g3dlite/G3D/g3dmath.h b/dep/include/g3dlite/G3D/g3dmath.h
new file mode 100644
index 00000000000..1f3eaaae57c
--- /dev/null
+++ b/dep/include/g3dlite/G3D/g3dmath.h
@@ -0,0 +1,525 @@
+/**
+ @file g3dmath.h
+
+ Math util class.
+
+ @maintainer Morgan McGuire, matrix@graphics3d.com
+ @cite highestBit by Jukka Liimatta
+
+ @created 2001-06-02
+ @edited 2006-01-16
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3DMATH_H
+#define 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 <string>
+#include <float.h>
+#include <limits>
+
+/*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
+
+namespace G3D {
+
+#if defined(_MSC_VER)
+
+#if !defined(_WIN64)
+
+/**
+ 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
+
+ __inline long int lrint (double flt) {
+ return (long int)floor(flt+0.5f);
+ }
+
+ __inline long int lrintf(float flt) {
+ return (long int)floorf(flt+0.5f);
+ }
+
+
+#endif
+
+#endif
+
+
+const double fuzzyEpsilon = 0.00001;
+
+/** Returns a reference to a static double.
+ This value should not be tested against directly, instead
+ G3D::isNan() and G3D::isFinite() will return reliable results. */
+inline const double& inf() {
+
+// We already have <limits> included but
+// not using it in older gcc for safe compilations
+#if (__GNUC__ == 2)
+ static const double i = 1.0/sin(0.0);
+#else
+ // double is a standard type and should have infinity
+ static const double i = std::numeric_limits<double>::infinity();
+#endif
+ return i;
+}
+
+/** Returns a reference to a static double.
+ This value should not be tested against directly, instead
+ G3D::isNan() and G3D::isFinite() will return reliable results. */
+inline const double& nan() {
+
+// We already have <limits> included but
+// not using it in older gcc for safe compilations
+#if (__GNUC__ == 2)
+ static const double n = 0.0/sin(0.0);
+#else
+ // double is a standard type and should have quiet NaN
+ static const double n = std::numeric_limits<double>::quiet_NaN();
+#endif
+ return n;
+}
+
+/** Returns a reference to a static double. Use instead of G3D_PI. */
+inline const double& pi() {
+ static const double p = 3.1415926535898;
+ return p;
+}
+
+/** Returns a reference to a static double. Use instead of G3D_HALF_PI. */
+inline const double& halfPi() {
+ static const double p = 1.5707963267949;
+ return p;
+}
+
+/** Returns a reference to a static double. Use instead of G3D_TWO_PI. */
+inline const double& twoPi() {
+ static const double p = 6.283185;
+ return p;
+}
+
+/** @def G3D_PI
+ @deprecated Use G3D::pi() instead. */
+#define G3D_PI (3.1415926535898)
+/** @def G3D_HALF_PI
+ @deprecated Use G3D::halfPi() instead. */
+#define G3D_HALF_PI (1.5707963267949)
+/** @def G3D_TWO_PI
+ @deprecated Use G3D::twoPi() instead. */
+#define G3D_TWO_PI (6.283185)
+
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+typedef int int32;
+typedef unsigned int uint32;
+
+#ifdef _MSC_EXTENSIONS
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+#else
+ typedef long long int64;
+ typedef unsigned long long uint64;
+#endif
+typedef unsigned int uint;
+
+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);
+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);
+}
+
+
+/**
+ 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).
+ */
+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);
+
+/**
+ Computes x % 3.
+ */
+int iMod3(int x);
+
+/**
+ [0, 1]
+ @deprecated use uniformRandom()
+ */
+double unitRandom ();
+
+/**
+ Uniform random number between low and hi, inclusive.
+ @deprecated use uniformRandom()
+ */
+double random(double low, double hi);
+
+/**
+ [-1, 1]
+ @deprecated use uniformRandom()
+ */
+double symmetricRandom ();
+
+/**
+ Uniform random number between low and hi, inclusive. [low, hi]
+ */
+float uniformRandom(float low = 0.0f, float hi = 1.0f);
+
+/**
+ Normally distributed random number.
+ */
+float gaussRandom(float mean = 0.0f, float stdev = 1.0f);
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+
+ /** VC6 lacks std::min and std::max */
+ inline double min(double x, double y) {
+ return std::_cpp_min(x, y);
+ }
+
+ /** VC6 lacks std::min and std::max */
+ inline float min(float x, float y) {
+ return std::_cpp_min(x, y);
+ }
+
+ /** VC6 lacks std::min and std::max */
+ inline int min(int x, int y) {
+ return std::_cpp_min(x, y);
+ }
+
+ /** VC6 lacks std::min and std::max */
+ inline double max(double x, double y) {
+ return std::_cpp_max(x, y);
+ }
+
+ /** VC6 lacks std::min and std::max */
+ inline float max(float x, float y) {
+ return std::_cpp_max(x, y);
+ }
+
+ /** VC6 lacks std::min and std::max */
+ inline int max(int x, int y) {
+ return std::_cpp_max(x, y);
+ }
+
+#else
+ template <class T>
+ inline T min(const T& x, const T& y) {
+ return std::min<T>(x, y);
+ }
+
+ template <class T>
+ inline T max(const T& x, const T& y) {
+ return std::max<T>(x, y);
+ }
+
+#endif
+
+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);
+}
+
+/**
+ Uses SSE to implement rsq.
+ @cite Nick nicolas@capens.net
+ */
+inline float SSErsq(float x) {
+
+ #if defined(SSE) && defined(G3D_WIN32) && !defined(_WIN64)
+ __asm {
+ movss xmm0, x
+ rsqrtss xmm0, xmm0
+ movss x, xmm0
+ }
+ return x;
+ #else
+ return 1.0f / sqrt(x);
+ #endif
+}
+
+/**
+ 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);
+
+/**
+ * True if num is a power of two.
+ */
+bool isPow2(int 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 double rsqrt(double x) {
+ return 1.0 / sqrt(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 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, hi);
+}
+
+
+} // namespace
+
+#ifdef _MSC_VER
+# pragma warning (pop)
+#endif
+
+#include "g3dmath.inl"
+
+#endif
+