00001 /* 00002 +----------------------------------------------------------------------+ 00003 | PHP Version 4 | 00004 +----------------------------------------------------------------------+ 00005 | Copyright (c) 1997-2003 The PHP Group | 00006 +----------------------------------------------------------------------+ 00007 | This source file is subject to version 2.02 of the PHP license, | 00008 | that is bundled with this package in the file LICENSE, and is | 00009 | available at through the world-wide-web at | 00010 | http://www.php.net/license/2_02.txt. | 00011 | If you did not receive a copy of the PHP license and are unable to | 00012 | obtain it through the world-wide-web, please send a note to | 00013 | license@php.net so we can mail you a copy immediately. | 00014 +----------------------------------------------------------------------+ 00015 | Authors: Rasmus Lerdorf <rasmus@php.net> | 00016 | Zeev Suraski <zeev@zend.com> | 00017 | Pedro Melo <melo@ip.pt> | 00018 | Sterling Hughes <sterling@php.net> | 00019 | | 00020 | Based on code from: Shawn Cokus <Cokus@math.washington.edu> | 00021 +----------------------------------------------------------------------+ 00022 */ 00023 /* $Id: rand.c,v 1.60.2.3 2004/01/19 03:16:04 sniper Exp $ */ 00024 00025 #include <stdlib.h> 00026 00027 #ifdef PHP_WIN32 00028 # ifndef WIN32_LEAN_AND_MEAN 00029 # define WIN32_LEAN_AND_MEAN 00030 # endif 00031 # include <windows.h> 00032 #endif 00033 00034 #if defined(NETWARE) && !defined(NEW_LIBC) /* For getpid() used below */ 00035 #include "netware/pwd.h" 00036 #endif 00037 00038 #include "php.h" 00039 #include "php_math.h" 00040 #include "php_rand.h" 00041 #include "php_lcg.h" 00042 00043 #include "basic_functions.h" 00044 00045 00046 /* SYSTEM RAND FUNCTIONS */ 00047 00048 /* {{{ php_srand 00049 */ 00050 PHPAPI void php_srand(long seed TSRMLS_DC) 00051 { 00052 #ifdef ZTS 00053 BG(rand_seed) = (unsigned int) seed; 00054 #else 00055 # if defined(HAVE_SRANDOM) 00056 srandom((unsigned int) seed); 00057 # elif defined(HAVE_SRAND48) 00058 srand48(seed); 00059 # else 00060 srand((unsigned int) seed); 00061 # endif 00062 #endif 00063 00064 /* Seed only once */ 00065 BG(rand_is_seeded) = 1; 00066 } 00067 /* }}} */ 00068 00069 /* {{{ php_rand 00070 */ 00071 PHPAPI long php_rand(TSRMLS_D) 00072 { 00073 long ret; 00074 00075 if (!BG(rand_is_seeded)) { 00076 php_srand(GENERATE_SEED() TSRMLS_CC); 00077 } 00078 00079 #ifdef ZTS 00080 ret = php_rand_r(&BG(rand_seed)); 00081 #else 00082 # if defined(HAVE_RANDOM) 00083 ret = random(); 00084 # elif defined(HAVE_LRAND48) 00085 ret = lrand48(); 00086 # else 00087 ret = rand(); 00088 # endif 00089 #endif 00090 00091 return ret; 00092 } 00093 /* }}} */ 00094 00095 00096 /* MT RAND FUNCTIONS */ 00097 00098 /* 00099 This is the ``Mersenne Twister'' random number generator MT19937, which 00100 generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) 00101 starting from any odd seed in 0..(2^32 - 1). This version is a recode 00102 by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by 00103 Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in 00104 July-August 1997). 00105 00106 Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha 00107 running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to 00108 generate 300 million random numbers; after recoding: 24.0 sec. for the same 00109 (i.e., 46.5% of original time), so speed is now about 12.5 million random 00110 number generations per second on this machine. 00111 00112 According to the URL <http://www.math.keio.ac.jp/~matumoto/emt.html> 00113 (and paraphrasing a bit in places), the Mersenne Twister is ``designed 00114 with consideration of the flaws of various existing generators,'' has 00115 a period of 2^19937 - 1, gives a sequence that is 623-dimensionally 00116 equidistributed, and ``has passed many stringent tests, including the 00117 die-hard test of G. Marsaglia and the load test of P. Hellekalek and 00118 S. Wegenkittl.'' It is efficient in memory usage (typically using 2506 00119 to 5012 bytes of static data, depending on data type sizes, and the code 00120 is quite short as well). It generates random numbers in batches of 624 00121 at a time, so the caching and pipelining of modern systems is exploited. 00122 It is also divide- and mod-free. 00123 00124 This library is free software; you can redistribute it and/or modify it 00125 under the terms of the GNU Library General Public License as published by 00126 the Free Software Foundation (either version 2 of the License or, at your 00127 option, any later version). This library is distributed in the hope that 00128 it will be useful, but WITHOUT ANY WARRANTY, without even the implied 00129 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 00130 the GNU Library General Public License for more details. You should have 00131 received a copy of the GNU Library General Public License along with this 00132 library; if not, write to the Free Software Foundation, Inc., 59 Temple 00133 Place, Suite 330, Boston, MA 02111-1307, USA. 00134 00135 The code as Shawn received it included the following notice: 00136 00137 Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. When 00138 you use this, send an e-mail to <matumoto@math.keio.ac.jp> with 00139 an appropriate reference to your work. 00140 00141 It would be nice to CC: <Cokus@math.washington.edu> when you write. 00142 00143 00144 00145 php_uint32 must be an unsigned integer type capable of holding at least 32 00146 bits; exactly 32 should be fastest, but 64 is better on an Alpha with 00147 GCC at -O3 optimization so try your options and see what's best for you 00148 00149 Melo: we should put some ifdefs here to catch those alphas... 00150 */ 00151 #define N MT_N /* length of state vector */ 00152 #define M (397) /* a period parameter */ 00153 #define K (0x9908B0DFU) /* a magic constant */ 00154 #define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ 00155 #define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ 00156 #define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ 00157 #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ 00158 00159 /* {{{ php_mt_srand 00160 */ 00161 PHPAPI void php_mt_srand(php_uint32 seed TSRMLS_DC) 00162 { 00163 /* 00164 We initialize state[0..(N-1)] via the generator 00165 00166 x_new = (69069 * x_old) mod 2^32 00167 00168 from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's 00169 _The Art of Computer Programming_, Volume 2, 3rd ed. 00170 00171 Notes (SJC): I do not know what the initial state requirements 00172 of the Mersenne Twister are, but it seems this seeding generator 00173 could be better. It achieves the maximum period for its modulus 00174 (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if 00175 x_initial can be even, you have sequences like 0, 0, 0, ...; 00176 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31, 00177 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below. 00178 00179 00180 Even if x_initial is odd, if x_initial is 1 mod 4 then 00181 00182 the lowest bit of x is always 1, 00183 the next-to-lowest bit of x is always 0, 00184 the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , 00185 the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... , 00186 the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... , 00187 ... 00188 00189 and if x_initial is 3 mod 4 then 00190 00191 the lowest bit of x is always 1, 00192 the next-to-lowest bit of x is always 1, 00193 the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , 00194 the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... , 00195 the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... , 00196 ... 00197 00198 The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is 00199 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It 00200 also does well in the dimension 2..5 spectral tests, but it could be 00201 better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth). 00202 00203 Note that the random number user does not see the values generated 00204 here directly since reloadMT() will always munge them first, so maybe 00205 none of all of this matters. In fact, the seed values made here could 00206 even be extra-special desirable if the Mersenne Twister theory says 00207 so-- that's why the only change I made is to restrict to odd seeds. 00208 */ 00209 00210 register php_uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = BG(state); 00211 register int j; 00212 00213 for (BG(left) = 0, *s++ = x, j = N; --j; 00214 *s++ = (x *= 69069U) & 0xFFFFFFFFU); 00215 00216 /* Seed only once */ 00217 BG(mt_rand_is_seeded) = 1; 00218 } 00219 /* }}} */ 00220 00221 /* {{{ php_mt_reload 00222 */ 00223 static php_uint32 php_mt_reload(TSRMLS_D) 00224 { 00225 register php_uint32 *p0 = BG(state), *p2 = BG(state) + 2, *pM = BG(state) + M, s0, s1; 00226 register int j; 00227 00228 if (BG(left) < -1) 00229 php_mt_srand(4357U TSRMLS_CC); 00230 00231 BG(left) = N - 1, BG(next) = BG(state) + 1; 00232 00233 for (s0 = BG(state)[0], s1 = BG(state)[1], j = N - M + 1; --j; s0 = s1, s1 = *p2++) 00234 *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); 00235 00236 for (pM = BG(state), j = M; --j; s0 = s1, s1 = *p2++) 00237 *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); 00238 00239 s1 = BG(state)[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); 00240 s1 ^= (s1 >> 11); 00241 s1 ^= (s1 << 7) & 0x9D2C5680U; 00242 s1 ^= (s1 << 15) & 0xEFC60000U; 00243 00244 return s1 ^ (s1 >> 18); 00245 } 00246 /* }}} */ 00247 00248 /* {{{ php_mt_rand 00249 */ 00250 PHPAPI php_uint32 php_mt_rand(TSRMLS_D) 00251 { 00252 php_uint32 y; 00253 00254 if (--BG(left) < 0) 00255 return php_mt_reload(TSRMLS_C); 00256 00257 y = *BG(next)++; 00258 y ^= (y >> 11); 00259 y ^= (y << 7) & 0x9D2C5680U; 00260 y ^= (y << 15) & 0xEFC60000U; 00261 00262 return y ^ (y >> 18); 00263 } 00264 /* }}} */ 00265 00266 /* {{{ proto void srand([int seed]) 00267 Seeds random number generator */ 00268 PHP_FUNCTION(srand) 00269 { 00270 long seed; 00271 00272 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &seed) == FAILURE) 00273 return; 00274 00275 if (ZEND_NUM_ARGS() == 0) 00276 seed = GENERATE_SEED(); 00277 00278 php_srand(seed TSRMLS_CC); 00279 } 00280 /* }}} */ 00281 00282 /* {{{ proto void mt_srand([int seed]) 00283 Seeds Mersenne Twister random number generator */ 00284 PHP_FUNCTION(mt_srand) 00285 { 00286 long seed; 00287 00288 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &seed) == FAILURE) 00289 return; 00290 00291 if (ZEND_NUM_ARGS() == 0) 00292 seed = GENERATE_SEED(); 00293 00294 php_mt_srand(seed TSRMLS_CC); 00295 } 00296 /* }}} */ 00297 00298 00299 /* 00300 * A bit of tricky math here. We want to avoid using a modulus because 00301 * that simply tosses the high-order bits and might skew the distribution 00302 * of random values over the range. Instead we map the range directly. 00303 * 00304 * We need to map the range from 0...M evenly to the range a...b 00305 * Let n = the random number and n' = the mapped random number 00306 * 00307 * Then we have: n' = a + n(b-a)/M 00308 * 00309 * We have a problem here in that only n==M will get mapped to b which 00310 # means the chances of getting b is much much less than getting any of 00311 # the other values in the range. We can fix this by increasing our range 00312 # artifically and using: 00313 # 00314 # n' = a + n(b-a+1)/M 00315 * 00316 # Now we only have a problem if n==M which would cause us to produce a 00317 # number of b+1 which would be bad. So we bump M up by one to make sure 00318 # this will never happen, and the final algorithm looks like this: 00319 # 00320 # n' = a + n(b-a+1)/(M+1) 00321 * 00322 * -RL 00323 */ 00324 00325 /* {{{ proto int rand([int min, int max]) 00326 Returns a random number */ 00327 PHP_FUNCTION(rand) 00328 { 00329 long min; 00330 long max; 00331 long number; 00332 int argc = ZEND_NUM_ARGS(); 00333 00334 if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) 00335 return; 00336 00337 number = php_rand(TSRMLS_C); 00338 if (argc == 2) { 00339 RAND_RANGE(number, min, max, PHP_RAND_MAX); 00340 } 00341 00342 RETURN_LONG(number); 00343 } 00344 /* }}} */ 00345 00346 /* {{{ proto int mt_rand([int min, int max]) 00347 Returns a random number from Mersenne Twister */ 00348 PHP_FUNCTION(mt_rand) 00349 { 00350 long min; 00351 long max; 00352 long number; 00353 int argc = ZEND_NUM_ARGS(); 00354 00355 if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) 00356 return; 00357 00358 if (!BG(mt_rand_is_seeded)) { 00359 php_mt_srand(GENERATE_SEED() TSRMLS_CC); 00360 } 00361 00362 /* 00363 * Melo: hmms.. randomMT() returns 32 random bits... 00364 * Yet, the previous php_rand only returns 31 at most. 00365 * So I put a right shift to loose the lsb. It *seems* 00366 * better than clearing the msb. 00367 * Update: 00368 * I talked with Cokus via email and it won't ruin the algorithm 00369 */ 00370 number = (long) (php_mt_rand(TSRMLS_C) >> 1); 00371 if (argc == 2) { 00372 RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); 00373 } 00374 00375 RETURN_LONG(number); 00376 } 00377 /* }}} */ 00378 00379 /* {{{ proto int getrandmax(void) 00380 Returns the maximum value a random number can have */ 00381 PHP_FUNCTION(getrandmax) 00382 { 00383 if (ZEND_NUM_ARGS() != 0) { 00384 WRONG_PARAM_COUNT; 00385 } 00386 00387 RETURN_LONG(PHP_RAND_MAX); 00388 } 00389 /* }}} */ 00390 00391 /* {{{ proto int mt_getrandmax(void) 00392 Returns the maximum value a random number from Mersenne Twister can have */ 00393 PHP_FUNCTION(mt_getrandmax) 00394 { 00395 if (ZEND_NUM_ARGS() != 0) { 00396 WRONG_PARAM_COUNT; 00397 } 00398 00399 /* 00400 * Melo: it could be 2^^32 but we only use 2^^31 to maintain 00401 * compatibility with the previous php_rand 00402 */ 00403 RETURN_LONG(PHP_MT_RAND_MAX); /* 2^^31 */ 00404 } 00405 /* }}} */ 00406 00407 /* 00408 * Local variables: 00409 * tab-width: 4 00410 * c-basic-offset: 4 00411 * End: 00412 * vim600: noet sw=4 ts=4 fdm=marker 00413 * vim<600: noet sw=4 ts=4 00414 */