diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-12 14:03:24 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-12 14:03:24 +0200 |
commit | aece2c5f0fef9088b615016f3177b1abd3a373bb (patch) | |
tree | 984c8c0e504d8407272432647a3c578641781b43 | |
parent | e36c39a46d16c080de1034db41b53abf483bdb88 (diff) | |
download | busybox-w32-aece2c5f0fef9088b615016f3177b1abd3a373bb.tar.gz busybox-w32-aece2c5f0fef9088b615016f3177b1abd3a373bb.tar.bz2 busybox-w32-aece2c5f0fef9088b615016f3177b1abd3a373bb.zip |
bc: tweak overflow detection in a^b
function old new delta
zbc_num_p 506 510 +4
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/bc.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index e12a20aec..a5d8734b3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Original code copyright (c) 2018 Gavin D. Howard and contributors. | 5 | * Original code copyright (c) 2018 Gavin D. Howard and contributors. |
6 | */ | 6 | */ |
7 | //TODO: | 7 | //TODO: |
8 | // maybe implement a^b for non-integer b? | 8 | // maybe implement a^b for non-integer b? (see zbc_num_p()) |
9 | 9 | ||
10 | #define DEBUG_LEXER 0 | 10 | #define DEBUG_LEXER 0 |
11 | #define DEBUG_COMPILE 0 | 11 | #define DEBUG_COMPILE 0 |
@@ -2163,6 +2163,9 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size | |||
2163 | if (b->num[i] != 0) | 2163 | if (b->num[i] != 0) |
2164 | RETURN_STATUS(bc_error("not an integer")); | 2164 | RETURN_STATUS(bc_error("not an integer")); |
2165 | 2165 | ||
2166 | // a^b for non-integer b (for a>0) can be implemented as exp(ln(a)*b). | ||
2167 | // Possibly better precision would be given by a^int(b) * exp(ln(a)*frac(b)). | ||
2168 | |||
2166 | if (b->len == 0) { | 2169 | if (b->len == 0) { |
2167 | bc_num_one(c); | 2170 | bc_num_one(c); |
2168 | RETURN_STATUS(BC_STATUS_SUCCESS); | 2171 | RETURN_STATUS(BC_STATUS_SUCCESS); |
@@ -2199,11 +2202,11 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size | |||
2199 | //but it can be improved to detect zero results etc. Example: with scale=0, | 2202 | //but it can be improved to detect zero results etc. Example: with scale=0, |
2200 | //result of 0.01^N for any N>1 is 0: 0.01^2 = 0.0001 ~= 0.00 (trunc to scale) | 2203 | //result of 0.01^N for any N>1 is 0: 0.01^2 = 0.0001 ~= 0.00 (trunc to scale) |
2201 | //then this would matter: | 2204 | //then this would matter: |
2202 | // if (new_scale >= pow) is false, we had overflow, correct | 2205 | // if a_rdx != 0 and new_scale < pow, we had overflow, |
2203 | // "new_scale" value is larger than ULONG_MAX, thus larger | 2206 | // correct "new_scale" value is larger than ULONG_MAX, |
2204 | // than any possible current value of "scale", | 2207 | // thus larger than any possible current value of "scale", |
2205 | // thus "scale = new_scale" should not be done: | 2208 | // thus "scale = new_scale" should not be done: |
2206 | if (new_scale >= pow) | 2209 | if (a_rdx == 0 || new_scale >= pow) |
2207 | if (new_scale < scale) | 2210 | if (new_scale < scale) |
2208 | scale = new_scale; | 2211 | scale = new_scale; |
2209 | } | 2212 | } |