Skip to content

Commit 246219e

Browse files
committed
Support object types in BCMath
1 parent f61aad8 commit 246219e

File tree

10 files changed

+1206
-34
lines changed

10 files changed

+1206
-34
lines changed

ext/bcmath/bcmath.c

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

ext/bcmath/bcmath.stub.php

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ext/bcmath/bcmath_arginfo.h

Lines changed: 117 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: 5 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

@@ -122,6 +124,8 @@ bool bc_is_near_zero(bc_num num, size_t scale);
122124

123125
bool bc_is_neg(bc_num num);
124126

127+
void bc_rm_trailing_zeros(bc_num num);
128+
125129
bc_num bc_add(bc_num n1, bc_num n2, size_t scale_min);
126130

127131
#define bc_add_ex(n1, n2, result, scale_min) do { \

ext/bcmath/libbcmath/src/long2num.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Saki Takamachi <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "bcmath.h"
18+
#include <stdbool.h>
19+
20+
#if SIZEOF_ZEND_LONG == 8
21+
# define BC_LONG_MAX_DIGITS 19
22+
#else
23+
# define BC_LONG_MAX_DIGITS 10
24+
#endif
25+
26+
void bc_long2num(bc_num *num, zend_long lval)
27+
{
28+
if (UNEXPECTED(lval == 0)) {
29+
*num = bc_copy_num(BCG(_zero_));
30+
return;
31+
}
32+
33+
bool negative = lval < 0;
34+
if (UNEXPECTED(lval == LONG_MIN)) {
35+
*num = bc_new_num_nonzeroed(BC_LONG_MAX_DIGITS, 0);
36+
char *ptr = (*num)->n_value;
37+
memcpy(ptr, LONG_MIN_DIGITS, BC_LONG_MAX_DIGITS);
38+
for (size_t i = 0; i < BC_LONG_MAX_DIGITS; i++) {
39+
*ptr = *ptr - '0';
40+
ptr++;
41+
}
42+
(*num)->n_sign = MINUS;
43+
return;
44+
} else if (negative) {
45+
lval = -lval;
46+
}
47+
48+
zend_long tmp = lval;
49+
size_t len = 0;
50+
while (tmp > 0) {
51+
tmp /= BASE;
52+
len++;
53+
}
54+
55+
*num = bc_new_num_nonzeroed(len, 0);
56+
char *ptr = (*num)->n_value + len - 1;
57+
for (; len > 0; len--) {
58+
*ptr-- = lval % BASE;
59+
lval /= BASE;
60+
}
61+
(*num)->n_sign = negative ? MINUS : PLUS;
62+
}

ext/bcmath/libbcmath/src/rmzero.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,16 @@ void _bc_rm_leading_zeros(bc_num num)
4444
num->n_len--;
4545
}
4646
}
47+
48+
void bc_rm_trailing_zeros(bc_num num)
49+
{
50+
if (num->n_scale == 0) {
51+
return;
52+
}
53+
54+
char *end = num->n_value + num->n_len + num->n_scale - 1;
55+
while (*end == 0 && num->n_scale > 0) {
56+
num->n_scale--;
57+
end--;
58+
}
59+
}

ext/bcmath/libbcmath/src/str2num.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static inline const char *bc_skip_zero_reverse(const char *scanner, const char *
106106
}
107107

108108
/* Assumes `num` points to NULL, i.e. does yet not hold a number. */
109-
bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, bool auto_scale)
109+
bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, size_t *full_scale, bool auto_scale)
110110
{
111111
size_t str_scale = 0;
112112
const char *ptr = str;
@@ -153,6 +153,10 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, boo
153153
goto fail;
154154
}
155155

156+
if (full_scale) {
157+
*full_scale = fractional_end - fractional_ptr;
158+
}
159+
156160
/* Exclude trailing zeros. */
157161
fractional_end = bc_skip_zero_reverse(fractional_end, fractional_ptr);
158162

@@ -167,6 +171,10 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, boo
167171
fractional_end -= str_scale - scale;
168172
str_scale = scale;
169173
}
174+
} else {
175+
if (full_scale) {
176+
*full_scale = 0;
177+
}
170178
}
171179

172180
after_fractional:

0 commit comments

Comments
 (0)