^long is a 64-bit long: fast-path-with-fallback ops + logical unsigned shift
Completes the JVM long-compatibility gap so clojure.test.check (and the property-based suites built on it, e.g. data.codec) run on jolt. A ^long is 64-bit but a Chez fixnum is only 61-bit, so the backend's fast fx comparison / quot / min / max / inc / dec ops raised on a full-width long (one from the PRNG or wrapping arithmetic). They now go through the jolt-l* macros (host/chez/seq.ss): the fx fast path when the operands ARE fixnums, the generic op otherwise — so e.g. ((fn [^long a ^long b] (< a b)) Long/MAX 1) is false, not an error. Arithmetic +/-/* keep the raw fx ops (under *unchecked-math* they're already the wrapping unchecked-*). Also fixes unsigned-bit-shift-right: it was an arithmetic (sign-propagating) shift, now a logical shift over the 64-bit two's-complement window, so (unsigned-bit-shift-right -1 1) is 2^63-1 like the JVM. Result: test.check 1.1.3 loads and runs (generators, quick-check, shrinking); data.codec's base64 property suite passes (12/12 defspecs; the 2 deftests check clojure.lang.IFn$OLLOL, a JVM primitive-fn interface, N/A). Both added to docs/libraries.md + the site. re-mint (backend/seed). make test green (+3 corpus rows, 0 new divergences, numeric gate updated to the jolt-l* ops), shakesmoke byte-identical.
This commit is contained in:
parent
a028cab04f
commit
3340635714
7 changed files with 62 additions and 20 deletions
|
|
@ -94,13 +94,18 @@
|
|||
(def ^:private dbl-ops
|
||||
{"+" "fl+" "-" "fl-" "*" "fl*" "/" "fl/" "min" "flmin" "max" "flmax"
|
||||
"<" "fl<?" ">" "fl>?" "<=" "fl<=?" ">=" "fl>=?" "=" "fl=?" "==" "fl=?"})
|
||||
;; A ^long is 64-bit; a Chez fixnum is only 61-bit. Arithmetic +/-/* keep the raw
|
||||
;; fx ops (the fast-arith path; under *unchecked-math* they're already rewritten to
|
||||
;; the wrapping unchecked-*). The comparisons / min/max / quot/rem/mod use the
|
||||
;; jolt-l* fast-path-with-fallback macros (host/chez/seq.ss) so a full 64-bit
|
||||
;; operand falls back to the generic op instead of raising.
|
||||
(def ^:private lng-ops
|
||||
{"+" "fx+" "-" "fx-" "*" "fx*" "min" "fxmin" "max" "fxmax"
|
||||
{"+" "fx+" "-" "fx-" "*" "fx*" "min" "jolt-l-min" "max" "jolt-l-max"
|
||||
;; unchecked-* WRAP to signed 64 bits (Java long), so they can't use the raising
|
||||
;; fx ops — the backend emits the wrapping jolt-unc* helpers (host/chez/seq.ss).
|
||||
"unchecked-add" "jolt-uncadd2" "unchecked-subtract" "jolt-uncsub2" "unchecked-multiply" "jolt-uncmul2"
|
||||
"quot" "fxquotient" "rem" "fxremainder" "mod" "fxmodulo"
|
||||
"<" "fx<?" ">" "fx>?" "<=" "fx<=?" ">=" "fx>=?" "=" "fx=?" "==" "fx=?"})
|
||||
"quot" "jolt-l-quot" "rem" "jolt-l-rem" "mod" "jolt-l-mod"
|
||||
"<" "jolt-l<" ">" "jolt-l>" "<=" "jolt-l<=" ">=" "jolt-l>=" "=" "jolt-l=" "==" "jolt-l="})
|
||||
|
||||
;; BigDecimal ops. jolt.passes.numeric tags an arithmetic/comparison invoke
|
||||
;; :num-kind :bigdec when every operand is a bigdec (or an integer literal); these
|
||||
|
|
@ -487,9 +492,10 @@
|
|||
(cond
|
||||
(and (= kind :double) (= nm "inc")) (str "(fl+ " (first args) " 1.0)")
|
||||
(and (= kind :double) (= nm "dec")) (str "(fl- " (first args) " 1.0)")
|
||||
(and (= kind :long) (= nm "inc")) (str "(fx1+ " (first args) ")")
|
||||
(and (= kind :long) (= nm "dec")) (str "(fx1- " (first args) ")")
|
||||
;; unchecked-inc/dec wrap (Java long), so the raising fx1+/fx1- can't be used.
|
||||
;; inc/dec tolerate a 64-bit operand (jolt-l-inc/dec fall back past fixnum range);
|
||||
;; unchecked-inc/dec wrap (Java long). Neither can use the raising fx1+/fx1-.
|
||||
(and (= kind :long) (= nm "inc")) (str "(jolt-l-inc " (first args) ")")
|
||||
(and (= kind :long) (= nm "dec")) (str "(jolt-l-dec " (first args) ")")
|
||||
(and (= kind :long) (= nm "unchecked-inc")) (str "(jolt-uncinc " (first args) ")")
|
||||
(and (= kind :long) (= nm "unchecked-dec")) (str "(jolt-uncdec " (first args) ")")
|
||||
:else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue