Hint-directed fast arithmetic: fl*/fx* from ^double/^long (round 1)
A ^double/^long param hint (or a float literal) now drives Chez flonum/fixnum ops instead of generic arithmetic — JVM-style primitive hints, available in every build and at -e (not gated on direct-linking or whole-program inference). New pass jolt.passes.numeric: a local forward type-flow seeded from ^double/^long fn-param hints (analyzer attaches :nhints per arity) and float literals, propagated through let inits / arithmetic / if / do. It tags an arithmetic invoke :num-kind :double|:long when every operand is that kind (an integer literal is a wildcard, coerced to a flonum in a double op). The back end lowers a tagged node to fl+/fl-/fl*/fl//fl<?/... or fx+/fx*/fx1+/fxquotient/... (unchecked-add etc. join the fixnum path; == too). Runs last in run-passes, both branches. Soundness: :long is seeded ONLY from an explicit ^long hint, never a bare integer literal, so un-hinted integer code keeps jolt's arbitrary-precision numbers — no fixnum-overflow surprise, no corpus divergence. :double comes from ^double hints and float literals (flonum arithmetic is always flonum, matching the generic result). A ^long hint is a promise the value is a fixnum: fx+ raises on overflow, like a JVM fixed-width long. Numeric-hinted params coerce at fn entry (exact->inexact / jolt->fx), the way the JVM coerces a primitive parameter — so the body's fl*/fx* ops can rely on the type even when a caller passes an exact int (e.g. Chez's (* 0 1.0) => exact 0). Round 1 specializes hinted straight-line / fn-body arithmetic. fl-ops are ~4x generic in a tight Chez loop, but realizing that on loop-carried accumulators needs loop-var typing — round 2. Sound foundation, gated by test/chez/numeric-test.ss.
This commit is contained in:
parent
2c18fcdc61
commit
59905a71fd
9 changed files with 567 additions and 236 deletions
|
|
@ -17,6 +17,17 @@
|
|||
;; --- rt arithmetic / logic shims (named in the emitter's native-ops) ----------
|
||||
(define (jolt-inc x) (+ x 1))
|
||||
(define (jolt-dec x) (- x 1))
|
||||
;; Coerce a ^long-hinted argument to a fixnum at fn entry, the way the JVM's
|
||||
;; longCast coerces a primitive-long parameter: truncate a flonum toward zero,
|
||||
;; pass an exact integer through, error if it doesn't fit a fixnum or isn't a
|
||||
;; number. The hint is a promise the value is a fixnum-range long; the body's fx*
|
||||
;; ops rely on it. (^double params coerce with the built-in exact->inexact.)
|
||||
(define (jolt->fx x)
|
||||
(let ((n (cond ((fixnum? x) x)
|
||||
((flonum? x) (exact (truncate x)))
|
||||
((rational? x) (exact (truncate x)))
|
||||
(else (error 'jolt "^long hint: not a number" x)))))
|
||||
(if (fixnum? n) n (error 'jolt "^long hint: value out of fixnum range" x))))
|
||||
;; jolt `not`: only nil and false are falsey.
|
||||
(define (jolt-not x) (if (jolt-truthy? x) #f #t))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue