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