Skip to content

Commit afdaeda

Browse files
committed
Merge branch 'PHP-5.6'
* PHP-5.6: update NEWS and UPGRADING Upated NEWS Address issues raised by @nikic Make sure min < max Mersenne Twister was added in GMP 4.2 Add test files Add gmp_random_bits(bits) and gmp_random_range(min, max) Change GMPs default PRNG to Mersenne Twister Conflicts: ext/gmp/gmp.c
2 parents 2842766 + 4773c1d commit afdaeda

File tree

4 files changed

+237
-9
lines changed

4 files changed

+237
-9
lines changed

ext/gmp/gmp.c

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random, 0, 0, 0)
104104
ZEND_ARG_INFO(0, limiter)
105105
ZEND_END_ARG_INFO()
106106

107+
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_bits, 0, 0, 1)
108+
ZEND_ARG_INFO(0, bits)
109+
ZEND_END_ARG_INFO()
110+
111+
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_range, 0, 0, 2)
112+
ZEND_ARG_INFO(0, min)
113+
ZEND_ARG_INFO(0, max)
114+
ZEND_END_ARG_INFO()
115+
107116
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_setbit, 0, 0, 2)
108117
ZEND_ARG_INFO(0, a)
109118
ZEND_ARG_INFO(0, index)
@@ -161,6 +170,8 @@ const zend_function_entry gmp_functions[] = {
161170
ZEND_FE(gmp_cmp, arginfo_gmp_binary)
162171
ZEND_FE(gmp_sign, arginfo_gmp_unary)
163172
ZEND_FE(gmp_random, arginfo_gmp_random)
173+
ZEND_FE(gmp_random_bits, arginfo_gmp_random_bits)
174+
ZEND_FE(gmp_random_range, arginfo_gmp_random_range)
164175
ZEND_FE(gmp_and, arginfo_gmp_binary)
165176
ZEND_FE(gmp_or, arginfo_gmp_binary)
166177
ZEND_FE(gmp_com, arginfo_gmp_unary)
@@ -1743,6 +1754,18 @@ ZEND_FUNCTION(gmp_sign)
17431754
}
17441755
/* }}} */
17451756

1757+
static void gmp_init_random(TSRMLS_D)
1758+
{
1759+
if (!GMPG(rand_initialized)) {
1760+
/* Initialize */
1761+
gmp_randinit_mt(GMPG(rand_state));
1762+
/* Seed */
1763+
gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
1764+
1765+
GMPG(rand_initialized) = 1;
1766+
}
1767+
}
1768+
17461769
/* {{{ proto GMP gmp_random([int limiter])
17471770
Gets random number */
17481771
ZEND_FUNCTION(gmp_random)
@@ -1755,16 +1778,8 @@ ZEND_FUNCTION(gmp_random)
17551778
}
17561779

17571780
INIT_GMP_RETVAL(gmpnum_result);
1781+
gmp_init_random(TSRMLS_C);
17581782

1759-
if (!GMPG(rand_initialized)) {
1760-
/* Initialize */
1761-
gmp_randinit_mt(GMPG(rand_state));
1762-
1763-
/* Seed */
1764-
gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
1765-
1766-
GMPG(rand_initialized) = 1;
1767-
}
17681783
#ifdef GMP_LIMB_BITS
17691784
mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
17701785
#else
@@ -1773,6 +1788,91 @@ ZEND_FUNCTION(gmp_random)
17731788
}
17741789
/* }}} */
17751790

