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

src/Random.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 #include <spl/types.h>
00018 
00019 #ifdef _WINDOWS
00020 #include <spl/configwin32.h>
00021 #else
00022 #include <spl/autoconf/config.h>
00023 #endif
00024 
00025 #ifdef HAVE_TIME_H
00026 #include <time.h>
00027 #endif
00028 #ifdef HAVE_SYS_TIME_H
00029 #include <sys/time.h>
00030 #endif
00031 #include <math.h>
00032 
00033 #include <spl/math/Random.h>
00034 
00035 #define RAND_MAX_COMBO (4294967295.0/2)
00036 
00037 Random::Random()
00038 {
00039         combo_x = 3;
00040         combo_y = 1;
00041         combo_z = 1;
00042         combo_v = 0;
00043 
00044         uint32 seed;
00045 
00046         time_t _t;
00047         time (&_t);
00048         seed = ((long)_t) & (((long)_t) << 16) & ((long)_t) & (((long)_t) << 16);
00049     combo_x = seed * 8 + 3;
00050     combo_y = seed * 2 + 1;
00051     combo_z = seed | 1;
00052     combo_v = 0;
00053 }
00054 
00055 Random::Random(int seed)
00056 {
00057     combo_x = seed * 8 + 3;
00058     combo_y = seed * 2 + 1;
00059     combo_z = seed | 1;
00060     combo_v = 0;
00061 }
00062 
00063 int Random::Next()
00064 {
00065     combo_v = combo_x * combo_y;
00066     combo_x = combo_y;
00067     combo_y = combo_v;
00068     combo_z = (combo_z & 65535L) * 30903 + (combo_z >> 16);
00069         int rnd = combo_y + combo_z;
00070         if ( rnd < 0 )
00071         {
00072                 return -1 * rnd;
00073         }
00074         return rnd;
00075 }
00076 
00077 int Random::Next(int max)
00078 {
00079         return Next() % max;
00080 }
00081 
00082 int Random::Next(int min, int max)
00083 {
00084         return (int)(NextDouble() * (max - min) + min);
00085 }
00086 
00087 double Random::NextDouble()
00088 {
00089         double val = fabs((double)Next()/(double)RAND_MAX_COMBO);
00090         ASSERT( val <= 1.0 );
00091         return val;
00092 }
00093 
00094 void Random::NextBytes(byte *data, int len)
00095 {
00096         for ( int x = 0; x < len; x++ )
00097         {
00098                 int next = Next(256);
00099                 ASSERT (next < 256);
00100                 data[x] = (byte)next;
00101         }
00102 }
00103 
00104 int Random::NextInt()
00105 {
00106     combo_v = combo_x * combo_y;
00107     combo_x = combo_y;
00108     combo_y = combo_v;
00109     combo_z = (combo_z & 65535L) * 30903 + (combo_z >> 16);
00110         return combo_y + combo_z;
00111 }