From aece2c5f0fef9088b615016f3177b1abd3a373bb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Jun 2021 14:03:24 +0200 Subject: [PATCH] bc: tweak overflow detection in a^b function old new delta zbc_num_p 506 510 +4 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 ++++++++----- 1 file 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 @@ * Original code copyright (c) 2018 Gavin D. Howard and contributors. */ //TODO: -// maybe implement a^b for non-integer b? +// maybe implement a^b for non-integer b? (see zbc_num_p()) #define DEBUG_LEXER 0 #define DEBUG_COMPILE 0 @@ -2163,6 +2163,9 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size if (b->num[i] != 0) RETURN_STATUS(bc_error("not an integer")); +// a^b for non-integer b (for a>0) can be implemented as exp(ln(a)*b). +// Possibly better precision would be given by a^int(b) * exp(ln(a)*frac(b)). + if (b->len == 0) { bc_num_one(c); 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 //but it can be improved to detect zero results etc. Example: with scale=0, //result of 0.01^N for any N>1 is 0: 0.01^2 = 0.0001 ~= 0.00 (trunc to scale) //then this would matter: - // if (new_scale >= pow) is false, we had overflow, correct - // "new_scale" value is larger than ULONG_MAX, thus larger - // than any possible current value of "scale", + // if a_rdx != 0 and new_scale < pow, we had overflow, + // correct "new_scale" value is larger than ULONG_MAX, + // thus larger than any possible current value of "scale", // thus "scale = new_scale" should not be done: - if (new_scale >= pow) + if (a_rdx == 0 || new_scale >= pow) if (new_scale < scale) scale = new_scale; }