Skip to content

Commit 0935213

Browse files
committed
use SIMD
1 parent d58fbe5 commit 0935213

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

ext/bcmath/libbcmath/src/doaddsub.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,57 @@ bc_num _bc_do_add(bc_num n1, bc_num n2, size_t scale_min)
7272
}
7373

7474
/* Now add the remaining fraction part and equal size integer parts. */
75-
for (count = 0; count < min_bytes; count++) {
75+
count = 0;
76+
/* Uses SIMD to perform calculations at high speed. */
77+
if (min_bytes >= sizeof(BC_UINT_T)) {
78+
sumptr++;
79+
n1ptr++;
80+
n2ptr++;
81+
while (count + sizeof(BC_UINT_T) <= min_bytes) {
82+
sumptr -= sizeof(BC_UINT_T);
83+
n1ptr -= sizeof(BC_UINT_T);
84+
n2ptr -= sizeof(BC_UINT_T);
85+
86+
BC_UINT_T n1bytes;
87+
BC_UINT_T n2bytes;
88+
memcpy(&n1bytes, n1ptr, sizeof(n1bytes));
89+
memcpy(&n2bytes, n2ptr, sizeof(n2bytes));
90+
91+
#if BC_LITTLE_ENDIAN
92+
/* Little endian requires changing the order of bytes. */
93+
n1bytes = BC_BSWAP(n1bytes);
94+
n2bytes = BC_BSWAP(n2bytes);
95+
#endif
96+
97+
n1bytes += SWAR_REPEAT(0xF6) + n2bytes + carry;
98+
/* If the most significant bit is 1, a carry down has occurred. */
99+
carry = !(n1bytes & ((BC_UINT_T) 1 << (8 * sizeof(BC_UINT_T) - 1)));
100+
101+
/*
102+
* Check the most significant bit of each of the bytes, and if it is 1, a carry down has
103+
* occurred. When carrying down occurs, due to the difference between decimal and hexadecimal
104+
* numbers, an extra 6 is added to the lower 4 bits.
105+
* Therefore, for a byte that has been carried down, set all the upper 4 bits to 0 and subtract
106+
* 6 from the lower 4 bits to adjust it to the correct value as a decimal number.
107+
*/
108+
BC_UINT_T sum_mask = ((n1bytes & SWAR_REPEAT(0x80)) >> 7) * 0xF6;
109+
n1bytes -= sum_mask;
110+
111+
#if BC_LITTLE_ENDIAN
112+
/* Little endian requires changing the order of bytes back. */
113+
n1bytes = BC_BSWAP(n1bytes);
114+
#endif
115+
116+
memcpy(sumptr, &n1bytes, sizeof(n1bytes));
117+
118+
count += sizeof(BC_UINT_T);
119+
}
120+
sumptr--;
121+
n1ptr--;
122+
n2ptr--;
123+
}
124+
125+
for (; count < min_bytes; count++) {
76126
*sumptr = *n1ptr-- + *n2ptr-- + carry;
77127
if (*sumptr >= BASE) {
78128
*sumptr -= BASE;

0 commit comments

Comments
 (0)