From f12676b880add28555804c5f343cd97ee00321d2 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Mon, 25 May 2026 16:48:14 +0900 Subject: [PATCH] test: 952 add frexpf64 runtime rows --- test/wcc/952_floats_run.c | 63 ++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/test/wcc/952_floats_run.c b/test/wcc/952_floats_run.c index 0f30eab5..7a7ba4e6 100644 --- a/test/wcc/952_floats_run.c +++ b/test/wcc/952_floats_run.c @@ -2,7 +2,7 @@ * 952_floats_run — runtime regression net for lib/math/floats fold-1 * (f64bits, f64frombits, isnan, isinf, signf64, absf64, copysignf64, * ispositivef64, isnegativef64) plus the fold-2a decompose step - * (issubnormalf64, normalizef64). The classify/sign/bits surface rides + * (issubnormalf64, normalizef64, frexpf64). The classify/sign/bits surface rides * the f64-codegen paths fixed by #96 (deref-load -> MOVSD/X0) and #97 * (compare consults PF for NaN); normalizef64 additionally rides the #102 * 16B-tuple-from-call receive (its (f64, i64) return) and the f64 multiply @@ -10,12 +10,14 @@ * 990-997 byte-id gates can't catch a reintroduction — only an * executed-and-checked runtime probe can. This file is that probe. * - * frexpf64 is intentionally absent: its Hare-exact `n == 0f64` guard - * miscompiles (a no-decimal f64 literal in a comparison never reaches XMM; - * gate-blind, both stages identical). See the hold-back note in - * lib/math/floats.ww. The normalizef64 rows below spill tuple fields to a - * let before any f64-literal comparison, since a tuple-field f64 compared - * directly against a literal (`r.0 == 0.0`) hits the same mis-load. + * frexpf64 rides two now-landed cgen fixes: the `n == 0f64` zero guard + * (#103 — a no-decimal f64 literal now reaches XMM) and its (f64, i64) + * tuple return + .0/.1 destructure (#105 — the tuple f64-word read). The + * frexpf64(0.0) row is the key regressor: it exercises both the early + * return AND the tuple receive. As with the normalizef64 rows, tuple + * fields are spilled to a let before any f64-literal comparison (a + * tuple-field f64 compared directly against a literal `r.0 == 0.0` was the + * #105 mis-load); the .1 i64 field is compared in place. * * Table-driven like 951_f64cgen_run: each row is a self-contained ww * program importing math; the C-side cstage `ww build -I lib` compiles @@ -172,6 +174,53 @@ static const struct row rows[] = { " const m: f64 = r.0;\n" " return m: i32;\n" "};\n", 42 }, + /* frexpf64 exact (mantissa, exp): 8.0 -> (0.5, 4), 1.0 -> (0.5, 1), + * 0.75 -> (0.75, 0), and the key 0.0 -> (0.0, 0) early-return row + * (rides #103 `n == 0f64` + #105 tuple receive). Tuple .0 spilled to a + * let before the f64-literal compare; .1 compared in place. */ + { "package main;\n" + "import math;\n" + "export fn main() i32 = {\n" + " const a = math.frexpf64(8.0);\n" + " const am: f64 = a.0;\n" + " if (am != 0.5) { return 1; };\n" + " if (a.1 != 4i64) { return 2; };\n" + " const b = math.frexpf64(1.0);\n" + " const bm: f64 = b.0;\n" + " if (bm != 0.5) { return 3; };\n" + " if (b.1 != 1i64) { return 4; };\n" + " const c = math.frexpf64(0.0);\n" + " const cm: f64 = c.0;\n" + " if (cm != 0.0) { return 5; };\n" + " if (c.1 != 0i64) { return 6; };\n" + " const d = math.frexpf64(0.75);\n" + " const dm: f64 = d.0;\n" + " if (dm != 0.75) { return 7; };\n" + " if (d.1 != 0i64) { return 8; };\n" + " return 0;\n" + "};\n", 0 }, + /* frexpf64 mantissa range + reconstruction: for a nonzero input the + * mantissa is in [0.5, 1) and mantissa * 2^exp reproduces n. 12.0 -> + * (0.75, 4); 0.75 * 16 (== 2^4) == 12. */ + { "package main;\n" + "import math;\n" + "export fn main() i32 = {\n" + " const r = math.frexpf64(12.0);\n" + " const m: f64 = r.0;\n" + " if (m < 0.5) { return 1; };\n" + " if (m >= 1.0) { return 2; };\n" + " if (r.1 != 4i64) { return 3; };\n" + " if (m * 16.0 != 12.0) { return 4; };\n" + " return 0;\n" + "};\n", 0 }, + /* frexpf64 value propagation: 1024.0 == 2^10 -> (0.5, 11); the i64 exp + * field cast to i32 propagates as 11. */ + { "package main;\n" + "import math;\n" + "export fn main() i32 = {\n" + " const r = math.frexpf64(1024.0);\n" + " return r.1: i32;\n" + "};\n", 11 }, { NULL, 0 } };