Skip to content

Commit a6d8707

Browse files
Implement clamp function
Co-authored-by: thinkverse <[email protected]>
1 parent 2bb98cd commit a6d8707

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

ext/standard/basic_functions.stub.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,12 @@ function min(mixed $value, mixed ...$values): mixed {}
16291629
*/
16301630
function max(mixed $value, mixed ...$values): mixed {}
16311631

1632+
/**
1633+
* @compile-time-eval
1634+
* @frameless-function {"arity": 3}
1635+
*/
1636+
function clamp(mixed $value, mixed $min, mixed $max): mixed {}
1637+
16321638
function array_walk(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {}
16331639

16341640
function array_walk_recursive(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {}

ext/standard/basic_functions_arginfo.h

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/math.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,59 @@ PHP_FUNCTION(round)
389389
}
390390
/* }}} */
391391

392+
/* {{{ Return the given value if in range of min and max */
393+
PHP_FUNCTION(clamp)
394+
{
395+
zval *zvalue, *zmin, *zmax;
396+
397+
ZEND_PARSE_PARAMETERS_START(3, 3)
398+
Z_PARAM_ZVAL(zvalue)
399+
Z_PARAM_ZVAL(zmin)
400+
Z_PARAM_ZVAL(zmax)
401+
ZEND_PARSE_PARAMETERS_END();
402+
403+
if (zend_compare(zmin, zmax) > 0) {
404+
zend_argument_value_error(2, "must be smaller than or equal to argument #3 ($max)");
405+
RETURN_THROWS();
406+
}
407+
408+
if (zend_compare(zmax, zvalue) == -1) {
409+
RETURN_COPY_VALUE(zmax);
410+
}
411+
412+
if (zend_compare(zvalue, zmin) == -1) {
413+
RETURN_COPY_VALUE(zmin);
414+
}
415+
416+
RETURN_COPY_VALUE(zvalue);
417+
}
418+
/* }}} */
419+
420+
/* {{{ Return the given value if in range of min and max */
421+
ZEND_FRAMELESS_FUNCTION(clamp, 3)
422+
{
423+
zval *zvalue, *zmin, *zmax;
424+
Z_FLF_PARAM_ZVAL(1, zvalue);
425+
Z_FLF_PARAM_ZVAL(2, zmin);
426+
Z_FLF_PARAM_ZVAL(3, zmax);
427+
428+
if (zend_compare(zmin, zmax) > 0) {
429+
zend_argument_value_error(2, "must be smaller than or equal to argument #3 ($max)");
430+
RETURN_THROWS();
431+
}
432+
433+
if (zend_compare(zmax, zvalue) == -1) {
434+
RETURN_COPY_VALUE(zmax);
435+
}
436+
437+
if (zend_compare(zvalue, zmin) == -1) {
438+
RETURN_COPY_VALUE(zmin);
439+
}
440+
441+
RETURN_COPY_VALUE(zvalue);
442+
}
443+
/* }}} */
444+
392445
/* {{{ Returns the sine of the number in radians */
393446
PHP_FUNCTION(sin)
394447
{

ext/standard/tests/math/clamp.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
clamp() tests
3+
--INI--
4+
precision=14
5+
date.timezone = UTC
6+
--FILE--
7+
<?php
8+
9+
var_dump(clamp(2, 1, 3));
10+
var_dump(clamp(0, 1, 3));
11+
var_dump(clamp(6, 1, 3));
12+
var_dump(clamp(2, 1.3, 3.4));
13+
var_dump(clamp(2.5, 1, 3));
14+
var_dump(clamp(2.5, 1.3, 3.4));
15+
var_dump(clamp(0, 1.3, 3.4));
16+
var_dump(clamp(M_PI, -INF, INF));
17+
var_dump(clamp("a", "c", "g"));
18+
var_dump(clamp("d", "c", "g"));
19+
echo clamp('2025-08-01', '2025-08-15', '2025-09-15'), "\n";
20+
echo clamp('2025-08-20', '2025-08-15', '2025-09-15'), "\n";
21+
22+
?>
23+
--EXPECT--
24+
int(2)
25+
int(1)
26+
int(3)
27+
int(2)
28+
float(2.5)
29+
float(2.5)
30+
float(1.3)
31+
float(3.141592653589793)
32+
string(1) "c"
33+
string(1) "d"
34+
2025-08-15
35+
2025-08-20

0 commit comments

Comments
 (0)