lib/math: checked sat_subu* unsigned saturating subtract (#28)
Port the deferred sat_subu8/16/32/64 from ref/hare/math/checked/saturating.ha:196,206,216,226 — clamp to types.U*_MIN (0) on underflow. Mirrors the existing sat_addu* shape (typed res forces the sub-word wrap, then the >a underflow test). Tests: sat_subu* normal+clamp rows plus a direct types min check (U*_MIN==0, RUNE_MIN=='\0'), wired into checked_test main().
This commit is contained in:
@@ -14,9 +14,8 @@
|
||||
// - the mul overflow compares need an explicit widening cast (no
|
||||
// implicit promotion in ww).
|
||||
//
|
||||
// Deferred (faithful subset, Hare splits per type): sat_subu8/16/32/64
|
||||
// (reference types::U*_MIN, not yet exported by lib/types); sat_*z (no
|
||||
// `size` type, #85); sat_muli64/sat_mulu64/sat_muli/sat_mulu (need
|
||||
// Deferred (faithful subset, Hare splits per type): sat_*z (no `size`
|
||||
// type, #85); sat_muli64/sat_mulu64/sat_muli/sat_mulu (need
|
||||
// math::mulu64); int/uint native-width sat_* (ww int is 64-bit — a width
|
||||
// divergence in the overflow boundary).
|
||||
|
||||
@@ -120,6 +119,30 @@ export fn sat_subi64(a: i64, b: i64) i64 = {
|
||||
return res;
|
||||
};
|
||||
|
||||
export fn sat_subu8(a: u8, b: u8) u8 = {
|
||||
let res: u8 = a - b;
|
||||
if (res > a) { return types.U8_MIN; };
|
||||
return res;
|
||||
};
|
||||
|
||||
export fn sat_subu16(a: u16, b: u16) u16 = {
|
||||
let res: u16 = a - b;
|
||||
if (res > a) { return types.U16_MIN; };
|
||||
return res;
|
||||
};
|
||||
|
||||
export fn sat_subu32(a: u32, b: u32) u32 = {
|
||||
let res: u32 = a - b;
|
||||
if (res > a) { return types.U32_MIN; };
|
||||
return res;
|
||||
};
|
||||
|
||||
export fn sat_subu64(a: u64, b: u64) u64 = {
|
||||
let res: u64 = a - b;
|
||||
if (res > a) { return types.U64_MIN; };
|
||||
return res;
|
||||
};
|
||||
|
||||
export fn sat_muli8(a: i8, b: i8) i8 = {
|
||||
let fullres: int = a: int * b: int;
|
||||
let res: i8 = fullres: i8;
|
||||
|
||||
Reference in New Issue
Block a user