suboti4_test.zig (2563B) - Raw
1 const subo = @import("subo.zig"); 2 const builtin = @import("builtin"); 3 const std = @import("std"); 4 const testing = std.testing; 5 const math = std.math; 6 7 fn test__suboti4(a: i128, b: i128) !void { 8 var result_ov: c_int = undefined; 9 var expected_ov: c_int = undefined; 10 const result = subo.__suboti4(a, b, &result_ov); 11 const expected: i128 = simple_suboti4(a, b, &expected_ov); 12 try testing.expectEqual(expected, result); 13 try testing.expectEqual(expected_ov, result_ov); 14 } 15 16 // 2 cases on evaluating `a-b`: 17 // 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b 18 // 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b 19 // `-b` evaluation may overflow, iff b==min, but this is handled by the hardware 20 pub fn simple_suboti4(a: i128, b: i128, overflow: *c_int) i128 { 21 overflow.* = 0; 22 const min: i128 = math.minInt(i128); 23 const max: i128 = math.maxInt(i128); 24 if (((b > 0) and (a < min + b)) or 25 ((b < 0) and (a > max + b))) 26 overflow.* = 1; 27 return a -% b; 28 } 29 30 test "suboti3" { 31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 32 33 const min: i128 = math.minInt(i128); 34 const max: i128 = math.maxInt(i128); 35 var i: i128 = 1; 36 while (i < max) : (i *|= 2) { 37 try test__suboti4(i, i); 38 try test__suboti4(-i, -i); 39 try test__suboti4(i, -i); 40 try test__suboti4(-i, i); 41 } 42 43 // edge cases 44 // 0 - 0 = 0 45 // MIN - MIN = 0 46 // MAX - MAX = 0 47 // 0 - MIN overflow 48 // 0 - MAX = MIN+1 49 // MIN - 0 = MIN 50 // MAX - 0 = MAX 51 // MIN - MAX overflow 52 // MAX - MIN overflow 53 try test__suboti4(0, 0); 54 try test__suboti4(min, min); 55 try test__suboti4(max, max); 56 try test__suboti4(0, min); 57 try test__suboti4(0, max); 58 try test__suboti4(min, 0); 59 try test__suboti4(max, 0); 60 try test__suboti4(min, max); 61 try test__suboti4(max, min); 62 63 // derived edge cases 64 // MIN+1 - MIN = 1 65 // MAX-1 - MAX = -1 66 // 1 - MIN overflow 67 // -1 - MIN = MAX 68 // -1 - MAX = MIN 69 // +1 - MAX = MIN+2 70 // MIN - 1 overflow 71 // MIN - -1 = MIN+1 72 // MAX - 1 = MAX-1 73 // MAX - -1 overflow 74 try test__suboti4(min + 1, min); 75 try test__suboti4(max - 1, max); 76 try test__suboti4(1, min); 77 try test__suboti4(-1, min); 78 try test__suboti4(-1, max); 79 try test__suboti4(1, max); 80 try test__suboti4(min, 1); 81 try test__suboti4(min, -1); 82 try test__suboti4(max, -1); 83 try test__suboti4(max, 1); 84 }