Skip to content

Commit 9970f07

Browse files
committed
wip
1 parent 6714a3b commit 9970f07

File tree

9 files changed

+969
-34
lines changed

9 files changed

+969
-34
lines changed

ext/bcmath/bcmath.c

Lines changed: 648 additions & 6 deletions
Large diffs are not rendered by default.

ext/bcmath/bcmath.stub.php

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,76 @@
22

33
/** @generate-class-entries */
44

5-
/** @refcount 1 */
6-
function bcadd(string $num1, string $num2, ?int $scale = null): string {}
5+
namespace {
6+
/** @refcount 1 */
7+
function bcadd(string $num1, string $num2, ?int $scale = null): string {}
78

8-
/** @refcount 1 */
9-
function bcsub(string $num1, string $num2, ?int $scale = null): string {}
9+
/** @refcount 1 */
10+
function bcsub(string $num1, string $num2, ?int $scale = null): string {}
1011

11-
/** @refcount 1 */
12-
function bcmul(string $num1, string $num2, ?int $scale = null): string {}
12+
/** @refcount 1 */
13+
function bcmul(string $num1, string $num2, ?int $scale = null): string {}
1314

14-
/** @refcount 1 */
15-
function bcdiv(string $num1, string $num2, ?int $scale = null): string {}
15+
/** @refcount 1 */
16+
function bcdiv(string $num1, string $num2, ?int $scale = null): string {}
1617

17-
/** @refcount 1 */
18-
function bcmod(string $num1, string $num2, ?int $scale = null): string {}
18+
/** @refcount 1 */
19+
function bcmod(string $num1, string $num2, ?int $scale = null): string {}
1920

20-
/** @refcount 1 */
21-
function bcpowmod(string $num, string $exponent, string $modulus, ?int $scale = null): string {}
21+
/** @refcount 1 */
22+
function bcpowmod(string $num, string $exponent, string $modulus, ?int $scale = null): string {}
2223

23-
/** @refcount 1 */
24-
function bcpow(string $num, string $exponent, ?int $scale = null): string {}
24+
/** @refcount 1 */
25+
function bcpow(string $num, string $exponent, ?int $scale = null): string {}
2526

26-
/** @refcount 1 */
27-
function bcsqrt(string $num, ?int $scale = null): string {}
27+
/** @refcount 1 */
28+
function bcsqrt(string $num, ?int $scale = null): string {}
2829

29-
function bccomp(string $num1, string $num2, ?int $scale = null): int {}
30+
function bccomp(string $num1, string $num2, ?int $scale = null): int {}
3031

31-
function bcscale(?int $scale = null): int {}
32+
function bcscale(?int $scale = null): int {}
3233

33-
/** @refcount 1 */
34-
function bcfloor(string $num): string {}
34+
/** @refcount 1 */
35+
function bcfloor(string $num): string {}
3536

36-
/** @refcount 1 */
37-
function bcceil(string $num): string {}
37+
/** @refcount 1 */
38+
function bcceil(string $num): string {}
3839

39-
/** @refcount 1 */
40-
function bcround(string $num, int $precision = 0, int $mode = PHP_ROUND_HALF_UP): string {}
40+
/** @refcount 1 */
41+
function bcround(string $num, int $precision = 0, int $mode = PHP_ROUND_HALF_UP): string {}
42+
}
43+
44+
namespace BcMath {
45+
final readonly class Number implements \Stringable {
46+
public string $value;
47+
public int $scale;
48+
49+
public function __construct(string|int $num) {}
50+
51+
public function add(Number|string|int $num, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
52+
53+
public function sub(Number|string|int $num, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
54+
55+
public function mul(Number|string|int $num, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
56+
57+
public function div(Number|string|int $num, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
58+
59+
public function mod(Number|string|int $num, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
60+
61+
public function powmod(Number|string|int $exponent, Number|string|int $modulus, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
62+
63+
public function pow(Number|string|int $exponent, ?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
64+
65+
public function sqrt(?int $scale = null, int $roundingMode = PHP_ROUND_HALF_UP): Number {}
66+
67+
public function floor(): Number {}
68+
69+
public function ceil(): Number {}
70+
71+
public function round(int $precision = 0, int $mode = PHP_ROUND_HALF_UP): Number {}
72+
73+
public function comp(Number|string|int $num, ?int $scale = null): int {}
74+
75+
public function __toString(): string {}
76+
}
77+
}

ext/bcmath/bcmath_arginfo.h

Lines changed: 111 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/bcmath/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ if test "$PHP_BCMATH" != "no"; then
1313
libbcmath/src/divmod.c
1414
libbcmath/src/doaddsub.c
1515
libbcmath/src/floor_or_ceil.c
16+
libbcmath/src/long2num.c
1617
libbcmath/src/init.c
1718
libbcmath/src/int2num.c
1819
libbcmath/src/nearzero.c

ext/bcmath/config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ARG_ENABLE("bcmath", "bc style precision math functions", "yes");
55
if (PHP_BCMATH == "yes") {
66
EXTENSION("bcmath", "bcmath.c", null, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
77
ADD_SOURCES("ext/bcmath/libbcmath/src", "add.c div.c init.c neg.c \
8-
raisemod.c sub.c compare.c divmod.c int2num.c \
8+
raisemod.c sub.c compare.c divmod.c int2num.c long2num.c \
99
num2long.c recmul.c sqrt.c zero.c doaddsub.c \
1010
floor_or_ceil.c nearzero.c num2str.c raise.c rmzero.c str2num.c \
1111
round.c convert.c", "bcmath");

ext/bcmath/libbcmath/src/bcmath.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ static inline bc_num bc_copy_num(bc_num num)
9898

9999
void bc_init_num(bc_num *num);
100100

101-
bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, bool auto_scale);
101+
bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, size_t *full_scale, bool auto_scale);
102+
103+
void bc_long2num(bc_num *num, zend_long lval);
102104

103105
zend_string *bc_num2str_ex(bc_num num, size_t scale);
104106

ext/bcmath/libbcmath/src/long2num.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Saki Takamachi <saki@php.net> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "bcmath.h"
18+
#include "convert.h"
19+
#include "private.h"
20+
#include <stdbool.h>
21+
22+
static inline size_t bc_count_len_in_vector(BC_VECTOR vector)
23+
{
24+
size_t len = 0;
25+
BC_VECTOR tmp = vector;
26+
#if BC_VECTOR_SIZE == 8
27+
tmp /= 10000;
28+
if (tmp > 0) {
29+
len += 4;
30+
} else {
31+
tmp = vector;
32+
}
33+
#endif
34+
35+
tmp /= 100;
36+
if (tmp > 0) {
37+
len += 2;
38+
} else {
39+
tmp = vector;
40+
}
41+
42+
if (tmp >= 10) {
43+
tmp += 2;
44+
} else {
45+
tmp += 1;
46+
}
47+
48+
return len;
49+
}
50+
51+
static inline void bc_bulk_convert_vector_to_num(BC_VECTOR vector, char *end)
52+
{
53+
#if BC_VECTOR_SIZE == 4
54+
bc_write_bcd_representation(vector, end - 3);
55+
#else
56+
bc_write_bcd_representation(vector / 10000, end - 7);
57+
bc_write_bcd_representation(vector % 10000, end - 3);
58+
#endif
59+
}
60+
61+
static inline void bc_convert_vector_to_num(BC_VECTOR vector, const char *ptr, char *end)
62+
{
63+
while (end >= ptr) {
64+
*end-- = vector % BASE;
65+
vector /= BASE;
66+
}
67+
}
68+
69+
void bc_long2num(bc_num *num, zend_long lval)
70+
{
71+
if (UNEXPECTED(lval == 0)) {
72+
*num = bc_copy_num(BCG(_zero_));
73+
return;
74+
}
75+
76+
bool negative = false;
77+
if (lval < 0) {
78+
lval = -lval;
79+
negative = true;
80+
}
81+
82+
BC_VECTOR low = lval % BC_VECTOR_BOUNDARY_NUM;
83+
lval /= BC_VECTOR_BOUNDARY_NUM;
84+
85+
BC_VECTOR mid = lval % BC_VECTOR_BOUNDARY_NUM;
86+
BC_VECTOR high = lval / BC_VECTOR_BOUNDARY_NUM;
87+
88+
size_t len;
89+
size_t vector_size;
90+
if (high > 0) {
91+
len = bc_count_len_in_vector(high) + BC_VECTOR_SIZE * 2;
92+
vector_size = 3;
93+
} else if (mid > 0) {
94+
len = bc_count_len_in_vector(mid) + BC_VECTOR_SIZE;
95+
vector_size = 2;
96+
} else {
97+
len = bc_count_len_in_vector(low);
98+
vector_size = 1;
99+
}
100+
101+
*num = bc_new_num_nonzeroed(len, 0);
102+
(*num)->n_sign = negative ? MINUS : PLUS;
103+
char *ptr = (*num)->n_value;
104+
char *end = ptr + len - 1;
105+
106+
switch (vector_size) {
107+
case 3:
108+
bc_bulk_convert_vector_to_num(low, end);
109+
end -= BC_VECTOR_SIZE;
110+
bc_bulk_convert_vector_to_num(mid, end);
111+
end -= BC_VECTOR_SIZE;
112+
bc_convert_vector_to_num(low, ptr, end);
113+
break;
114+
case 2:
115+
bc_bulk_convert_vector_to_num(low, end);
116+
end -= BC_VECTOR_SIZE;
117+
bc_convert_vector_to_num(low, ptr, end);
118+
break;
119+
case 1:
120+
bc_convert_vector_to_num(low, ptr, end);
121+
break;
122+
}
123+
}

0 commit comments

Comments
 (0)