Last active
December 17, 2021 05:59
-
-
Save matu3ba/ca26361231d21b0ca0f79b0f2753c92d to your computer and use it in GitHub Desktop.
abs implementations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Observation: only MIN has no abs | |
// 2s complement is ~x+1 | |
// 2s compl of MIN == MIN, since ~0b100..00 + 1 == 0b011..11 + 1 == 0b100..00 | |
// NOTE: 2s complement of 0 would overflow ~0x00..00 + 1 == 0xff..ff + 1 kaboom | |
// working version | |
fn absvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST { | |
return struct { | |
fn f(a: ST) callconv(.C) ST { | |
var x = a; | |
if (x < 0) { | |
x = ~x +% 1; // 2s complement | |
if (x < 0) // did we overflow? | |
return -1; | |
} | |
return x; | |
} | |
}.f; | |
} | |
// LLVM version (not optimal) | |
fn absvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST { | |
return struct { | |
fn f(a: ST) callconv(.C) ST { | |
const UT = switch (ST) { | |
i32 => u32, | |
i64 => u64, | |
i128 => u128, | |
else => unreachable, | |
}; | |
const N: UT = @bitSizeOf(ST); | |
const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1))); | |
if (a == min) | |
return -1; // replace with @panic("abs: overflow"); | |
const sign: ST = a >> (N - 1); | |
return (a ^ sign) - sign; | |
} | |
}.f; | |
} | |
// optimal version in software | |
fn absvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST { | |
return struct { | |
fn f(a: ST) callconv(.C) ST { | |
const UT = switch (ST) { | |
i32 => u32, | |
i64 => u64, | |
i128 => u128, | |
else => unreachable, | |
}; | |
var x: ST = a; | |
const N: UT = @bitSizeOf(ST); | |
const sign: ST = a >> N - 1; | |
x +%= sign; | |
x ^= sign; | |
if (x < 0) | |
return -1; // replace with @panic("abs: overflow"); instead | |
return x; | |
} | |
}.f; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment