• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Math.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #ifdef _WIN32
00018 #include <spl/configwin32.h>
00019 #else
00020 #include <spl/autoconf/config.h>
00021 #endif
00022 
00023 #ifdef HAVE_TIME_H
00024 #include <time.h>
00025 #endif
00026 #ifdef HAVE_SYS_TIME_H
00027 #include <sys/time.h>
00028 #endif
00029 
00030 #include <spl/math/Math.h>
00031 
00032 uint32 Math::combo_x = 3;
00033 uint32 Math::combo_y = 1;
00034 uint32 Math::combo_z = 1;
00035 uint32 Math::combo_v = 0;
00036 bool Math::gInited = false;
00037 
00038 #define RAND_MAX_COMBO (4294967295.0/2)
00039 
00040 IHashable::~IHashable()
00041 {
00042 }
00043 
00044 IComparable::~IComparable()
00045 {
00046 }
00047 
00048 IMemoryValidate::~IMemoryValidate()
00049 {
00050 }
00051 
00052 void Math::InitRandom()
00053 {
00054         uint32 seed;
00055 
00056         time_t _t;
00057         time (&_t);
00058         seed = ((long)_t) & (((long)_t) << 16) & ((long)_t) & (((long)_t) << 16);
00059     combo_x = seed * 8 + 3;
00060     combo_y = seed * 2 + 1;
00061     combo_z = seed | 1;
00062     combo_v = 0;
00063 }
00064 
00065 double Math::Random()
00066 {
00067         return fabs((double)(RandomInt())/(double)RAND_MAX_COMBO);
00068 }
00069 
00070 int Math::RandomInt()
00071 {
00072         if ( ! gInited )
00073         {
00074                 InitRandom();
00075         }
00076     combo_v = combo_x * combo_y;
00077     combo_x = combo_y;
00078     combo_y = combo_v;
00079     combo_z = (combo_z & 65535L) * 30903 + (combo_z >> 16);
00080         return combo_y + combo_z;
00081 }
00082 
00083 // Internal method to test if a positive number is prime.
00084 // Not an efficient algorithm.
00085 bool Math::IsPrime( const int n ) 
00086 {
00087         if( n == 2 || n == 3 )
00088         {
00089                 return true;
00090         }
00091         if( n == 1 || n % 2 == 0 )
00092         {
00093                 return false;
00094         }
00095         for( int i = 3; i * i <= n; i += 2 )
00096         {
00097                 if( n % i == 0 )
00098                 {
00099                         return false;
00100                 }
00101         }
00102         return true;
00103 }
00104 
00105 // Internal method to return a prime number at least as large as n.
00106 // Assumes n > 0.
00107 int Math::NextPrime( const int n )
00108 {
00109         int prime = n;
00110         if( prime % 2 == 0 )
00111         {
00112                 prime++;
00113         }
00114         for( ; !IsPrime( prime ); prime += 2 )
00115         {
00116         }
00117         return prime;
00118 }
00119 
00120 int32 Math::Hash( const float32 i )
00121 {
00122         double fractpart, intpart;
00123         fractpart = modf (i, &intpart);
00124         
00125         return ( ((int)intpart ) ^ (int)(fractpart * 100000) );
00126 }
00127 
00128 int32 Math::Hash( const float64 i )
00129 {
00130         double fractpart, intpart;
00131         fractpart = modf (i, &intpart);
00132         
00133         return ( ((int)intpart ) ^ (int)(fractpart * 100000) );
00134 }
00135 
00136 int32 Math::Hash( const char *str )
00137 {
00138         int len = (int)strlen(str);
00139         int x;
00140         int hash = 0;
00141         int lenmod4 = len % 4;
00142         int part;
00143 
00144         ASSERT( (len - lenmod4)%4 == 0 );
00145         for ( x = 0; x < len - lenmod4; x+=4 )
00146         {
00147                 part = str[x];
00148 
00149                 /*ASSERT_PTR( &str->cstr[x+1] );*/
00150                 part |= (int)str[x+1] << 8;
00151 
00152                 /*ASSERT_PTR( &str->cstr[x+2] );*/
00153                 part |= (int)str[x+2] << 16;
00154 
00155                 /*ASSERT_PTR( &str->cstr[x+3] );*/
00156                 part |= (int)str[x+3] << 24;
00157 
00158                 hash ^= part;
00159         }
00160         part = 0;
00161         if ( lenmod4 > 2 )
00162         {
00163                 /*ASSERT_PTR( &str->cstr[len-3] );*/
00164                 part |= (int)str[len-3];
00165         }
00166         if ( lenmod4 > 1 )
00167         {
00168                 /*ASSERT_PTR( &str->cstr[len-2] );*/
00169                 part |= (int)str[len-2];
00170         }
00171         if ( lenmod4 > 0 )
00172         {
00173                 /*ASSERT_PTR( &str->cstr[len-1] );*/
00174                 part |= (int)str[len-1];
00175                 hash ^= part;
00176         }
00177         if ( hash < 0 )
00178         {
00179                 return -hash;
00180         }
00181         return hash;
00182 }
00183 
00184 int32 Math::Hash( const IHashable& i)
00185 {
00186         return i.HashCode();
00187 }
00188 
00189 int32 Math::Hash( const IHashable *i)
00190 {
00191         return i->HashCode();
00192 }
00193 
00194 float32 FastMath::InvSqrt(float32 x)
00195 {
00196         /* A very fast function to calculate the approximate inverse square root of a
00197          * floating point value and a helper function that uses it for getting the
00198          * normal squareroot. For an explanation of the inverse squareroot function
00199          * read:
00200          * http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf
00201          *
00202          * Unfortunately the original creator of this function seems to be unknown.
00203          */
00204         union { int i; float32 x; } tmp;
00205         float32 xhalf = 0.5f * x;
00206         tmp.x = x;
00207         tmp.i = 0x5f375a86 - (tmp.i >> 1);
00208         x = tmp.x;
00209         x = x * (1.5f - xhalf * x * x);
00210         return x;
00211 }
00212 
00213 float64 FastMath::m_sinus[4096];
00214 float64 FastMath::m_cosinus[4096];
00215 bool FastMath::m_trig = false;
00216 float64 FastMath::m_rad2scale = 4096.0 / Math::PI() / 2.0;
00217 float64 FastMath::m_pad = 256 * Math::PI();
00218 
00219 int FastMath::m_fastRandoms[32];
00220 int FastMath::m_fastRndPointer = 0;
00221 bool FastMath::m_fastRndInit = false;
00222 
00223 void FastMath::BuildTrig()
00224 {
00225         for (int i = 0; i < 4096; i++)
00226         {
00227                 m_sinus[i] = Math::Sin((float64) (i / m_rad2scale));
00228                 m_cosinus[i] = Math::Cos((float64) (i / m_rad2scale));
00229         }
00230         m_trig = true;
00231 }
00232 
00233 void FastMath::CropBuffer(int *buffer, int size, int min, int max)
00234 {
00235         for (int i = size - 1; i >= 0; i--) 
00236         {
00237                 buffer[i] = Crop(buffer[i], min, max);
00238         }
00239 }
00240 
00241 int FastMath::FastRandom(int bits)
00242 {
00243         if ( bits < 1 ) 
00244                 return 0;
00245         m_fastRndPointer = (m_fastRndPointer+1) & 31;
00246         if (!m_fastRndInit)
00247         {
00248                 for (int i=0;i<32;i++) 
00249                 {
00250                         m_fastRandoms[i] = (int)Random(0,0xFFFFFF);
00251                 }
00252                 m_fastRndInit = true;
00253         }
00254         return m_fastRandoms[m_fastRndPointer]&(1<<(bits-1));
00255 }