lib/strconv: f64tos Ryū shortest float→string (#106 fold-5a)

Graduate f64tos from the lossy fixed-point placeholder to Ryū shortest-
round-trippable (ftos.ha:432 + ftos_ryu.ha). f64tos(n:f64) str, G-format
(void/NONE) — the faithful documented subset (full parametric fftosf is
dead code for G/void/NONE → deferred #64). Ryū core decomposed: struct-
RETURN + scalar params (Hare's r128 idiom; avoids tuple-ABI #163-166).
f64 powers tables [15][2]/[13][2]u64 (2D #156). Zero float literals.
Both E+F encode paths reachable+tested, no dead code.

Graduation (lib-note "don't keep both"): old lossy f64tos deleted; fmt
fprintf_f64_huge "huge"→"9.5e18" (improvement). 5 value-faithful filed-
bug dodges (byte-id, documented): #167/#169/#170/#43/#144. Test 908.
Make test 186/186 incl 990-997 byte-id + combined_ww_fresh.

Drew's strconv 5-fold plan — primary completion (f64tos). f32tos coda
#67 (behind #143); parametric ftosf #64.
This commit is contained in:
2026-05-27 15:39:03 +09:00
parent 81796cd533
commit 0e66073e32
11 changed files with 3219 additions and 762 deletions

View File

@@ -563,7 +563,8 @@ fn closedstream(s: *io.stream) void = {
match (c) { case void => {}; case io.closed => fail(); };
};
// Pins the strconv.f64tos "huge" fallback through the fmt dispatch.
// Pins a large magnitude through the fmt dispatch — post-Ryū-graduation
// (fold-5) this is scientific notation, not the old lossy "huge" fallback.
// Catches any regression where mods accidentally pre-truncate the view.
@test fn fprintf_f64_huge() void = {
let mem: memio.state;
@@ -571,10 +572,10 @@ fn closedstream(s: *io.stream) void = {
memio.dynamic(&mem, &s);
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", 9.5e18);
match (r) {
case let n: i32 => { if (n != 4) { fail(); }; };
case let n: i32 => { if (n != 6) { fail(); }; }; // "9.5e18"
case io.closed => fail();
};
if (!streq(memio.string(&mem), "huge")) { fail(); };
if (!streq(memio.string(&mem), "9.5e18")) { fail(); };
let c: (void | io.closed) = io.close(&s);
match (c) { case void => {}; case io.closed => fail(); };
};