Skip to content

Commit 1b9eb78

Browse files
committed
Add Random\Randomizer\GetFloatBounds
1 parent 99fe310 commit 1b9eb78

File tree

5 files changed

+77
-11
lines changed

5 files changed

+77
-11
lines changed

ext/random/php_random.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ extern PHPAPI zend_class_entry *random_ce_Random_Engine_PcgOneseq128XslRr64;
268268
extern PHPAPI zend_class_entry *random_ce_Random_Engine_Mt19937;
269269
extern PHPAPI zend_class_entry *random_ce_Random_Engine_Xoshiro256StarStar;
270270
extern PHPAPI zend_class_entry *random_ce_Random_Engine_Secure;
271+
271272
extern PHPAPI zend_class_entry *random_ce_Random_Randomizer;
273+
extern PHPAPI zend_class_entry *random_ce_Random_Randomizer_GetFloatBounds;
272274

273275
static inline php_random_engine *php_random_engine_from_obj(zend_object *object) {
274276
return (php_random_engine *)((char *)(object) - XtOffsetOf(php_random_engine, std));

ext/random/random.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include "php.h"
2828

29+
#include "Zend/zend_enum.h"
2930
#include "Zend/zend_exceptions.h"
3031

3132
#include "php_random.h"
@@ -75,6 +76,7 @@ PHPAPI zend_class_entry *random_ce_Random_Engine_Xoshiro256StarStar;
7576
PHPAPI zend_class_entry *random_ce_Random_Engine_Secure;
7677

7778
PHPAPI zend_class_entry *random_ce_Random_Randomizer;
79+
PHPAPI zend_class_entry *random_ce_Random_Randomizer_GetFloatBounds;
7880

7981
PHPAPI zend_class_entry *random_ce_Random_RandomError;
8082
PHPAPI zend_class_entry *random_ce_Random_BrokenRandomEngineError;
@@ -898,6 +900,9 @@ PHP_MINIT_FUNCTION(random)
898900
random_randomizer_object_handlers.free_obj = randomizer_free_obj;
899901
random_randomizer_object_handlers.clone_obj = NULL;
900902

903+
/* Random\Randomizer\GetFloatBounds */
904+
random_ce_Random_Randomizer_GetFloatBounds = register_class_Random_Randomizer_GetFloatBounds();
905+
901906
register_random_symbols(module_number);
902907

903908
return SUCCESS;

ext/random/random.stub.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ public function generate(): string {}
111111
}
112112
}
113113

114+
namespace Random\Randomizer
115+
{
116+
enum GetFloatBounds {
117+
case ClosedOpen;
118+
case ClosedClosed;
119+
}
120+
}
121+
114122
namespace Random
115123
{
116124
interface Engine
@@ -135,7 +143,7 @@ public function nextInt(): int {}
135143

136144
public function nextFloat(): float {}
137145

138-
public function getFloat(float $min, float $max): float {}
146+
public function getFloat(float $min, float $max, Randomizer\GetFloatBounds $bounds = GetFloatBounds::ClosedOpen): float {}
139147

140148
public function getInt(int $min, int $max): int {}
141149

ext/random/random_arginfo.h

Lines changed: 18 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/random/randomizer.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "ext/standard/php_array.h"
2525
#include "ext/standard/php_string.h"
2626

27+
#include "Zend/zend_enum.h"
2728
#include "Zend/zend_exceptions.h"
2829

2930
static inline void randomizer_common_init(php_random_randomizer *randomizer, zend_object *engine_object) {
@@ -160,6 +161,32 @@ static uint64_t getFloat_ceilint(double a, double b, double g)
160161
return (s != si) ? (uint64_t)si : (uint64_t)si + (e > 0);
161162
}
162163

164+
static double getFloat_closed_open(const php_random_algo *algo, php_random_status *status, double min, double max)
165+
{
166+
double g = getFloat_gamma(min, max);
167+
uint64_t hi = getFloat_ceilint(min, max, g);
168+
uint64_t k = algo->range(status, 1, hi);
169+
170+
if (fabs(min) <= fabs(max)) {
171+
return k == hi ? min : max - k * g;
172+
} else {
173+
return min + (k - 1) * g;
174+
}
175+
}
176+
177+
static double getFloat_closed_closed(const php_random_algo *algo, php_random_status *status, double min, double max)
178+
{
179+
double g = getFloat_gamma(min, max);
180+
uint64_t hi = getFloat_ceilint(min, max, g);
181+
uint64_t k = algo->range(status, 0, hi);
182+
183+
if (fabs(min) <= fabs(max)) {
184+
return k == hi ? min : max - k * g;
185+
} else {
186+
return k == hi ? max : min + k * g;
187+
}
188+
}
189+
163190
/* {{{ Generates a random float within [min, max).
164191
*
165192
* The algorithm used is the γ-section algorithm as published in:
@@ -172,10 +199,14 @@ PHP_METHOD(Random_Randomizer, getFloat)
172199
{
173200
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
174201
double min, max;
202+
zend_object *bounds = NULL;
203+
zend_string *bounds_name = zend_string_init("ClosedOpen", strlen("ClosedOpen"), 1);
175204

176-
ZEND_PARSE_PARAMETERS_START(2, 2)
205+
ZEND_PARSE_PARAMETERS_START(2, 3)
177206
Z_PARAM_DOUBLE(min)
178207
Z_PARAM_DOUBLE(max)
208+
Z_PARAM_OPTIONAL
209+
Z_PARAM_OBJ_OF_CLASS(bounds, random_ce_Random_Randomizer_GetFloatBounds);
179210
ZEND_PARSE_PARAMETERS_END();
180211

181212
#ifndef __STDC_IEC_559__
@@ -188,15 +219,18 @@ PHP_METHOD(Random_Randomizer, getFloat)
188219
RETURN_THROWS();
189220
}
190221

191-
double g = getFloat_gamma(min, max);
192-
uint64_t hi = getFloat_ceilint(min, max, g);
193-
uint64_t k = randomizer->algo->range(randomizer->status, 1, hi);
194-
195-
if (fabs(min) <= fabs(max)) {
196-
RETURN_DOUBLE(k == hi ? min : max - k * g);
197-
} else {
198-
RETURN_DOUBLE(min + (k - 1) * g);
222+
if (bounds) {
223+
zval *case_name = zend_enum_fetch_case_name(bounds);
224+
bounds_name = Z_STR_P(case_name);
225+
}
226+
227+
if (zend_string_equals_literal(bounds_name, "ClosedOpen")) {
228+
RETURN_DOUBLE(getFloat_closed_open(randomizer->algo, randomizer->status, min, max));
229+
}
230+
if (zend_string_equals_literal(bounds_name, "ClosedClosed")) {
231+
RETURN_DOUBLE(getFloat_closed_closed(randomizer->algo, randomizer->status, min, max));
199232
}
233+
ZEND_UNREACHABLE();
200234
}
201235
/* }}} */
202236

0 commit comments

Comments
 (0)