]> granicus.if.org Git - php/commitdiff
Fix mt_rand impl. Provide legacy impl. access.
authorLeigh <leigh@php.net>
Tue, 5 Jul 2016 10:54:07 +0000 (11:54 +0100)
committerLeigh <leigh@php.net>
Tue, 5 Jul 2016 10:54:07 +0000 (11:54 +0100)
ext/standard/basic_functions.c
ext/standard/basic_functions.h
ext/standard/mt_rand.c
ext/standard/php_math.h
ext/standard/php_mt_rand.h
ext/standard/tests/math/mt_rand_value.phpt

index 55e1f7e2eb6947ea1ed0a6254e18dec6c2fc84a8..e712d762161d15cefc46e957e5bdce609f79a467 100644 (file)
@@ -35,6 +35,7 @@
 #include "zend_operators.h"
 #include "ext/standard/php_dns.h"
 #include "ext/standard/php_uuencode.h"
+#include "ext/standard/php_mt_rand.h"
 
 #ifdef PHP_WIN32
 #include "win32/php_win32_globals.h"
@@ -1887,24 +1888,29 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_srand, 0, 0, 0)
        ZEND_ARG_INFO(0, seed)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO_EX(arginfo_mt_srand, 0, 0, 0)
-       ZEND_ARG_INFO(0, seed)
-ZEND_END_ARG_INFO()
-
 ZEND_BEGIN_ARG_INFO_EX(arginfo_rand, 0, 0, 0)
        ZEND_ARG_INFO(0, min)
        ZEND_ARG_INFO(0, max)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO(arginfo_getrandmax, 0)
+ZEND_END_ARG_INFO()
+/* }}} */
+/* {{{ mt_rand.c */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mt_srand, 0, 0, 0)
+       ZEND_ARG_INFO(0, seed)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_mt_rand, 0, 0, 0)
        ZEND_ARG_INFO(0, min)
        ZEND_ARG_INFO(0, max)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO(arginfo_getrandmax, 0)
+ZEND_BEGIN_ARG_INFO(arginfo_mt_getrandmax, 0)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO(arginfo_mt_getrandmax, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mt_rand_mode, 0, 0, 1)
+       ZEND_ARG_INFO(0, mode)
 ZEND_END_ARG_INFO()
 /* }}} */
 /* {{{ random.c */
@@ -2865,6 +2871,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */
        PHP_FE(mt_rand,                                                                                                         arginfo_mt_rand)
        PHP_FE(mt_srand,                                                                                                                arginfo_mt_srand)
        PHP_FE(mt_getrandmax,                                                                                                   arginfo_mt_getrandmax)
+       PHP_FE(mt_rand_mode,                                                                                                    arginfo_mt_rand_mode)
 
        PHP_FE(random_bytes,                                                                                                    arginfo_random_bytes)
        PHP_FE(random_int,                                                                                                      arginfo_random_int)
@@ -3479,6 +3486,7 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */
 {
        BG(rand_is_seeded) = 0;
        BG(mt_rand_is_seeded) = 0;
+       BG(mt_rand_mode) = MT_RAND_MT19937;
        BG(umask) = -1;
        BG(next) = NULL;
        BG(left) = -1;
@@ -3660,6 +3668,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
        BASIC_MINIT_SUBMODULE(standard_filters)
        BASIC_MINIT_SUBMODULE(user_filters)
        BASIC_MINIT_SUBMODULE(password)
+       BASIC_MINIT_SUBMODULE(mt_rand)
 
 #if defined(HAVE_LOCALECONV) && defined(ZTS)
        BASIC_MINIT_SUBMODULE(localeconv)
index bef446d60bb1d33db67176cd6bc2714ac20c7762..c3b6cedf6db228c8f4f84a061618cdc7f9b78acf 100644 (file)
@@ -200,6 +200,7 @@ typedef struct _php_basic_globals {
 
        zend_bool rand_is_seeded; /* Whether rand() has been seeded */
        zend_bool mt_rand_is_seeded; /* Whether mt_rand() has been seeded */
+       zend_long mt_rand_mode;
 
        /* syslog.c */
        char *syslog_device;
index 381f827a95d89dc6c3ae87782f8b283609d736e9..a684c5cf72c2246ab2669d6e55509a8f5a2c8837 100644 (file)
@@ -91,7 +91,8 @@
 #define loBits(u)     ((u) & 0x7FFFFFFFU)  /* mask     the highest   bit of u */
 #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
 
-#define twist(m,u,v)  (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(u))) & 0x9908b0dfU))
+#define twist(m,u,v)  (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(v))) & 0x9908b0dfU))
+#define twist_php(m,u,v)  (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(u))) & 0x9908b0dfU))
 
 /* {{{ php_mt_initialize
  */
@@ -125,11 +126,20 @@ static inline void php_mt_reload(void)
        register uint32_t *p = state;
        register int i;
 
-       for (i = N - M; i--; ++p)
-               *p = twist(p[M], p[0], p[1]);
-       for (i = M; --i; ++p)
-               *p = twist(p[M-N], p[0], p[1]);
-       *p = twist(p[M-N], p[0], state[0]);
+       if (BG(mt_rand_mode) == MT_RAND_MT19937) {
+               for (i = N - M; i--; ++p)
+                       *p = twist(p[M], p[0], p[1]);
+               for (i = M; --i; ++p)
+                       *p = twist(p[M-N], p[0], p[1]);
+               *p = twist(p[M-N], p[0], state[0]);
+       }
+       else {
+               for (i = N - M; i--; ++p)
+                       *p = twist_php(p[M], p[0], p[1]);
+               for (i = M; --i; ++p)
+                       *p = twist_php(p[M-N], p[0], p[1]);
+               *p = twist_php(p[M-N], p[0], state[0]);
+       }
        BG(left) = N;
        BG(next) = state;
 }
@@ -267,6 +277,33 @@ PHP_FUNCTION(mt_getrandmax)
 }
 /* }}} */
 
