Commit c24a49a1a7

vegecode <39607947+vegecode@users.noreply.github.com>
2019-04-05 17:04:46
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
1 parent aecbd18
Changed files (1)
std
special
compiler_rt
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) {
-                return @bitCast(f32, aAbs | quotientSign);
-            } else {
-                // infinity * zero = NaN
+            // infinity / infinity = NaN
+            if (bAbs == infRep) {
                 return @bitCast(f32, qnanRep);
             }
+            // infinity / anything else = +/- infinity
+            else {
+                return @bitCast(f32, aAbs | quotientSign);
+            }
         }
 
-        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;