diff options
author | Anatol Belski <ab@php.net> | 2016-12-03 15:44:36 +0100 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2016-12-03 15:50:21 +0100 |
commit | c5af4b25851d2a38b6dc84bfa2b2131f6bbc02f8 (patch) | |
tree | 155798ddaafa246dbfca60cd5c942a5b5ee036f7 | |
parent | 143ee76fe4ad26041174caad32ed239fb0e28275 (diff) | |
download | php-git-c5af4b25851d2a38b6dc84bfa2b2131f6bbc02f8.tar.gz |
Improve multiplication on x64.
Thanks Bob for the spot.
-rw-r--r-- | Zend/tests/zend_signed_multiply-64bit-2.phpt | 149 | ||||
-rw-r--r-- | Zend/tests/zend_signed_multiply-64bit.phpt | 2 | ||||
-rw-r--r-- | Zend/zend_multiply.h | 16 |
3 files changed, 165 insertions, 2 deletions
diff --git a/Zend/tests/zend_signed_multiply-64bit-2.phpt b/Zend/tests/zend_signed_multiply-64bit-2.phpt new file mode 100644 index 0000000000..f0a3bafa5e --- /dev/null +++ b/Zend/tests/zend_signed_multiply-64bit-2.phpt @@ -0,0 +1,149 @@ +--TEST-- +Zend signed multiply 64-bit, variation 2 +--SKIPIF-- +<?php if ((1 << 31) < 0) print "skip Running on 32-bit target"; ?> +--FILE-- +<?php +for($c = -16; $c < 0; $c++) { + var_dump($c, intdiv(PHP_INT_MIN, 10), intdiv(PHP_INT_MIN, 10) * $c); + echo "-----------\n"; +} +for($c = 0; $c <= 16; $c++) { + var_dump($c, intdiv(PHP_INT_MAX, 10), intdiv(PHP_INT_MAX, 10) * $c); + echo "-----------\n"; +} +?> +--EXPECTF-- +int(-16) +int(-922337203685477580) +float(1.4757395258968E+19) +----------- +int(-15) +int(-922337203685477580) +float(1.3835058055282E+19) +----------- +int(-14) +int(-922337203685477580) +float(1.2912720851597E+19) +----------- +int(-13) +int(-922337203685477580) +float(1.1990383647911E+19) +----------- +int(-12) +int(-922337203685477580) +float(1.1068046444226E+19) +----------- +int(-11) +int(-922337203685477580) +float(1.014570924054E+19) +----------- +int(-10) +int(-922337203685477580) +int(9223372036854775800) +----------- +int(-9) +int(-922337203685477580) +int(8301034833169298220) +----------- +int(-8) +int(-922337203685477580) +int(7378697629483820640) +----------- +int(-7) +int(-922337203685477580) +int(6456360425798343060) +----------- +int(-6) +int(-922337203685477580) +int(5534023222112865480) +----------- +int(-5) +int(-922337203685477580) +int(4611686018427387900) +----------- +int(-4) +int(-922337203685477580) +int(3689348814741910320) +----------- +int(-3) +int(-922337203685477580) +int(2767011611056432740) +----------- +int(-2) +int(-922337203685477580) +int(1844674407370955160) +----------- +int(-1) +int(-922337203685477580) +int(922337203685477580) +----------- +int(0) +int(922337203685477580) +int(0) +----------- +int(1) +int(922337203685477580) +int(922337203685477580) +----------- +int(2) +int(922337203685477580) +int(1844674407370955160) +----------- +int(3) +int(922337203685477580) +int(2767011611056432740) +----------- +int(4) +int(922337203685477580) +int(3689348814741910320) +----------- +int(5) +int(922337203685477580) +int(4611686018427387900) +----------- +int(6) +int(922337203685477580) +int(5534023222112865480) +----------- +int(7) +int(922337203685477580) +int(6456360425798343060) +----------- +int(8) +int(922337203685477580) +int(7378697629483820640) +----------- +int(9) +int(922337203685477580) +int(8301034833169298220) +----------- +int(10) +int(922337203685477580) +int(9223372036854775800) +----------- +int(11) +int(922337203685477580) +float(1.014570924054E+19) +----------- +int(12) +int(922337203685477580) +float(1.1068046444226E+19) +----------- +int(13) +int(922337203685477580) +float(1.1990383647911E+19) +----------- +int(14) +int(922337203685477580) +float(1.2912720851597E+19) +----------- +int(15) +int(922337203685477580) +float(1.3835058055282E+19) +----------- +int(16) +int(922337203685477580) +float(1.4757395258968E+19) +----------- + diff --git a/Zend/tests/zend_signed_multiply-64bit.phpt b/Zend/tests/zend_signed_multiply-64bit.phpt index 94a6e035fa..d392b2e78a 100644 --- a/Zend/tests/zend_signed_multiply-64bit.phpt +++ b/Zend/tests/zend_signed_multiply-64bit.phpt @@ -1,5 +1,5 @@ --TEST-- -Zend signed multiply 64-bit +Zend signed multiply 64-bit, variation 1 --SKIPIF-- <?php if ((1 << 31) < 0) print "skip Running on 32-bit target"; ?> --FILE-- diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index 9790c1faa3..7a600f8296 100644 --- a/Zend/zend_multiply.h +++ b/Zend/zend_multiply.h @@ -83,7 +83,20 @@ #elif defined(ZEND_WIN32) -#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ +# ifdef _M_X64 +# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ + __int64 __high; \ + __int64 __low = _mul128((a), (b), &__high); \ + if ((__low >> 63i64) == __high) { \ + (usedval) = 0; \ + (lval) = __low; \ + } else { \ + (usedval) = 1; \ + (dval) = (double)(a) * (double)(b); \ + } \ +} while (0) +# else +# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ zend_long __lres = (a) * (b); \ long double __dres = (long double)(a) * (long double)(b); \ long double __delta = (long double) __lres - __dres; \ @@ -93,6 +106,7 @@ (lval) = __lres; \ } \ } while (0) +# endif #elif defined(__powerpc64__) && defined(__GNUC__) |