00001 // sg_random.c -- routines to handle random number generation 00002 // 00003 // Written by Curtis Olson, started July 1997. 00004 // 00005 // Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Library General Public 00009 // License as published by the Free Software Foundation; either 00010 // version 2 of the License, or (at your option) any later version. 00011 // 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 // Library General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this program; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 // 00021 // $Id: sg__random_8c_source.html,v 1.3 2010/02/23 22:10:16 curt Exp $ 00022 00023 00024 /* 00025 * "Cleaned up" and simplified Mersenne Twister implementation. 00026 * Vastly smaller and more easily understood and embedded. Stores the 00027 * state in a user-maintained structure instead of static memory, so 00028 * you can have more than one, or save snapshots of the RNG state. 00029 * Lacks the "init_by_array()" feature of the original code in favor 00030 * of the simpler 32 bit seed initialization. Lacks the floating 00031 * point generator, which is an orthogonal problem not related to 00032 * random number generation. Verified to be identical to the original 00033 * MT199367ar code through the first 10M generated numbers. 00034 */ 00035 00036 00037 00038 #ifdef HAVE_CONFIG_H 00039 # include <simgear_config.h> 00040 #endif 00041 00042 #include <stdio.h> 00043 #include <stdlib.h> // for random(), srandom() 00044 #include <time.h> // for time() to seed srandom() 00045 00046 #include "sg_random.h" 00047 00048 // Structure for the random number functions. 00049 mt random_seed; 00050 00051 #define MT(i) mt->array[i] 00052 00053 void mt_init(mt *mt, unsigned int seed) 00054 { 00055 int i; 00056 MT(0)= seed; 00057 for(i=1; i<MT_N; i++) 00058 MT(i) = (1812433253 * (MT(i-1) ^ (MT(i-1) >> 30)) + i); 00059 mt->index = MT_N+1; 00060 } 00061 00062 unsigned int mt_rand32(mt *mt) 00063 { 00064 unsigned int i, y; 00065 if(mt->index >= MT_N) { 00066 for(i=0; i<MT_N; i++) { 00067 y = (MT(i) & 0x80000000) | (MT((i+1)%MT_N) & 0x7fffffff); 00068 MT(i) = MT((i+MT_M)%MT_N) ^ (y>>1) ^ (y&1 ? 0x9908b0df : 0); 00069 } 00070 mt->index = 0; 00071 } 00072 y = MT(mt->index++); 00073 y ^= (y >> 11); 00074 y ^= (y << 7) & 0x9d2c5680; 00075 y ^= (y << 15) & 0xefc60000; 00076 y ^= (y >> 18); 00077 return y; 00078 } 00079 00080 double mt_rand(mt *mt) 00081 { 00082 /* divided by 2^32-1 */ 00083 return (double)mt_rand32(mt) * (1.0/4294967295.0); 00084 } 00085 00086 // Seed the random number generater with time() so we don't see the 00087 // same sequence every time 00088 void sg_srandom_time() { 00089 mt_init(&random_seed, (unsigned int) time(NULL)); 00090 } 00091 00092 // Seed the random number generater with time() in 10 minute intervals 00093 // so we get the same sequence within 10 minutes interval. 00094 // This is useful for synchronizing two display systems. 00095 void sg_srandom_time_10() { 00096 mt_init(&random_seed, (unsigned int) time(NULL) / 600); 00097 } 00098 00099 // Seed the random number generater with your own seed so can set up 00100 // repeatable randomization. 00101 void sg_srandom( unsigned int seed ) { 00102 mt_init(&random_seed, seed); 00103 } 00104 00105 // return a random number between [0.0, 1.0) 00106 double sg_random() { 00107 return mt_rand(&random_seed); 00108 } 00109