source: GTP/trunk/App/Games/Jungle_Rumble/src/physic/foundation/include/NxMath.h @ 1378

Revision 1378, 20.9 KB checked in by giegl, 18 years ago (diff)

GTPD - Jungle Rumble - integrate into GTP SVN structure

Line 
1#ifndef NX_FOUNDATION_NXMATH
2#define NX_FOUNDATION_NXMATH
3/*----------------------------------------------------------------------------*\
4|
5|                                               Public Interface to NovodeX Technology
6|
7|                                                            www.novodex.com
8|
9\*----------------------------------------------------------------------------*/
10/** \addtogroup foundation
11  @{
12*/
13
14#include <math.h>
15#include <float.h>
16#include <stdlib.h>     //for rand()
17
18#include "Nx.h"
19#include "NxFPU.h"
20
21#ifdef log2
22#undef log2
23#endif
24
25//constants
26static const NxF64 NxPiF64              = 3.141592653589793;
27static const NxF64 NxHalfPiF64  = 1.57079632679489661923;
28static const NxF64 NxTwoPiF64   = 6.28318530717958647692;
29static const NxF64 NxInvPiF64   = 0.31830988618379067154;
30//we can get bad range checks if we use double prec consts to check single prec results.
31static const NxF32 NxPiF32              = 3.141592653589793f;
32static const NxF32 NxHalfPiF32  = 1.57079632679489661923f;
33static const NxF32 NxTwoPiF32   = 6.28318530717958647692f;
34static const NxF32 NxInvPiF32   = 0.31830988618379067154f;
35
36
37#if defined(min) || defined(max)
38#error Error: min or max is #defined, probably in <windows.h>.  Put #define NOMINMAX before including windows.h to suppress windows global min,max macros.
39#endif
40
41/**
42\brief Static class with stateless scalar math routines.
43*/
44class NxMath
45        {
46        public:
47
48// Type conversion and rounding
49                /**
50                \brief Returns true if the two numbers are within eps of each other.
51                */
52                NX_INLINE static bool equals(NxF32,NxF32,NxF32 eps);
53
54                /**
55                \brief Returns true if the two numbers are within eps of each other.
56                */
57                NX_INLINE static bool equals(NxF64,NxF64,NxF64 eps);
58                /**
59                \brief The floor function returns a floating-point value representing the largest integer that is less than or equal to x.
60                */
61                NX_INLINE static NxF32 floor(NxF32);
62                /**
63                \brief The floor function returns a floating-point value representing the largest integer that is less than or equal to x.
64                */
65                NX_INLINE static NxF64 floor(NxF64);
66
67
68                /**
69                \brief The ceil function returns a single value representing the smallest integer that is greater than or equal to x.
70                */
71                NX_INLINE static NxF32 ceil(NxF32);
72                /**
73                \brief The ceil function returns a double value representing the smallest integer that is greater than or equal to x.
74                */
75                NX_INLINE static NxF64 ceil(NxF64);
76
77                /**
78                \brief Truncates the float to an integer.
79                */
80                NX_INLINE static NxI32 trunc(NxF32);
81                /**
82                \brief Truncates the double precision float to an integer.
83                */
84                NX_INLINE static NxI32 trunc(NxF64);
85
86
87                /**
88                \brief abs returns the absolute value of its argument.
89                */
90                NX_INLINE static NxF32 abs(NxF32);
91                /**
92                \brief abs returns the absolute value of its argument.
93                */
94                NX_INLINE static NxF64 abs(NxF64);
95                /**
96                \brief abs returns the absolute value of its argument.
97                */
98                NX_INLINE static NxI32 abs(NxI32);
99
100
101                /**
102                \brief sign returns the sign of its argument. The sign of zero is undefined.
103                */
104                NX_INLINE static NxF32 sign(NxF32);
105                /**
106                \brief sign returns the sign of its argument. The sign of zero is undefined.
107                */
108                NX_INLINE static NxF64 sign(NxF64);
109                /**
110                \brief sign returns the sign of its argument. The sign of zero is undefined.
111                */
112                NX_INLINE static NxI32 sign(NxI32);
113
114
115                /**
116                \brief The return value is the greater of the two specified values.
117                */
118                NX_INLINE static NxF32 max(NxF32,NxF32);
119                /**
120                \brief The return value is the greater of the two specified values.
121                */
122                NX_INLINE static NxF64 max(NxF64,NxF64);
123                /**
124                \brief The return value is the greater of the two specified values.
125                */
126                NX_INLINE static NxI32 max(NxI32,NxI32);
127                /**
128                \brief The return value is the greater of the two specified values.
129                */
130                NX_INLINE static NxU32 max(NxU32,NxU32);
131                /**
132                \brief The return value is the greater of the two specified values.
133                */
134                NX_INLINE static NxU16 max(NxU16,NxU16);
135               
136               
137                /**
138                \brief The return value is the lesser of the two specified values.
139                */
140                NX_INLINE static NxF32 min(NxF32,NxF32);
141                /**
142                \brief The return value is the lesser of the two specified values.
143                */
144                NX_INLINE static NxF64 min(NxF64,NxF64);
145                /**
146                \brief The return value is the lesser of the two specified values.
147                */
148                NX_INLINE static NxI32 min(NxI32,NxI32);
149                /**
150                \brief The return value is the lesser of the two specified values.
151                */
152                NX_INLINE static NxU32 min(NxU32,NxU32);
153                /**
154                \brief The return value is the lesser of the two specified values.
155                */
156                NX_INLINE static NxU16 min(NxU16,NxU16);
157               
158                /**
159                \brief mod returns the floating-point remainder of x / y.
160               
161                If the value of y is 0.0, mod returns a quiet NaN.
162                */
163                NX_INLINE static NxF32 mod(NxF32 x, NxF32 y);
164                /**
165                \brief mod returns the floating-point remainder of x / y.
166               
167                If the value of y is 0.0, mod returns a quiet NaN.
168                */
169                NX_INLINE static NxF64 mod(NxF64 x, NxF64 y);
170
171                /**
172                \brief Clamps v to the range [hi,lo]
173                */
174                NX_INLINE static NxF32 clamp(NxF32 v, NxF32 hi, NxF32 low);
175                /**
176                \brief Clamps v to the range [hi,lo]
177                */
178                NX_INLINE static NxF64 clamp(NxF64 v, NxF64 hi, NxF64 low);
179                /**
180                \brief Clamps v to the range [hi,lo]
181                */
182                NX_INLINE static NxU32 clamp(NxU32 v, NxU32 hi, NxU32 low);
183                /**
184                \brief Clamps v to the range [hi,lo]
185                */
186                NX_INLINE static NxI32 clamp(NxI32 v, NxI32 hi, NxI32 low);
187
188                //!powers
189                /**
190                \brief Square root.
191                */
192                NX_INLINE static NxF32 sqrt(NxF32);
193                /**
194                \brief Square root.
195                */
196                NX_INLINE static NxF64 sqrt(NxF64);
197               
198                /**
199                \brief reciprocal square root.
200                */
201                NX_INLINE static NxF32 recipSqrt(NxF32);
202                /**
203                \brief reciprocal square root.
204                */
205                NX_INLINE static NxF64 recipSqrt(NxF64);
206               
207                /**
208                \brief Calculates x raised to the power of y.
209                */
210                NX_INLINE static NxF32 pow(NxF32 x, NxF32 y);
211                /**
212                \brief Calculates x raised to the power of y.
213                */
214                NX_INLINE static NxF64 pow(NxF64 x, NxF64 y);
215               
216               
217                /**
218                \brief Calculates e^n
219                */
220                NX_INLINE static NxF32 exp(NxF32);
221                /**
222                \brief Calculates e^n
223                */
224                NX_INLINE static NxF64 exp(NxF64);
225               
226                /**
227                \brief Calculates logarithms.
228                */
229                NX_INLINE static NxF32 logE(NxF32);
230                /**
231                \brief Calculates logarithms.
232                */
233                NX_INLINE static NxF64 logE(NxF64);
234                /**
235                \brief Calculates logarithms.
236                */
237                NX_INLINE static NxF32 log2(NxF32);
238                /**
239                \brief Calculates logarithms.
240                */
241                NX_INLINE static NxF64 log2(NxF64);
242                /**
243                \brief Calculates logarithms.
244                */
245                NX_INLINE static NxF32 log10(NxF32);
246                /**
247                \brief Calculates logarithms.
248                */
249                NX_INLINE static NxF64 log10(NxF64);
250
251                //!trigonometry -- all angles are in radians.
252               
253                /**
254                \brief Converts degrees to radians.
255                */
256                NX_INLINE static NxF32 degToRad(NxF32);
257                /**
258                \brief Converts degrees to radians.
259                */
260                NX_INLINE static NxF64 degToRad(NxF64);
261
262                /**
263                \brief Converts radians to degrees.
264                */
265                NX_INLINE static NxF32 radToDeg(NxF32);
266                /**
267                \brief Converts radians to degrees.
268                */
269                NX_INLINE static NxF64 radToDeg(NxF64);
270
271                /**
272                \brief Sine of an angle.
273
274                <b>Unit:</b> Radians
275                */
276                NX_INLINE static NxF32 sin(NxF32);
277                /**
278                \brief Sine of an angle.
279
280                <b>Unit:</b> Radians
281                */
282                NX_INLINE static NxF64 sin(NxF64);
283               
284                /**
285                \brief Cosine of an angle.
286
287                <b>Unit:</b> Radians
288                */
289                NX_INLINE static NxF32 cos(NxF32);
290                /**
291                \brief Cosine of an angle.
292
293                <b>Unit:</b> Radians
294                */
295                NX_INLINE static NxF64 cos(NxF64);
296
297                /**
298                \brief Computes both the sin and cos.
299
300                <b>Unit:</b> Radians
301                */
302                NX_INLINE static void sinCos(NxF32, NxF32 & sin, NxF32 & cos);
303
304                /**
305                \brief Computes both the sin and cos.
306
307                <b>Unit:</b> Radians
308                */
309                NX_INLINE static void sinCos(NxF64, NxF64 & sin, NxF64 & cos);
310
311
312                /**
313                \brief Tangent of an angle.
314
315                <b>Unit:</b> Radians
316                */
317                NX_INLINE static NxF32 tan(NxF32);
318                /**
319                \brief Tangent of an angle.
320
321                <b>Unit:</b> Radians
322                */
323                NX_INLINE static NxF64 tan(NxF64);
324               
325                /**
326                \brief Arcsine.
327               
328                Returns angle between -PI/2 and PI/2 in radians
329
330                <b>Unit:</b> Radians
331                */
332                NX_INLINE static NxF32 asin(NxF32);
333                /**
334                \brief Arcsine.
335               
336                Returns angle between -PI/2 and PI/2 in radians
337
338                <b>Unit:</b> Radians
339                */
340                NX_INLINE static NxF64 asin(NxF64);
341               
342                /**
343                \brief Arccosine.
344               
345                Returns angle between 0 and PI in radians
346
347                <b>Unit:</b> Radians
348                */
349                NX_INLINE static NxF32 acos(NxF32);
350               
351                /**
352                \brief Arccosine.
353               
354                Returns angle between 0 and PI in radians
355
356                <b>Unit:</b> Radians
357                */
358                NX_INLINE static NxF64 acos(NxF64);
359               
360                /**
361                \brief ArcTangent.
362               
363                Returns angle between -PI/2 and PI/2 in radians
364
365                <b>Unit:</b> Radians
366                */
367                NX_INLINE static NxF32 atan(NxF32);
368                /**
369                \brief ArcTangent.
370               
371                Returns angle between -PI/2 and PI/2 in radians
372
373                <b>Unit:</b> Radians
374                */
375                NX_INLINE static NxF64 atan(NxF64);
376
377                /**
378                \brief Arctangent of (x/y) with correct sign.
379               
380                Returns angle between -PI and PI in radians
381
382                <b>Unit:</b> Radians
383                */
384                NX_INLINE static NxF32 atan2(NxF32 x, NxF32 y);
385                /**
386                \brief Arctangent of (x/y) with correct sign.
387               
388                Returns angle between -PI and PI in radians
389
390                <b>Unit:</b> Radians
391                */
392                NX_INLINE static NxF64 atan2(NxF64 x, NxF64 y);
393
394                //random numbers
395               
396                /**
397                \brief uniform random number in [a,b]
398                */
399                NX_INLINE static NxF32 rand(NxF32 a,NxF32 b);
400               
401                /**
402                \brief uniform random number in [a,b]
403                */
404                NX_INLINE static NxI32 rand(NxI32 a,NxI32 b);
405
406                /**
407                \brief hashing: hashes an array of n 32 bit values      to a 32 bit value.
408               
409                Because the output bits are uniformly distributed, the caller may mask
410                off some of the bits to index into a hash table smaller than 2^32.
411                */
412                NX_INLINE static NxU32 hash(NxU32 * array, NxU32 n);
413
414                /**
415                \brief hash32
416                */
417                NX_INLINE static int hash32(int);
418
419                /**
420                \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc.
421                */
422                NX_INLINE static bool isFinite(NxF32 x);
423               
424                /**
425                \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc.
426                */
427                NX_INLINE static bool isFinite(NxF64 x);
428        };
429
430/*
431Many of these are just implemented as NX_INLINE calls to the C lib right now,
432but later we could replace some of them with some approximations or more
433clever stuff.
434*/
435NX_INLINE bool NxMath::equals(NxF32 a,NxF32 b,NxF32 eps)
436        {
437        const NxF32 diff = NxMath::abs(a - b);
438        return (diff < eps);
439        }
440
441NX_INLINE bool NxMath::equals(NxF64 a,NxF64 b,NxF64 eps)
442        {
443        const NxF64 diff = NxMath::abs(a - b);
444        return (diff < eps);
445        }
446
447NX_INLINE NxF32 NxMath::floor(NxF32 a)
448        {
449        return ::floorf(a);
450        }
451
452NX_INLINE NxF64 NxMath::floor(NxF64 a)
453        {
454        return ::floor(a);
455        }
456
457NX_INLINE NxF32 NxMath::ceil(NxF32 a)
458        {
459        return ::ceilf(a);
460        }
461
462NX_INLINE NxF64 NxMath::ceil(NxF64 a)
463        {
464        return ::ceil(a);
465        }
466
467NX_INLINE NxI32 NxMath::trunc(NxF32 a)
468        {
469        return (NxI32) a;       // ### PT: this actually depends on FPU settings
470        }
471
472NX_INLINE NxI32 NxMath::trunc(NxF64 a)
473        {
474        return (NxI32) a;       // ### PT: this actually depends on FPU settings
475        }
476
477NX_INLINE NxF32 NxMath::abs(NxF32 a)
478        {
479        return ::fabsf(a);
480        }
481
482NX_INLINE NxF64 NxMath::abs(NxF64 a)
483        {
484        return ::fabs(a);
485        }
486
487NX_INLINE NxI32 NxMath::abs(NxI32 a)
488        {
489        return ::abs(a);
490        }
491
492NX_INLINE NxF32 NxMath::sign(NxF32 a)
493        {
494        return (a >= 0.0f) ? 1.0f : -1.0f;
495        }
496
497NX_INLINE NxF64 NxMath::sign(NxF64 a)
498        {
499        return (a >= 0.0) ? 1.0 : -1.0;
500        }
501
502NX_INLINE NxI32 NxMath::sign(NxI32 a)
503        {
504        return (a >= 0) ? 1 : -1;
505        }
506
507NX_INLINE NxF32 NxMath::max(NxF32 a,NxF32 b)
508        {
509        return (a < b) ? b : a;
510        }
511
512NX_INLINE NxF64 NxMath::max(NxF64 a,NxF64 b)
513        {
514        return (a < b) ? b : a;
515        }
516
517NX_INLINE NxI32 NxMath::max(NxI32 a,NxI32 b)
518        {
519        return (a < b) ? b : a;
520        }
521
522NX_INLINE NxU32 NxMath::max(NxU32 a,NxU32 b)
523        {
524        return (a < b) ? b : a;
525        }
526
527NX_INLINE NxU16 NxMath::max(NxU16 a,NxU16 b)
528        {
529        return (a < b) ? b : a;
530        }
531
532NX_INLINE NxF32 NxMath::min(NxF32 a,NxF32 b)
533        {
534        return (a < b) ? a : b;
535        }
536
537NX_INLINE NxF64 NxMath::min(NxF64 a,NxF64 b)
538        {
539        return (a < b) ? a : b;
540        }
541
542NX_INLINE NxI32 NxMath::min(NxI32 a,NxI32 b)
543        {
544        return (a < b) ? a : b;
545        }
546
547NX_INLINE NxU32 NxMath::min(NxU32 a,NxU32 b)
548        {
549        return (a < b) ? a : b;
550        }
551
552NX_INLINE NxU16 NxMath::min(NxU16 a,NxU16 b)
553        {
554        return (a < b) ? a : b;
555        }
556
557NX_INLINE NxF32 NxMath::mod(NxF32 x, NxF32 y)
558        {
559        return (NxF32)::fmod(x,y);
560        }
561
562NX_INLINE NxF64 NxMath::mod(NxF64 x, NxF64 y)
563        {
564        return ::fmod(x,y);
565        }
566
567NX_INLINE NxF32 NxMath::clamp(NxF32 v, NxF32 hi, NxF32 low)
568        {
569        if (v > hi)
570                return hi;
571        else if (v < low)
572                return low;
573        else
574                return v;
575        }
576
577NX_INLINE NxF64 NxMath::clamp(NxF64 v, NxF64 hi, NxF64 low)
578        {
579        if (v > hi)
580                return hi;
581        else if (v < low)
582                return low;
583        else
584                return v;
585        }
586
587NX_INLINE NxU32 NxMath::clamp(NxU32 v, NxU32 hi, NxU32 low)
588        {
589        if (v > hi)
590                return hi;
591        else if (v < low)
592                return low;
593        else
594                return v;
595        }
596
597NX_INLINE NxI32 NxMath::clamp(NxI32 v, NxI32 hi, NxI32 low)
598        {
599        if (v > hi)
600                return hi;
601        else if (v < low)
602                return low;
603        else
604                return v;
605        }
606
607NX_INLINE NxF32 NxMath::sqrt(NxF32 a)
608        {
609        return ::sqrtf(a);
610        }
611
612NX_INLINE NxF64 NxMath::sqrt(NxF64 a)
613        {
614        return ::sqrt(a);
615        }
616
617NX_INLINE NxF32 NxMath::recipSqrt(NxF32 a)
618        {
619        return 1.0f/::sqrtf(a);
620        }
621
622NX_INLINE NxF64 NxMath::recipSqrt(NxF64 a)
623        {
624        return 1.0/::sqrt(a);
625        }
626
627NX_INLINE NxF32 NxMath::pow(NxF32 x, NxF32 y)
628        {
629        return ::powf(x,y);
630        }
631
632NX_INLINE NxF64 NxMath::pow(NxF64 x, NxF64 y)
633        {
634        return ::pow(x,y);
635        }
636
637NX_INLINE NxF32 NxMath::exp(NxF32 a)
638        {
639        return ::expf(a);
640        }
641
642NX_INLINE NxF64 NxMath::exp(NxF64 a)
643        {
644        return ::exp(a);
645        }
646
647NX_INLINE NxF32 NxMath::logE(NxF32 a)
648        {
649        return ::logf(a);
650        }
651
652NX_INLINE NxF64 NxMath::logE(NxF64 a)
653        {
654        return ::log(a);
655        }
656
657NX_INLINE NxF32 NxMath::log2(NxF32 a)
658        {
659        const NxF32 ln2 = (NxF32)0.693147180559945309417;
660    return ::logf(a) / ln2;
661        }
662
663NX_INLINE NxF64 NxMath::log2(NxF64 a)
664        {
665        const NxF64 ln2 = (NxF64)0.693147180559945309417;
666    return ::log(a) / ln2;
667        }
668
669NX_INLINE NxF32 NxMath::log10(NxF32 a)
670        {
671        return (NxF32)::log10(a);
672        }
673
674NX_INLINE NxF64 NxMath::log10(NxF64 a)
675        {
676        return ::log10(a);
677        }
678
679NX_INLINE NxF32 NxMath::degToRad(NxF32 a)
680        {
681        return (NxF32)0.01745329251994329547 * a;
682        }
683
684NX_INLINE NxF64 NxMath::degToRad(NxF64 a)
685        {
686        return (NxF64)0.01745329251994329547 * a;
687        }
688
689NX_INLINE NxF32 NxMath::radToDeg(NxF32 a)
690        {
691        return (NxF32)57.29577951308232286465 * a;
692        }
693
694NX_INLINE NxF64 NxMath::radToDeg(NxF64 a)
695        {
696        return (NxF64)57.29577951308232286465 * a;
697        }
698
699NX_INLINE NxF32 NxMath::sin(NxF32 a)
700        {
701        return ::sinf(a);
702        }
703
704NX_INLINE NxF64 NxMath::sin(NxF64 a)
705        {
706        return ::sin(a);
707        }
708
709NX_INLINE NxF32 NxMath::cos(NxF32 a)
710        {
711        return ::cosf(a);
712        }
713
714NX_INLINE NxF64 NxMath::cos(NxF64 a)
715        {
716        return ::cos(a);
717        }
718
719// Calling fsincos instead of fsin+fcos
720NX_INLINE void NxMath::sinCos(NxF32 f, NxF32& s, NxF32& c)
721        {
722#ifdef WIN32
723                NxF32 localCos, localSin;
724                NxF32 local = f;
725                _asm    fld             local
726                _asm    fsincos
727                _asm    fstp    localCos
728                _asm    fstp    localSin
729                c = localCos;
730                s = localSin;
731#else
732                c = cosf(f);
733                s = sinf(f);
734#endif
735        }
736
737NX_INLINE void NxMath::sinCos(NxF64 a, NxF64 & s, NxF64 & c)
738        {
739        s = ::sin(a);
740        c = ::cos(a);
741        }
742
743NX_INLINE NxF32 NxMath::tan(NxF32 a)
744        {
745        return ::tanf(a);
746        }
747
748NX_INLINE NxF64 NxMath::tan(NxF64 a)
749        {
750        return ::tan(a);
751        }
752
753NX_INLINE NxF32 NxMath::asin(NxF32 f)
754        {
755        // Take care of FPU inaccuracies
756        if(f>=1.0f)     return (NxF32)NxHalfPiF32;
757        if(f<=-1.0f)return -(NxF32)NxHalfPiF32;
758                                return ::asinf(f);
759        }
760
761NX_INLINE NxF64 NxMath::asin(NxF64 f)
762        {
763        // Take care of FPU inaccuracies
764        if(f>=1.0)      return (NxF32)NxHalfPiF64;
765        if(f<=-1.0)     return -(NxF32)NxHalfPiF64;
766                                return ::asin(f);
767        }
768
769NX_INLINE NxF32 NxMath::acos(NxF32 f)
770        {
771        // Take care of FPU inaccuracies
772        if(f>=1.0f)     return 0.0f;
773        if(f<=-1.0f)return (NxF32)NxPiF32;
774                                return ::acosf(f);
775        }
776
777NX_INLINE NxF64 NxMath::acos(NxF64 f)
778        {
779        // Take care of FPU inaccuracies
780        if(f>=1.0)      return 0.0;
781        if(f<=-1.0)     return (NxF64)NxPiF64;
782                                return ::acos(f);
783        }
784
785NX_INLINE NxF32 NxMath::atan(NxF32 a)
786        {
787        return ::atanf(a);
788        }
789
790NX_INLINE NxF64 NxMath::atan(NxF64 a)
791        {
792        return ::atan(a);
793        }
794
795NX_INLINE NxF32 NxMath::atan2(NxF32 x, NxF32 y)
796        {
797        return ::atan2f(x,y);
798        }
799
800NX_INLINE NxF64 NxMath::atan2(NxF64 x, NxF64 y)
801        {
802        return ::atan2(x,y);
803        }
804
805NX_INLINE NxF32 NxMath::rand(NxF32 a,NxF32 b)
806        {
807        const NxF32 r = (NxF32)::rand()/((NxF32)RAND_MAX+1);
808        return r*(b-a) + a;
809        }
810
811NX_INLINE NxI32 NxMath::rand(NxI32 a,NxI32 b)
812        {
813        return a + (NxI32)(::rand()%(b-a));
814        }
815
816/*
817--------------------------------------------------------------------
818lookup2.c, by Bob Jenkins, December 1996, Public Domain.
819hash(), hash2(), hash3, and mix() are externally useful functions.
820Routines to test the hash are included if SELF_TEST is defined.
821You can use this free for any purpose.  It has no warranty.
822--------------------------------------------------------------------
823--------------------------------------------------------------------
824mix -- mix 3 32-bit values reversibly.
825For every delta with one or two bit set, and the deltas of all three
826  high bits or all three low bits, whether the original value of a,b,c
827  is almost all zero or is uniformly distributed,
828* If mix() is run forward or backward, at least 32 bits in a,b,c
829  have at least 1/4 probability of changing.
830* If mix() is run forward, every bit of c will change between 1/3 and
831  2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
832mix() was built out of 36 single-cycle latency instructions in a
833  structure that could supported 2x parallelism, like so:
834      a -= b;
835      a -= c; x = (c>>13);
836      b -= c; a ^= x;
837      b -= a; x = (a<<8);
838      c -= a; b ^= x;
839      c -= b; x = (b>>13);
840      ...
841  Unfortunately, superscalar Pentiums and Sparcs can't take advantage
842  of that parallelism.  They've also turned some of those single-cycle
843  latency instructions into multi-cycle latency instructions.  Still,
844  this is the fastest good hash I could find.  There were about 2^^68
845  to choose from.  I only looked at a billion or so.
846--------------------------------------------------------------------
847*/
848#define NX_HASH_MIX(a,b,c) \
849{ \
850  a -= b; a -= c; a ^= (c>>13); \
851  b -= c; b -= a; b ^= (a<<8); \
852  c -= a; c -= b; c ^= (b>>13); \
853  a -= b; a -= c; a ^= (c>>12);  \
854  b -= c; b -= a; b ^= (a<<16); \
855  c -= a; c -= b; c ^= (b>>5); \
856  a -= b; a -= c; a ^= (c>>3);  \
857  b -= c; b -= a; b ^= (a<<10); \
858  c -= a; c -= b; c ^= (b>>15); \
859}
860
861/*
862--------------------------------------------------------------------
863 This works on all machines.  hash2() is identical to hash() on
864 little-endian machines, except that the length has to be measured
865 in ub4s instead of bytes.  It is much faster than hash().  It
866 requires
867 -- that the key be an array of ub4's, and
868 -- that all your machines have the same endianness, and
869 -- that the length be the number of ub4's in the key
870--------------------------------------------------------------------
871*/
872NX_INLINE NxU32 NxMath::hash(  NxU32 *k, NxU32 length)
873//register ub4 *k;        /* the key */
874//register ub4  length;   /* the length of the key, in ub4s */
875        {
876        NxU32 a,b,c,len;
877
878        /* Set up the internal state */
879        len = length;
880        a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
881        c = 0;           /* the previous hash value */
882
883        /*---------------------------------------- handle most of the key */
884        while (len >= 3)
885        {
886          a += k[0];
887          b += k[1];
888          c += k[2];
889          NX_HASH_MIX(a,b,c);
890          k += 3; len -= 3;
891        }
892
893        /*-------------------------------------- handle the last 2 ub4's */
894        c += length;
895        switch(len)              /* all the case statements fall through */
896        {
897         /* c is reserved for the length */
898        case 2 : b+=k[1];
899        case 1 : a+=k[0];
900         /* case 0: nothing left to add */
901        }
902        NX_HASH_MIX(a,b,c);
903        /*-------------------------------------------- report the result */
904        return c;
905        }
906#undef NX_HASH_MIX
907
908NX_INLINE int NxMath::hash32(int key)
909        {
910        key += ~(key << 15);
911        key ^=  (key >> 10);
912        key +=  (key << 3);
913        key ^=  (key >> 6);
914        key += ~(key << 11);
915        key ^=  (key >> 16);
916        return key;
917        }
918
919
920NX_INLINE bool NxMath::isFinite(NxF32 f)
921        {
922        #if defined(_MSC_VER)
923        return (0 == ((_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF) & _fpclass(f) ));
924        #else
925        return true;
926        #endif
927       
928        }
929
930NX_INLINE bool NxMath::isFinite(NxF64 f)
931        {
932        #if defined(_MSC_VER)
933        return (0 == ((_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF) & _fpclass(f) ));
934        #else
935        return true;
936        #endif
937        }
938
939 /** @} */
940#endif
941
942
943//AGCOPYRIGHTBEGIN
944///////////////////////////////////////////////////////////////////////////
945// Copyright © 2005 AGEIA Technologies.
946// All rights reserved. www.ageia.com
947///////////////////////////////////////////////////////////////////////////
948//AGCOPYRIGHTEND
949
Note: See TracBrowser for help on using the repository browser.