zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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 }