1791+
/* {{{ proto GMP gmp_random_bits(int bits)
1792+
Gets a random number in the range 0 to (2 ** n) - 1 */
1793+
ZEND_FUNCTION(gmp_random_bits)
1794+
{
1795+
long bits;
1796+
mpz_ptr gmpnum_result;
1797+
1798+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bits) == FAILURE) {
1799+
return;
1800+
}
1801+
1802+
if (bits <= 0) {
1803+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The number of bits must be positive");
1804+
RETURN_FALSE;
1805+
}
1806+
1807+
INIT_GMP_RETVAL(gmpnum_result);
1808+
gmp_init_random(TSRMLS_C);
1809+
1810+
mpz_urandomb(gmpnum_result, GMPG(rand_state), bits);
1811+
}
1812+
/* }}} */
1813+
1814+
/* {{{ proto GMP gmp_random_range(mixed min, mixed max)
1815+
Gets a random number in the range min to max */
1816+
ZEND_FUNCTION(gmp_random_range)
1817+
{
1818+
zval *min_arg, *max_arg;
1819+
mpz_ptr gmpnum_min, gmpnum_max, gmpnum_result;
1820+
gmp_temp_t temp_a, temp_b;
1821+
1822+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &min_arg, &max_arg) == FAILURE) {
1823+
return;
1824+
}
1825+
1826+
gmp_init_random(TSRMLS_C);
1827+
1828+
FETCH_GMP_ZVAL(gmpnum_max, max_arg, temp_a);
1829+
1830+
if (Z_TYPE_P(min_arg) == IS_LONG && Z_LVAL_P(min_arg) >= 0) {
1831+
if (mpz_cmp_ui(gmpnum_max, Z_LVAL_P(min_arg)) <= 0) {
1832+
FREE_GMP_TEMP(temp_a);
1833+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The minimum value must be less than the maximum value");
1834+
RETURN_FALSE;
1835+
}
1836+
1837+
INIT_GMP_RETVAL(gmpnum_result);
1838+
1839+
if (Z_LVAL_P(min_arg)) {
1840+
mpz_sub_ui(gmpnum_max, gmpnum_max, Z_LVAL_P(min_arg));
1841+
}
1842+
1843+
mpz_add_ui(gmpnum_max, gmpnum_max, 1);
1844+
mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
1845+
1846+
if (Z_LVAL_P(min_arg)) {
1847+
mpz_add_ui(gmpnum_result, gmpnum_result, Z_LVAL_P(min_arg));
1848+
}
1849+
1850+
FREE_GMP_TEMP(temp_a);
1851+
1852+
}
1853+
else {
1854+
FETCH_GMP_ZVAL_DEP(gmpnum_min, min_arg, temp_b, temp_a);
1855+
1856+
if (mpz_cmp(gmpnum_max, gmpnum_min) <= 0) {
1857+
FREE_GMP_TEMP(temp_b);
1858+
FREE_GMP_TEMP(temp_a);
1859+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The minimum value must be less than the maximum value");
1860+
RETURN_FALSE;
1861+
}
1862+
1863+
INIT_GMP_RETVAL(gmpnum_result);
1864+
1865+
mpz_sub(gmpnum_max, gmpnum_max, gmpnum_min);
1866+
mpz_add_ui(gmpnum_max, gmpnum_max, 1);
1867+
mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
1868+
mpz_add(gmpnum_result, gmpnum_result, gmpnum_min);
1869+
1870+
FREE_GMP_TEMP(temp_b);
1871+
FREE_GMP_TEMP(temp_a);
1872+
}
1873+
}
1874+
/* }}} */
1875+
17761876
/* {{{ proto GMP gmp_and(mixed a, mixed b)
17771877
Calculates logical AND of a and b */
17781878
ZEND_FUNCTION(gmp_and)

ext/gmp/php_gmp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ ZEND_FUNCTION(gmp_or);
6666
ZEND_FUNCTION(gmp_com);
6767
ZEND_FUNCTION(gmp_xor);
6868
ZEND_FUNCTION(gmp_random);
69+
ZEND_FUNCTION(gmp_random_bits);
70+
ZEND_FUNCTION(gmp_random_range);
6971
ZEND_FUNCTION(gmp_setbit);
7072
ZEND_FUNCTION(gmp_clrbit);
7173
ZEND_FUNCTION(gmp_scan0);

