X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2Fsg_random.c;h=d9f6bcb78f9c8642abc3ab32c2c807cd370e00e1;hb=584ee1364f25e5c3795f9ff4633a792cba39bfc7;hp=c602bb53cd84f65ed63c84efe2bd46c1286c7896;hpb=f9cbf8361dd8cbc24e077d667f83dcf91a8ade67;p=simgear.git diff --git a/simgear/math/sg_random.c b/simgear/math/sg_random.c index c602bb53..d9f6bcb7 100644 --- a/simgear/math/sg_random.c +++ b/simgear/math/sg_random.c @@ -14,58 +14,26 @@ // 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 @@ -77,94 +45,70 @@ #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> 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> 30)) + i); + mt->index = MT_N+1; } -static void next_state(void) +void mt_init_time_10(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]); + mt_init(mt, (unsigned int) time(NULL) / 600); +} - for (j=M; --j; p++) - *p = p[M-N] ^ TWIST(p[0], p[1]); +unsigned int mt_rand32(mt *mt) +{ + unsigned int i, y; + if(mt->index >= MT_N) { + for(i=0; i>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); } -