summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Taggart <alex.taggart@expojure.com>2011-04-29 11:04:34 -0700
committerStuart Halloway <stu@thinkrelevance.com>2011-05-06 09:45:52 -0400
commit601d9521f88f8fb00e670d2823857cdcb2b2e1c3 (patch)
treef41f3d88d723c4ff5bcaa949d10468bd6b72a34c
parente89e95fe82f430cc5fe9ea1c3f1974434a9ccda3 (diff)
Remove bit-ops' support for boxed numbers.
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
-rw-r--r--src/clj/clojure/core.clj28
-rw-r--r--src/jvm/clojure/lang/Numbers.java374
-rw-r--r--test/clojure/test_clojure/numbers.clj22
3 files changed, 145 insertions, 279 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 2d982475..3f122846 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1268,11 +1268,25 @@
:added "1.0"}
[x n] (. clojure.lang.Numbers shiftRight x n))
+(defn integer?
+ "Returns true if n is an integer"
+ {:added "1.0"
+ :static true}
+ [n]
+ (or (instance? Integer n)
+ (instance? Long n)
+ (instance? clojure.lang.BigInt n)
+ (instance? BigInteger n)
+ (instance? Short n)
+ (instance? Byte n)))
+
(defn even?
"Returns true if n is even, throws an exception if n is not an integer"
{:added "1.0"
:static true}
- [n] (zero? (bit-and n 1)))
+ [n] (if (integer? n)
+ (zero? (bit-and (clojure.lang.RT/uncheckedLongCast n) 1))
+ (throw (IllegalArgumentException. (str "Argument must be an integer: " n)))))
(defn odd?
"Returns true if n is odd, throws an exception if n is not an integer"
@@ -3091,18 +3105,6 @@
[x]
(instance? Number x))
-(defn integer?
- "Returns true if n is an integer"
- {:added "1.0"
- :static true}
- [n]
- (or (instance? Integer n)
- (instance? Long n)
- (instance? clojure.lang.BigInt n)
- (instance? BigInteger n)
- (instance? Short n)
- (instance? Byte n)))
-
(defn mod
"Modulus of num and div. Truncates toward negative infinity."
{:added "1.0"
diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java
index 2e71b826..a5c151b9 100644
--- a/src/jvm/clojure/lang/Numbers.java
+++ b/src/jvm/clojure/lang/Numbers.java
@@ -85,36 +85,6 @@ static abstract class OpsP implements Ops{
}
}
-static interface BitOps{
- BitOps combine(BitOps y);
-
- BitOps bitOpsWith(LongBitOps x);
-
- BitOps bitOpsWith(BigIntBitOps x);
-
- public Number not(Number x);
-
- public Number and(Number x, Number y);
-
- public Number or(Number x, Number y);
-
- public Number xor(Number x, Number y);
-
- public Number andNot(Number x, Number y);
-
- public Number clearBit(Number x, int n);
-
- public Number setBit(Number x, int n);
-
- public Number flipBit(Number x, int n);
-
- public boolean testBit(Number x, int n);
-
- public Number shiftLeft(Number x, int n);
-
- public Number shiftRight(Number x, int n);
-}
-
static public boolean isZero(Object x){
return ops(x).isZero((Number)x);
@@ -385,76 +355,37 @@ static public Number divide(BigInteger n, BigInteger d){
(d.signum() < 0 ? d.negate() : d));
}
-static public Number not(Object x){
- return bitOps(x).not((Number)x);
-}
-
-
-static public Number and(Object x, Object y){
- return bitOps(x).combine(bitOps(y)).and((Number)x, (Number)y);
-}
-
-static public Number or(Object x, Object y){
- return bitOps(x).combine(bitOps(y)).or((Number)x, (Number)y);
-}
-
-static public Number xor(Object x, Object y){
- return bitOps(x).combine(bitOps(y)).xor((Number)x, (Number)y);
-}
-
-static public Number andNot(Number x, Number y){
- return bitOps(x).combine(bitOps(y)).andNot(x, y);
-}
-
-static public Number clearBit(Number x, int n){
- if(n < 0)
- throw new ArithmeticException("Negative bit index");
- return bitOps(x).clearBit(x, n);
-}
-
-static public Number setBit(Number x, int n){
- if(n < 0)
- throw new ArithmeticException("Negative bit index");
- return bitOps(x).setBit(x, n);
-}
-
-static public Number flipBit(Number x, int n){
- if(n < 0)
- throw new ArithmeticException("Negative bit index");
- return bitOps(x).flipBit(x, n);
+static public int shiftLeftInt(int x, int n){
+ return x << n;
}
-static public boolean testBit(Number x, int n){
- if(n < 0)
- throw new ArithmeticException("Negative bit index");
- return bitOps(x).testBit(x, n);
+static public long shiftLeft(Object x, Object y){
+ return shiftLeft(bitOpsCast(x),bitOpsCast(y));
}
-
-static public Number shiftLeft(Object x, Object n){
- return bitOps(x).shiftLeft((Number)x, ((Number)n).intValue());
+static public long shiftLeft(Object x, long y){
+ return shiftLeft(bitOpsCast(x),y);
}
-
-static public int shiftLeftInt(int x, int n){
- return x << n;
+static public long shiftLeft(long x, Object y){
+ return shiftLeft(x,bitOpsCast(y));
}
-
-static public long shiftLeft(long x, int n){
- if(n < 0)
- return shiftRight(x, -n);
+static public long shiftLeft(long x, long n){
return x << n;
}
-static public Number shiftRight(Object x, Object n){
- return bitOps(x).shiftRight((Number)x, ((Number)n).intValue());
-}
-
static public int shiftRightInt(int x, int n){
return x >> n;
}
-static public long shiftRight(long x, int n){
- if(n < 0)
- return shiftLeft(x, -n);
+static public long shiftRight(Object x, Object y){
+ return shiftRight(bitOpsCast(x),bitOpsCast(y));
+}
+static public long shiftRight(Object x, long y){
+ return shiftRight(bitOpsCast(x),y);
+}
+static public long shiftRight(long x, Object y){
+ return shiftRight(x,bitOpsCast(y));
+}
+static public long shiftRight(long x, long n){
return x >> n;
}
@@ -999,147 +930,12 @@ final static class BigDecimalOps extends OpsP{
}
}
-final static class LongBitOps implements BitOps{
- public BitOps combine(BitOps y){
- return y.bitOpsWith(this);
- }
-
- final public BitOps bitOpsWith(LongBitOps x){
- return this;
- }
-
- final public BitOps bitOpsWith(BigIntBitOps x){
- return BIGINT_BITOPS;
- }
-
- public Number not(Number x){
- return num(~x.longValue());
- }
-
- public Number and(Number x, Number y){
- return num(x.longValue() & y.longValue());
- }
-
- public Number or(Number x, Number y){
- return num(x.longValue() | y.longValue());
- }
-
- public Number xor(Number x, Number y){
- return num(x.longValue() ^ y.longValue());
- }
-
- public Number andNot(Number x, Number y){
- return num(x.longValue() & ~y.longValue());
- }
-
- public Number clearBit(Number x, int n){
- if(n < 63)
- return (num(x.longValue() & ~(1L << n)));
- else
- return BigInt.fromBigInteger(toBigInteger(x).clearBit(n));
- }
-
- public Number setBit(Number x, int n){
- if(n < 63)
- return num(x.longValue() | (1L << n));
- else
- return BigInt.fromBigInteger(toBigInteger(x).setBit(n));
- }
-
- public Number flipBit(Number x, int n){
- if(n < 63)
- return num(x.longValue() ^ (1L << n));
- else
- return BigInt.fromBigInteger(toBigInteger(x).flipBit(n));
- }
-
- public boolean testBit(Number x, int n){
- if(n < 64)
- return (x.longValue() & (1L << n)) != 0;
- else
- return toBigInteger(x).testBit(n);
- }
-
- public Number shiftLeft(Number x, int n){
- if(n < 0)
- return shiftRight(x, -n);
- return num(Numbers.shiftLeft(x.longValue(), n));
- }
-
- public Number shiftRight(Number x, int n){
- if(n < 0)
- return shiftLeft(x, -n);
- return num(x.longValue() >> n);
- }
-}
-
-final static class BigIntBitOps implements BitOps{
- public BitOps combine(BitOps y){
- return y.bitOpsWith(this);
- }
-
- final public BitOps bitOpsWith(LongBitOps x){
- return this;
- }
-
- final public BitOps bitOpsWith(BigIntBitOps x){
- return this;
- }
-
- public Number not(Number x){
- return BigInt.fromBigInteger(toBigInteger(x).not());
- }
-
- public Number and(Number x, Number y){
- return BigInt.fromBigInteger(toBigInteger(x).and(toBigInteger(y)));
- }
-
- public Number or(Number x, Number y){
- return BigInt.fromBigInteger(toBigInteger(x).or(toBigInteger(y)));
- }
-
- public Number xor(Number x, Number y){
- return BigInt.fromBigInteger(toBigInteger(x).xor(toBigInteger(y)));
- }
-
- public Number andNot(Number x, Number y){
- return BigInt.fromBigInteger(toBigInteger(x).andNot(toBigInteger(y)));
- }
-
- public Number clearBit(Number x, int n){
- return BigInt.fromBigInteger(toBigInteger(x).clearBit(n));
- }
-
- public Number setBit(Number x, int n){
- return BigInt.fromBigInteger(toBigInteger(x).setBit(n));
- }
-
- public Number flipBit(Number x, int n){
- return BigInt.fromBigInteger(toBigInteger(x).flipBit(n));
- }
-
- public boolean testBit(Number x, int n){
- return toBigInteger(x).testBit(n);
- }
-
- public Number shiftLeft(Number x, int n){
- return BigInt.fromBigInteger(toBigInteger(x).shiftLeft(n));
- }
-
- public Number shiftRight(Number x, int n){
- return BigInt.fromBigInteger(toBigInteger(x).shiftRight(n));
- }
-}
-
static final LongOps LONG_OPS = new LongOps();
static final DoubleOps DOUBLE_OPS = new DoubleOps();
static final RatioOps RATIO_OPS = new RatioOps();
static final BigIntOps BIGINT_OPS = new BigIntOps();
static final BigDecimalOps BIGDECIMAL_OPS = new BigDecimalOps();
-static final LongBitOps LONG_BITOPS = new LongBitOps();
-static final BigIntBitOps BIGINT_BITOPS = new BigIntBitOps();
-
static public enum Category {INTEGER, FLOATING, DECIMAL, RATIO};
static Ops ops(Object x){
@@ -1186,21 +982,16 @@ static Category category(Object x){
return Category.INTEGER;
}
-static BitOps bitOps(Object x){
+static long bitOpsCast(Object x){
Class xc = x.getClass();
- if(xc == Long.class)
- return LONG_BITOPS;
- else if(xc == Integer.class)
- return LONG_BITOPS;
- else if(xc == BigInt.class)
- return BIGINT_BITOPS;
- else if(xc == BigInteger.class)
- return BIGINT_BITOPS;
- else if(xc == Double.class || xc == Float.class || xc == BigDecimalOps.class || xc == Ratio.class)
- throw new ArithmeticException("bit operation on non integer type: " + xc);
- else
- return LONG_BITOPS;
+ if(xc == Long.class
+ || xc == Integer.class
+ || xc == Short.class
+ || xc == Byte.class)
+ return RT.longCast(x);
+ // no bignums, no decimals
+ throw new IllegalArgumentException("bit operation not supported for: " + xc);
}
static public float[] float_array(int size, Object init){
@@ -1622,6 +1413,9 @@ static public int unchecked_int_multiply(int x, int y){
// return ~x;
//}
+static public long not(Object x){
+ return not(bitOpsCast(x));
+}
static public long not(long x){
return ~x;
}
@@ -1629,48 +1423,116 @@ static public long not(long x){
// return x & y;
//}
-static public long and(long x, long y){
- return x & y;
+static public long and(Object x, Object y){
+ return and(bitOpsCast(x),bitOpsCast(y));
}
-
-static public Number and(Object x, long y){
- return and(x, (Object)y);
+static public long and(Object x, long y){
+ return and(bitOpsCast(x),y);
}
-
-static public Number and(long x, Object y){
- return and((Object)x, y);
+static public long and(long x, Object y){
+ return and(x,bitOpsCast(y));
+}
+static public long and(long x, long y){
+ return x & y;
}
//static public int or(int x, int y){
// return x | y;
//}
-static public long or(long x, long y){
- return x | y;
+static public long or(Object x, Object y){
+ return or(bitOpsCast(x),bitOpsCast(y));
}
-
-static public Number or(Object x, long y){
- return or(x, (Object)y);
+static public long or(Object x, long y){
+ return or(bitOpsCast(x),y);
}
-
-static public Number or(long x, Object y){
- return or((Object)x, y);
+static public long or(long x, Object y){
+ return or(x,bitOpsCast(y));
+}
+static public long or(long x, long y){
+ return x | y;
}
//static public int xor(int x, int y){
// return x ^ y;
//}
+static public long xor(Object x, Object y){
+ return xor(bitOpsCast(x),bitOpsCast(y));
+}
+static public long xor(Object x, long y){
+ return xor(bitOpsCast(x),y);
+}
+static public long xor(long x, Object y){
+ return xor(x,bitOpsCast(y));
+}
static public long xor(long x, long y){
return x ^ y;
}
-static public Number xor(Object x, long y){
- return xor(x, (Object)y);
+static public long andNot(Object x, Object y){
+ return andNot(bitOpsCast(x),bitOpsCast(y));
+}
+static public long andNot(Object x, long y){
+ return andNot(bitOpsCast(x),y);
+}
+static public long andNot(long x, Object y){
+ return andNot(x,bitOpsCast(y));
+}
+static public long andNot(long x, long y){
+ return x & ~y;
}
-static public Number xor(long x, Object y){
- return xor((Object)x, y);
+static public long clearBit(Object x, Object y){
+ return clearBit(bitOpsCast(x),bitOpsCast(y));
+}
+static public long clearBit(Object x, long y){
+ return clearBit(bitOpsCast(x),y);
+}
+static public long clearBit(long x, Object y){
+ return clearBit(x,bitOpsCast(y));
+}
+static public long clearBit(long x, long n){
+ return x & (1L << n);
+}
+
+static public long setBit(Object x, Object y){
+ return setBit(bitOpsCast(x),bitOpsCast(y));
+}
+static public long setBit(Object x, long y){
+ return setBit(bitOpsCast(x),y);
+}
+static public long setBit(long x, Object y){
+ return setBit(x,bitOpsCast(y));
+}
+static public long setBit(long x, long n){
+ return x | (1L << n);
+}
+
+static public long flipBit(Object x, Object y){
+ return flipBit(bitOpsCast(x),bitOpsCast(y));
+}
+static public long flipBit(Object x, long y){
+ return flipBit(bitOpsCast(x),y);
+}
+static public long flipBit(long x, Object y){
+ return flipBit(x,bitOpsCast(y));
+}
+static public long flipBit(long x, long n){
+ return x ^ (1L << n);
+}
+
+static public boolean testBit(Object x, Object y){
+ return testBit(bitOpsCast(x),bitOpsCast(y));
+}
+static public boolean testBit(Object x, long y){
+ return testBit(bitOpsCast(x),y);
+}
+static public boolean testBit(long x, Object y){
+ return testBit(x,bitOpsCast(y));
+}
+static public boolean testBit(long x, long n){
+ return (x & (1L << n)) != 0;
}
//static public int minus(int x, int y){
diff --git a/test/clojure/test_clojure/numbers.clj b/test/clojure/test_clojure/numbers.clj
index 08cf60c2..3bd54050 100644
--- a/test/clojure/test_clojure/numbers.clj
+++ b/test/clojure/test_clojure/numbers.clj
@@ -418,8 +418,8 @@
(even? 0)
(not (even? 5))
(even? 8))
- (is (thrown? ArithmeticException (even? 1/2)))
- (is (thrown? ArithmeticException (even? (double 10)))))
+ (is (thrown? IllegalArgumentException (even? 1/2)))
+ (is (thrown? IllegalArgumentException (even? (double 10)))))
(deftest test-odd?
(are [x] (true? x)
@@ -428,8 +428,8 @@
(not (odd? 0))
(odd? 5)
(not (odd? 8)))
- (is (thrown? ArithmeticException (odd? 1/2)))
- (is (thrown? ArithmeticException (odd? (double 10)))))
+ (is (thrown? IllegalArgumentException (odd? 1/2)))
+ (is (thrown? IllegalArgumentException (odd? (double 10)))))
(defn- expt
"clojure.contrib.math/expt is a better and much faster impl, but this works.
@@ -443,10 +443,11 @@ Math/pow overflows to Infinity."
2r1000 (bit-shift-left 2r1 3)
2r00101110 (bit-shift-left 2r00010111 1)
2r00101110 (apply bit-shift-left [2r00010111 1])
- 2r01 (bit-shift-left 2r10 -1)
+ 0 (bit-shift-left 2r10 -1) ; truncated to least 6-bits, 63
(expt 2 32) (bit-shift-left 1 32)
- (expt 2N 10000) (bit-shift-left 1N 10000)
- ))
+ (expt 2 16) (bit-shift-left 1 10000) ; truncated to least 6-bits, 16
+ )
+ (is (thrown? IllegalArgumentException (bit-shift-left 1N 1))))
(deftest test-bit-shift-right
(are [x y] (= x y)
@@ -456,10 +457,11 @@ Math/pow overflows to Infinity."
2r000 (bit-shift-right 2r100 3)
2r0001011 (bit-shift-right 2r00010111 1)
2r0001011 (apply bit-shift-right [2r00010111 1])
- 2r100 (bit-shift-right 2r10 -1)
+ 0 (bit-shift-right 2r10 -1) ; truncated to least 6-bits, 63
1 (bit-shift-right (expt 2 32) 32)
- 1N (bit-shift-right (expt 2N 10000) 10000)
- ))
+ 1 (bit-shift-right (expt 2 16) 10000) ; truncated to least 6-bits, 16
+ )
+ (is (thrown? IllegalArgumentException (bit-shift-right 1N 1))))
;; arrays