diff options
author | Alexander Taggart <alex.taggart@expojure.com> | 2011-04-29 11:04:34 -0700 |
---|---|---|
committer | Stuart Halloway <stu@thinkrelevance.com> | 2011-05-06 09:45:52 -0400 |
commit | 601d9521f88f8fb00e670d2823857cdcb2b2e1c3 (patch) | |
tree | f41f3d88d723c4ff5bcaa949d10468bd6b72a34c | |
parent | e89e95fe82f430cc5fe9ea1c3f1974434a9ccda3 (diff) |
Remove bit-ops' support for boxed numbers.
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
-rw-r--r-- | src/clj/clojure/core.clj | 28 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Numbers.java | 374 | ||||
-rw-r--r-- | test/clojure/test_clojure/numbers.clj | 22 |
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 |