test: 952 add frexpf64 runtime rows

This commit is contained in:
2026-05-25 16:48:14 +09:00
parent 9311e6ca4e
commit f12676b880

View File

@@ -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 }
};