From 748e7dd4c79f0fef101a30b91252388f945254b9 Mon Sep 17 00:00:00 2001 From: Rangi Date: Wed, 17 Feb 2021 09:25:02 -0500 Subject: [PATCH] Fix calculation of 2**30 In exponent(), 'base *= base;' should not run when base is 65536, since it overflows an int32_t. This also optimizes exponent() based on gcc and clang -O3 test cases in godbolt.org. --- src/asm/rpn.c | 6 ++++-- src/link/patch.c | 6 ++++-- test/asm/math.asm | 4 +++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/asm/rpn.c b/src/asm/rpn.c index 4c20af86..08ff8773 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -283,14 +283,16 @@ static int32_t shift(int32_t shiftee, int32_t amount) } } -static int32_t exponent(int32_t base, int32_t power) +static int32_t exponent(int32_t base, uint32_t power) { int32_t result = 1; - while (power) { + for (;;) { if (power % 2) result *= base; power /= 2; + if (!power) + break; base *= base; } diff --git a/src/link/patch.c b/src/link/patch.c index 05cdf96a..5d576e64 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -21,14 +21,16 @@ #include "extern/err.h" -static int32_t exponent(int32_t base, int32_t power) +static int32_t exponent(int32_t base, uint32_t power) { int32_t result = 1; - while (power) { + for (;;) { if (power % 2) result *= base; power /= 2; + if (!power) + break; base *= base; } diff --git a/test/asm/math.asm b/test/asm/math.asm index 3d1dace4..7411bb32 100644 --- a/test/asm/math.asm +++ b/test/asm/math.asm @@ -12,7 +12,9 @@ v equs "Y +" ENDM test (v 2)*(v 10)**(v 2)*(v 2) == (v 400) - test -(v 3)**(v 4) == v -81 + test -(v 3)**(v 4) == (v -81) + test (v 1) << (v 30) == (v $4000_0000) + test (v 2)**(v 30) == (v $4000_0000) assert DIV(5.0, 2.0) == 2.5 assert DIV(-5.0, 2.0) == -2.5