aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-06-12 14:03:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-06-12 14:03:24 +0200
commitaece2c5f0fef9088b615016f3177b1abd3a373bb (patch)
tree984c8c0e504d8407272432647a3c578641781b43
parente36c39a46d16c080de1034db41b53abf483bdb88 (diff)
downloadbusybox-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.c13
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 }