// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
-// You should have received a copy of the GNU Library General Public
-// License along with this library; if not, write to the
-// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-// Boston, MA 02111-1307, USA.
+// 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.
//
// $Id$
-/*
- A C-program for MT19937, with initialization improved 2002/2/10.
- Coded by Takuji Nishimura and Makoto Matsumoto.
- This is a faster version by taking Shawn Cokus's optimization,
- Matthe Bellew's simplification, Isaku Wada's real version.
+/*
+ * "Cleaned up" and simplified Mersenne Twister implementation.
+ * Vastly smaller and more easily understood and embedded. Stores the
+ * state in a user-maintained structure instead of static memory, so
+ * you can have more than one, or save snapshots of the RNG state.
+ * Lacks the "init_by_array()" feature of the original code in favor
+ * of the simpler 32 bit seed initialization. Lacks the floating
+ * point generator, which is an orthogonal problem not related to
+ * random number generation. Verified to be identical to the original
+ * MT199367ar code through the first 10M generated numbers.
+ */
- Before using, initialize the state by using init_genrand(seed)
- or init_by_array(init_key, key_length).
- 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.
-
-
- Any feedback is very welcome.
- http://www.math.keio.ac.jp/matumoto/emt.html
- email: matumoto@math.keio.ac.jp
-*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#include "sg_random.h"
-/* Period parameters */
-#define N 624
-#define M 397
-#define MATRIX_A 0x9908b0dfUL /* constant vector a */
-#define UMASK 0x80000000UL /* most significant w-r bits */
-#define LMASK 0x7fffffffUL /* least significant r bits */
-#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
-#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
-
-static unsigned long state[N]; /* the array for the state vector */
-static int left = 1;
-static int initf = 0;
-static unsigned long *next;
-
-/* initializes state[N] with a seed */
-void init_genrand(unsigned long s)
+// Structure for the random number functions.
+mt random_seed;
+
+#define MT(i) mt->array[i]
+
+void mt_init(mt *mt, unsigned int seed)
{
- int j;
- state[0]= s & 0xffffffffUL;
- for (j=1; j<N; j++) {
- state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
- /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
- /* In the previous versions, MSBs of the seed affect */
- /* only MSBs of the array state[]. */
- /* 2002/01/09 modified by Makoto Matsumoto */
- state[j] &= 0xffffffffUL; /* for >32 bit machines */
- }
- left = 1; initf = 1;
+ int i;
+ MT(0)= seed;
+ for(i=1; i<MT_N; i++)
+ MT(i) = (1812433253 * (MT(i-1) ^ (MT(i-1) >> 30)) + i);
+ mt->index = MT_N+1;
}
-static void next_state(void)
+unsigned int mt_rand32(mt *mt)
{
- unsigned long *p=state;
- int j;
-
- /* if init_genrand() has not been called, */
- /* a default initial seed is used */
- if (initf==0) init_genrand(5489UL);
-
- left = N;
- next = state;
-
- for (j=N-M+1; --j; p++)
- *p = p[M] ^ TWIST(p[0], p[1]);
-
- for (j=M; --j; p++)
- *p = p[M-N] ^ TWIST(p[0], p[1]);
+ unsigned int i, y;
+ if(mt->index >= MT_N) {
+ for(i=0; i<MT_N; i++) {
+ y = (MT(i) & 0x80000000) | (MT((i+1)%MT_N) & 0x7fffffff);
+ MT(i) = MT((i+MT_M)%MT_N) ^ (y>>1) ^ (y&1 ? 0x9908b0df : 0);
+ }
+ mt->index = 0;
+ }
+ y = MT(mt->index++);
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680;
+ y ^= (y << 15) & 0xefc60000;
+ y ^= (y >> 18);
+ return y;
+}
- *p = p[M-N] ^ TWIST(p[0], state[0]);
+double mt_rand(mt *mt)
+{
+ /* divided by 2^32-1 */
+ return (double)mt_rand32(mt) * (1.0/4294967295.0);
}
// Seed the random number generater with time() so we don't see the
// same sequence every time
void sg_srandom_time() {
- init_genrand(time(NULL));
+ mt_init(&random_seed, (unsigned int) time(NULL));
}
+// Seed the random number generater with time() in 10 minute intervals
+// so we get the same sequence within 10 minutes interval.
+// This is useful for synchronizing two display systems.
+void sg_srandom_time_10() {
+ mt_init(&random_seed, (unsigned int) time(NULL) / 600);
+}
// Seed the random number generater with your own seed so can set up
// repeatable randomization.
void sg_srandom( unsigned int seed ) {
- init_genrand( seed );
+ mt_init(&random_seed, seed);
}
-
// return a random number between [0.0, 1.0)
double sg_random() {
- unsigned long y;
-
- if (--left == 0)
- next_state();
- y = *next++;
-
- /* Tempering */
- y ^= (y >> 11);
- y ^= (y << 7) & 0x9d2c5680UL;
- y ^= (y << 15) & 0xefc60000UL;
- y ^= (y >> 18);
-
- return (double)y * (1.0/4294967295.0);
- /* divided by 2^32-1 */
+ return mt_rand(&random_seed);
}
-