ref: 748e7dd4c79f0fef101a30b91252388f945254b9
parent: d049ffc0f0a508f9d48d27e850692f54b6c062f8
author: Rangi <[email protected]>
date: Wed Feb 17 04:25:02 EST 2021
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.
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -283,14 +283,16 @@
}
}
-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;
}
--- 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;
}
--- a/test/asm/math.asm
+++ b/test/asm/math.asm
@@ -12,7 +12,9 @@
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