Commit 85026cce authored by Stephen M. Webb's avatar Stephen M. Webb

debian/patches/0002-replace-mersenne-twister.patch: new file

parent 731ef96c
......@@ -7,8 +7,9 @@ wfmath (1.0.1-1) unstable; urgency=low
* debian/control: used canonical form for VCS-* fields
* debian/rules: forced verbose build
* debian/libwfmath-1.0-1.lintian-overrides: new file
* debian/patches/0002-replace-mersenne-twister.patch: new file
-- Stephen M. Webb <stephen.webb@bregmasoft.ca> Tue, 04 Jun 2013 13:45:11 -0400
-- Stephen M. Webb <stephen.webb@bregmasoft.ca> Fri, 09 Aug 2013 18:40:13 -0400
wfmath (0.3.12-3) unstable; urgency=low
......
......@@ -5,12 +5,39 @@ Files: *
Copyright: 1999-2011 The Worldforge Project
2002-2009 Ron Steinke
2002-2011 Al Riddoch
2012-2013 Stephen M. Webb <stephen.webb@bregmasoft.ca>
License: GPL-2+
Files: wfmath/MersenneTwister.h
Files: wfmath/randgen.cpp
Copyright: 1997-2002 Makoto Matsumoto and Takuji Nishimura
2000-2003 Richard J. Wagner
License: BSD
2002-2009 Ron Steinke
2013 Stephen M. Webb <stephen.webb@bregmasoft.ca>
License: GPL-2+ or BSD-3-clause
Files: debian/*
Copyright: 2002 Michael Koch <konqueror@gmx.de>
2012-2013 Stephen M. Webb <stephen.webb@bregmasoft.ca>
License: GPL-2+
License: GPL-2+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
.
On Debian systems, the full text of the GNU General Public License version 2
can be found in the file `/usr/share/common-licenses/GPL-2'.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
License: BSD-3-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
......@@ -34,26 +61,3 @@ License: BSD
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Files: debian/*
Copyright: 2002 Michael Koch <konqueror@gmx.de>
2012 Stephen M. Webb <stephen.webb@bregmasoft.ca>
License: GPL-2+
License: GPL-2+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
.
On Debian systems, the full text of the GNU General Public License version 2
can be found in the file `/usr/share/common-licenses/GPL-2'.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
......@@ -206,9 +206,12 @@ libwfmath-1.0.so.1 libwfmath-1.0-1 #MINVER#
_ZN6WFMath5PointILi3EEixEi@Base 1.0.1
_ZN6WFMath5UnionILi2EEENS_7AxisBoxIXT_EEERKS2_S4_@Base 1.0.1
_ZN6WFMath5UnionILi3EEENS_7AxisBoxIXT_EEERKS2_S4_@Base 1.0.1
(optional=inline)_ZN6WFMath6MTRand1NE@Base 1.0.1
(optional=inline)_ZN6WFMath6MTRand4SAVEE@Base 1.0.1
_ZN6WFMath6MTRand10state_sizeE@Base 1.0.1
_ZN6WFMath6MTRand4loadERSi@Base 1.0.1
_ZN6WFMath6MTRand4seedEPjj@Base 1.0.1
_ZN6WFMath6MTRand4seedEj@Base 1.0.1
_ZN6WFMath6MTRand4seedEv@Base 1.0.1
_ZN6WFMath6MTRand7randIntEv@Base 1.0.1
_ZN6WFMath6MTRand8instanceE@Base 1.0.1
_ZN6WFMath6RotBoxILi2EE11orientationEv@Base 1.0.1
_ZN6WFMath6RotBoxILi2EE11rotatePointERKNS_9RotMatrixILi2EEERKNS_5PointILi2EEE@Base 1.0.1
......@@ -813,6 +816,7 @@ libwfmath-1.0.so.1 libwfmath-1.0-1 #MINVER#
_ZNK6WFMath5PointILi3EEeqERKS1_@Base 1.0.1
_ZNK6WFMath5PointILi3EEixEi@Base 1.0.1
_ZNK6WFMath5PointILi3EEneERKS1_@Base 1.0.1
_ZNK6WFMath6MTRand4saveERSo@Base 1.0.1
_ZNK6WFMath6RotBoxILi2EE10numCornersEv@Base 1.0.1
_ZNK6WFMath6RotBoxILi2EE11boundingBoxEv@Base 1.0.1
_ZNK6WFMath6RotBoxILi2EE11orientationEv@Base 1.0.1
......
Description: replace the Wagner MersenneTwister.h file with a custom one
There was a lack of complete clarity regarding whether a comment appearing in
this file constituted distribution license restrictions or not. Replacing the
file entirely eliminates the ambiguity.
Author: Stephen M. Webb <stephen.webb@bregmasoft.ca>
--- a/wfmath/MersenneTwister.h
+++ b/wfmath/MersenneTwister.h
@@ -1,381 +1,140 @@
// MersenneTwister.h
-// Mersenne Twister random number generator -- a C++ class MTRand
-// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
-// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
-
-// The Mersenne Twister is an algorithm for generating random numbers. It
-// was designed with consideration of the flaws in various other generators.
-// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
-// are far greater. The generator is also fast; it avoids multiplication and
-// division, and it benefits from caches and pipelines. For more information
-// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
-
-// Reference
-// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
-// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
-// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
-
-// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
-// Copyright (C) 2000 - 2003, Richard J. Wagner
-// All rights reserved.
//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
+// The WorldForge Project
+// Copyright (C) 2013 The WorldForge Project
//
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The names of its contributors may not be used to endorse or promote
-// products derived from this software without specific prior written
-// permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The original code included the following notice:
-//
-// When you use this, send an email to: matumoto@math.keio.ac.jp
-// with an appropriate reference to your work.
-//
-// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
-// when you write.
-
-// changed the #ifndef for wfmath in case someone uses both the lib
-// and the identical header separately
-
-#ifndef MERSENNETWISTER_WFMATH_H
-#define MERSENNETWISTER_WFMATH_H
-
-// Not thread safe (unless auto-initialization is avoided and each thread has
-// its own MTRand object)
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// For information about WorldForge and its authors, please contact
+// the Worldforge Web Site at http://www.worldforge.org.
+//
+#ifndef WFMATH_MERSENNE_TWISTER_H_
+#define WFMATH_MERSENNE_TWISTER_H_
#include <iosfwd>
#include <climits>
#include <cmath>
-
-// namespace safety for inclusion in the lib
+#include <stdint.h>
namespace WFMath {
class MTRand {
-// Data
public:
- typedef unsigned long uint32; // unsigned integer type, at least 32 bits
-
- static const uint32 N = 624; // length of state vector
- static const uint32 SAVE = N + 1; // length of array for save()
-
-protected:
- static const uint32 M = 397; // period parameter
-
- uint32 state[N]; // internal state
- uint32 *pNext; // next value to get from state
- int left; // number of values left before reload needed
+ typedef uint32_t uint32;
+ static const uint32 state_size = 624;
-//Methods
public:
- MTRand( const uint32& oneSeed ); // initialize with a simple uint32
- MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
- MTRand(); // auto-initialize with /dev/urandom or time() and clock()
-
- // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
- // values together, otherwise the generator state can be learned after
- // reading 624 consecutive values.
-
- // Access to 32-bit random numbers
- template<typename FloatT>
- FloatT rand(); // real number in [0,1]
- float randf(); // real number in [0,1]
- float randf( const float& n ); // real number in [0,n]
- double rand(); // real number in [0,1]
- double rand( const double& n ); // real number in [0,n]
- double randExc(); // real number in [0,1)
- double randExc( const double& n ); // real number in [0,n)
- double randDblExc(); // real number in (0,1)
- double randDblExc( const double& n ); // real number in (0,n)
- uint32 randInt(); // integer in [0,2^32-1]
- uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
- double operator()() { return rand(); } // same as rand()
-
- // Access to 53-bit random numbers (capacity of IEEE double precision)
- double rand53(); // real number in [0,1)
-
- // Access to nonuniform random number distributions
- double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
-
- // Re-seeding functions with same behavior as initializers
- void seed( const uint32 oneSeed );
- void seed( uint32 *const bigSeed, const uint32 seedLength = N );
- void seed();
-
- // Saving and loading generator state
- void save( uint32* saveArray ) const; // to array of size SAVE
- void load( uint32 *const loadArray ); // from such array
- friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
- friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
-
- static MTRand instance;
-
-protected:
- void initialize( const uint32 oneSeed );
- void reload();
- uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
- uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
- uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
- uint32 mixBits( const uint32& u, const uint32& v ) const
- { return hiBit(u) | loBits(v); }
- uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
- { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
+ MTRand();
+ MTRand(uint32 oneSeed);
+ MTRand(uint32* const bigSeed, uint32 const seedLength = state_size);
+
+ // real-valued random numbers on [0, 1] or [0, n]
+ template<typename FloatT>
+ FloatT rand();
+ double rand();
+ double rand(const double& n);
+
+ // integer-valued random numbers on [0, 2^32-1] or [0, n]
+ uint32 randInt();
+ uint32 randInt(uint32 n);
+
+ void seed();
+ void seed(uint32 oneSeed);
+ void seed(uint32* const init_vector, uint32 init_vector_length = state_size);
+
+ std::ostream& save(std::ostream&) const;
+ std::istream& load(std::istream&);
+
+ static MTRand instance;
+
+private:
+ uint32 state[state_size];
+ uint32 index;
};
-inline MTRand::MTRand( const uint32& oneSeed ) : pNext(0), left(0)
- { seed(oneSeed); }
-
-inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength ) : pNext(0), left(0)
- { seed(bigSeed,seedLength); }
-
-inline MTRand::MTRand() : pNext(0), left(0)
- { seed(); }
+inline MTRand::MTRand(uint32 s)
+: index(0)
+{ seed(s); }
+
+inline MTRand::MTRand(uint32* const bigSeed, const uint32 seedLength)
+: index(0)
+{ seed(bigSeed, seedLength); }
+
+inline MTRand::MTRand()
+: index(0)
+{ seed(); }
template<>
inline float MTRand::rand<float>()
- { return float(randInt()) * (1.0f/4294967295.0f); }
+{ return float(randInt()) * (1.0f/4294967295.0f); }
template<>
inline double MTRand::rand<double>()
- { return double(randInt()) * (1.0/4294967295.0); }
-
-inline float MTRand::randf()
- { return float(randInt()) * (1.0f/4294967295.0f); }
-
-inline float MTRand::randf( const float& n )
- { return randf() * n; }
+{ return double(randInt()) * (1.0/4294967295.0); }
inline double MTRand::rand()
- { return double(randInt()) * (1.0/4294967295.0); }
+{ return double(randInt()) * (1.0/4294967295.0); }
inline double MTRand::rand( const double& n )
- { return rand() * n; }
-
-inline double MTRand::randExc()
- { return double(randInt()) * (1.0/4294967296.0); }
-
-inline double MTRand::randExc( const double& n )
- { return randExc() * n; }
-
-inline double MTRand::randDblExc()
- { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
-
-inline double MTRand::randDblExc( const double& n )
- { return randDblExc() * n; }
-
-inline double MTRand::rand53()
-{
- uint32 a = randInt() >> 5, b = randInt() >> 6;
- return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
-}
-
-inline double MTRand::randNorm( const double& mean, const double& variance )
-{
- // Return a real number from a normal (Gaussian) distribution with given
- // mean and variance by Box-Muller method
- double r = std::sqrt( -2.0 * std::log( 1.0-randDblExc()) ) * variance;
- double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
- return mean + r * std::cos(phi);
-}
-
-inline MTRand::uint32 MTRand::randInt()
-{
- // Pull a 32-bit integer from the generator state
- // Every other access function simply transforms the numbers extracted here
-
- if( left == 0 ) reload();
- --left;
-
- register uint32 s1;
- s1 = *pNext++;
- s1 ^= (s1 >> 11);
- s1 ^= (s1 << 7) & 0x9d2c5680UL;
- s1 ^= (s1 << 15) & 0xefc60000UL;
- return ( s1 ^ (s1 >> 18) );
-}
-
-inline MTRand::uint32 MTRand::randInt( const uint32& n )
-{
- // Find which bits are used in n
- // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
- uint32 used = n;
- used |= used >> 1;
- used |= used >> 2;
- used |= used >> 4;
- used |= used >> 8;
- used |= used >> 16;
-
- // Draw numbers until one is found in [0,n]
- uint32 i;
- do
- i = randInt() & used; // toss unused bits to shorten search
- while( i > n );
- return i;
-}
-
-
-inline void MTRand::seed( const uint32 oneSeed )
-{
- // Seed the generator with a simple uint32
- initialize(oneSeed);
- reload();
-}
+{ return rand() * n; }
-inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
+inline MTRand::uint32 MTRand::randInt(uint32 n)
{
- // Seed the generator with an array of uint32's
- // There are 2^19937-1 possible initial states. This function allows
- // all of those to be accessed by providing at least 19937 bits (with a
- // default seed length of N = 624 uint32's). Any bits above the lower 32
- // in each element are discarded.
- // Just call seed() if you want to get array from /dev/urandom
- initialize(19650218UL);
- register unsigned i = 1;
- register uint32 j = 0;
- register unsigned k = ( N > seedLength ? N : seedLength );
- for( ; k; --k )
- {
- state[i] =
- state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
- state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
- state[i] &= 0xffffffffUL;
- ++i; ++j;
- if( i >= N ) { state[0] = state[N-1]; i = 1; }
- if( j >= seedLength ) j = 0;
- }
- for( k = N - 1; k; --k )
- {
- state[i] =
- state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
- state[i] -= i;
- state[i] &= 0xffffffffUL;
- ++i;
- if( i >= N ) { state[0] = state[N-1]; i = 1; }
- }
- state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
- reload();
+ uint32 used = n;
+ used |= used >> 1;
+ used |= used >> 2;
+ used |= used >> 4;
+ used |= used >> 8;
+ used |= used >> 16;
+
+ uint32 i;
+ do
+ i = randInt() & used;
+ while( i > n );
+ return i;
}
-inline void MTRand::initialize( const uint32 seed )
+#if 0
+inline void MTRand::save(uint32* saveArray) const
{
- // Initialize generator state with seed
- // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
- // In previous versions, most significant bits (MSBs) of the seed affect
- // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
- register uint32 *s = state;
- register uint32 *r = state;
- register unsigned i = 1;
- *s++ = seed & 0xffffffffUL;
- for( ; i < N; ++i )
- {
- *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
- r++;
- }
+ register uint32 *sa = saveArray;
+ register const uint32 *s = state;
+ register int i = state_size;
+ for( ; i--; *sa++ = *s++ ) {}
+ *sa = left;
}
-inline void MTRand::reload()
+inline void MTRand::load(uint32 *const loadArray)
{
- // Generate N new values in state
- // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
- register uint32 *p = state;
- register int i;
- for( i = N - M; i--; ++p )
- *p = twist( p[M], p[0], p[1] );
- for( i = M; --i; ++p )
- *p = twist( p[M-N], p[0], p[1] );
- *p = twist( p[M-N], p[0], state[0] );
-
- left = N, pNext = state;
-}
-
-
-
-inline void MTRand::save( uint32* saveArray ) const
-{
- register uint32 *sa = saveArray;
- register const uint32 *s = state;
- register int i = N;
- for( ; i--; *sa++ = *s++ ) {}
- *sa = left;
-}
-
-
-inline void MTRand::load( uint32 *const loadArray )
-{
- register uint32 *s = state;
- register uint32 *la = loadArray;
- register int i = N;
- for( ; i--; *s++ = *la++ ) {}
- left = *la;
- pNext = &state[N-left];
+ register uint32 *s = state;
+ register uint32 *la = loadArray;
+ register int i = state_size;
+ for( ; i--; *s++ = *la++ ) {}
+ left = *la;
+ pNext = &state[state_size-left];
}
+#endif
+std::ostream& operator<<(std::ostream& os, MTRand const& mtrand);
+std::istream& operator>>(std::istream& is, MTRand& mtrand);
} // namespace
-#endif // MERSENNETWISTER_H
-
-// Change log:
-//
-// v0.1 - First release on 15 May 2000
-// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
-// - Translated from C to C++
-// - Made completely ANSI compliant
-// - Designed convenient interface for initialization, seeding, and
-// obtaining numbers in default or user-defined ranges
-// - Added automatic seeding from /dev/urandom or time() and clock()
-// - Provided functions for saving and loading generator state
-//
-// v0.2 - Fixed bug which reloaded generator one step too late
-//
-// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
-//
-// v0.4 - Removed trailing newline in saved generator format to be consistent
-// with output format of built-in types
-//
-// v0.5 - Improved portability by replacing static const int's with enum's and
-// clarifying return values in seed(); suggested by Eric Heimburg
-// - Removed MAXINT constant; use 0xffffffffUL instead
-//
-// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
-// - Changed integer [0,n] generator to give better uniformity
-//
-// v0.7 - Fixed operator precedence ambiguity in reload()
-// - Added access for real numbers in (0,1) and (0,n)
-//
-// v0.8 - Included time.h header to properly support time_t and clock_t
-//
-// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
-// - Allowed for seeding with arrays of any length
-// - Added access for real numbers in [0,1) with 53-bit resolution
-// - Added access for real numbers from normal (Gaussian) distributions
-// - Increased overall speed by optimizing twist()
-// - Doubled speed of integer [0,n] generation
-// - Fixed out-of-range number generation on 64-bit machines
-// - Improved portability by substituting literal constants for long enum's
-// - Changed license from GNU LGPL to BSD
+#endif // WFMATH_MERSENNE_TWISTER_H_
--- a/wfmath/randgen.cpp
+++ b/wfmath/randgen.cpp
@@ -1,7 +1,7 @@
// randgen.cpp (time and random number implementation)
//
// The WorldForge Project
-// Copyright (C) 2002 The WorldForge Project
+// Copyright (C) 2002, 2013 The WorldForge Project
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -19,75 +19,205 @@
//
// For information about WorldForge and its authors, please contact
// the Worldforge Web Site at http://www.worldforge.org.
+//
+// Portions of the code in this file were copied and modified from
+// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
+//
+// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The names of its contributors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
-// Author: Ron Steinke
+// Original Author: Ron Steinke
// Created: 2002-5-23
#include "randgen.h"
#include "timestamp.h"
#include <ctime>
#include <cstdio>
+#include <istream>
+#include <ostream>
#ifdef HAVE_CONFIG_H
- #include "config.h"
+ #include "config.h"
#endif
namespace WFMath {
-const MTRand::uint32 MTRand::N;
-const MTRand::uint32 MTRand::SAVE;
+const MTRand::uint32 MTRand::state_size;
MTRand MTRand::instance;
+static const MTRand::uint32 period = 397;
+static const MTRand::uint32 MATRIX_A = 0x9908b0df;
+static const MTRand::uint32 UPPER_MASK = 0x80000000;
+static const MTRand::uint32 LOWER_MASK = 0x7fffffff;
+
+
static MTRand::uint32 hash( time_t t, clock_t c )
{
- // Get a uint32 from t and c
- // Better than uint32(x) in case x is floating point in [0,1]
- // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
-
- typedef MTRand::uint32 uint32;
-
- // guarantee time-based seeds will change
- static uint32 differ = 0;
-
- uint32 h1 = 0;
- unsigned char *p = (unsigned char *) &t;
- for( size_t i = 0; i < sizeof(t); ++i )
- {
- h1 *= UCHAR_MAX + 2U;
- h1 += p[i];
- }
- uint32 h2 = 0;
- p = (unsigned char *) &c;
- for( size_t j = 0; j < sizeof(c); ++j )
- {
- h2 *= UCHAR_MAX + 2U;
- h2 += p[j];
- }
- return ( h1 + differ++ ) ^ h2;
+ // Get a uint32 from t and c
+ // Better than uint32(x) in case x is floating point in [0,1]
+ // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
+
+ typedef MTRand::uint32 uint32;
+
+ // guarantee time-based seeds will change
+ static uint32 differ = 0;
+
+ uint32 h1 = 0;
+ unsigned char *p = (unsigned char *) &t;
+ for( size_t i = 0; i < sizeof(t); ++i )
+ {
+ h1 *= UCHAR_MAX + 2U;
+ h1 += p[i];
+ }
+ uint32 h2 = 0;
+ p = (unsigned char *) &c;
+ for( size_t j = 0; j < sizeof(c); ++j )
+ {
+ h2 *= UCHAR_MAX + 2U;
+ h2 += p[j];
+ }
+ return ( h1 + differ++ ) ^ h2;
}
+
void MTRand::seed()
{
- // Seed the generator with an array from /dev/urandom if available
- // Otherwise use a hash of time() and clock() values
-
- // First try getting an array from /dev/urandom
- FILE* urandom = fopen( "/dev/urandom", "rb" );
- if( urandom )
- {
- uint32 bigSeed[N];
- register uint32 *s = bigSeed;
- register int i = N;
- register bool success = true;
- while( success && i-- )
- success = fread( s++, sizeof(uint32), 1, urandom );
- fclose(urandom);
- if( success ) { seed( bigSeed, N ); return; }
- }
-
- // Was not successful, so use time() and clock() instead
- seed( hash( time(NULL), clock() ) );
+ // First try getting an array from /dev/urandom
+ FILE* urandom = fopen( "/dev/urandom", "rb" );
+ if( urandom )
+ {
+ uint32 init_vector[state_size];
+ register uint32 *s = init_vector;
+ register int i = state_size;
+ register bool success = true;