root/trunk/dep/include/g3dlite/G3D/g3dmath.h @ 2

Revision 2, 10.7 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/**
2 @file g3dmath.h
3 
4 Math util class.
5 
6 @maintainer Morgan McGuire, matrix@graphics3d.com
7 @cite highestBit by Jukka Liimatta
8 
9 @created 2001-06-02
10 @edited  2006-01-16
11
12 Copyright 2000-2006, Morgan McGuire.
13 All rights reserved.
14 */
15
16#ifndef G3DMATH_H
17#define G3DMATH_H
18
19#ifdef _MSC_VER
20// Disable conditional expression is constant, which occurs incorrectly on inlined functions
21#   pragma warning (push)
22#   pragma warning (disable : 4127)
23// disable: "C++ exception handler used"
24#   pragma warning (disable : 4530)
25#endif
26
27#include "G3D/platform.h"
28#include <ctype.h>
29#include <string>
30#include <float.h>
31#include <limits>
32
33/*These defines enable functionality introduced with the 1999 ISO C
34**standard. They must be defined before the inclusion of math.h to
35**engage them. If optimisation is enabled, these functions will be
36**inlined. With optimisation switched off, you have to link in the
37**maths library using -lm.
38*/
39
40#define _ISOC9X_SOURCE1
41#define _ISOC99_SOURCE1
42#define __USE_ISOC9X1
43#define __USE_ISOC991
44
45#include <math.h>
46
47#include "G3D/debug.h"
48
49#undef min
50#undef max
51
52namespace G3D {
53
54#if defined(_MSC_VER)
55   
56#if !defined(_WIN64)
57
58/**
59   Win32 implementation of the C99 fast rounding routines.
60   
61   @cite routines are
62   Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
63   
64   Permission to use, copy, modify, distribute, and sell this file for any
65   purpose is hereby granted without fee, provided that the above copyright
66   and this permission notice appear in all copies.  No representations are
67   made about the suitability of this software for any purpose.  It is
68   provided "as is" without express or implied warranty.
69*/
70
71__inline long int lrint (double flt) {
72    int intgr;
73
74    _asm {
75        fld flt
76        fistp intgr
77    };
78
79    return intgr;
80}
81
82__inline long int lrintf(float flt) {
83    int intgr;
84
85    _asm {
86        fld flt
87        fistp intgr
88    };
89
90    return intgr;
91}
92
93#else
94
95    __inline long int lrint (double flt) {
96        return (long int)floor(flt+0.5f);
97    }
98
99    __inline long int lrintf(float flt) {
100        return (long int)floorf(flt+0.5f);
101    }
102
103
104#endif
105
106#endif
107
108
109const double fuzzyEpsilon = 0.00001;
110
111/** Returns a reference to a static double.
112    This value should not be tested against directly, instead
113    G3D::isNan() and G3D::isFinite() will return reliable results. */
114inline const double& inf() {
115
116// We already have <limits> included but
117// not using it in older gcc for safe compilations
118#if (__GNUC__ == 2)   
119    static const double i = 1.0/sin(0.0);
120#else
121    // double is a standard type and should have infinity
122    static const double i = std::numeric_limits<double>::infinity();
123#endif
124        return i;
125}
126
127/** Returns a reference to a static double.
128    This value should not be tested against directly, instead
129    G3D::isNan() and G3D::isFinite() will return reliable results. */
130inline const double& nan() {
131
132// We already have <limits> included but
133// not using it in older gcc for safe compilations
134#if (__GNUC__ == 2)
135    static const double n = 0.0/sin(0.0);
136#else
137    // double is a standard type and should have quiet NaN
138    static const double n = std::numeric_limits<double>::quiet_NaN();
139#endif
140        return n;
141}
142
143/** Returns a reference to a static double. Use instead of G3D_PI. */
144inline const double& pi() {
145    static const double p = 3.1415926535898;
146    return p;
147}
148
149/** Returns a reference to a static double. Use instead of G3D_HALF_PI. */
150inline const double& halfPi() {
151    static const double p = 1.5707963267949;
152    return p;
153}
154
155/** Returns a reference to a static double. Use instead of G3D_TWO_PI. */
156inline const double& twoPi() {
157    static const double p = 6.283185;
158    return p;
159}
160
161/** @def G3D_PI
162    @deprecated Use G3D::pi() instead. */
163#define G3D_PI      (3.1415926535898)
164/** @def G3D_HALF_PI
165    @deprecated Use G3D::halfPi() instead. */
166#define G3D_HALF_PI (1.5707963267949)
167/** @def G3D_TWO_PI
168    @deprecated Use G3D::twoPi() instead. */
169#define G3D_TWO_PI  (6.283185)
170
171typedef signed char             int8;
172typedef unsigned char   uint8;
173typedef short                   int16;
174typedef unsigned short  uint16;
175typedef int                             int32;
176typedef unsigned int    uint32;
177
178#ifdef _MSC_EXTENSIONS
179    typedef __int64                        int64;
180    typedef unsigned __int64   uint64;
181#else
182    typedef long long              int64;
183    typedef unsigned long long uint64;
184#endif
185typedef unsigned int uint;
186
187typedef float                   float32;
188typedef double                  float64;
189
190int iAbs(int iValue);
191int iCeil(double fValue);
192
193/**
194 Clamps the value to the range [low, hi] (inclusive)
195 */
196int iClamp(int val, int low, int hi);
197double clamp(double val, double low, double hi);
198float clamp(float val, float low, float hi);
199
200/**
201 Returns a + (b - a) * f;
202 */
203inline double lerp(double a, double b, double f) {
204    return a + (b - a) * f;
205}
206
207inline float lerp(float a, float b, float f) {
208    return a + (b - a) * f;
209}
210
211/**
212 Wraps the value to the range [0, hi) (exclusive
213 on the high end).  This is like the clock arithmetic
214 produced by % (modulo) except the result is guaranteed
215 to be positive.
216 */
217int iWrap(int val, int hi);
218
219int iFloor(double fValue);
220
221int iSign(int iValue);
222int iSign(double fValue);
223
224inline int iSign(float f) {
225    return iSign((double)f);
226}
227
228
229/**
230    Fast round to integer using the lrint routine.
231    Typically 6x faster than casting to integer.
232 */
233inline int iRound(double fValue) {
234    return lrint(fValue);
235}
236
237/**
238    Fast round to integer using the lrint routine.
239    Typically 6x faster than casting to integer.
240 */
241inline int iRound(float f) {
242    return lrintf(f);
243}
244
245/**
246 Returns a random number uniformly at random between low and hi
247 (inclusive).
248 */
249int iRandom(int low, int hi);
250
251double abs (double fValue);
252double aCos (double fValue);
253double aSin (double fValue);
254double aTan (double fValue);
255double aTan2 (double fY, double fX);
256double sign (double fValue);
257double square (double fValue);
258
259/**
260 Returns true if the argument is a finite real number.
261 */
262bool isFinite(double x);
263
264/**
265 Returns true if the argument is NaN (not a number).
266 You can't use x == nan to test this because all
267 comparisons against nan return false.
268 */
269bool isNaN(double x);
270
271/**
272 Computes x % 3.
273 */
274int iMod3(int x);
275
276/**
277 [0, 1]
278 @deprecated use uniformRandom()
279 */
280double unitRandom ();
281
282/**
283 Uniform random number between low and hi, inclusive.
284 @deprecated use uniformRandom()
285 */
286double random(double low, double hi);
287
288/**
289 [-1, 1]
290 @deprecated use uniformRandom()
291 */
292double symmetricRandom ();
293
294/**
295 Uniform random number between low and hi, inclusive. [low, hi]
296 */
297float uniformRandom(float low = 0.0f, float hi = 1.0f);
298
299/**
300 Normally distributed random number.
301 */
302float gaussRandom(float mean = 0.0f, float stdev = 1.0f);
303
304#if defined(_MSC_VER) && (_MSC_VER <= 1200)
305
306    /** VC6 lacks std::min and std::max */
307    inline double min(double x, double y) {
308        return std::_cpp_min(x, y);
309    }
310
311    /** VC6 lacks std::min and std::max */
312    inline float min(float x, float y) {
313        return std::_cpp_min(x, y);
314    }
315
316    /** VC6 lacks std::min and std::max */
317    inline int min(int x, int y) {
318        return std::_cpp_min(x, y);
319    }
320
321    /** VC6 lacks std::min and std::max */
322    inline double max(double x, double y) {
323        return std::_cpp_max(x, y);
324    }
325
326    /** VC6 lacks std::min and std::max */
327    inline float max(float x, float y) {
328        return std::_cpp_max(x, y);
329    }
330
331    /** VC6 lacks std::min and std::max */
332    inline int max(int x, int y) {
333        return std::_cpp_max(x, y);
334    }
335
336#else
337    template <class T>
338    inline T min(const T& x, const T& y) {
339        return std::min<T>(x, y);
340    }
341
342    template <class T>
343    inline T max(const T& x, const T& y) {
344        return std::max<T>(x, y);
345    }
346
347#endif
348
349int iMin(int x, int y);
350int iMax(int x, int y);
351
352double square(double x);
353double sumSquares(double x, double y);
354double sumSquares(double x, double y, double z);
355double distance(double x, double y);
356double distance(double x, double y, double z);
357
358/**
359  Returnes the 0-based index of the highest 1 bit from
360  the left.  -1 means the number was 0.
361
362  @cite Based on code by jukka@liimatta.org
363 */ 
364int highestBit(uint32 x);
365
366/**
367 Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply
368 fuzzyEq(a, c), although that will be the case on some
369 occasions.
370 */
371bool fuzzyEq(double a, double b);
372
373/** True if a is definitely not equal to b. 
374    Guaranteed false if a == b.
375    Possibly false when a != b.*/
376bool fuzzyNe(double a, double b);
377
378/** Is a strictly greater than b? (Guaranteed false if a <= b).
379    (Possibly false if a > b) */
380bool fuzzyGt(double a, double b);
381
382/** Is a near or greater than b? */
383bool fuzzyGe(double a, double b);
384
385/** Is a strictly less than b? (Guaranteed false if a >= b)*/
386bool fuzzyLt(double a, double b);
387
388/** Is a near or less than b? */
389bool fuzzyLe(double a, double b);
390
391/**
392 Computes 1 / sqrt(x).
393 */
394inline float rsq(float x) {
395    return 1.0f / sqrtf(x);
396}
397
398/**
399 Uses SSE to implement rsq.
400 @cite Nick nicolas@capens.net
401 */
402inline float SSErsq(float x) {
403
404    #if defined(SSE) && defined(G3D_WIN32) && !defined(_WIN64)
405        __asm {
406           movss xmm0, x
407           rsqrtss xmm0, xmm0
408           movss x, xmm0
409        }
410        return x;
411    #else
412        return 1.0f / sqrt(x);
413    #endif
414}
415
416/**
417 Return the next power of 2 higher than the input
418 If the input is already a power of 2, the output will be the same
419 as the input.
420 */
421int ceilPow2(unsigned int in);
422
423/**
424 * True if num is a power of two.
425 */
426bool isPow2(int num);
427
428bool isOdd(int num);
429bool isEven(int num);
430
431double toRadians(double deg);
432double toDegrees(double rad);
433
434/**
435 Returns true if x is not exactly equal to 0.0f.
436 */
437inline bool any(float x) {
438    return x != 0;
439}
440
441/**
442 Returns true if x is not exactly equal to 0.0f.
443 */
444inline bool all(float x) {
445    return x != 0;
446}
447
448/**
449 v / v (for DirectX/Cg support)
450 */
451inline float normalize(float v) {
452    return v / v;
453}
454
455/**
456 a * b (for DirectX/Cg support)
457 */
458inline float dot(float a, float b) {
459    return a * b;
460}
461
462
463/**
464 a * b (for DirectX/Cg support)
465 */
466inline float mul(float a, float b) {
467    return a * b;
468}
469
470/**
471 2^x
472 */
473inline double exp2(double x) {
474    return pow(2.0, x);
475}
476
477inline double rsqrt(double x) {
478    return 1.0 / sqrt(x);
479}
480
481
482/**
483 sin(x)/x
484 */
485inline double sinc(double x) {
486    double r = sin(x) / x;
487
488    if (isNaN(r)) {
489        return 1.0;
490    } else {
491        return r;
492    }
493}
494
495/**
496 Computes a floating point modulo; the result is t wrapped to the range [lo, hi).
497 */
498inline double wrap(double t, double lo, double hi) {
499    if ((t >= lo) && (t < hi)) {
500        return t;
501    }
502
503    debugAssert(hi > lo);
504
505    double interval = hi - lo;
506
507    return t - interval * iFloor((t - lo) / interval);
508
509}
510
511inline double wrap(double t, double hi) {
512    return wrap(t, 0, hi);
513}
514
515
516} // namespace
517
518#ifdef _MSC_VER
519#   pragma warning (pop)
520#endif
521
522#include "g3dmath.inl"
523
524#endif
525
Note: See TracBrowser for help on using the browser.