From b152633ecb2030e2de1f83d2d42193185ea1bc21 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 9 Sep 2017 15:43:02 +0200 Subject: [PATCH] Scale support for bcmod() As of commit 90dcbbe (PHP-7.2+) bcmod() supports non-integral parameters as well. Since formerly only integer modulus has been supported, it did not make much sense to cater to the scale with regard to the result. However, now it does for consistency with other BCMath operations. Therefore, we add support for an optional `scale` parameter and fall back to the default scale (`bcmath.scale`) as usual. --- ext/bcmath/bcmath.c | 21 +++++++++++++++++---- ext/bcmath/tests/bcmod.phpt | 4 ++-- ext/bcmath/tests/bcmod_error1.phpt | 4 ++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index e8b87dceff0..fdabb410666 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -60,9 +60,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_bcdiv, 0, 0, 2) ZEND_ARG_INFO(0, scale) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_bcmod, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_bcmod, 0, 0, 2) ZEND_ARG_INFO(0, left_operand) ZEND_ARG_INFO(0, right_operand) + ZEND_ARG_INFO(0, scale) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpowmod, 0, 0, 3) @@ -388,26 +389,38 @@ PHP_FUNCTION(bcdiv) } /* }}} */ -/* {{{ proto string bcmod(string left_operand, string right_operand) +/* {{{ proto string bcmod(string left_operand, string right_operand [, int scale]) Returns the modulus of the two arbitrary precision operands */ PHP_FUNCTION(bcmod) { zend_string *left, *right; + zend_long scale_param = 0; bc_num first, second, result; + int scale = (int)BCG(bc_precision); - ZEND_PARSE_PARAMETERS_START(2, 2) + ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) Z_PARAM_STR(right) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(scale_param) ZEND_PARSE_PARAMETERS_END(); + if (ZEND_NUM_ARGS() == 3) { + scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + } + bc_init_num(&first); bc_init_num(&second); bc_init_num(&result); php_str2num(&first, ZSTR_VAL(left)); php_str2num(&second, ZSTR_VAL(right)); - switch (bc_modulo(first, second, &result, 0)) { + switch (bc_modulo(first, second, &result, scale)) { case 0: + if (result->n_scale > scale) { + result = split_bc_num(result); + result->n_scale = scale; + } RETVAL_STR(bc_num2str(result)); break; case -1: diff --git a/ext/bcmath/tests/bcmod.phpt b/ext/bcmath/tests/bcmod.phpt index 5657e02ddc0..3e9ab25cb89 100644 --- a/ext/bcmath/tests/bcmod.phpt +++ b/ext/bcmath/tests/bcmod.phpt @@ -9,7 +9,7 @@ bcmath.scale=0 echo bcmod("11", "2"),"\n"; echo bcmod("-1", "5"),"\n"; echo bcmod("8728932001983192837219398127471", "1928372132132819737213"),"\n"; -echo bcmod("3.5", "4"),"\n"; +echo bcmod("3.5", "4", 1),"\n"; echo bcmod("1071", "357.5"),"\n"; ?> --EXPECT-- @@ -17,4 +17,4 @@ echo bcmod("1071", "357.5"),"\n"; -1 1459434331351930289678 3.5 -356.0 +356 diff --git a/ext/bcmath/tests/bcmod_error1.phpt b/ext/bcmath/tests/bcmod_error1.phpt index e36dce285db..68a6dae470e 100644 --- a/ext/bcmath/tests/bcmod_error1.phpt +++ b/ext/bcmath/tests/bcmod_error1.phpt @@ -7,7 +7,7 @@ antoni@solucionsinternet.com --FILE-- --EXPECTF-- -Warning: bcmod() expects exactly 2 parameters, 3 given in %s.php on line %d +Warning: bcmod() expects at most 3 parameters, 4 given in %s.php on line %d