Skip to content

Commit c5af4b2

Browse files
committed
Improve multiplication on x64.
Thanks Bob for the spot.
1 parent 143ee76 commit c5af4b2

File tree

3 files changed

+165
-2
lines changed

3 files changed

+165
-2
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
--TEST--
2+
Zend signed multiply 64-bit, variation 2
3+
--SKIPIF--
4+
<?php if ((1 << 31) < 0) print "skip Running on 32-bit target"; ?>
5+
--FILE--
6+
<?php
7+
for($c = -16; $c < 0; $c++) {
8+
var_dump($c, intdiv(PHP_INT_MIN, 10), intdiv(PHP_INT_MIN, 10) * $c);
9+
echo "-----------\n";
10+
}
11+
for($c = 0; $c <= 16; $c++) {
12+
var_dump($c, intdiv(PHP_INT_MAX, 10), intdiv(PHP_INT_MAX, 10) * $c);
13+
echo "-----------\n";
14+
}
15+
?>
16+
--EXPECTF--
17+
int(-16)
18+
int(-922337203685477580)
19+
float(1.4757395258968E+19)
20+
-----------
21+
int(-15)
22+
int(-922337203685477580)
23+
float(1.3835058055282E+19)
24+
-----------
25+
int(-14)
26+
int(-922337203685477580)
27+
float(1.2912720851597E+19)
28+
-----------
29+
int(-13)
30+
int(-922337203685477580)
31+
float(1.1990383647911E+19)
32+
-----------
33+
int(-12)
34+
int(-922337203685477580)
35+
float(1.1068046444226E+19)
36+
-----------
37+
int(-11)
38+
int(-922337203685477580)
39+
float(1.014570924054E+19)
40+
-----------
41+
int(-10)
42+
int(-922337203685477580)
43+
int(9223372036854775800)
44+
-----------
45+
int(-9)
46+
int(-922337203685477580)
47+
int(8301034833169298220)
48+
-----------
49+
int(-8)
50+
int(-922337203685477580)
51+
int(7378697629483820640)
52+
-----------
53+
int(-7)
54+
int(-922337203685477580)
55+
int(6456360425798343060)
56+
-----------
57+
int(-6)
58+
int(-922337203685477580)
59+
int(5534023222112865480)
60+
-----------
61+
int(-5)
62+
int(-922337203685477580)
63+
int(4611686018427387900)
64+
-----------
65+
int(-4)
66+
int(-922337203685477580)
67+
int(3689348814741910320)
68+
-----------
69+
int(-3)
70+
int(-922337203685477580)
71+
int(2767011611056432740)
72+
-----------
73+
int(-2)
74+
int(-922337203685477580)
75+
int(1844674407370955160)
76+
-----------
77+
int(-1)
78+
int(-922337203685477580)
79+
int(922337203685477580)
80+
-----------
81+
int(0)
82+
int(922337203685477580)
83+
int(0)
84+
-----------
85+
int(1)
86+
int(922337203685477580)
87+
int(922337203685477580)
88+
-----------
89+
int(2)
90+
int(922337203685477580)
91+
int(1844674407370955160)
92+
-----------
93+
int(3)
94+
int(922337203685477580)
95+
int(2767011611056432740)
96+
-----------
97+
int(4)
98+
int(922337203685477580)
99+
int(3689348814741910320)
100+
-----------
101+
int(5)
102+
int(922337203685477580)
103+
int(4611686018427387900)
104+
-----------
105+
int(6)
106+
int(922337203685477580)
107+
int(5534023222112865480)
108+
-----------
109+
int(7)
110+
int(922337203685477580)
111+
int(6456360425798343060)
112+
-----------
113+
int(8)
114+
int(922337203685477580)
115+
int(7378697629483820640)
116+
-----------
117+
int(9)
118+
int(922337203685477580)
119+
int(8301034833169298220)
120+
-----------
121+
int(10)
122+
int(922337203685477580)
123+
int(9223372036854775800)
124+
-----------
125+
int(11)
126+
int(922337203685477580)
127+
float(1.014570924054E+19)
128+
-----------
129+
int(12)
130+
int(922337203685477580)
131+
float(1.1068046444226E+19)
132+
-----------
133+
int(13)
134+
int(922337203685477580)
135+
float(1.1990383647911E+19)
136+
-----------
137+
int(14)
138+
int(922337203685477580)
139+
float(1.2912720851597E+19)
140+
-----------
141+
int(15)
142+
int(922337203685477580)
143+
float(1.3835058055282E+19)
144+
-----------
145+
int(16)
146+
int(922337203685477580)
147+
float(1.4757395258968E+19)
148+
-----------
149+

Zend/tests/zend_signed_multiply-64bit.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Zend signed multiply 64-bit
2+
Zend signed multiply 64-bit, variation 1
33
--SKIPIF--
44
<?php if ((1 << 31) < 0) print "skip Running on 32-bit target"; ?>
55
--FILE--

Zend/zend_multiply.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,20 @@
8383

8484
#elif defined(ZEND_WIN32)
8585

86-
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
86+
# ifdef _M_X64
87+
# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
88+
__int64 __high; \
89+
__int64 __low = _mul128((a), (b), &__high); \
90+
if ((__low >> 63i64) == __high) { \
91+
(usedval) = 0; \
92+
(lval) = __low; \
93+
} else { \
94+
(usedval) = 1; \
95+
(dval) = (double)(a) * (double)(b); \
96+
} \
97+
} while (0)
98+
# else
99+
# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
87100
zend_long __lres = (a) * (b); \
88101
long double __dres = (long double)(a) * (long double)(b); \
89102
long double __delta = (long double) __lres - __dres; \
@@ -93,6 +106,7 @@
93106
(lval) = __lres; \
94107
} \
95108
} while (0)
109+
# endif
96110

97111
#elif defined(__powerpc64__) && defined(__GNUC__)
98112

0 commit comments

Comments
 (0)