From c24a49a1a7a74937fca4375fe418a92c398c013f Mon Sep 17 00:00:00 2001 From: vegecode <39607947+vegecode@users.noreply.github.com> Date: Fri, 5 Apr 2019 10:04:46 -0500 Subject: [PATCH] Fixes to divsf3 (#2186) * Fixes to divsf3 Embarrassingly failed to notice a section that was unchanged from where it was copied from mulXf3.zig. The test cases for this function series div{s,d,t}f3 are very incomplete and don't exercise all code paths. Remove unnecessary switch from divsf3 left during development from when I tried to make it generic to support f32, f64, and f128 in one go. Make runtime safety dependent on whether a test is being run. * divsf3: switch plus to minus --- std/special/compiler_rt/divsf3.zig | 49 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/std/special/compiler_rt/divsf3.zig b/std/special/compiler_rt/divsf3.zig index 6624a60d75..49215bccfb 100644 --- a/std/special/compiler_rt/divsf3.zig +++ b/std/special/compiler_rt/divsf3.zig @@ -3,8 +3,10 @@ // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c const std = @import("std"); +const builtin = @import("builtin"); pub extern fn __divsf3(a: f32, b: f32) f32 { + @setRuntimeSafety(builtin.is_test); const Z = @IntType(false, f32.bit_count); const typeWidth = f32.bit_count; @@ -37,41 +39,43 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { const aAbs: Z = @bitCast(Z, a) & absMask; const bAbs: Z = @bitCast(Z, b) & absMask; - // NaN * anything = qNaN + // NaN / anything = qNaN if (aAbs > infRep) return @bitCast(f32, @bitCast(Z, a) | quietBit); - // anything * NaN = qNaN + // anything / NaN = qNaN if (bAbs > infRep) return @bitCast(f32, @bitCast(Z, b) | quietBit); if (aAbs == infRep) { - // infinity * non-zero = +/- infinity - if (bAbs != 0) { + // infinity / infinity = NaN + if (bAbs == infRep) { + return @bitCast(f32, qnanRep); + } + // infinity / anything else = +/- infinity + else { return @bitCast(f32, aAbs | quotientSign); - } else { - // infinity * zero = NaN - return @bitCast(f32, qnanRep); } } - if (bAbs == infRep) { - //? non-zero * infinity = +/- infinity - if (aAbs != 0) { - return @bitCast(f32, bAbs | quotientSign); - } else { - // zero * infinity = NaN + // anything else / infinity = +/- 0 + if (bAbs == infRep) return @bitCast(f32, quotientSign); + + if (aAbs == 0) { + // zero / zero = NaN + if (bAbs == 0) { return @bitCast(f32, qnanRep); } + // zero / anything else = +/- zero + else { + return @bitCast(f32, quotientSign); + } } - - // zero * anything = +/- zero - if (aAbs == 0) return @bitCast(f32, quotientSign); - // anything * zero = +/- zero - if (bAbs == 0) return @bitCast(f32, quotientSign); + // anything else / zero = +/- infinity + if (bAbs == 0) return @bitCast(f32, infRep | quotientSign); // one or both of a or b is denormal, the other (if applicable) is a // normal number. Renormalize one or both of a and b, and set scale to // include the necessary exponent adjustment. if (aAbs < implicitBit) scale +%= normalize(f32, &aSignificand); - if (bAbs < implicitBit) scale +%= normalize(f32, &bSignificand); + if (bAbs < implicitBit) scale -%= normalize(f32, &bSignificand); } // Or in the implicit significand bit. (If we fell through from the @@ -85,11 +89,7 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { // [1, 2.0) and get a Q32 approximate reciprocal using a small minimax // polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This // is accurate to about 3.5 binary digits. - const q31b = switch (f32) { - f32 => bSignificand << 8, - f64 => bSignificand >> 21, - else => @compileError("Type not implemented."), - }; + const q31b = bSignificand << 8; var reciprocal = u32(0x7504f333) -% q31b; // Now refine the reciprocal estimate using a Newton-Raphson iteration: @@ -186,6 +186,7 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { } fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { + @setRuntimeSafety(builtin.is_test); const Z = @IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); const implicitBit = Z(1) << significandBits;