From c5af4b25851d2a38b6dc84bfa2b2131f6bbc02f8 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 3 Dec 2016 15:44:36 +0100 Subject: [PATCH] Improve multiplication on x64. Thanks Bob for the spot. --- Zend/tests/zend_signed_multiply-64bit-2.phpt | 149 +++++++++++++++++++ Zend/tests/zend_signed_multiply-64bit.phpt | 2 +- Zend/zend_multiply.h | 16 +- 3 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/zend_signed_multiply-64bit-2.phpt 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 00000000000..f0a3bafa5e5 --- /dev/null +++ b/Zend/tests/zend_signed_multiply-64bit-2.phpt @@ -0,0 +1,149 @@ +--TEST-- +Zend signed multiply 64-bit, variation 2 +--SKIPIF-- + +--FILE-- + +--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 94a6e035fac..d392b2e78a9 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-- --FILE-- diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index 9790c1faa32..7a600f82960 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__)