summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeigh <leigh@php.net>2016-07-05 11:54:07 +0100
committerLeigh <leigh@php.net>2016-07-05 11:54:07 +0100
commit7981a294bd2fb329d404001c369517e2953b92a6 (patch)
treef1d47a0087e106a4bb8aadc7d6a567d9f38bef34
parenteba6e7ce9ac721b072ee3afb1cae883b774f3714 (diff)
downloadphp-git-7981a294bd2fb329d404001c369517e2953b92a6.tar.gz
Fix mt_rand impl. Provide legacy impl. access.
-rw-r--r--ext/standard/basic_functions.c21
-rw-r--r--ext/standard/basic_functions.h1
-rw-r--r--ext/standard/mt_rand.c49
-rw-r--r--ext/standard/php_math.h1
-rw-r--r--ext/standard/php_mt_rand.h5
-rw-r--r--ext/standard/tests/math/mt_rand_value.phpt35
6 files changed, 100 insertions, 12 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 55e1f7e2eb..e712d76216 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -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)
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index bef446d60b..c3b6cedf6d 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -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;
diff --git a/ext/standard/mt_rand.c b/ext/standard/mt_rand.c
index 381f827a95..a684c5cf72 100644
--- a/ext/standard/mt_rand.c
+++ b/ext/standard/mt_rand.c
@@ -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
diff --git a/ext/standard/php_math.h b/ext/standard/php_math.h
index 406fd49dcd..91cd3e498e 100644
--- a/ext/standard/php_math.h
+++ b/ext/standard/php_math.h
@@ -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);
diff --git a/ext/standard/php_mt_rand.h b/ext/standard/php_mt_rand.h
index 84ef1915c6..9d926b5538 100644
--- a/ext/standard/php_mt_rand.h
+++ b/ext/standard/php_mt_rand.h
@@ -27,8 +27,13 @@
#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 */
diff --git a/ext/standard/tests/math/mt_rand_value.phpt b/ext/standard/tests/math/mt_rand_value.phpt
index 772305ad63..c71b61e9b0 100644
--- a/ext/standard/tests/math/mt_rand_value.phpt
+++ b/ext/standard/tests/math/mt_rand_value.phpt
@@ -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