ludic/examples/library/bignum.ludic
Orkuncakilkaya bd6b12d2ea
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 19s
ci / build-and-test (push) Successful in 1m28s
commit-lint / conventional-commits (push) Successful in 5s
docs / build-and-deploy (push) Successful in 22s
feat(types): BigInt + Decimal exact economy numbers (#52)
Types phase 2 — the "money problem". A splice-on-demand bignum engine
(runtime/native/bignum.ludic, self-contained, only intrinsics) exposed as
two namespaces:

- BigInt.* — arbitrary-precision integer (sign-magnitude, base-1e9 limbs):
  from/parse, add/sub/mul/pow, div/mod (by int), cmp/eq/is_zero, to_int, str.
  For idle counters and exact huge currencies that overflow a 32/64-bit int.
- Decimal.* — exact base-10 fixed point (BigInt mantissa + decimal scale):
  from/parse, exact add/sub/mul, cmp/eq, scale/rescale (truncate), str.
  So 0.10 + 0.20 is exactly 0.30 — no binary rounding.

Both exact => deterministic; no f32/f64. Wired: parser splice trigger
(g_uses_bignum), emit_call dispatch, reseeded seed, a self-asserting example
(examples/library/bignum.ludic + feat_case), and per-symbol docs + inventory.
All suites green incl. golden renders byte-identical and the bootstrap fixpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-31 18:45:14 +03:00

30 lines
1.8 KiB
Text

# bignum.ludic — BigInt.* (arbitrary-precision integers) and Decimal.* (exact
# base-10 money). Each assertion that holds prints its number, so a full run
# prints:
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# Both types are exact, so they are deterministic (see runtime/native/bignum.ludic).
program BigNum {
entry {
# --- BigInt: exact integers with no upper bound ---
let a = BigInt.parse("123456789012345678901234567890")
let b = BigInt.from(1000000)
if BigInt.str(BigInt.mul(a, b)) == "123456789012345678901234567890000000" { print(1) }
if BigInt.str(BigInt.pow(BigInt.from(2), 100)) == "1267650600228229401496703205376" { print(2) }
if BigInt.str(BigInt.add(a, a)) == "246913578024691357802469135780" { print(3) }
if BigInt.str(BigInt.sub(BigInt.from(5), BigInt.from(12))) == "-7" { print(4) }
if BigInt.cmp(a, b) == 1 { print(5) }
if BigInt.eq(BigInt.from(42), BigInt.parse("42")) { print(6) }
if BigInt.str(BigInt.div(BigInt.parse("1000000000000000000"), 7)) == "142857142857142857" { print(7) }
if BigInt.mod(BigInt.from(17), 5) == 2 { print(8) }
if BigInt.is_zero(BigInt.sub(a, a)) { print(9) }
if BigInt.to_int(BigInt.from(2024)) == 2024 { print(10) }
# --- Decimal: money that adds up exactly (binary floats can't) ---
if Decimal.str(Decimal.add(Decimal.parse("0.10"), Decimal.parse("0.20"))) == "0.30" { print(11) }
if Decimal.str(Decimal.mul(Decimal.parse("19.99"), Decimal.from(3))) == "59.97" { print(12) }
if Decimal.eq(Decimal.parse("1.5"), Decimal.parse("1.50")) { print(13) }
if Decimal.str(Decimal.rescale(Decimal.parse("3.14159"), 2)) == "3.14" { print(14) }
if Decimal.str(Decimal.sub(Decimal.parse("100.00"), Decimal.parse("0.01"))) == "99.99" { print(15) }
if Decimal.cmp(Decimal.parse("2.5"), Decimal.parse("2.49")) == 1 { print(16) }
}
}