[git commit] bc: tweak overflow detection in a^b

Denys Vlasenko vda.linux at googlemail.com
Sat Jun 12 12:03:24 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=aece2c5f0fef9088b615016f3177b1abd3a373bb
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
zbc_num_p                                            506     510      +4

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 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;
 	}


More information about the busybox-cvs mailing list