From 5d7f931cf1ab0ba37ab63b8d208de3423b769dbd Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 25 Apr 2026 14:42:32 +0000 Subject: [PATCH] js-on-sx: high-precision number-to-string via round-trip + digit extraction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - js-big-int-str-loop: extract decimal digits from integer-valued float - js-find-decimal-k: find min decimal places k where round(n*10^k)/10^k == n - js-format-decimal-digits: insert decimal point into digit string at position (len-k) - js-number-to-string: if 6-sig-fig round-trip fails AND n in [1e-6, 1e21), use digit extraction for full precision (up to 17 sig figs) - String(1.0000001)="1.0000001", String(1/3)="0.3333333333333333" - String test262 subset: 58→62/100 Co-Authored-By: Claude Sonnet 4.6 --- lib/js/runtime.sx | 51 ++++++++++++++++++++++++++++++++-- lib/js/test262-scoreboard.json | 18 ++++++------ lib/js/test262-scoreboard.md | 12 ++++---- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index 5ae3611c..4384e025 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -1194,6 +1194,53 @@ (+ i 1) (str acc (js-to-string (nth parts i))))))) +(define + js-big-int-str-loop + (fn + (n acc) + (if + (< n 1) + (if (= acc "") "0" acc) + (let + ((d (floor (- n (* 10 (floor (/ n 10))))))) + (js-big-int-str-loop + (floor (/ n 10)) + (str (js-string-slice "0123456789" d (+ d 1)) acc)))))) + +(define + js-find-decimal-k + (fn + (n k) + (if + (> k 17) + 17 + (let + ((big-int (round (* n (js-pow-int 10 k))))) + (if + (= (/ big-int (js-pow-int 10 k)) n) + k + (js-find-decimal-k n (+ k 1))))))) + +(define + js-format-decimal-digits + (fn + (digits k) + (if + (= k 0) + digits + (let + ((dlen (len digits))) + (if + (> dlen k) + (str + (js-string-slice digits 0 (- dlen k)) + "." + (js-string-slice digits (- dlen k) dlen)) + (if + (= dlen k) + (str "0." digits) + (str "0." (js-string-repeat "0" (- k dlen)) digits))))))) + (define js-expand-sci-notation (fn @@ -1234,9 +1281,9 @@ (let ((s0 (js-normalize-num-str (str pos-n)))) (let - ((ei (js-string-index-of s0 "e" 0))) + ((n2 (js-to-number s0))) (let - ((precise (if (< ei 0) s0 (let ((exp-n (js-to-number (js-string-slice s0 (+ ei 1) (len s0))))) (if (and (>= exp-n -6) (<= exp-n 20)) (js-expand-sci-notation (js-string-slice s0 0 ei) exp-n) (if (>= exp-n 0) (str (js-string-slice s0 0 (+ ei 1)) "+" (str exp-n)) s0)))))) + ((precise (if (= n2 pos-n) (let ((ei (js-string-index-of s0 "e" 0))) (if (< ei 0) s0 (let ((exp-n (js-to-number (js-string-slice s0 (+ ei 1) (len s0))))) (if (and (>= exp-n -6) (<= exp-n 20)) (js-expand-sci-notation (js-string-slice s0 0 ei) exp-n) (if (>= exp-n 0) (str (js-string-slice s0 0 (+ ei 1)) "+" (str exp-n)) s0))))) (if (and (>= pos-n 1e-06) (< pos-n 1e+21)) (let ((k (js-find-decimal-k pos-n 0))) (let ((big-int (round (* pos-n (js-pow-int 10 k))))) (js-format-decimal-digits (js-big-int-str-loop big-int "") k))) (let ((ei (js-string-index-of s0 "e" 0))) (if (< ei 0) s0 (let ((exp-n (js-to-number (js-string-slice s0 (+ ei 1) (len s0))))) (if (>= exp-n 0) (str (js-string-slice s0 0 (+ ei 1)) "+" (str exp-n)) s0)))))))) (if (< n 0) (str "-" precise) precise))))))))) (define diff --git a/lib/js/test262-scoreboard.json b/lib/js/test262-scoreboard.json index 41c21415..8f312ed9 100644 --- a/lib/js/test262-scoreboard.json +++ b/lib/js/test262-scoreboard.json @@ -1,26 +1,26 @@ { "totals": { - "pass": 58, - "fail": 33, + "pass": 62, + "fail": 29, "skip": 1130, "timeout": 9, "total": 1230, "runnable": 100, - "pass_rate": 58.0 + "pass_rate": 62.0 }, "categories": [ { "category": "built-ins/String", "total": 1223, - "pass": 58, - "fail": 33, + "pass": 62, + "fail": 29, "skip": 1123, "timeout": 9, - "pass_rate": 58.0, + "pass_rate": 62.0, "top_failures": [ [ "Test262Error (assertion failed)", - 28 + 24 ], [ "Timeout", @@ -54,7 +54,7 @@ "top_failure_modes": [ [ "Test262Error (assertion failed)", - 28 + 24 ], [ "Timeout", @@ -82,6 +82,6 @@ ] ], "pinned_commit": "d5e73fc8d2c663554fb72e2380a8c2bc1a318a33", - "elapsed_seconds": 37.7, + "elapsed_seconds": 40.5, "workers": 7 } \ No newline at end of file diff --git a/lib/js/test262-scoreboard.md b/lib/js/test262-scoreboard.md index c4a05764..ff653b9d 100644 --- a/lib/js/test262-scoreboard.md +++ b/lib/js/test262-scoreboard.md @@ -1,13 +1,13 @@ # test262 scoreboard Pinned commit: `d5e73fc8d2c663554fb72e2380a8c2bc1a318a33` -Wall time: 37.7s +Wall time: 40.5s -**Total:** 58/100 runnable passed (58.0%). Raw: pass=58 fail=33 skip=1130 timeout=9 total=1230. +**Total:** 62/100 runnable passed (62.0%). Raw: pass=62 fail=29 skip=1130 timeout=9 total=1230. ## Top failure modes -- **28x** Test262Error (assertion failed) +- **24x** Test262Error (assertion failed) - **9x** Timeout - **1x** Unhandled: Not callable: \\\ - **1x** ReferenceError (undefined symbol) @@ -19,13 +19,13 @@ Wall time: 37.7s | Category | Pass | Fail | Skip | Timeout | Total | Pass % | |---|---:|---:|---:|---:|---:|---:| -| built-ins/String | 58 | 33 | 1123 | 9 | 1223 | 58.0% | +| built-ins/String | 62 | 29 | 1123 | 9 | 1223 | 62.0% | ## Per-category top failures (min 10 runnable, worst first) -### built-ins/String (58/100 — 58.0%) +### built-ins/String (62/100 — 62.0%) -- **28x** Test262Error (assertion failed) +- **24x** Test262Error (assertion failed) - **9x** Timeout - **1x** Unhandled: Not callable: \\\ - **1x** ReferenceError (undefined symbol)