forked from ziglang/zig
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compiler_rt: add __absvsi2, __absvdi2, __absvti2
- abs can only overflow, if a == MIN - comparing the sign change from wrapping addition is branchless - tests: MIN, MIN+1,..MIN+4, -42, -7, -1, 0, 1, 7.. See ziglang#1290
- Loading branch information
Showing
6 changed files
with
133 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// absv - absolute oVerflow | ||
// * @panic, if value can not be represented | ||
// - absvXi4_generic for unoptimized version | ||
|
||
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, | ||
}; | ||
// taken from Bit Twiddling Hacks | ||
// compute the integer absolute value (abs) without branching | ||
var x: ST = a; | ||
const N: UT = @bitSizeOf(ST); | ||
const sign: ST = a >> N - 1; | ||
x +%= sign; | ||
x ^= sign; | ||
if (x < 0) | ||
@panic("compiler_rt absv: overflow"); | ||
return x; | ||
} | ||
}.f; | ||
} | ||
pub const __absvsi2 = absvXi_generic(i32); | ||
pub const __absvdi2 = absvXi_generic(i64); | ||
pub const __absvti2 = absvXi_generic(i128); | ||
|
||
test { | ||
_ = @import("absvsi2_test.zig"); | ||
_ = @import("absvdi2_test.zig"); | ||
_ = @import("absvti2_test.zig"); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const absv = @import("absv.zig"); | ||
const testing = @import("std").testing; | ||
|
||
fn test__absvdi2(a: i64, expected: i64) !void { | ||
var result = absv.__absvdi2(a); | ||
try testing.expectEqual(expected, result); | ||
} | ||
|
||
test "absvdi2" { | ||
// -2^63 <= i64 <= 2^63-1 | ||
// 2^63 = 9223372036854775808 | ||
// 2^63-1 = 9223372036854775807 | ||
// TODO write panic handler for testing panics | ||
//try test__absvdi2(-9223372036854775808, -5); // tested with return -5; and panic | ||
try test__absvdi2(-9223372036854775807, 9223372036854775807); | ||
try test__absvdi2(-9223372036854775806, 9223372036854775806); | ||
try test__absvdi2(-9223372036854775805, 9223372036854775805); | ||
try test__absvdi2(-9223372036854775804, 9223372036854775804); | ||
try test__absvdi2(-42, 42); | ||
try test__absvdi2(-7, 7); | ||
try test__absvdi2(-1, 1); | ||
try test__absvdi2(0, 0); | ||
try test__absvdi2(1, 1); | ||
try test__absvdi2(7, 7); | ||
try test__absvdi2(42, 42); | ||
try test__absvdi2(9223372036854775804, 9223372036854775804); | ||
try test__absvdi2(9223372036854775805, 9223372036854775805); | ||
try test__absvdi2(9223372036854775806, 9223372036854775806); | ||
try test__absvdi2(9223372036854775807, 9223372036854775807); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const absv = @import("absv.zig"); | ||
const testing = @import("std").testing; | ||
|
||
fn test__absvsi2(a: i32, expected: i32) !void { | ||
var result = absv.__absvsi2(a); | ||
try testing.expectEqual(expected, result); | ||
} | ||
|
||
test "absvsi2" { | ||
// -2^31 <= i32 <= 2^31-1 | ||
// 2^31 = 2147483648 | ||
// 2^31-1 = 2147483647 | ||
// TODO write panic handler for testing panics | ||
//try test__absvsi2(-2147483648, -5); // tested with return -5; and panic | ||
try test__absvsi2(-2147483647, 2147483647); | ||
try test__absvsi2(-2147483646, 2147483646); | ||
try test__absvsi2(-2147483645, 2147483645); | ||
try test__absvsi2(-2147483644, 2147483644); | ||
try test__absvsi2(-42, 42); | ||
try test__absvsi2(-7, 7); | ||
try test__absvsi2(-1, 1); | ||
try test__absvsi2(0, 0); | ||
try test__absvsi2(1, 1); | ||
try test__absvsi2(7, 7); | ||
try test__absvsi2(42, 42); | ||
try test__absvsi2(2147483644, 2147483644); | ||
try test__absvsi2(2147483645, 2147483645); | ||
try test__absvsi2(2147483646, 2147483646); | ||
try test__absvsi2(2147483647, 2147483647); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const absv = @import("absv.zig"); | ||
const testing = @import("std").testing; | ||
|
||
fn test__absvti2(a: i128, expected: i128) !void { | ||
var result = absv.__absvti2(a); | ||
try testing.expectEqual(expected, result); | ||
} | ||
|
||
test "absvti2" { | ||
// -2^127 <= i128 <= 2^127-1 | ||
// 2^127 = 170141183460469231731687303715884105728 | ||
// 2^127+1 = 170141183460469231731687303715884105727 | ||
// TODO write panic handler for testing panics | ||
//try test__absvti2(-170141183460469231731687303715884105728, -5); // tested with return -5; and panic | ||
try test__absvti2(-170141183460469231731687303715884105727, 170141183460469231731687303715884105727); | ||
try test__absvti2(-170141183460469231731687303715884105726, 170141183460469231731687303715884105726); | ||
try test__absvti2(-170141183460469231731687303715884105725, 170141183460469231731687303715884105725); | ||
try test__absvti2(-170141183460469231731687303715884105724, 170141183460469231731687303715884105724); | ||
try test__absvti2(-42, 42); | ||
try test__absvti2(-7, 7); | ||
try test__absvti2(-1, 1); | ||
try test__absvti2(0, 0); | ||
try test__absvti2(1, 1); | ||
try test__absvti2(7, 7); | ||
try test__absvti2(42, 42); | ||
try test__absvti2(170141183460469231731687303715884105724, 170141183460469231731687303715884105724); | ||
try test__absvti2(170141183460469231731687303715884105725, 170141183460469231731687303715884105725); | ||
try test__absvti2(170141183460469231731687303715884105726, 170141183460469231731687303715884105726); | ||
try test__absvti2(170141183460469231731687303715884105727, 170141183460469231731687303715884105727); | ||
} |