mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
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:
committed by
Andrew Kelley
parent
fd74c5742d
commit
07b08b9638
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user