ext/gmp/tests/gmp_random_bits.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
gmp_random_bits() basic tests
3+
--SKIPIF--
4+
<?php if (!extension_loaded("gmp")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
8+
var_dump(gmp_random_bits());
9+
var_dump(gmp_random_bits(0));
10+
var_dump(gmp_random_bits(-1));
11+
12+
// If these error the test fails.
13+
gmp_random_bits(1);
14+
gmp_random_bits(1024);
15+
16+
// 2 seconds to make sure the numbers stay in range
17+
$start = microtime(true);
18+
$limit = (2 ** 30) - 1;
19+
while (1) {
20+
for ($i = 0; $i < 5000; $i++) {
21+
$result = gmp_random_bits(30);
22+
if ($result < 0 || $result > $limit) {
23+
print "RANGE VIOLATION\n";
24+
var_dump($result);
25+
break 2;
26+
}
27+
}
28+
29+
if (microtime(true) - $start > 2) {
30+
break;
31+
}
32+
}
33+
34+
echo "Done\n";
35+
?>
36+
--EXPECTF--
37+
Warning: gmp_random_bits() expects exactly 1 parameter, 0 given in %s on line %d
38+
NULL
39+
40+
Warning: gmp_random_bits(): The number of bits must be positive in %s on line %d
41+
bool(false)
42+
43+
Warning: gmp_random_bits(): The number of bits must be positive in %s on line %d
44+
bool(false)
45+
Done

ext/gmp/tests/gmp_random_range.phpt

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
--TEST--
2+
gmp_random_range() basic tests
3+
--SKIPIF--
4+
<?php if (!extension_loaded("gmp")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
8+
$minusTen = gmp_init(-1);
9+
$plusTen = gmp_init(1);
10+
$zero = gmp_init(0);
11+
12+
var_dump(gmp_random_range());
13+
var_dump(gmp_random_range(10));
14+
var_dump(gmp_random_range(10, -10));
15+
16+
var_dump(gmp_random_range($plusTen, $minusTen));
17+
var_dump(gmp_random_range($plusTen, $zero));
18+
19+
// If these error the test fails.
20+
gmp_random_range(0, 10);
21+
gmp_random_range(1, 10);
22+
gmp_random_range(-1, 10);
23+
gmp_random_range(-10, 0);
24+
gmp_random_range(-10, -1);
25+
26+
gmp_random_range(0, $plusTen);
27+
gmp_random_range(1, $plusTen);
28+
gmp_random_range(-1, $plusTen);
29+
30+
gmp_random_range($zero, $plusTen);
31+
gmp_random_range($minusTen, $plusTen);
32+
33+
// 2 seconds to make sure the numbers stay in range
34+
$start = microtime(true);
35+
while (1) {
36+
for ($i = 0; $i < 5000; $i++) {
37+
$result = gmp_random_range(0, 1000);
38+
if ($result < 0 || $result > 1000) {
39+
print "RANGE VIOLATION 1\n";
40+
var_dump($result);
41+
break 2;
42+
}
43+
44+
$result = gmp_random_range(-1000, 0);
45+
if ($result < -1000 || $result > 0) {
46+
print "RANGE VIOLATION 2\n";
47+
var_dump($result);
48+
break 2;
49+
}
50+
51+
$result = gmp_random_range(-500, 500);
52+
if ($result < -500 || $result > 500) {
53+
print "RANGE VIOLATION 3\n";
54+
var_dump($result);
55+
break 2;
56+
}
57+
}
58+
59+
if (microtime(true) - $start > 2) {
60+
break;
61+
}
62+
}
63+
64+
echo "Done\n";
65+
?>
66+
--EXPECTF--
67+
Warning: gmp_random_range() expects exactly 2 parameters, 0 given in %s on line %d
68+
NULL
69+
70+
Warning: gmp_random_range() expects exactly 2 parameters, 1 given in %s on line %d
71+
NULL
72+
73+
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
74+
bool(false)
75+
76+
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
77+
bool(false)
78+
79+
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
80+
bool(false)
81+
Done

0 commit comments

Comments
 (0)