commit da8260b9fe82b1cb2d5472370da512d21384a344
parent 875b6cb909a59dcce164cc88c85a120ae98d0a26
Author: Sebastian <sebastian@sebsite.pw>
Date: Sat, 20 Apr 2024 22:17:58 -0400
math::checked: fix subi* with *_MAX and *_MIN
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/math/checked/checked.ha b/math/checked/checked.ha
@@ -2,6 +2,7 @@
// (c) Hare authors <https://harelang.org>
use math;
+use types;
// Adds 'a' and 'b', returning the result and whether overflow occurred.
export fn addi8(a: i8, b: i8) (i8, bool) = {
@@ -132,7 +133,11 @@ export fn addu64(a: u64, b: u64) (u64, bool) = {
};
// Subtracts 'b' from 'a', returning the result and whether overflow occurred.
-export fn subi8(a: i8, b: i8) (i8, bool) = addi8(a, -b);
+export fn subi8(a: i8, b: i8) (i8, bool) = {
+ const res = a - b;
+ const overflow = a < 0 != b < 0 && a < 0 != res < 0;
+ return (res, overflow);
+};
@test fn subi8() void = {
const (res, overflow) = subi8(-100, 20);
@@ -141,10 +146,17 @@ export fn subi8(a: i8, b: i8) (i8, bool) = addi8(a, -b);
const (res, overflow) = subi8(-100, 50);
assert(res == 106);
assert(overflow);
+ const (res, overflow) = subi8(types::I8_MAX, types::I8_MIN);
+ assert(res == -1);
+ assert(overflow);
};
// Subtracts 'b' from 'a', returning the result and whether overflow occurred.
-export fn subi16(a: i16, b: i16) (i16, bool) = addi16(a, -b);
+export fn subi16(a: i16, b: i16) (i16, bool) = {
+ const res = a - b;
+ const overflow = a < 0 != b < 0 && a < 0 != res < 0;
+ return (res, overflow);
+};
@test fn subi16() void = {
const (res, overflow) = subi16(-32700, 60);
@@ -153,10 +165,17 @@ export fn subi16(a: i16, b: i16) (i16, bool) = addi16(a, -b);
const (res, overflow) = subi16(-32700, 100);
assert(res == 32736);
assert(overflow);
+ const (res, overflow) = subi16(types::I16_MAX, types::I16_MIN);
+ assert(res == -1);
+ assert(overflow);
};
// Subtracts 'b' from 'a', returning the result and whether overflow occurred.
-export fn subi32(a: i32, b: i32) (i32, bool) = addi32(a, -b);
+export fn subi32(a: i32, b: i32) (i32, bool) = {
+ const res = a - b;
+ const overflow = a < 0 != b < 0 && a < 0 != res < 0;
+ return (res, overflow);
+};
@test fn subi32() void = {
const (res, overflow) = subi32(-2147483600, 40);
@@ -165,10 +184,17 @@ export fn subi32(a: i32, b: i32) (i32, bool) = addi32(a, -b);
const (res, overflow) = subi32(-2147483600, 100);
assert(res == 2147483596);
assert(overflow);
+ const (res, overflow) = subi32(types::I32_MAX, types::I32_MIN);
+ assert(res == -1);
+ assert(overflow);
};
// Subtracts 'b' from 'a', returning the result and whether overflow occurred.
-export fn subi64(a: i64, b: i64) (i64, bool) = addi64(a, -b);
+export fn subi64(a: i64, b: i64) (i64, bool) = {
+ const res = a - b;
+ const overflow = a < 0 != b < 0 && a < 0 != res < 0;
+ return (res, overflow);
+};
@test fn subi64() void = {
const (res, overflow) = subi64(-9223372036854775800, 5);
@@ -177,6 +203,9 @@ export fn subi64(a: i64, b: i64) (i64, bool) = addi64(a, -b);
const (res, overflow) = subi64(-9223372036854775800, 10);
assert(res == 9223372036854775806);
assert(overflow);
+ const (res, overflow) = subi64(types::I64_MAX, types::I64_MIN);
+ assert(res == -1);
+ assert(overflow);
};
// Subtracts 'b' from 'a', returning the result and whether overflow occurred.