| 1 | /** |
|---|
| 2 | @file g3dmath.inl |
|---|
| 3 | |
|---|
| 4 | @maintainer Morgan McGuire, matrix@graphics3d.com |
|---|
| 5 | |
|---|
| 6 | @created 2001-06-02 |
|---|
| 7 | @edited 2006-01-14 |
|---|
| 8 | */ |
|---|
| 9 | |
|---|
| 10 | #include <stdlib.h> |
|---|
| 11 | |
|---|
| 12 | #ifdef _MSC_VER |
|---|
| 13 | // Disable conditional expression is constant, which occurs incorrectly on inlined functions |
|---|
| 14 | # pragma warning (push) |
|---|
| 15 | # pragma warning( disable : 4127 ) |
|---|
| 16 | #endif |
|---|
| 17 | |
|---|
| 18 | namespace G3D { |
|---|
| 19 | |
|---|
| 20 | inline bool isNaN(double x) { |
|---|
| 21 | bool b1 = (x < 0.0); |
|---|
| 22 | bool b2 = (x >= 0.0); |
|---|
| 23 | bool b3 = !(b1 || b2); |
|---|
| 24 | return b3; |
|---|
| 25 | } |
|---|
| 26 | |
|---|
| 27 | inline bool isFinite(double x) { |
|---|
| 28 | return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf()); |
|---|
| 29 | } |
|---|
| 30 | |
|---|
| 31 | //---------------------------------------------------------------------------- |
|---|
| 32 | inline int iAbs (int iValue) { |
|---|
| 33 | return ( iValue >= 0 ? iValue : -iValue ); |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | //---------------------------------------------------------------------------- |
|---|
| 37 | inline int iCeil (double fValue) { |
|---|
| 38 | return int(::ceil(fValue)); |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | //---------------------------------------------------------------------------- |
|---|
| 42 | |
|---|
| 43 | inline int iClamp(int val, int low, int hi) { |
|---|
| 44 | debugAssert(low <= hi); |
|---|
| 45 | if (val <= low) { |
|---|
| 46 | return low; |
|---|
| 47 | } else if (val >= hi) { |
|---|
| 48 | return hi; |
|---|
| 49 | } else { |
|---|
| 50 | return val; |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | //---------------------------------------------------------------------------- |
|---|
| 55 | |
|---|
| 56 | inline double clamp(double val, double low, double hi) { |
|---|
| 57 | debugAssert(low <= hi); |
|---|
| 58 | if (val <= low) { |
|---|
| 59 | return low; |
|---|
| 60 | } else if (val >= hi) { |
|---|
| 61 | return hi; |
|---|
| 62 | } else { |
|---|
| 63 | return val; |
|---|
| 64 | } |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | inline float clamp(float val, float low, float hi) { |
|---|
| 68 | debugAssert(low <= hi); |
|---|
| 69 | if (val <= low) { |
|---|
| 70 | return low; |
|---|
| 71 | } else if (val >= hi) { |
|---|
| 72 | return hi; |
|---|
| 73 | } else { |
|---|
| 74 | return val; |
|---|
| 75 | } |
|---|
| 76 | } |
|---|
| 77 | //---------------------------------------------------------------------------- |
|---|
| 78 | |
|---|
| 79 | inline int iWrap(int val, int hi) { |
|---|
| 80 | if (val < 0) { |
|---|
| 81 | return ((val % hi) + hi) % hi; |
|---|
| 82 | } else { |
|---|
| 83 | return val % hi; |
|---|
| 84 | } |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | //---------------------------------------------------------------------------- |
|---|
| 88 | inline int iFloor (double fValue) { |
|---|
| 89 | return int(::floor(fValue)); |
|---|
| 90 | } |
|---|
| 91 | |
|---|
| 92 | //---------------------------------------------------------------------------- |
|---|
| 93 | inline int iSign (int iValue) { |
|---|
| 94 | return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) ); |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | inline int iSign (double fValue) { |
|---|
| 98 | return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) ); |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | //---------------------------------------------------------------------------- |
|---|
| 102 | inline double abs (double fValue) { |
|---|
| 103 | return double(::fabs(fValue)); |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | //---------------------------------------------------------------------------- |
|---|
| 107 | inline double aCos (double fValue) { |
|---|
| 108 | if ( -1.0 < fValue ) { |
|---|
| 109 | if ( fValue < 1.0 ) |
|---|
| 110 | return double(::acos(fValue)); |
|---|
| 111 | else |
|---|
| 112 | return 0.0; |
|---|
| 113 | } else { |
|---|
| 114 | return G3D_PI; |
|---|
| 115 | } |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | //---------------------------------------------------------------------------- |
|---|
| 119 | inline double aSin (double fValue) { |
|---|
| 120 | if ( -1.0 < fValue ) { |
|---|
| 121 | if ( fValue < 1.0 ) { |
|---|
| 122 | return double(::asin(fValue)); |
|---|
| 123 | } else { |
|---|
| 124 | return -G3D_HALF_PI; |
|---|
| 125 | } |
|---|
| 126 | } else { |
|---|
| 127 | return G3D_HALF_PI; |
|---|
| 128 | } |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | //---------------------------------------------------------------------------- |
|---|
| 132 | inline double aTan (double fValue) { |
|---|
| 133 | return double(::atan(fValue)); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | //---------------------------------------------------------------------------- |
|---|
| 137 | inline double aTan2 (double fY, double fX) { |
|---|
| 138 | return double(::atan2(fY, fX)); |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | //---------------------------------------------------------------------------- |
|---|
| 142 | inline double sign (double fValue) { |
|---|
| 143 | if (fValue > 0.0) { |
|---|
| 144 | return 1.0; |
|---|
| 145 | } |
|---|
| 146 | |
|---|
| 147 | if (fValue < 0.0) { |
|---|
| 148 | return -1.0; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | return 0.0; |
|---|
| 152 | } |
|---|
| 153 | |
|---|
| 154 | inline double G3D_DEPRECATED unitRandom () { |
|---|
| 155 | return double(::rand()) / double(RAND_MAX); |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | inline float uniformRandom(float low, float hi) { |
|---|
| 159 | return (hi - low) * float(::rand()) / float(RAND_MAX) + low; |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | |
|---|
| 163 | //---------------------------------------------------------------------------- |
|---|
| 164 | inline double G3D_DEPRECATED symmetricRandom () { |
|---|
| 165 | return 2.0 * double(::rand()) / double(RAND_MAX) - 1.0; |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | //---------------------------------------------------------------------------- |
|---|
| 169 | inline double square(double x) { |
|---|
| 170 | return x * x; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | //---------------------------------------------------------------------------- |
|---|
| 174 | inline double sumSquares(double x, double y) { |
|---|
| 175 | return x*x + y*y; |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | //---------------------------------------------------------------------------- |
|---|
| 179 | inline double sumSquares(double x, double y, double z) { |
|---|
| 180 | return x*x + y*y + z*z; |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | //---------------------------------------------------------------------------- |
|---|
| 184 | inline double distance(double x, double y) { |
|---|
| 185 | return sqrt(sumSquares(x, y)); |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | //---------------------------------------------------------------------------- |
|---|
| 189 | inline double distance(double x, double y, double z) { |
|---|
| 190 | return sqrt(sumSquares(x, y, z)); |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | //---------------------------------------------------------------------------- |
|---|
| 194 | |
|---|
| 195 | /** @deprecated use G3D::min */ |
|---|
| 196 | inline int iMin(int x, int y) { |
|---|
| 197 | return (x >= y) ? y : x; |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | //---------------------------------------------------------------------------- |
|---|
| 201 | /** @deprecated use G3D::min */ |
|---|
| 202 | inline int iMax(int x, int y) { |
|---|
| 203 | return (x >= y) ? x : y; |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | //---------------------------------------------------------------------------- |
|---|
| 207 | inline int ceilPow2(unsigned int in) { |
|---|
| 208 | in -= 1; |
|---|
| 209 | |
|---|
| 210 | in |= in >> 16; |
|---|
| 211 | in |= in >> 8; |
|---|
| 212 | in |= in >> 4; |
|---|
| 213 | in |= in >> 2; |
|---|
| 214 | in |= in >> 1; |
|---|
| 215 | |
|---|
| 216 | return in + 1; |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | inline bool isPow2(int num) { |
|---|
| 220 | return ((num & -num) == num); |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | inline bool isOdd(int num) { |
|---|
| 224 | return (num & 1) == 1; |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | inline bool isEven(int num) { |
|---|
| 228 | return (num & 1) == 0; |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | inline double toRadians(double deg) { |
|---|
| 232 | return deg * G3D_PI / 180.0; |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | inline double toDegrees(double rad) { |
|---|
| 236 | return rad * 180.0 / G3D_PI; |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | /** |
|---|
| 240 | Computes an appropriate epsilon for comparing a and b. |
|---|
| 241 | */ |
|---|
| 242 | inline double eps(double a, double b) { |
|---|
| 243 | // For a and b to be nearly equal, they must have nearly |
|---|
| 244 | // the same magnitude. This means that we can ignore b |
|---|
| 245 | // since it either has the same magnitude or the comparison |
|---|
| 246 | // will fail anyway. |
|---|
| 247 | (void)b; |
|---|
| 248 | const double aa = abs(a) + 1; |
|---|
| 249 | if (aa == inf()) { |
|---|
| 250 | return fuzzyEpsilon; |
|---|
| 251 | } else { |
|---|
| 252 | return fuzzyEpsilon * aa; |
|---|
| 253 | } |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | inline bool fuzzyEq(double a, double b) { |
|---|
| 257 | return (a == b) || (abs(a - b) <= eps(a, b)); |
|---|
| 258 | } |
|---|
| 259 | |
|---|
| 260 | inline bool fuzzyNe(double a, double b) { |
|---|
| 261 | return ! fuzzyEq(a, b); |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | inline bool fuzzyGt(double a, double b) { |
|---|
| 265 | return a > b + eps(a, b); |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | inline bool fuzzyGe(double a, double b) { |
|---|
| 269 | return a > b - eps(a, b); |
|---|
| 270 | } |
|---|
| 271 | |
|---|
| 272 | inline bool fuzzyLt(double a, double b) { |
|---|
| 273 | return a < b - eps(a, b); |
|---|
| 274 | } |
|---|
| 275 | |
|---|
| 276 | inline bool fuzzyLe(double a, double b) { |
|---|
| 277 | return a < b + eps(a, b); |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | inline int iMod3(int x) { |
|---|
| 281 | return x % 3; |
|---|
| 282 | } |
|---|
| 283 | |
|---|
| 284 | } // namespace G3D |
|---|
| 285 | |
|---|
| 286 | #ifdef _MSC_VER |
|---|
| 287 | // Disable conditional expression is constant, which occurs incorrectly on inlined functions |
|---|
| 288 | # pragma warning (pop) |
|---|
| 289 | #endif |
|---|