addo.zig (1752B) - Raw
1 const std = @import("std"); 2 const common = @import("./common.zig"); 3 pub const panic = @import("common.zig").panic; 4 5 comptime { 6 @export(&__addosi4, .{ .name = "__addosi4", .linkage = common.linkage, .visibility = common.visibility }); 7 @export(&__addodi4, .{ .name = "__addodi4", .linkage = common.linkage, .visibility = common.visibility }); 8 @export(&__addoti4, .{ .name = "__addoti4", .linkage = common.linkage, .visibility = common.visibility }); 9 } 10 11 // addo - add overflow 12 // * return a+%b. 13 // * return if a+b overflows => 1 else => 0 14 // - addoXi4_generic as default 15 16 inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { 17 @setRuntimeSafety(common.test_safety); 18 overflow.* = 0; 19 const sum: ST = a +% b; 20 // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract 21 // Let sum = a +% b == a + b + carry == wraparound addition. 22 // Overflow in a+b+carry occurs, iff a and b have opposite signs 23 // and the sign of a+b+carry is the same as a (or equivalently b). 24 // Slower routine: res = ~(a ^ b) & ((sum ^ a) 25 // Faster routine: res = (sum ^ a) & (sum ^ b) 26 // Overflow occurred, iff (res < 0) 27 if (((sum ^ a) & (sum ^ b)) < 0) 28 overflow.* = 1; 29 return sum; 30 } 31 32 pub fn __addosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 { 33 return addoXi4_generic(i32, a, b, overflow); 34 } 35 pub fn __addodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 { 36 return addoXi4_generic(i64, a, b, overflow); 37 } 38 pub fn __addoti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 { 39 return addoXi4_generic(i128, a, b, overflow); 40 } 41 42 test { 43 _ = @import("addosi4_test.zig"); 44 _ = @import("addodi4_test.zig"); 45 _ = @import("addoti4_test.zig"); 46 }