Skip to content

Commit

Permalink
Unify numeric semantics around longs, with throw on overflow. Allow n…
Browse files Browse the repository at this point in the history
…umeric literals to be primitive initializers. Canonicalize boxing of integers, if it fits in int, is Integer, else Long, thus primitive coercions can't be used to get particular boxed types, use Long/valueOf etc. Ask for BigIntegers if you want arbitrary precision, new literal number format - append 'N' for BigInteger. BigIntegers do not reduce automatically, are contagious. New particular names for unchecked ops - unchecked-xxx-int or unchecked-xxx-long. You should need far fewer hints for primitive perf, and avoid int casts and any casting of numeric literals, see:

http://gist.github.com/440102
  • Loading branch information
richhickey committed Jun 16, 2010
1 parent 8fbafa9 commit 6ab3e4c
Show file tree
Hide file tree
Showing 9 changed files with 1,075 additions and 900 deletions.
140 changes: 98 additions & 42 deletions src/clj/clojure/core.clj
Expand Up @@ -970,61 +970,117 @@
:added "1.0"}
[x] (. clojure.lang.Numbers (dec x)))

(defn unchecked-inc
"Returns a number one greater than x, an int or long.
(defn unchecked-inc-int

This comment has been minimized.

Copy link
@swannodette

swannodette Jun 16, 2010

It looks like amap and areduce still need to be updated to use this.

"Returns a number one greater than x, an int.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_inc ~x)))
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_int_inc ~x)))
:added "1.0"}
[x] (. clojure.lang.Numbers (unchecked_inc x)))
[x] (. clojure.lang.Numbers (unchecked_int_inc x)))

(defn unchecked-dec
"Returns a number one less than x, an int or long.
(defn unchecked-inc-long
"Returns a number one greater than x, a long.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_dec ~x)))
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_long_inc ~x)))
:added "1.0"}
[x] (. clojure.lang.Numbers (unchecked_dec x)))
[x] (. clojure.lang.Numbers (unchecked_long_inc x)))

(defn unchecked-negate
"Returns the negation of x, an int or long.
(defn unchecked-dec-int
"Returns a number one less than x, an int.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_negate ~x)))
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_int_dec ~x)))
:added "1.0"}
[x] (. clojure.lang.Numbers (unchecked_negate x)))
[x] (. clojure.lang.Numbers (unchecked_int_dec x)))

(defn unchecked-add
"Returns the sum of x and y, both int or long.
(defn unchecked-dec-long
"Returns a number one less than x, a long.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_add ~x ~y)))
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_long_dec ~x)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_add x y)))
[x] (. clojure.lang.Numbers (unchecked_long_dec x)))

(defn unchecked-subtract
"Returns the difference of x and y, both int or long.
(defn unchecked-negate-int
"Returns the negation of x, an int.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_subtract ~x ~y)))
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_int_negate ~x)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_subtract x y)))
[x] (. clojure.lang.Numbers (unchecked_int_negate x)))

(defn unchecked-multiply
"Returns the product of x and y, both int or long.
(defn unchecked-negate-long
"Returns the negation of x, a long.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_multiply ~x ~y)))
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_long_negate ~x)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_multiply x y)))
[x] (. clojure.lang.Numbers (unchecked_long_negate x)))

(defn unchecked-divide
"Returns the division of x by y, both int or long.
(defn unchecked-add-int
"Returns the sum of x and y, both int.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_add ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_int_add x y)))

(defn unchecked-add-long
"Returns the sum of x and y, both long.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_add ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_long_add x y)))

(defn unchecked-subtract-int
"Returns the difference of x and y, both int.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_subtract ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_int_subtract x y)))

(defn unchecked-subtract-long
"Returns the difference of x and y, both long.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_subtract ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_long_subtract x y)))

(defn unchecked-multiply-int
"Returns the product of x and y, both int.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_multiply ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_int_multiply x y)))

(defn unchecked-multiply-long
"Returns the product of x and y, both long.
Note - uses a primitive operator subject to overflow."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_multiply ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_long_multiply x y)))

(defn unchecked-divide-int
"Returns the division of x by y, both int.
Note - uses a primitive operator subject to truncation."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_divide ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_int_divide x y)))

(defn unchecked-divide-long
"Returns the division of x by y, both long.
Note - uses a primitive operator subject to truncation."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_divide ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_long_divide x y)))

(defn unchecked-remainder-int
"Returns the remainder of division of x by y, both int.
Note - uses a primitive operator subject to truncation."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_divide ~x ~y)))
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_remainder ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_divide x y)))
[x y] (. clojure.lang.Numbers (unchecked_int_remainder x y)))

(defn unchecked-remainder
"Returns the remainder of division of x by y, both int or long.
(defn unchecked-remainder-long
"Returns the remainder of division of x by y, both long.
Note - uses a primitive operator subject to truncation."
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_remainder ~x ~y)))
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_remainder ~x ~y)))
:added "1.0"}
[x y] (. clojure.lang.Numbers (unchecked_remainder x y)))
[x y] (. clojure.lang.Numbers (unchecked_long_remainder x y)))

