From ae5e2302a9f03e5ce5bc2d8b93a10accf66a89e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 5 Oct 2022 21:25:05 +0200 Subject: [PATCH 01/11] Add Randomizer::nextFloat() --- ext/random/random.stub.php | 2 ++ ext/random/random_arginfo.h | 6 +++++- ext/random/randomizer.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/ext/random/random.stub.php b/ext/random/random.stub.php index 0a178f2657dc2..8344a67ceacfe 100644 --- a/ext/random/random.stub.php +++ b/ext/random/random.stub.php @@ -133,6 +133,8 @@ public function __construct(?Engine $engine = null) {} public function nextInt(): int {} + public function nextFloat(): float {} + public function getInt(int $min, int $max): int {} public function getBytes(int $length): string {} diff --git a/ext/random/random_arginfo.h b/ext/random/random_arginfo.h index fc272607360d0..c82bf4e21baa6 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6cc9022516ce23c2e95af30606db43e9fc28e38a */ + * Stub hash: 8d73c0e257a519353863fe89ec059b42a9223a99 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() @@ -90,6 +90,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_Random_Randomizer_nextInt arginfo_mt_getrandmax +#define arginfo_class_Random_Randomizer_nextFloat arginfo_lcg_value + #define arginfo_class_Random_Randomizer_getInt arginfo_random_int #define arginfo_class_Random_Randomizer_getBytes arginfo_random_bytes @@ -131,6 +133,7 @@ ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jump); ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong); ZEND_METHOD(Random_Randomizer, __construct); ZEND_METHOD(Random_Randomizer, nextInt); +ZEND_METHOD(Random_Randomizer, nextFloat); ZEND_METHOD(Random_Randomizer, getInt); ZEND_METHOD(Random_Randomizer, getBytes); ZEND_METHOD(Random_Randomizer, shuffleArray); @@ -207,6 +210,7 @@ static const zend_function_entry class_Random_CryptoSafeEngine_methods[] = { static const zend_function_entry class_Random_Randomizer_methods[] = { ZEND_ME(Random_Randomizer, __construct, arginfo_class_Random_Randomizer___construct, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, nextInt, arginfo_class_Random_Randomizer_nextInt, ZEND_ACC_PUBLIC) + ZEND_ME(Random_Randomizer, nextFloat, arginfo_class_Random_Randomizer_nextFloat, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, getInt, arginfo_class_Random_Randomizer_getInt, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, getBytes, arginfo_class_Random_Randomizer_getBytes, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, shuffleArray, arginfo_class_Random_Randomizer_shuffleArray, ZEND_ACC_PUBLIC) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 0e3d90120b6fc..a655e981ec4b4 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -109,6 +109,41 @@ PHP_METHOD(Random_Randomizer, nextInt) } /* }}} */ +/* {{{ Generate a float in [0, 1) */ +PHP_METHOD(Random_Randomizer, nextFloat) +{ + php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS); + uint64_t result; + size_t total_size; + + ZEND_PARSE_PARAMETERS_NONE(); + + result = 0; + total_size = 0; + do { + uint64_t r = randomizer->algo->generate(randomizer->status); + result = result | (r << (total_size * 8)); + total_size += randomizer->status->last_generated_size; + if (EG(exception)) { + RETURN_THROWS(); + } + } while (total_size < sizeof(uint64_t)); + + /* A double has 53 bits of precision, thus we must not + * use the full 64 bits of the uint64_t, because we would + * introduce a bias / rounding error. + */ + const double step_size = 1.0 / (1ULL << 53); + + /* Use the upper 53 bits, because some engine's lower bits + * are of lower quality. + */ + result = (result >> 11); + + RETURN_DOUBLE(step_size * result); +} +/* }}} */ + /* {{{ Generate random number in range */ PHP_METHOD(Random_Randomizer, getInt) { From 7fb6ba2b1cc85c784da80e0db643a90cb2fdf604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 10 Oct 2022 17:40:57 +0200 Subject: [PATCH 02/11] Check that doubles are IEEE-754 in Randomizer::nextFloat() --- ext/random/randomizer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index a655e981ec4b4..1096a45b06c45 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -118,6 +118,11 @@ PHP_METHOD(Random_Randomizer, nextFloat) ZEND_PARSE_PARAMETERS_NONE(); +#ifndef __STDC_IEC_559__ + zend_throw_exception(random_ce_Random_RandomException, "The nextFloat() method requires the underlying 'double' representation to be IEEE-754.", 0); + RETURN_THROWS(); +#endif + result = 0; total_size = 0; do { @@ -133,6 +138,7 @@ PHP_METHOD(Random_Randomizer, nextFloat) * use the full 64 bits of the uint64_t, because we would * introduce a bias / rounding error. */ + ZEND_ASSERT(DBL_MANT_DIG == 53); const double step_size = 1.0 / (1ULL << 53); /* Use the upper 53 bits, because some engine's lower bits From 985a7fa2bb4a13898dede6119d40e979ee00b3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 10 Oct 2022 18:00:30 +0200 Subject: [PATCH 03/11] Add Randomizer::nextFloat() tests --- .../03_randomizer/methods/nextFloat.phpt | 49 +++++++++++++++++++ .../methods/nextFloat_spacing.phpt | 41 ++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 ext/random/tests/03_randomizer/methods/nextFloat.phpt create mode 100644 ext/random/tests/03_randomizer/methods/nextFloat_spacing.phpt diff --git a/ext/random/tests/03_randomizer/methods/nextFloat.phpt b/ext/random/tests/03_randomizer/methods/nextFloat.phpt new file mode 100644 index 0000000000000..c8e7046226ec4 --- /dev/null +++ b/ext/random/tests/03_randomizer/methods/nextFloat.phpt @@ -0,0 +1,49 @@ +--TEST-- +Random: Randomizer: nextFloat(): Basic functionality +--FILE-- +nextFloat(); + + if ($result < 0 || $result >= 1) { + die("failure: out of range at {$i}"); + } + } +} + +die('success'); + +?> +--EXPECT-- +Random\Engine\Mt19937 +Random\Engine\Mt19937 +Random\Engine\PcgOneseq128XslRr64 +Random\Engine\Xoshiro256StarStar +Random\Engine\Secure +Random\Engine\Test\TestShaEngine +success diff --git a/ext/random/tests/03_randomizer/methods/nextFloat_spacing.phpt b/ext/random/tests/03_randomizer/methods/nextFloat_spacing.phpt new file mode 100644 index 0000000000000..133d5ff056eab --- /dev/null +++ b/ext/random/tests/03_randomizer/methods/nextFloat_spacing.phpt @@ -0,0 +1,41 @@ +--TEST-- +Random: Randomizer: nextFloat(): Return values are evenly spaced. +--FILE-- +value; + } +} + +$zero = new Randomizer(new StaticEngine("\x00\x00\x00\x00\x00\x00\x00\x00")); +$one = new Randomizer(new StaticEngine("\x00\x08\x00\x00\x00\x00\x00\x00")); +$two = new Randomizer(new StaticEngine("\x00\x10\x00\x00\x00\x00\x00\x00")); + +$max_minus_two = new Randomizer(new StaticEngine("\x00\xe8\xff\xff\xff\xff\xff\xff")); +$max_minus_one = new Randomizer(new StaticEngine("\x00\xf0\xff\xff\xff\xff\xff\xff")); +$max = new Randomizer(new StaticEngine("\x00\xf8\xff\xff\xff\xff\xff\xff")); + +var_dump($one->nextFloat() - $one->nextFloat() === $zero->nextFloat()); +var_dump($two->nextFloat() - $one->nextFloat() === $one->nextFloat()); +var_dump($max->nextFloat() - $max_minus_one->nextFloat() === $one->nextFloat()); +var_dump($max_minus_one->nextFloat() - $max_minus_two->nextFloat() === $one->nextFloat()); +var_dump($max->nextFloat() - $max_minus_two->nextFloat() === $two->nextFloat()); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) From 786cfafdebb3011b938b452186749dc0d1665c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 11 Oct 2022 23:09:36 +0200 Subject: [PATCH 04/11] Add Randomizer::getFloat() implementing the y-section algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The algorithm is published in: Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022. https://doi.org/10.1145/3503512 --- ext/random/random.stub.php | 2 + ext/random/random_arginfo.h | 9 ++++- ext/random/randomizer.c | 74 +++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/ext/random/random.stub.php b/ext/random/random.stub.php index 8344a67ceacfe..d44a8ecce1136 100644 --- a/ext/random/random.stub.php +++ b/ext/random/random.stub.php @@ -135,6 +135,8 @@ public function nextInt(): int {} public function nextFloat(): float {} + public function getFloat(float $min, float $max): float {} + public function getInt(int $min, int $max): int {} public function getBytes(int $length): string {} diff --git a/ext/random/random_arginfo.h b/ext/random/random_arginfo.h index c82bf4e21baa6..f313182d3e67e 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8d73c0e257a519353863fe89ec059b42a9223a99 */ + * Stub hash: 38402d67bee6e4a5936dada33498f36c602b3df2 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() @@ -92,6 +92,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_Random_Randomizer_nextFloat arginfo_lcg_value +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Random_Randomizer_getFloat, 0, 2, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, min, IS_DOUBLE, 0) + ZEND_ARG_TYPE_INFO(0, max, IS_DOUBLE, 0) +ZEND_END_ARG_INFO() + #define arginfo_class_Random_Randomizer_getInt arginfo_random_int #define arginfo_class_Random_Randomizer_getBytes arginfo_random_bytes @@ -134,6 +139,7 @@ ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong); ZEND_METHOD(Random_Randomizer, __construct); ZEND_METHOD(Random_Randomizer, nextInt); ZEND_METHOD(Random_Randomizer, nextFloat); +ZEND_METHOD(Random_Randomizer, getFloat); ZEND_METHOD(Random_Randomizer, getInt); ZEND_METHOD(Random_Randomizer, getBytes); ZEND_METHOD(Random_Randomizer, shuffleArray); @@ -211,6 +217,7 @@ static const zend_function_entry class_Random_Randomizer_methods[] = { ZEND_ME(Random_Randomizer, __construct, arginfo_class_Random_Randomizer___construct, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, nextInt, arginfo_class_Random_Randomizer_nextInt, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, nextFloat, arginfo_class_Random_Randomizer_nextFloat, ZEND_ACC_PUBLIC) + ZEND_ME(Random_Randomizer, getFloat, arginfo_class_Random_Randomizer_getFloat, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, getInt, arginfo_class_Random_Randomizer_getInt, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, getBytes, arginfo_class_Random_Randomizer_getBytes, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, shuffleArray, arginfo_class_Random_Randomizer_shuffleArray, ZEND_ACC_PUBLIC) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 1096a45b06c45..a7975ce5b9dd9 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -150,6 +150,80 @@ PHP_METHOD(Random_Randomizer, nextFloat) } /* }}} */ +static double getFloat_gamma_low(double x) +{ + return x - nextafter(x, -DBL_MAX); +} + +static double getFloat_gamma_high(double x) +{ + return nextafter(x, DBL_MAX) - x; +} + +static double getFloat_gamma(double x, double y) +{ + double high = getFloat_gamma_high(x); + double low = getFloat_gamma_low(y); + + return high > low ? high : low; +} + +static uint64_t getFloat_ceilint(double a, double b, double g) +{ + double s = b / g - a / g; + double e; + + if (fabs(a) <= fabs(b)) { + e = -a / g - (s - b / g); + } else { + e = b / g - (s + a / g); + } + + double si = ceil(s); + + return (s != si) ? (uint64_t)si : (uint64_t)si + (e > 0); +} + +/* {{{ Generates a random float within [min, max). + * + * The algorithm used is the γ-section algorithm as published in: + * + * Drawing Random Floating-Point Numbers from an Interval. Frédéric + * Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022. + * https://doi.org/10.1145/3503512 + */ +PHP_METHOD(Random_Randomizer, getFloat) +{ + php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS); + double min, max; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_DOUBLE(min) + Z_PARAM_DOUBLE(max) + ZEND_PARSE_PARAMETERS_END(); + +#ifndef __STDC_IEC_559__ + zend_throw_exception(random_ce_Random_RandomException, "The nextFloat() method requires the underlying 'double' representation to be IEEE-754.", 0); + RETURN_THROWS(); +#endif + + if (UNEXPECTED(max < min)) { + zend_argument_value_error(2, "must be greater than or equal to argument #1 ($min)"); + RETURN_THROWS(); + } + + double g = getFloat_gamma(min, max); + uint64_t hi = getFloat_ceilint(min, max, g); + uint64_t k = randomizer->algo->range(randomizer->status, 1, hi); + + if (fabs(min) <= fabs(max)) { + RETURN_DOUBLE(k == hi ? min : max - k * g); + } else { + RETURN_DOUBLE(min + (k - 1) * g); + } +} +/* }}} */ + /* {{{ Generate random number in range */ PHP_METHOD(Random_Randomizer, getInt) { From ca10d6c44ca8f55a378fec53a2235c26da763ae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 13 Oct 2022 19:49:46 +0200 Subject: [PATCH 05/11] Fix error message in Randomizer::getFloat() --- ext/random/randomizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index a7975ce5b9dd9..6b041e70232e9 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -203,7 +203,7 @@ PHP_METHOD(Random_Randomizer, getFloat) ZEND_PARSE_PARAMETERS_END(); #ifndef __STDC_IEC_559__ - zend_throw_exception(random_ce_Random_RandomException, "The nextFloat() method requires the underlying 'double' representation to be IEEE-754.", 0); + zend_throw_exception(random_ce_Random_RandomException, "The getFloat() method requires the underlying 'double' representation to be IEEE-754.", 0); RETURN_THROWS(); #endif From 5a6b02ee452328bc4850b63ec9b3acb6f2faa6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 13 Oct 2022 19:51:33 +0200 Subject: [PATCH 06/11] Fix method order in randomizer.c --- ext/random/randomizer.c | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 6b041e70232e9..93f5733a6156d 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -88,27 +88,6 @@ PHP_METHOD(Random_Randomizer, __construct) } /* }}} */ -/* {{{ Generate positive random number */ -PHP_METHOD(Random_Randomizer, nextInt) -{ - php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS); - uint64_t result; - - ZEND_PARSE_PARAMETERS_NONE(); - - result = randomizer->algo->generate(randomizer->status); - if (EG(exception)) { - RETURN_THROWS(); - } - if (randomizer->status->last_generated_size > sizeof(zend_long)) { - zend_throw_exception(random_ce_Random_RandomException, "Generated value exceeds size of int", 0); - RETURN_THROWS(); - } - - RETURN_LONG((zend_long) (result >> 1)); -} -/* }}} */ - /* {{{ Generate a float in [0, 1) */ PHP_METHOD(Random_Randomizer, nextFloat) { @@ -224,6 +203,27 @@ PHP_METHOD(Random_Randomizer, getFloat) } /* }}} */ +/* {{{ Generate positive random number */ +PHP_METHOD(Random_Randomizer, nextInt) +{ + php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS); + uint64_t result; + + ZEND_PARSE_PARAMETERS_NONE(); + + result = randomizer->algo->generate(randomizer->status); + if (EG(exception)) { + RETURN_THROWS(); + } + if (randomizer->status->last_generated_size > sizeof(zend_long)) { + zend_throw_exception(random_ce_Random_RandomException, "Generated value exceeds size of int", 0); + RETURN_THROWS(); + } + + RETURN_LONG((zend_long) (result >> 1)); +} +/* }}} */ + /* {{{ Generate random number in range */ PHP_METHOD(Random_Randomizer, getInt) { From 3ad1788250941934170b110eb62ffa4b407a1e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 13 Oct 2022 19:55:29 +0200 Subject: [PATCH 07/11] Simplify `nextafter()` to `nextup()` / `nextdown()` --- ext/random/randomizer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 93f5733a6156d..94eb0248bbbb7 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -131,12 +131,12 @@ PHP_METHOD(Random_Randomizer, nextFloat) static double getFloat_gamma_low(double x) { - return x - nextafter(x, -DBL_MAX); + return x - nextdown(x); } static double getFloat_gamma_high(double x) { - return nextafter(x, DBL_MAX) - x; + return nextup(x) - x; } static double getFloat_gamma(double x, double y) From 1be43c145dc8a575073f96a740594263d62d5f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 13 Oct 2022 19:57:17 +0200 Subject: [PATCH 08/11] Implement getFloat_gamma() optimization see https://github.com/php/php-src/pull/9679/files#r994668327 --- ext/random/randomizer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 94eb0248bbbb7..630263f9c5ebc 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -141,10 +141,7 @@ static double getFloat_gamma_high(double x) static double getFloat_gamma(double x, double y) { - double high = getFloat_gamma_high(x); - double low = getFloat_gamma_low(y); - - return high > low ? high : low; + return (fabs(x) > fabs(y)) ? getFloat_gamma_high(x) : getFloat_gamma_low(y); } static uint64_t getFloat_ceilint(double a, double b, double g) From 5ed75dcf12b0094e7997289490b3e1fed966e5cb Mon Sep 17 00:00:00 2001 From: Danack Date: Sun, 16 Oct 2022 19:02:51 +0200 Subject: [PATCH 09/11] Functions/methods should either work or not be present. Probably. --- ext/random/random.c | 11 +++++++++++ ext/random/random.stub.php | 2 ++ ext/random/random_arginfo.h | 17 +++++++++++++++-- ext/random/randomizer.c | 17 ++--------------- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/ext/random/random.c b/ext/random/random.c index cc1dec4ac8c7c..81aabe866841f 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -62,6 +62,17 @@ # include #endif +// The nextFloat() method requires the underlying 'double' representation to be IEEE-754. +#ifdef __STDC_IEC_559__ +/* A double has 53 bits of precision, thus we must not + * use the full 64 bits of the uint64_t, because we would + * introduce a bias / rounding error. + */ +#if DBL_MANT_DIG == 53 +#define HAVE_RANDOMIZER_FLOAT +#endif +#endif + #include "random_arginfo.h" PHPAPI ZEND_DECLARE_MODULE_GLOBALS(random) diff --git a/ext/random/random.stub.php b/ext/random/random.stub.php index d44a8ecce1136..d02b4cd495b15 100644 --- a/ext/random/random.stub.php +++ b/ext/random/random.stub.php @@ -133,9 +133,11 @@ public function __construct(?Engine $engine = null) {} public function nextInt(): int {} +#if HAVE_RANDOMIZER_FLOAT public function nextFloat(): float {} public function getFloat(float $min, float $max): float {} +#endif public function getInt(int $min, int $max): int {} diff --git a/ext/random/random_arginfo.h b/ext/random/random_arginfo.h index f313182d3e67e..2353fbe7c5e80 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 38402d67bee6e4a5936dada33498f36c602b3df2 */ + * Stub hash: b894663b0ecc38e515dc70c2863159df0739adf4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() @@ -90,12 +90,17 @@ ZEND_END_ARG_INFO() #define arginfo_class_Random_Randomizer_nextInt arginfo_mt_getrandmax -#define arginfo_class_Random_Randomizer_nextFloat arginfo_lcg_value +#if HAVE_RANDOMIZER_NEXTFLOAT +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Random_Randomizer_nextFloat, 0, 0, IS_DOUBLE, 0) +ZEND_END_ARG_INFO() +#endif +#if HAVE_RANDOMIZER_NEXTFLOAT ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Random_Randomizer_getFloat, 0, 2, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, min, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, max, IS_DOUBLE, 0) ZEND_END_ARG_INFO() +#endif #define arginfo_class_Random_Randomizer_getInt arginfo_random_int @@ -138,8 +143,12 @@ ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jump); ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong); ZEND_METHOD(Random_Randomizer, __construct); ZEND_METHOD(Random_Randomizer, nextInt); +#if HAVE_RANDOMIZER_NEXTFLOAT ZEND_METHOD(Random_Randomizer, nextFloat); +#endif +#if HAVE_RANDOMIZER_NEXTFLOAT ZEND_METHOD(Random_Randomizer, getFloat); +#endif ZEND_METHOD(Random_Randomizer, getInt); ZEND_METHOD(Random_Randomizer, getBytes); ZEND_METHOD(Random_Randomizer, shuffleArray); @@ -216,8 +225,12 @@ static const zend_function_entry class_Random_CryptoSafeEngine_methods[] = { static const zend_function_entry class_Random_Randomizer_methods[] = { ZEND_ME(Random_Randomizer, __construct, arginfo_class_Random_Randomizer___construct, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, nextInt, arginfo_class_Random_Randomizer_nextInt, ZEND_ACC_PUBLIC) +#if HAVE_RANDOMIZER_NEXTFLOAT ZEND_ME(Random_Randomizer, nextFloat, arginfo_class_Random_Randomizer_nextFloat, ZEND_ACC_PUBLIC) +#endif +#if HAVE_RANDOMIZER_NEXTFLOAT ZEND_ME(Random_Randomizer, getFloat, arginfo_class_Random_Randomizer_getFloat, ZEND_ACC_PUBLIC) +#endif ZEND_ME(Random_Randomizer, getInt, arginfo_class_Random_Randomizer_getInt, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, getBytes, arginfo_class_Random_Randomizer_getBytes, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, shuffleArray, arginfo_class_Random_Randomizer_shuffleArray, ZEND_ACC_PUBLIC) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 630263f9c5ebc..27d28654d0f35 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -88,6 +88,7 @@ PHP_METHOD(Random_Randomizer, __construct) } /* }}} */ +#if HAVE_RANDOMIZER_FLOAT /* {{{ Generate a float in [0, 1) */ PHP_METHOD(Random_Randomizer, nextFloat) { @@ -97,11 +98,6 @@ PHP_METHOD(Random_Randomizer, nextFloat) ZEND_PARSE_PARAMETERS_NONE(); -#ifndef __STDC_IEC_559__ - zend_throw_exception(random_ce_Random_RandomException, "The nextFloat() method requires the underlying 'double' representation to be IEEE-754.", 0); - RETURN_THROWS(); -#endif - result = 0; total_size = 0; do { @@ -113,11 +109,6 @@ PHP_METHOD(Random_Randomizer, nextFloat) } } while (total_size < sizeof(uint64_t)); - /* A double has 53 bits of precision, thus we must not - * use the full 64 bits of the uint64_t, because we would - * introduce a bias / rounding error. - */ - ZEND_ASSERT(DBL_MANT_DIG == 53); const double step_size = 1.0 / (1ULL << 53); /* Use the upper 53 bits, because some engine's lower bits @@ -178,11 +169,6 @@ PHP_METHOD(Random_Randomizer, getFloat) Z_PARAM_DOUBLE(max) ZEND_PARSE_PARAMETERS_END(); -#ifndef __STDC_IEC_559__ - zend_throw_exception(random_ce_Random_RandomException, "The getFloat() method requires the underlying 'double' representation to be IEEE-754.", 0); - RETURN_THROWS(); -#endif - if (UNEXPECTED(max < min)) { zend_argument_value_error(2, "must be greater than or equal to argument #1 ($min)"); RETURN_THROWS(); @@ -199,6 +185,7 @@ PHP_METHOD(Random_Randomizer, getFloat) } } /* }}} */ +#endif // HAVE_RANDOMIZER_FLOAT /* {{{ Generate positive random number */ PHP_METHOD(Random_Randomizer, nextInt) From 6d49d3013d18879a383e0ddfc74f476158a2f241 Mon Sep 17 00:00:00 2001 From: Danack Date: Sun, 16 Oct 2022 19:12:33 +0200 Subject: [PATCH 10/11] Skip tests when nextfloat unavailable. --- ext/random/random_arginfo.h | 14 +++++++------- .../tests/03_randomizer/methods/nextFloat.phpt | 6 ++++++ .../03_randomizer/methods/nextFloat_spacing.phpt | 6 ++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ext/random/random_arginfo.h b/ext/random/random_arginfo.h index 2353fbe7c5e80..2a341f68df34f 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b894663b0ecc38e515dc70c2863159df0739adf4 */ + * Stub hash: 85e67324eb9e1865048f07e2389fb5c3fc7f13e4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() @@ -90,12 +90,12 @@ ZEND_END_ARG_INFO() #define arginfo_class_Random_Randomizer_nextInt arginfo_mt_getrandmax -#if HAVE_RANDOMIZER_NEXTFLOAT +#if HAVE_RANDOMIZER_FLOAT ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Random_Randomizer_nextFloat, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() #endif -#if HAVE_RANDOMIZER_NEXTFLOAT +#if HAVE_RANDOMIZER_FLOAT ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Random_Randomizer_getFloat, 0, 2, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, min, IS_DOUBLE, 0) ZEND_ARG_TYPE_INFO(0, max, IS_DOUBLE, 0) @@ -143,10 +143,10 @@ ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jump); ZEND_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong); ZEND_METHOD(Random_Randomizer, __construct); ZEND_METHOD(Random_Randomizer, nextInt); -#if HAVE_RANDOMIZER_NEXTFLOAT +#if HAVE_RANDOMIZER_FLOAT ZEND_METHOD(Random_Randomizer, nextFloat); #endif -#if HAVE_RANDOMIZER_NEXTFLOAT +#if HAVE_RANDOMIZER_FLOAT ZEND_METHOD(Random_Randomizer, getFloat); #endif ZEND_METHOD(Random_Randomizer, getInt); @@ -225,10 +225,10 @@ static const zend_function_entry class_Random_CryptoSafeEngine_methods[] = { static const zend_function_entry class_Random_Randomizer_methods[] = { ZEND_ME(Random_Randomizer, __construct, arginfo_class_Random_Randomizer___construct, ZEND_ACC_PUBLIC) ZEND_ME(Random_Randomizer, nextInt, arginfo_class_Random_Randomizer_nextInt, ZEND_ACC_PUBLIC) -#if HAVE_RANDOMIZER_NEXTFLOAT +#if HAVE_RANDOMIZER_FLOAT ZEND_ME(Random_Randomizer, nextFloat, arginfo_class_Random_Randomizer_nextFloat, ZEND_ACC_PUBLIC) #endif -#if HAVE_RANDOMIZER_NEXTFLOAT +#if HAVE_RANDOMIZER_FLOAT ZEND_ME(Random_Randomizer, getFloat, arginfo_class_Random_Randomizer_getFloat, ZEND_ACC_PUBLIC) #endif ZEND_ME(Random_Randomizer, getInt, arginfo_class_Random_Randomizer_getInt, ZEND_ACC_PUBLIC) diff --git a/ext/random/tests/03_randomizer/methods/nextFloat.phpt b/ext/random/tests/03_randomizer/methods/nextFloat.phpt index c8e7046226ec4..2b8c1fac6cbf8 100644 --- a/ext/random/tests/03_randomizer/methods/nextFloat.phpt +++ b/ext/random/tests/03_randomizer/methods/nextFloat.phpt @@ -1,5 +1,11 @@ --TEST-- Random: Randomizer: nextFloat(): Basic functionality +--SKIPIF-- + Date: Sun, 16 Oct 2022 23:14:24 +0200 Subject: [PATCH 11/11] Fix nextFloat test syntax --- ext/random/tests/03_randomizer/methods/nextFloat.phpt | 2 +- ext/random/tests/03_randomizer/methods/nextFloat_spacing.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/random/tests/03_randomizer/methods/nextFloat.phpt b/ext/random/tests/03_randomizer/methods/nextFloat.phpt index 2b8c1fac6cbf8..81d27bd005f32 100644 --- a/ext/random/tests/03_randomizer/methods/nextFloat.phpt +++ b/ext/random/tests/03_randomizer/methods/nextFloat.phpt @@ -2,10 +2,10 @@ Random: Randomizer: nextFloat(): Basic functionality --SKIPIF-- --FILE-- --FILE--