+/* {{{ proto int mt_rand_mode(int)
+   Switch mt_rand between standard and legacy modes */
+PHP_FUNCTION(mt_rand_mode)
+{
+       zend_long mode;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &mode) == FAILURE) {
+               return;
+       }
+
+       switch (mode) {
+               case MT_RAND_PHP:
+                       BG(mt_rand_mode) = MT_RAND_PHP;
+                       break;
+               default:
+                       BG(mt_rand_mode) = MT_RAND_MT19937;
+       }
+}
+/* }}} */
+PHP_MINIT_FUNCTION(mt_rand)
+{
+       REGISTER_LONG_CONSTANT("MT_RAND_MT19937", MT_RAND_MT19937, CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("MT_RAND_PHP",     MT_RAND_PHP, CONST_CS | CONST_PERSISTENT);
+
+       return SUCCESS;
+}
+
 /*
  * Local variables:
  * tab-width: 4
index 406fd49dcd9c02166f0ac7a9bdf53d149afc026d..91cd3e498e3517a6f4932876725aa52fc55a0838 100644 (file)
@@ -51,6 +51,7 @@ PHP_FUNCTION(getrandmax);
 PHP_FUNCTION(mt_srand);
 PHP_FUNCTION(mt_rand);
 PHP_FUNCTION(mt_getrandmax);
+PHP_FUNCTION(mt_rand_mode);
 PHP_FUNCTION(abs);
 PHP_FUNCTION(ceil);
 PHP_FUNCTION(floor);
index 84ef1915c6a7d9e314d04d4cdb7f9f41e5cb50e8..9d926b5538b29b3b51177809122e122d06e83379 100644 (file)
 
 #define PHP_MT_RAND_MAX ((zend_long) (0x7FFFFFFF)) /* (1<<31) - 1 */
 
+#define MT_RAND_MT19937 0
+#define MT_RAND_PHP 1
+
 PHPAPI void php_mt_srand(uint32_t seed);
 PHPAPI uint32_t php_mt_rand(void);
 
+PHP_MINIT_FUNCTION(mt_rand);
+
 #endif /* PHP_MT_RAND_H */
 
index 772305ad632f2c5ada5b2a737d7e69f2e42faea1..c71b61e9b00496b427a0823d30e3bcbf576cbcdd 100644 (file)
@@ -3,6 +3,22 @@ Test mt_rand() output
 --FILE--
 <?php
 
+mt_rand_mode(MT_RAND_PHP);
+mt_srand(12345678);
+
+for ($i=0; $i<16; $i++) {
+    echo mt_rand().PHP_EOL;
+}
+echo PHP_EOL;
+
+$x = 0;
+for ($i=0; $i<1024; $i++) {
+    $x ^= mt_rand();
+}
+echo $x.PHP_EOL;
+echo PHP_EOL;
+
+mt_rand_mode(MT_RAND_MT19937);
 mt_srand(12345678);
 
 for ($i=0; $i<16; $i++) {
@@ -42,3 +58,22 @@ echo $x.PHP_EOL;
 853386222
 
 1571178311
+
+527860569
+1711027313
+1280820687
+688176834
+770499160
+412773096
+813703253
+898651287
+52508912
+757323740
+511765911
+274407457
+833082629
+1923803667
+1461450755
+1301698200
+
+1612214270