summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-10-02 15:06:09 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-10-11 16:36:11 +0200
commite35bdb49121ac451384b6c443850ce67e7c5be63 (patch)
treeccffaba90a7f4e325afc0e272681ce3e77228792
parent28ed73d94a7c5e08221cf13048a6bdde603fc234 (diff)
downloadphp-git-e35bdb49121ac451384b6c443850ce67e7c5be63.tar.gz
Add fdiv() function
The fdiv() function is part of the fmod() / intdiv() family. It implements a floating-point division with IEEE-754 semantics. That is, division by zero is considered well-defined and does not trigger any kind of diagnostic. Instead one of INF, -INF or NAN will be returned, depending on the case. This is in preparation for throwing DivisionByZeroError from the standard division operator.
-rw-r--r--UPGRADING5
-rwxr-xr-xext/standard/basic_functions.c6
-rw-r--r--ext/standard/math.c19
-rw-r--r--ext/standard/php_math.h1
-rw-r--r--ext/standard/tests/math/fdiv.phpt78
5 files changed, 109 insertions, 0 deletions
diff --git a/UPGRADING b/UPGRADING
index 7d26e22019..7783f92f9b 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -318,6 +318,11 @@ PHP 8.0 UPGRADE NOTES
6. New Functions
========================================
+- Standard:
+ . Added fdiv() method, which performs a floating-point devision under
+ IEEE 754 semantics. Division by zero is considered well-defined and
+ will return one of Inf, -Inf or NaN.
+
========================================
7. New Classes and Interfaces
========================================
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 01071dd244..1c3ad1d2bd 100755
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -1143,6 +1143,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_fmod, 0)
ZEND_ARG_INFO(0, y)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_fdiv, 0)
+ ZEND_ARG_INFO(0, dividend)
+ ZEND_ARG_INFO(0, divisor)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO(arginfo_intdiv, 0)
ZEND_ARG_INFO(0, dividend)
ZEND_ARG_INFO(0, divisor)
@@ -1933,6 +1938,7 @@ static const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(base_convert, arginfo_base_convert)
PHP_FE(number_format, arginfo_number_format)
PHP_FE(fmod, arginfo_fmod)
+ PHP_FE(fdiv, arginfo_fdiv)
PHP_FE(intdiv, arginfo_intdiv)
#ifdef HAVE_INET_NTOP
PHP_RAW_NAMED_FE(inet_ntop, zif_inet_ntop, arginfo_inet_ntop)
diff --git a/ext/standard/math.c b/ext/standard/math.c
index b2e56f5a27..be3516400a 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -1300,6 +1300,25 @@ PHP_FUNCTION(fmod)
}
/* }}} */
+/* {{{ proto float fdiv(float dividend, float divisor)
+ Perform floating-point division of dividend / divisor
+ with IEEE-754 semantics for division by zero. */
+#ifdef __clang__
+__attribute__((no_sanitize("float-divide-by-zero")))
+#endif
+PHP_FUNCTION(fdiv)
+{
+ double dividend, divisor;
+
+ ZEND_PARSE_PARAMETERS_START(2, 2)
+ Z_PARAM_DOUBLE(dividend)
+ Z_PARAM_DOUBLE(divisor)
+ ZEND_PARSE_PARAMETERS_END();
+
+ RETURN_DOUBLE(dividend / divisor);
+}
+/* }}} */
+
/* {{{ proto int intdiv(int dividend, int divisor)
Returns the integer quotient of the division of dividend by divisor */
PHP_FUNCTION(intdiv)
diff --git a/ext/standard/php_math.h b/ext/standard/php_math.h
index 39751a7f89..e85fd120f2 100644
--- a/ext/standard/php_math.h
+++ b/ext/standard/php_math.h
@@ -59,6 +59,7 @@ PHP_FUNCTION(octdec);
PHP_FUNCTION(base_convert);
PHP_FUNCTION(number_format);
PHP_FUNCTION(fmod);
+PHP_FUNCTION(fdiv);
PHP_FUNCTION(deg2rad);
PHP_FUNCTION(rad2deg);
PHP_FUNCTION(intdiv);
diff --git a/ext/standard/tests/math/fdiv.phpt b/ext/standard/tests/math/fdiv.phpt
new file mode 100644
index 0000000000..dd50cfdb78
--- /dev/null
+++ b/ext/standard/tests/math/fdiv.phpt
@@ -0,0 +1,78 @@
+--TEST--
+fdiv() function
+--FILE--
+<?php
+
+var_dump(fdiv(10, 3));
+var_dump(fdiv(10., 3.));
+var_dump(fdiv(-10., 2.5));
+var_dump(fdiv(10., -2.5));
+echo "\n";
+var_dump(fdiv(10., 0.));
+var_dump(fdiv(10., -0.));
+var_dump(fdiv(-10., 0.));
+var_dump(fdiv(-10., -0.));
+echo "\n";
+var_dump(fdiv(INF, 0.));
+var_dump(fdiv(INF, -0.));
+var_dump(fdiv(-INF, 0.));
+var_dump(fdiv(-INF, -0.));
+echo "\n";
+var_dump(fdiv(0., 0.));
+var_dump(fdiv(0., -0.));
+var_dump(fdiv(-0., 0.));
+var_dump(fdiv(-0., -0.));
+echo "\n";
+var_dump(fdiv(INF, INF));
+var_dump(fdiv(INF, -INF));
+var_dump(fdiv(-INF, INF));
+var_dump(fdiv(-INF, -INF));
+echo "\n";
+var_dump(fdiv(0., INF));
+var_dump(fdiv(0., -INF));
+var_dump(fdiv(-0., INF));
+var_dump(fdiv(-0., -INF));
+echo "\n";
+var_dump(fdiv(NAN, NAN));
+var_dump(fdiv(INF, NAN));
+var_dump(fdiv(0., NAN));
+var_dump(fdiv(NAN, INF));
+var_dump(fdiv(NAN, 0.));
+
+?>
+--EXPECT--
+float(3.3333333333333)
+float(3.3333333333333)
+float(-4)
+float(-4)
+
+float(INF)
+float(-INF)
+float(-INF)
+float(INF)
+
+float(INF)
+float(-INF)
+float(-INF)
+float(INF)
+
+float(NAN)
+float(NAN)
+float(NAN)
+float(NAN)
+
+float(NAN)
+float(NAN)
+float(NAN)
+float(NAN)
+
+float(0)
+float(-0)
+float(-0)
+float(0)
+
+float(NAN)
+float(NAN)
+float(NAN)
+float(NAN)
+float(NAN)