authorgravatar for chrboesch@noreply.codeberg.orgChris Boesch <chrboesch@noreply.codeberg.org> 2026-02-13 20:49:14+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-13 20:49:14+01:00
log07b08b96389a1dd60bc150a5ed72586ee57b2303
treefc9cc3fbb8ee85d14d75bada735a3e308027f919
parentfd74c5742d3c8343868516c03a6a0695280744d1

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>

2 files changed, 27 insertions(+), 3 deletions(-)

lib/compiler_rt/divtf3.zig+22-3
......@@ -222,10 +222,29 @@ inline fn div(a: f128, b: f128) f128 {
222222 // The rounded result is normal; return it.
223223 return @bitCast(absResult | quotientSign);
224224 }
225 // Result is denormal with exponent 0
226 return @bitCast(absResult | quotientSign);
227 } else {
228 // For denormals with writtenExponent < 0,
229 // the implicit bit must be shifted into the mantissa (IEEE 754)
230 const shiftAmount = @as(u7, @intCast(1 - writtenExponent));
231
232 // Check for underflow
233 if (shiftAmount > significandBits) {
234 return @bitCast(quotientSign);
235 }
236
237 // Round the quotient before pushing
238 const shouldRound = (residual << 1) > bSignificand;
239 const roundedQuotient = quotient +% @as(u113, @intFromBool(shouldRound));
240
241 // Move to the denormal range and apply the mask
242 const denormQuotient = roundedQuotient >> shiftAmount;
243 const absResult = denormQuotient & significandMask;
244
245 // Add sign to denormal mantissa and return
246 return @bitCast(absResult | quotientSign);
225247 }
226 // Flush denormals to zero. In the future, it would be nice to add
227 // code to round them correctly.
228 return @bitCast(quotientSign);
229248 } else {
230249 const round = @intFromBool((residual << 1) >= bSignificand);
231250 // Clear the implicit bit
lib/compiler_rt/divtf3_test.zig+5
......@@ -46,4 +46,9 @@ test "divtf3" {
4646 try test__divtf3(0x1.2345f6b77b7a8953365433abcdefp+234, 0x1.edcba987d6bb3aa467754354321fp-4055, 0x50bf2e02f0798d36, 0x5e6fcb6b60044078);
4747 try test__divtf3(6.72420628622418701252535563464350521E-4932, 2.0, 0x0001000000000000, 0);
4848 try test__divtf3(1.0, 0x1.ffffffffffffffffffffffffffffp-1, 0x3FFF000000000000, 1);
49
50 try test__divtf3(std.math.floatMin(f128), 2.0, 0x0000800000000000, 0x0000000000000000);
51 try test__divtf3(std.math.floatMin(f128), 4.0, 0x0000400000000000, 0x0000000000000000);
52 try test__divtf3(1.0, 0x1.0000000000000000000000000001p16382, 0x0000ffffffffffff, 0xfffffffffffffffe);
53 try test__divtf3(1.2, std.math.floatMax(f128), 0x00004ccccccccccc, 0xcccccccccccccccd);
4954}