mirror of
https://github.com/php/php-src.git
synced 2024-12-04 15:23:44 +08:00
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
This commit is contained in:
commit
afdaedaa26
118
ext/gmp/gmp.c
118
ext/gmp/gmp.c
@ -104,6 +104,15 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, limiter)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_bits, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, bits)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_random_range, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, min)
|
||||
ZEND_ARG_INFO(0, max)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_gmp_setbit, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, a)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
@ -161,6 +170,8 @@ const zend_function_entry gmp_functions[] = {
|
||||
ZEND_FE(gmp_cmp, arginfo_gmp_binary)
|
||||
ZEND_FE(gmp_sign, arginfo_gmp_unary)
|
||||
ZEND_FE(gmp_random, arginfo_gmp_random)
|
||||
ZEND_FE(gmp_random_bits, arginfo_gmp_random_bits)
|
||||
ZEND_FE(gmp_random_range, arginfo_gmp_random_range)
|
||||
ZEND_FE(gmp_and, arginfo_gmp_binary)
|
||||
ZEND_FE(gmp_or, arginfo_gmp_binary)
|
||||
ZEND_FE(gmp_com, arginfo_gmp_unary)
|
||||
@ -1743,6 +1754,18 @@ ZEND_FUNCTION(gmp_sign)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void gmp_init_random(TSRMLS_D)
|
||||
{
|
||||
if (!GMPG(rand_initialized)) {
|
||||
/* Initialize */
|
||||
gmp_randinit_mt(GMPG(rand_state));
|
||||
/* Seed */
|
||||
gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
|
||||
|
||||
GMPG(rand_initialized) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ proto GMP gmp_random([int limiter])
|
||||
Gets random number */
|
||||
ZEND_FUNCTION(gmp_random)
|
||||
@ -1755,16 +1778,8 @@ ZEND_FUNCTION(gmp_random)
|
||||
}
|
||||
|
||||
INIT_GMP_RETVAL(gmpnum_result);
|
||||
gmp_init_random(TSRMLS_C);
|
||||
|
||||
if (!GMPG(rand_initialized)) {
|
||||
/* Initialize */
|
||||
gmp_randinit_mt(GMPG(rand_state));
|
||||
|
||||
/* Seed */
|
||||
gmp_randseed_ui(GMPG(rand_state), GENERATE_SEED());
|
||||
|
||||
GMPG(rand_initialized) = 1;
|
||||
}
|
||||
#ifdef GMP_LIMB_BITS
|
||||
mpz_urandomb(gmpnum_result, GMPG(rand_state), GMP_ABS (limiter) * GMP_LIMB_BITS);
|
||||
#else
|
||||
@ -1773,6 +1788,91 @@ ZEND_FUNCTION(gmp_random)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto GMP gmp_random_bits(int bits)
|
||||
Gets a random number in the range 0 to (2 ** n) - 1 */
|
||||
ZEND_FUNCTION(gmp_random_bits)
|
||||
{
|
||||
long bits;
|
||||
mpz_ptr gmpnum_result;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bits) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bits <= 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The number of bits must be positive");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
INIT_GMP_RETVAL(gmpnum_result);
|
||||
gmp_init_random(TSRMLS_C);
|
||||
|
||||
mpz_urandomb(gmpnum_result, GMPG(rand_state), bits);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto GMP gmp_random_range(mixed min, mixed max)
|
||||
Gets a random number in the range min to max */
|
||||
ZEND_FUNCTION(gmp_random_range)
|
||||
{
|
||||
zval *min_arg, *max_arg;
|
||||
mpz_ptr gmpnum_min, gmpnum_max, gmpnum_result;
|
||||
gmp_temp_t temp_a, temp_b;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &min_arg, &max_arg) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
gmp_init_random(TSRMLS_C);
|
||||
|
||||
FETCH_GMP_ZVAL(gmpnum_max, max_arg, temp_a);
|
||||
|
||||
if (Z_TYPE_P(min_arg) == IS_LONG && Z_LVAL_P(min_arg) >= 0) {
|
||||
if (mpz_cmp_ui(gmpnum_max, Z_LVAL_P(min_arg)) <= 0) {
|
||||
FREE_GMP_TEMP(temp_a);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The minimum value must be less than the maximum value");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
INIT_GMP_RETVAL(gmpnum_result);
|
||||
|
||||
if (Z_LVAL_P(min_arg)) {
|
||||
mpz_sub_ui(gmpnum_max, gmpnum_max, Z_LVAL_P(min_arg));
|
||||
}
|
||||
|
||||
mpz_add_ui(gmpnum_max, gmpnum_max, 1);
|
||||
mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
|
||||
|
||||
if (Z_LVAL_P(min_arg)) {
|
||||
mpz_add_ui(gmpnum_result, gmpnum_result, Z_LVAL_P(min_arg));
|
||||
}
|
||||
|
||||
FREE_GMP_TEMP(temp_a);
|
||||
|
||||
}
|
||||
else {
|
||||
FETCH_GMP_ZVAL_DEP(gmpnum_min, min_arg, temp_b, temp_a);
|
||||
|
||||
if (mpz_cmp(gmpnum_max, gmpnum_min) <= 0) {
|
||||
FREE_GMP_TEMP(temp_b);
|
||||
FREE_GMP_TEMP(temp_a);
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The minimum value must be less than the maximum value");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
INIT_GMP_RETVAL(gmpnum_result);
|
||||
|
||||
mpz_sub(gmpnum_max, gmpnum_max, gmpnum_min);
|
||||
mpz_add_ui(gmpnum_max, gmpnum_max, 1);
|
||||
mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
|
||||
mpz_add(gmpnum_result, gmpnum_result, gmpnum_min);
|
||||
|
||||
FREE_GMP_TEMP(temp_b);
|
||||
FREE_GMP_TEMP(temp_a);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto GMP gmp_and(mixed a, mixed b)
|
||||
Calculates logical AND of a and b */
|
||||
ZEND_FUNCTION(gmp_and)
|
||||
|
@ -66,6 +66,8 @@ ZEND_FUNCTION(gmp_or);
|
||||
ZEND_FUNCTION(gmp_com);
|
||||
ZEND_FUNCTION(gmp_xor);
|
||||
ZEND_FUNCTION(gmp_random);
|
||||
ZEND_FUNCTION(gmp_random_bits);
|
||||
ZEND_FUNCTION(gmp_random_range);
|
||||
ZEND_FUNCTION(gmp_setbit);
|
||||
ZEND_FUNCTION(gmp_clrbit);
|
||||
ZEND_FUNCTION(gmp_scan0);
|
||||
|
45
ext/gmp/tests/gmp_random_bits.phpt
Normal file
45
ext/gmp/tests/gmp_random_bits.phpt
Normal file
@ -0,0 +1,45 @@
|
||||
--TEST--
|
||||
gmp_random_bits() basic tests
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("gmp")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(gmp_random_bits());
|
||||
var_dump(gmp_random_bits(0));
|
||||
var_dump(gmp_random_bits(-1));
|
||||
|
||||
// If these error the test fails.
|
||||
gmp_random_bits(1);
|
||||
gmp_random_bits(1024);
|
||||
|
||||
// 2 seconds to make sure the numbers stay in range
|
||||
$start = microtime(true);
|
||||
$limit = (2 ** 30) - 1;
|
||||
while (1) {
|
||||
for ($i = 0; $i < 5000; $i++) {
|
||||
$result = gmp_random_bits(30);
|
||||
if ($result < 0 || $result > $limit) {
|
||||
print "RANGE VIOLATION\n";
|
||||
var_dump($result);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (microtime(true) - $start > 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: gmp_random_bits() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: gmp_random_bits(): The number of bits must be positive in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: gmp_random_bits(): The number of bits must be positive in %s on line %d
|
||||
bool(false)
|
||||
Done
|
81
ext/gmp/tests/gmp_random_range.phpt
Normal file
81
ext/gmp/tests/gmp_random_range.phpt
Normal file
@ -0,0 +1,81 @@
|
||||
--TEST--
|
||||
gmp_random_range() basic tests
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("gmp")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$minusTen = gmp_init(-1);
|
||||
$plusTen = gmp_init(1);
|
||||
$zero = gmp_init(0);
|
||||
|
||||
var_dump(gmp_random_range());
|
||||
var_dump(gmp_random_range(10));
|
||||
var_dump(gmp_random_range(10, -10));
|
||||
|
||||
var_dump(gmp_random_range($plusTen, $minusTen));
|
||||
var_dump(gmp_random_range($plusTen, $zero));
|
||||
|
||||
// If these error the test fails.
|
||||
gmp_random_range(0, 10);
|
||||
gmp_random_range(1, 10);
|
||||
gmp_random_range(-1, 10);
|
||||
gmp_random_range(-10, 0);
|
||||
gmp_random_range(-10, -1);
|
||||
|
||||
gmp_random_range(0, $plusTen);
|
||||
gmp_random_range(1, $plusTen);
|
||||
gmp_random_range(-1, $plusTen);
|
||||
|
||||
gmp_random_range($zero, $plusTen);
|
||||
gmp_random_range($minusTen, $plusTen);
|
||||
|
||||
// 2 seconds to make sure the numbers stay in range
|
||||
$start = microtime(true);
|
||||
while (1) {
|
||||
for ($i = 0; $i < 5000; $i++) {
|
||||
$result = gmp_random_range(0, 1000);
|
||||
if ($result < 0 || $result > 1000) {
|
||||
print "RANGE VIOLATION 1\n";
|
||||
var_dump($result);
|
||||
break 2;
|
||||
}
|
||||
|
||||
$result = gmp_random_range(-1000, 0);
|
||||
if ($result < -1000 || $result > 0) {
|
||||
print "RANGE VIOLATION 2\n";
|
||||
var_dump($result);
|
||||
break 2;
|
||||
}
|
||||
|
||||
$result = gmp_random_range(-500, 500);
|
||||
if ($result < -500 || $result > 500) {
|
||||
print "RANGE VIOLATION 3\n";
|
||||
var_dump($result);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (microtime(true) - $start > 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: gmp_random_range() expects exactly 2 parameters, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: gmp_random_range() expects exactly 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: gmp_random_range(): The minimum value must be less than the maximum value in %s on line %d
|
||||
bool(false)
|
||||
Done
|
Loading…
Reference in New Issue
Block a user