Numbers-style category dispatch for binary numeric ops
Arithmetic and comparisons lowered to raw Chez ops, so an operand outside Chez's tower (BigDecimal) crashed with a raw condition, and Chez contagion leaked: (* 1.0 0) gave exact 0 where the JVM gives 0.0, (* ##Inf 0) gave 0 instead of ##NaN, (/ 1 0) raised an untyped error. One seam now (host/chez/seq.ss): call position emits jolt-n* macros with the both-Chez-numbers fast path open-coded; value position folds through the same binary ops. Anything outside the tower falls to per-op slow hooks that java/bigdec.ss extends, so bigdec arithmetic works in every position (the old static-only :bigdec typing limitation is gone). JVM rules patched into the fast path: a double operand wins, an exact zero divisor throws ArithmeticException while a double zero divisor yields Inf/NaN, quot/rem/mod cover ratios and doubles, min/max return the original operand with NaN winning, a nil operand is NPE and a non-number CCE, zero-arg -// throw ArityException at runtime instead of failing expansion. Also: with-precision now binds *math-context* and bigdec results round with real RoundingMode semantics (UNNECESSARY throws; division rounds to precision instead of throwing); rationalize goes through the shortest decimal print like BigDecimal.valueOf (the identity stub is gone); ratios coerce to bigdec like Numbers.toBigDecimal; min/max int-literal operands no longer coerce to flonum in the numeric pass. Perf neutral: fib and seq benches unchanged (the fast path is two type checks the optimizer folds); hinted fl/fx paths untouched. 19 JVM-certified corpus rows; cts baseline 5614->5730 pass, 192->88 errors, 84->79 baselined namespaces.
This commit is contained in:
parent
38abc1be84
commit
e66a91750e
13 changed files with 1106 additions and 729 deletions
|
|
@ -127,10 +127,36 @@ arithmetic, `=`, and `hash` behave exactly as the JVM — but report `Long`, not
|
|||
`Byte`/`Short`/`Integer`, so `(class (byte 5))` and `(instance? Byte (byte 5))`
|
||||
diverge. This is substrate-inherent: a Chez fixnum is an immediate `identical?`
|
||||
to the plain integer (nothing to tag, and numbers carry no metadata), so the only
|
||||
faithful representation is a boxed type — which would crash raw compiled `(+ …)`
|
||||
(arithmetic emits a bare Chez `+`) or force every `+`/`-`/`*` through an
|
||||
unwrapping dispatcher, de-optimizing all arithmetic. Same shape as the accepted
|
||||
BigInt-vs-Long unification.
|
||||
faithful representation is a boxed type — which would crash the compiled
|
||||
arithmetic fast path (both operands Chez numbers → the raw Chez op) or force
|
||||
every `+`/`-`/`*` through an unwrapping dispatcher, de-optimizing all
|
||||
arithmetic. Same shape as the accepted BigInt-vs-Long unification.
|
||||
|
||||
## Number operations
|
||||
|
||||
Binary arithmetic and comparisons follow the JVM's `Numbers.ops(x, y)` category
|
||||
dispatch. Every position (call, value, higher-order) funnels a binary op through
|
||||
one seam (`host/chez/seq.ss`): operands inside Chez's tower take the native op
|
||||
with the JVM contagion rules patched in; an operand outside it (BigDecimal)
|
||||
falls to a slow hook the numeric shim extends (`host/chez/java/bigdec.ss`); a
|
||||
non-numeric operand throws `ClassCastException`. The rules the corpus pins
|
||||
(`numbers / ops dispatch`, `numbers / with-precision`, `numbers / rationalize`):
|
||||
|
||||
- A double operand wins: `(* 1.0 0)` is `0.0` (Chez's exact-zero shortcut must
|
||||
not leak), `(* ##Inf 0)` is `##NaN`, `(+ 1.5M 2.0)` is `3.5`.
|
||||
- Division: an exact zero divisor throws `ArithmeticException`; a double zero
|
||||
divisor yields `##Inf`/`##-Inf`/`##NaN`. `(/ 1M 3M)` with no bound
|
||||
`*math-context*` throws (non-terminating); under `with-precision` it rounds.
|
||||
- `quot`/`rem`/`mod` cover the full tower (ratios truncate; doubles keep double;
|
||||
`mod` takes the divisor's sign; zero divisor throws in both worlds).
|
||||
- `min`/`max` return the *original* operand (`(min 1 2.0)` is `1`, exact); a
|
||||
`##NaN` operand wins.
|
||||
- `with-precision` binds `*math-context*`; BigDecimal results round to the
|
||||
precision with the `java.math.RoundingMode` semantics (default `HALF_UP`,
|
||||
`UNNECESSARY` throws).
|
||||
- `rationalize` routes a double through its shortest decimal print
|
||||
(`BigDecimal.valueOf`), so `(rationalize 1.1)` is `11/10`, not the exact
|
||||
binary expansion.
|
||||
|
||||
## Hosting jolt on a new runtime
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue