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.15 2007-12-17 15:37:10 curt Exp $ 00022 00023 00024 /* 00025 A C-program for MT19937, with initialization improved 2002/2/10. 00026 Coded by Takuji Nishimura and Makoto Matsumoto. 00027 This is a faster version by taking Shawn Cokus's optimization, 00028 Matthe Bellew's simplification, Isaku Wada's real version. 00029 00030 Before using, initialize the state by using init_genrand(seed) 00031 or init_by_array(init_key, key_length). 00032 00033 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 00034 All rights reserved. 00035 00036 Redistribution and use in source and binary forms, with or without 00037 modification, are permitted provided that the following conditions 00038 are met: 00039 00040 1. Redistributions of source code must retain the above copyright 00041 notice, this list of conditions and the following disclaimer. 00042 00043 2. Redistributions in binary form must reproduce the above copyright 00044 notice, this list of conditions and the following disclaimer in the 00045 documentation and/or other materials provided with the distribution. 00046 00047 3. The names of its contributors may not be used to endorse or promote 00048 products derived from this software without specific prior written 00049 permission. 00050 00051 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00052 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00053 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00054 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00055 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00056 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00057 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00058 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00059 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00060 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00061 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00062 00063 00064 Any feedback is very welcome. 00065 http://www.math.keio.ac.jp/matumoto/emt.html 00066 email: matumoto@math.keio.ac.jp 00067 */ 00068 00069 #ifdef HAVE_CONFIG_H 00070 # include <simgear_config.h> 00071 #endif 00072 00073 #include <stdio.h> 00074 #include <stdlib.h> // for random(), srandom() 00075 #include <time.h> // for time() to seed srandom() 00076 00077 #include "sg_random.h" 00078 00079 /* Period parameters */ 00080 #define N 624 00081 #define M 397 00082 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ 00083 #define UMASK 0x80000000UL /* most significant w-r bits */ 00084 #define LMASK 0x7fffffffUL /* least significant r bits */ 00085 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) 00086 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) 00087 00088 static unsigned long state[N]; /* the array for the state vector */ 00089 static int left = 1; 00090 static int initf = 0; 00091 static unsigned long *next; 00092 00093 /* initializes state[N] with a seed */ 00094 void init_genrand(unsigned long s) 00095 { 00096 int j; 00097 state[0]= s & 0xffffffffUL; 00098 for (j=1; j<N; j++) { 00099 state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j); 00100 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 00101 /* In the previous versions, MSBs of the seed affect */ 00102 /* only MSBs of the array state[]. */ 00103 /* 2002/01/09 modified by Makoto Matsumoto */ 00104 state[j] &= 0xffffffffUL; /* for >32 bit machines */ 00105 } 00106 left = 1; initf = 1; 00107 } 00108 00109 static void next_state(void) 00110 { 00111 unsigned long *p=state; 00112 int j; 00113 00114 /* if init_genrand() has not been called, */ 00115 /* a default initial seed is used */ 00116 if (initf==0) init_genrand(5489UL); 00117 00118 left = N; 00119 next = state; 00120 00121 for (j=N-M+1; --j; p++) 00122 *p = p[M] ^ TWIST(p[0], p[1]); 00123 00124 for (j=M; --j; p++) 00125 *p = p[M-N] ^ TWIST(p[0], p[1]); 00126 00127 *p = p[M-N] ^ TWIST(p[0], state[0]); 00128 } 00129 00130 // Seed the random number generater with time() so we don't see the 00131 // same sequence every time 00132 void sg_srandom_time() { 00133 init_genrand(time(NULL)); 00134 } 00135 00136 // Seed the random number generater with time() in 10 minute intervals 00137 // so we get the same sequence within 10 minutes interval. 00138 // This is useful for synchronizing two display systems. 00139 void sg_srandom_time_10() { 00140 init_genrand(time(NULL) / 600); 00141 } 00142 00143 00144 // Seed the random number generater with your own seed so can set up 00145 // repeatable randomization. 00146 void sg_srandom( unsigned int seed ) { 00147 init_genrand( seed ); 00148 } 00149 00150 00151 // return a random number between [0.0, 1.0) 00152 double sg_random() { 00153 unsigned long y; 00154 00155 if (--left == 0) 00156 next_state(); 00157 y = *next++; 00158 00159 /* Tempering */ 00160 y ^= (y >> 11); 00161 y ^= (y << 7) & 0x9d2c5680UL; 00162 y ^= (y << 15) & 0xefc60000UL; 00163 y ^= (y >> 18); 00164 00165 return (double)y * (1.0/4294967295.0); 00166 /* divided by 2^32-1 */ 00167 } 00168 00169
1.5.1