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