compiler_rt: Implemented missing handling of denormal numbers when dividing f128 (#30198)

Replaces the "flush denormals to zero" placeholder in divtf3.zig with IEEE 754 denormal support including rounding.

fixes #30179

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30198
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
Co-authored-by: Chris Boesch <chrboesch@noreply.codeberg.org>
Co-committed-by: Chris Boesch <chrboesch@noreply.codeberg.org>
This commit is contained in:
Chris Boesch
2026-02-13 20:49:14 +01:00
committed by Andrew Kelley
parent fd74c5742d
commit 07b08b9638
2 changed files with 27 additions and 3 deletions
+22 -3
View File
@@ -222,10 +222,29 @@ inline fn div(a: f128, b: f128) f128 {
// The rounded result is normal; return it.
return @bitCast(absResult | quotientSign);
}
// Result is denormal with exponent 0
return @bitCast(absResult | quotientSign);
} else {
// For denormals with writtenExponent < 0,
// the implicit bit must be shifted into the mantissa (IEEE 754)
const shiftAmount = @as(u7, @intCast(1 - writtenExponent));
// Check for underflow
if (shiftAmount > significandBits) {
return @bitCast(quotientSign);
}
// Round the quotient before pushing
const shouldRound = (residual << 1) > bSignificand;
const roundedQuotient = quotient +% @as(u113, @intFromBool(shouldRound));
// Move to the denormal range and apply the mask
const denormQuotient = roundedQuotient >> shiftAmount;
const absResult = denormQuotient & significandMask;
// Add sign to denormal mantissa and return
return @bitCast(absResult | quotientSign);
}
// Flush denormals to zero. In the future, it would be nice to add
// code to round them correctly.
return @bitCast(quotientSign);
} else {
const round = @intFromBool((residual << 1) >= bSignificand);
// Clear the implicit bit
+5
View File
@@ -46,4 +46,9 @@ test "divtf3" {
try test__divtf3(0x1.2345f6b77b7a8953365433abcdefp+234, 0x1.edcba987d6bb3aa467754354321fp-4055, 0x50bf2e02f0798d36, 0x5e6fcb6b60044078);
try test__divtf3(6.72420628622418701252535563464350521E-4932, 2.0, 0x0001000000000000, 0);
try test__divtf3(1.0, 0x1.ffffffffffffffffffffffffffffp-1, 0x3FFF000000000000, 1);
try test__divtf3(std.math.floatMin(f128), 2.0, 0x0000800000000000, 0x0000000000000000);
try test__divtf3(std.math.floatMin(f128), 4.0, 0x0000400000000000, 0x0000000000000000);
try test__divtf3(1.0, 0x1.0000000000000000000000000001p16382, 0x0000ffffffffffff, 0xfffffffffffffffe);
try test__divtf3(1.2, std.math.floatMax(f128), 0x00004ccccccccccc, 0xcccccccccccccccd);
}