Files
rose-ash/lib/haskell/tests/numerics.sx
giles 1b7bd86b43
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m8s
haskell: Phase 10 — Float show with .0 suffix and scientific form (+4 tests, 22/22)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 07:55:54 +00:00

142 lines
3.9 KiB
Plaintext

;; numerics.sx — Phase 10 numeric tower verification.
;;
;; Practical integer-precision limit in Haskell-on-SX:
;; • Raw SX `(* a b)` stays exact up to ±2^62 (≈ 4.6e18, OCaml int63).
;; • BUT the Haskell tokenizer/parser parses an integer literal as a float
;; once it exceeds 2^53 (≈ 9.007e15). Once any operand is a float, the
;; binop result is a float (and decimal-precision is lost past 2^53).
;; • Therefore: programs that stay below ~9e15 are exact; larger literals
;; or accumulated products silently become floats. `factorial 18` is the
;; last factorial that stays exact (6.4e15); `factorial 19` already floats.
;;
;; In Haskell terms, `Int` and `Integer` both currently map to SX number, so
;; we don't yet support arbitrary-precision Integer. Documented; unbounded
;; Integer is out of scope for Phase 10 — see Phase 11+ if it becomes needed.
(define
hk-as-list
(fn
(xs)
(cond
((and (list? xs) (= (first xs) "[]")) (list))
((and (list? xs) (= (first xs) ":"))
(cons (nth xs 1) (hk-as-list (nth xs 2))))
(:else xs))))
(hk-test
"factorial 10 = 3628800 (small, exact)"
(hk-deep-force
(hk-run "fact 0 = 1\nfact n = n * fact (n - 1)\nmain = fact 10"))
3628800)
(hk-test
"factorial 15 = 1307674368000 (mid-range, exact)"
(hk-deep-force
(hk-run "fact 0 = 1\nfact n = n * fact (n - 1)\nmain = fact 15"))
1307674368000)
(hk-test
"factorial 18 = 6402373705728000 (last exact factorial)"
(hk-deep-force
(hk-run "fact 0 = 1\nfact n = n * fact (n - 1)\nmain = fact 18"))
6402373705728000)
(hk-test
"1000000 * 1000000 = 10^12 (exact)"
(hk-deep-force (hk-run "main = 1000000 * 1000000"))
1000000000000)
(hk-test
"1000000000 * 1000000000 = 10^18 (exact, at boundary)"
(hk-deep-force (hk-run "main = 1000000000 * 1000000000"))
1e+18)
(hk-test
"2^62 boundary: pow accumulates exactly"
(hk-deep-force
(hk-run "pow b 0 = 1\npow b n = b * pow b (n - 1)\nmain = pow 2 62"))
4.6116860184273879e+18)
(hk-test
"show factorial 12 = 479001600 (whole, fits in 32-bit)"
(hk-deep-force
(hk-run "fact 0 = 1\nfact n = n * fact (n - 1)\nmain = show (fact 12)"))
"479001600")
(hk-test
"negate large positive — preserves magnitude"
(hk-deep-force (hk-run "main = negate 1000000000000000000"))
-1e+18)
(hk-test
"abs negative large — preserves magnitude"
(hk-deep-force (hk-run "main = abs (negate 1000000000000000000)"))
1e+18)
(hk-test
"div on large ints"
(hk-deep-force (hk-run "main = div 1000000000000000000 1000000000"))
1000000000)
(hk-test
"fromIntegral 42 = 42 (identity in our runtime)"
(hk-deep-force (hk-run "main = fromIntegral 42"))
42)
(hk-test
"fromIntegral preserves negative"
(hk-deep-force (hk-run "main = fromIntegral (negate 7)"))
-7)
(hk-test
"fromIntegral round-trips through arithmetic"
(hk-deep-force (hk-run "main = fromIntegral 5 + fromIntegral 3"))
8)
(hk-test
"fromIntegral in a program (mixing with map)"
(hk-as-list (hk-deep-force (hk-run "main = map fromIntegral [1,2,3]")))
(list 1 2 3))
(hk-test
"toInteger 100 = 100 (identity)"
(hk-deep-force (hk-run "main = toInteger 100"))
100)
(hk-test
"fromInteger 7 = 7 (identity)"
(hk-deep-force (hk-run "main = fromInteger 7"))
7)
(hk-test
"toInteger / fromInteger round-trip"
(hk-deep-force (hk-run "main = fromInteger (toInteger 42)"))
42)
(hk-test
"toInteger preserves negative"
(hk-deep-force (hk-run "main = toInteger (negate 13)"))
-13)
(hk-test
"show 3.14 = 3.14"
(hk-deep-force (hk-run "main = show 3.14"))
"3.14")
(hk-test
"show 1.0e10 — whole-valued float renders as decimal (int/float ambiguity)"
(hk-deep-force (hk-run "main = show 1.0e10"))
"10000000000")
(hk-test
"show 0.001 uses scientific form (sub-0.1)"
(hk-deep-force (hk-run "main = show 0.001"))
"1.0e-3")
(hk-test
"show negative float"
(hk-deep-force (hk-run "main = show (negate 3.14)"))
"-3.14")
{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}