]> git.mxchange.org Git - simgear.git/blobdiff - simgear/math/sg_random.c
Boolean uniforms are now updatable by properties
[simgear.git] / simgear / math / sg_random.c
index b58cf9387f861650390d3087060295ecda862a28..e9004323b2fa93f7d5744005fa71abefb9b70088 100644 (file)
 // $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.
-
-   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
-*/
+/*
+ * "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.
+ */
+
+
 
 #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() {
-    init_genrand(time(NULL) / 600);
+    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);
 }
 
-