(defn pos?
"Returns true if num is greater than zero, else false"
Expand Down Expand Up @@ -2183,11 +2239,11 @@
[bindings & body]
(let [i (first bindings)
n (second bindings)]
`(let [n# (int ~n)]
`(let [n# ~n]
(loop [~i (int 0)]
(when (< ~i n#)
~@body
(recur (inc ~i)))))))
(recur (unchecked-inc-long ~i)))))))

(defn map
"Returns a lazy sequence consisting of the result of applying f to the
Expand Down Expand Up @@ -2553,17 +2609,17 @@
{:tag 'clojure.lang.IChunk})
count- (gensym "count_")
i- (gensym "i_")
recform `(recur (next ~seq-) nil (int 0) (int 0))
recform `(recur (next ~seq-) nil 0 0)
steppair (step recform (nnext exprs))
needrec (steppair 0)
subform (steppair 1)
recform-chunk
`(recur ~seq- ~chunk- ~count- (unchecked-inc ~i-))
`(recur ~seq- ~chunk- ~count- (unchecked-inc-long ~i-))
steppair-chunk (step recform-chunk (nnext exprs))
subform-chunk (steppair-chunk 1)]
[true
`(loop [~seq- (seq ~v), ~chunk- nil,
~count- (int 0), ~i- (int 0)]
~count- 0, ~i- 0]
(if (< ~i- ~count-)
(let [~k (.nth ~chunk- ~i-)]
~subform-chunk
Expand Down Expand Up @@ -2660,11 +2716,11 @@
(= 2 (count bindings)) "exactly 2 forms in binding vector")
(let [i (first bindings)
n (second bindings)]
`(let [n# (int ~n)]
(loop [~i (int 0)]
`(let [n# ~n]
(loop [~i 0]
(when (< ~i n#)
~@body
(recur (unchecked-inc ~i)))))))
(recur (unchecked-inc-long ~i)))))))

#_(defn into
"Returns a new coll consisting of to-coll with all of the items of
Expand Down Expand Up @@ -3849,12 +3905,12 @@
(= k :when) `(if ~v
~(do-cmod etc)
(recur
(unchecked-inc ~gi)))
(unchecked-inc-long ~gi)))
(keyword? k)
(err "Invalid 'for' keyword " k)
:else
`(do (chunk-append ~gb ~body-expr)
(recur (unchecked-inc ~gi)))))]
(recur (unchecked-inc-long ~gi)))))]
`(fn ~giter [~gxs]
(lazy-seq
(loop [~gxs ~gxs]
Expand Down
6 changes: 3 additions & 3 deletions src/clj/clojure/genclass.clj
Expand Up @@ -299,22 +299,22 @@
(arg-types (count ptypes)))))
;expecting [[super-ctor-args] state] returned
(. gen dup)
(. gen push 0)
(. gen push (int 0))
(. gen (invokeStatic rt-type nth-method))
(. gen storeLocal local)

(. gen (loadThis))
(. gen dupX1)
(dotimes [i (count super-pclasses)]
(. gen loadLocal local)
(. gen push i)
(. gen push (int i))
(. gen (invokeStatic rt-type nth-method))
(. clojure.lang.Compiler$HostExpr (emitUnboxArg nil gen (nth super-pclasses i))))
(. gen (invokeConstructor super-type super-m))

(if state
(do
(. gen push 1)
(. gen push (int 1))
(. gen (invokeStatic rt-type nth-method))
(. gen (putField ctype state-name obj-type)))
(. gen pop))
Expand Down
6 changes: 3 additions & 3 deletions src/clj/clojure/gvec.clj
Expand Up @@ -62,11 +62,11 @@
(if (< aidx (count vec))
(let [node (.arrayFor vec aidx)
result (loop [result result
node-idx (bit-and (int 0x1f) aidx)]
node-idx (bit-and 0x1f aidx)]
(if (< node-idx (.alength am node))
(recur (f result (.aget am node node-idx)) (inc node-idx))
result))]
(recur result (bit-and (int 0xffe0) (+ aidx (int 32)))))
(recur result (bit-and 0xffe0 (+ aidx 32))))
result)))

clojure.lang.ISeq
Expand Down Expand Up @@ -141,7 +141,7 @@
(if (= i cnt)
hash
(let [val (.nth this i)]
(recur (unchecked-add (unchecked-multiply (int 31) hash)
(recur (unchecked-add-int (unchecked-multiply-int 31 hash)
(clojure.lang.Util/hash val))
(inc i))))))

Expand Down

0 comments on commit 6ab3e4c

Please sign in to comment.