hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mmath/checked/checked.ha | 37+++++++++++++++++++++++++++++++++----
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.