BigDecimal call-position arithmetic via :bigdec type (Phase 2)
A direct (+ 1.5M 2.5M) emits a raw Chez + that rejects the bigdec record. Rather than guard every arithmetic call site (measured 2-4x on unhinted fixnum loops), let the analyzer dispatch where it can prove the type. jolt.passes.numeric seeds a :bigdec kind from the M-literal and flows it through let/loop/if like the existing :double/:long kinds; an arithmetic/comparison invoke whose operands are all bigdec (integer literals allowed) gets :num-kind :bigdec. The back end (bd-ops + emit-numeric) lowers those to the bigdec.ss engine (jbd-add/-sub/-mul/-div, jbd-lt?/…, jbd-zero?/-pos?/-neg?, jbd-quot/-rem). Zero cost on non-bigdec code: with no bigdec literals present the kind never arises, so emission is byte-identical — the re-mint leaves prelude.ss unchanged, only image.ss (the compiler) moves. Gaps (filed): a bigdec mixed with a flonum in call position, and a bigdec the analyzer types :any, still hit the raw op and throw; use value position or a literal-typed let. Re-mint (numeric/backend are seed sources). 16 JVM-certified corpus rows.
This commit is contained in:
parent
bd7b75fb5d
commit
6fcc9fa8e6
5 changed files with 240 additions and 180 deletions
|
|
@ -9,12 +9,19 @@
|
|||
;; larger scale; multiply adds scales; divide gives the exact quotient at minimal
|
||||
;; scale or throws ArithmeticException on a non-terminating expansion. Clojure
|
||||
;; contagion: a bigdec mixed with an integer stays a bigdec; a flonum operand wins
|
||||
;; (the result is a double). jbd+/jbd-/jbd*/jbd-div and the comparison helpers are
|
||||
;; the shared engine; the value-position shims (jolt-add/-sub/-mul/-div, compare)
|
||||
;; route through them when a bigdec is present, leaving the inlined native hot path
|
||||
;; untouched. Call-position `(+ 1.5M 2.5M)` reaches the raw Chez op and needs the
|
||||
;; analyzer's :bigdec type to dispatch (not yet wired); use it through reduce/apply
|
||||
;; or a let where the type is known.
|
||||
;; (the result is a double). jbd-add/-sub/-mul/-div, the jbd-lt?/…/zero? helpers,
|
||||
;; and jbd-quot/-rem are the shared engine. Two paths reach it, both leaving the
|
||||
;; inlined native hot path untouched:
|
||||
;; - value position ((reduce + bigs)/(apply * bigs)): the jolt-add/-sub/-mul/-div
|
||||
;; and compare shims dispatch here when a bigdec operand is present.
|
||||
;; - call position ((+ 1.5M 2.5M), (< a b), (zero? b)): jolt.passes.numeric tags
|
||||
;; the invoke :num-kind :bigdec when every operand is statically a bigdec (M
|
||||
;; literal or a let-bound copy, integer literals allowed), and the back end
|
||||
;; lowers it to the jbd op. Non-bigdec code is unaffected.
|
||||
;; Gaps (a runtime bigdec the analyzer can't see statically): a bigdec mixed with a
|
||||
;; flonum in call position ((+ 1.5M 2.0)) and arithmetic over a bigdec the analyzer
|
||||
;; types as :any ((+ (bigdec x) 1)) fall through to the raw op and throw; use value
|
||||
;; position or a literal-typed let.
|
||||
|
||||
(define-record-type jbigdec (fields unscaled scale) (nongenerative chez-jbigdec-v1))
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue