| 1 | const std = @import("std"); |
| 2 | const math = std.math; |
| 3 | const testing = std.testing; |
| 4 | |
| 5 | const div_f80 = @import("divxf3.zig").div_f80; |
| 6 | |
| 7 | const nanRep: u80 = @as(u80, @bitCast(math.nan(f80))); |
| 8 | const infRep: u80 = @as(u80, @bitCast(math.inf(f80))); |
| 9 | const negInfRep: u80 = @as(u80, @bitCast(-math.inf(f80))); |
| 10 | |
| 11 | fn compareResult(result: f80, expected: u80) bool { |
| 12 | const rep: u80 = @bitCast(result); |
| 13 | |
| 14 | if (rep == expected) return true; |
| 15 | // test other possible NaN representations (signal NaN) |
| 16 | if (math.isNan(result) and math.isNan(@as(f80, @bitCast(expected)))) return true; |
| 17 | |
| 18 | return false; |
| 19 | } |
| 20 | |
| 21 | fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void { |
| 22 | const x = div_f80(a, b); |
| 23 | const ret = compareResult(x, expected); |
| 24 | try testing.expect(ret == true); |
| 25 | } |
| 26 | |
| 27 | fn test__divxf3(a: f80, b: f80) !void { |
| 28 | const integerBit = 1 << math.floatFractionalBits(f80); |
| 29 | const x = div_f80(a, b); |
| 30 | |
| 31 | // Next float (assuming normal, non-zero result) |
| 32 | const x_plus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) + 1) | integerBit); |
| 33 | // Prev float (assuming normal, non-zero result) |
| 34 | const x_minus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) - 1) | integerBit); |
| 35 | |
| 36 | // Make sure result is more accurate than the adjacent floats |
| 37 | const err_x = @abs(@mulAdd(f80, x, b, -a)); |
| 38 | const err_x_plus_eps = @abs(@mulAdd(f80, x_plus_eps, b, -a)); |
| 39 | const err_x_minus_eps = @abs(@mulAdd(f80, x_minus_eps, b, -a)); |
| 40 | |
| 41 | try testing.expect(err_x_minus_eps > err_x); |
| 42 | try testing.expect(err_x_plus_eps > err_x); |
| 43 | } |
| 44 | |
| 45 | test "divxf3" { |
| 46 | try expect__divxf3_result(math.nan(f80), 0x1.23456789abcdefp+5, nanRep); |
| 47 | try expect__divxf3_result(0x1.23456789abcdefp+5, math.nan(f80), nanRep); |
| 48 | try expect__divxf3_result(math.inf(f80), 0x1.23456789abcdefp+5, infRep); |
| 49 | try expect__divxf3_result(-math.inf(f80), 0x1.23456789abcdefp+5, negInfRep); |
| 50 | try expect__divxf3_result(0x1.23456789abcdefp+5, math.inf(f80), 0x0); |
| 51 | try expect__divxf3_result(0x1.23456789abcdefp+5, -math.inf(f80), 0x80000000000000000000); |
| 52 | try expect__divxf3_result(math.inf(f80), math.inf(f80), nanRep); |
| 53 | try expect__divxf3_result(0.0, 0.0, nanRep); |
| 54 | try expect__divxf3_result(-0.0, 0.0, nanRep); |
| 55 | try expect__divxf3_result(0.0, 1.0, 0x0); |
| 56 | try expect__divxf3_result(-0.0, 1.0, 0x80000000000000000000); |
| 57 | try expect__divxf3_result(1.0, 0.0, infRep); |
| 58 | try expect__divxf3_result(1.0, -0.0, negInfRep); |
| 59 | |
| 60 | try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.eedcbaba3a94546558237654321fp-1); |
| 61 | try test__divxf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50, 0x1.ed2c3ba15935332532287654321fp-9); |
| 62 | try test__divxf3(0x1.2345f6aaaa786555f42432abcdefp+456, 0x1.edacbba9874f765463544dd3621fp+6400); |
| 63 | try test__divxf3(0x1.2d3456f789ba6322bc665544edefp-234, 0x1.eddcdba39f3c8b7a36564354321fp-4455); |
| 64 | try test__divxf3(0x1.2345f6b77b7a8953365433abcdefp+234, 0x1.edcba987d6bb3aa467754354321fp-4055); |
| 65 | try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.a2b34c56d745382f9abf2c3dfeffp-50); |
| 66 | try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.1234567890abcdef987654321123p0); |
| 67 | try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.12394205810257120adae8929f23p+16); |
| 68 | try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.febdcefa1231245f9abf2c3dfeffp-50); |
| 69 | |
| 70 | // Result rounds down to zero |
| 71 | try expect__divxf3_result(6.72420628622418701252535563464350521E-4932, 2.0, 0x0); |
| 72 | } |