diff options
author | Rich Hickey <richhickey@gmail.com> | 2010-06-12 12:02:10 -0400 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2010-06-12 12:02:10 -0400 |
commit | c5d0985af6c17103eaabe523e442f14c29916266 (patch) | |
tree | 91619f359a55d19b6f2ad02e9cd102afa43bd3f1 | |
parent | 3f74c9ff6e9bf8e5e120129ea1c1c7e4719b4dcc (diff) |
incomplete work in progress
-rw-r--r-- | src/clj/clojure/core_print.clj | 5 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 17 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 12 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Numbers.java | 455 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 |
5 files changed, 75 insertions, 418 deletions
diff --git a/src/clj/clojure/core_print.clj b/src/clj/clojure/core_print.clj index b10cd14f..21af0ac9 100644 --- a/src/clj/clojure/core_print.clj +++ b/src/clj/clojure/core_print.clj @@ -242,6 +242,7 @@ (defmethod print-dup java.lang.Double [o w] (print-method o w)) (defmethod print-dup clojure.lang.Ratio [o w] (print-method o w)) (defmethod print-dup java.math.BigDecimal [o w] (print-method o w)) +(defmethod print-dup java.math.BigInteger [o w] (print-method o w)) (defmethod print-dup clojure.lang.PersistentHashMap [o w] (print-method o w)) (defmethod print-dup clojure.lang.PersistentHashSet [o w] (print-method o w)) (defmethod print-dup clojure.lang.PersistentVector [o w] (print-method o w)) @@ -278,6 +279,10 @@ (.write w (str b)) (.write w "M")) +(defmethod print-method java.math.BigInteger [b, ^Writer w] + (.write w (str b)) + (.write w "N")) + (defmethod print-method java.util.regex.Pattern [p ^Writer w] (.write w "#\"") (loop [[^Character c & r :as s] (seq (.pattern ^java.util.regex.Pattern p)) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 4485fe5f..12ef1b31 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -5391,7 +5391,10 @@ public static class RecurExpr implements Expr{ { if(!(arg instanceof MaybePrimitiveExpr && arg.hasJavaClass() && arg.getJavaClass() == primc)) throw new IllegalArgumentException("recur arg for primitive local: " + - lb.name + " must be matching primitive"); + lb.name + " must be matching primitive, had: " + + arg.getJavaClass().getName() + + ", needed: " + + primc.getName()); } catch(Exception e) { @@ -7217,7 +7220,7 @@ public static class CaseExpr extends UntypedExpr{ for(Object o : ((Map)args.nth(6)).entrySet()) { Map.Entry e = (Map.Entry) o; - Integer minhash = (Integer) e.getKey(); + Integer minhash = ((Number)e.getKey()).intValue(); MapEntry me = (MapEntry) e.getValue(); Expr testExpr = new ConstantExpr(me.getKey()); tests.put(minhash, testExpr); @@ -7243,12 +7246,12 @@ public static class CaseExpr extends UntypedExpr{ Var.popThreadBindings(); } - return new CaseExpr((Integer) LINE.deref(), + return new CaseExpr(((Number)LINE.deref()).intValue(), testexpr, - (Integer)args.nth(1), - (Integer)args.nth(2), - (Integer)args.nth(3), - (Integer)args.nth(4), + ((Number)args.nth(1)).intValue(), + ((Number)args.nth(2)).intValue(), + ((Number)args.nth(3)).intValue(), + ((Number)args.nth(4)).intValue(), defaultExpr, tests,thens,args.nth(7) != RT.F); diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index 9c906ba9..409ec858 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -47,7 +47,7 @@ static Pattern symbolPat = Pattern.compile("[:]?([\\D&&[^/]].*/)?([\\D&&[^/]][^/ //static Pattern intPat = Pattern.compile("[-+]?[0-9]+\\.?"); static Pattern intPat = Pattern.compile( - "([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)"); + "([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)(N)?"); static Pattern ratioPat = Pattern.compile("([-+]?[0-9]+)/([0-9]+)"); static Pattern floatPat = Pattern.compile("([-+]?[0-9]+(\\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?"); static final Symbol SLASH = Symbol.create("/"); @@ -327,7 +327,11 @@ private static Object matchNumber(String s){ if(m.matches()) { if(m.group(2) != null) - return 0; + { + if(m.group(8) != null) + return BigInteger.ZERO; + return new Long(0); + } boolean negate = (m.group(1).equals("-")); String n; int radix = 10; @@ -342,7 +346,9 @@ private static Object matchNumber(String s){ if(n == null) return null; BigInteger bn = new BigInteger(n, radix); - return Numbers.reduce(negate ? bn.negate() : bn); + if(m.group(8) != null) + return negate ? bn.negate() : bn; + return Numbers.reduceBigInteger(negate ? bn.negate() : bn); } m = floatPat.matcher(s); if(m.matches()) diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java index 2aaabee2..3c82bbdf 100644 --- a/src/jvm/clojure/lang/Numbers.java +++ b/src/jvm/clojure/lang/Numbers.java @@ -21,12 +21,8 @@ public class Numbers{ static interface Ops{ Ops combine(Ops y); - Ops opsWith(IntegerOps x); - Ops opsWith(LongOps x); - Ops opsWith(FloatOps x); - Ops opsWith(DoubleOps x); Ops opsWith(RatioOps x); @@ -65,8 +61,6 @@ static interface Ops{ static interface BitOps{ BitOps combine(BitOps y); - BitOps bitOpsWith(IntegerBitOps x); - BitOps bitOpsWith(LongBitOps x); BitOps bitOpsWith(BigIntegerBitOps x); @@ -161,7 +155,7 @@ static Number quotient(double n, double d){ } else { //bigint quotient - return reduce(new BigDecimal(q).toBigInteger()); + return reduceBigInteger(new BigDecimal(q).toBigInteger()); } } @@ -173,7 +167,7 @@ static Number remainder(double n, double d){ } else { //bigint quotient - Number bq = reduce(new BigDecimal(q).toBigInteger()); + Number bq = reduceBigInteger(new BigDecimal(q).toBigInteger()); return (n - bq.doubleValue() * d); } } @@ -263,24 +257,25 @@ static public Number reduce(Number val){ if(val instanceof Long) return reduce(val.longValue()); else if (val instanceof BigInteger) - return reduce((BigInteger) val); + return reduceBigInteger((BigInteger) val); return val; } -static public Number reduce(BigInteger val){ +static public Number reduceBigInteger(BigInteger val){ int bitLength = val.bitLength(); if(bitLength < 32) return val.intValue(); - else if(bitLength < 64) + else + if(bitLength < 64) return val.longValue(); else return val; } static public Number reduce(long val){ - if(val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) - return (int) val; - else +// if(val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) +// return (int) val; +// else return val; } @@ -293,9 +288,9 @@ static public Number divide(BigInteger n, BigInteger d){ n = n.divide(gcd); d = d.divide(gcd); if(d.equals(BigInteger.ONE)) - return reduce(n); + return reduceBigInteger(n); else if(d.equals(BigInteger.ONE.negate())) - return reduce(n.negate()); + return reduceBigInteger(n.negate()); return new Ratio((d.signum() < 0 ? n.negate() : n), (d.signum() < 0 ? d.negate() : d)); } @@ -361,150 +356,15 @@ static public int shiftRight(int x, int n){ return x >> n; } -final static class IntegerOps implements Ops{ - public Ops combine(Ops y){ - return y.opsWith(this); - } - - final public Ops opsWith(IntegerOps x){ - return this; - } - - final public Ops opsWith(LongOps x){ - return LONG_OPS; - } - - final public Ops opsWith(FloatOps x){ - return FLOAT_OPS; - } - - final public Ops opsWith(DoubleOps x){ - return DOUBLE_OPS; - } - - final public Ops opsWith(RatioOps x){ - return RATIO_OPS; - } - - final public Ops opsWith(BigIntegerOps x){ - return BIGINTEGER_OPS; - } - - final public Ops opsWith(BigDecimalOps x){ - return BIGDECIMAL_OPS; - } - - public boolean isZero(Number x){ - return x.intValue() == 0; - } - - public boolean isPos(Number x){ - return x.intValue() > 0; - } - - public boolean isNeg(Number x){ - return x.intValue() < 0; - } - - final public Number add(Number x, Number y){ - long ret = x.longValue() + y.longValue(); - if(ret <= Integer.MAX_VALUE && ret >= Integer.MIN_VALUE) - return (int) ret; - return ret; - } - - final public Number multiply(Number x, Number y){ - long ret = x.longValue() * y.longValue(); - if(ret <= Integer.MAX_VALUE && ret >= Integer.MIN_VALUE) - return (int) ret; - return ret; - } - - static int gcd(int u, int v){ - while(v != 0) - { - int r = u % v; - u = v; - v = r; - } - return u; - } - - public Number divide(Number x, Number y){ - int n = x.intValue(); - int val = y.intValue(); - int gcd = gcd(n, val); - if(gcd == 0) - return 0; - - n = n / gcd; - int d = val / gcd; - if(d == 1) - return n; - if(d < 0) - { - n = -n; - d = -d; - } - return new Ratio(BigInteger.valueOf(n), BigInteger.valueOf(d)); - } - - public Number quotient(Number x, Number y){ - return x.intValue() / y.intValue(); - } - - public Number remainder(Number x, Number y){ - return x.intValue() % y.intValue(); - } - - public boolean equiv(Number x, Number y){ - return x.intValue() == y.intValue(); - } - - public boolean lt(Number x, Number y){ - return x.intValue() < y.intValue(); - } - - //public Number subtract(Number x, Number y); - final public Number negate(Number x){ - int val = x.intValue(); - if(val > Integer.MIN_VALUE) - return -val; - return -((long) val); - } - - public Number inc(Number x){ - int val = x.intValue(); - if(val < Integer.MAX_VALUE) - return val + 1; - return (long) val + 1; - } - - public Number dec(Number x){ - int val = x.intValue(); - if(val > Integer.MIN_VALUE) - return val - 1; - return (long) val - 1; - } -} - final static class LongOps implements Ops{ public Ops combine(Ops y){ return y.opsWith(this); } - final public Ops opsWith(IntegerOps x){ - return this; - } - final public Ops opsWith(LongOps x){ return this; } - final public Ops opsWith(FloatOps x){ - return FLOAT_OPS; - } - final public Ops opsWith(DoubleOps x){ return DOUBLE_OPS; } @@ -534,19 +394,11 @@ final static class LongOps implements Ops{ } final public Number add(Number x, Number y){ - long lx = x.longValue(), ly = y.longValue(); - long ret = lx + ly; - if ((ret ^ lx) < 0 && (ret ^ ly) < 0) - return BIGINTEGER_OPS.add(x, y); - return ret; + return Numbers.add(x.longValue(),y.longValue()); } final public Number multiply(Number x, Number y){ - long lx = x.longValue(), ly = y.longValue(); - long ret = lx * ly; - if (ly != 0 && ret/ly != lx) - return BIGINTEGER_OPS.multiply(x, y); - return ret; + return Numbers.multiply(x.longValue(),y.longValue()); } static long gcd(long u, long v){ @@ -597,110 +449,17 @@ final static class LongOps implements Ops{ //public Number subtract(Number x, Number y); final public Number negate(Number x){ long val = x.longValue(); - if(val > Long.MIN_VALUE) - return -val; - return BigInteger.valueOf(val).negate(); + return Numbers.minus(val); } public Number inc(Number x){ long val = x.longValue(); - if(val < Long.MAX_VALUE) - return val + 1; - return BIGINTEGER_OPS.inc(x); + return Numbers.inc(val); } public Number dec(Number x){ long val = x.longValue(); - if(val > Long.MIN_VALUE) - return val - 1; - return BIGINTEGER_OPS.dec(x); - } -} - -final static class FloatOps implements Ops{ - public Ops combine(Ops y){ - return y.opsWith(this); - } - - final public Ops opsWith(IntegerOps x){ - return this; - } - - final public Ops opsWith(LongOps x){ - return this; - } - - final public Ops opsWith(FloatOps x){ - return this; - } - - final public Ops opsWith(DoubleOps x){ - return DOUBLE_OPS; - } - - final public Ops opsWith(RatioOps x){ - return this; - } - - final public Ops opsWith(BigIntegerOps x){ - return this; - } - - final public Ops opsWith(BigDecimalOps x){ - return this; - } - - public boolean isZero(Number x){ - return x.floatValue() == 0; - } - - public boolean isPos(Number x){ - return x.floatValue() > 0; - } - - public boolean isNeg(Number x){ - return x.floatValue() < 0; - } - - final public Number add(Number x, Number y){ - return x.floatValue() + y.floatValue(); - } - - final public Number multiply(Number x, Number y){ - return x.floatValue() * y.floatValue(); - } - - public Number divide(Number x, Number y){ - return x.floatValue() / y.floatValue(); - } - - public Number quotient(Number x, Number y){ - return Numbers.quotient(x.doubleValue(), y.doubleValue()); - } - - public Number remainder(Number x, Number y){ - return Numbers.remainder(x.doubleValue(), y.doubleValue()); - } - - public boolean equiv(Number x, Number y){ - return x.floatValue() == y.floatValue(); - } - - public boolean lt(Number x, Number y){ - return x.floatValue() < y.floatValue(); - } - - //public Number subtract(Number x, Number y); - final public Number negate(Number x){ - return -x.floatValue(); - } - - public Number inc(Number x){ - return x.floatValue() + 1; - } - - public Number dec(Number x){ - return x.floatValue() - 1; + return Numbers.dec(val); } } @@ -709,18 +468,10 @@ final static class DoubleOps implements Ops{ return y.opsWith(this); } - final public Ops opsWith(IntegerOps x){ - return this; - } - final public Ops opsWith(LongOps x){ return this; } - final public Ops opsWith(FloatOps x){ - return this; - } - final public Ops opsWith(DoubleOps x){ return this; } @@ -796,18 +547,10 @@ final static class RatioOps implements Ops{ return y.opsWith(this); } - final public Ops opsWith(IntegerOps x){ - return this; - } - final public Ops opsWith(LongOps x){ return this; } - final public Ops opsWith(FloatOps x){ - return FLOAT_OPS; - } - final public Ops opsWith(DoubleOps x){ return DOUBLE_OPS; } @@ -866,7 +609,7 @@ final static class RatioOps implements Ops{ Ratio ry = toRatio(y); BigInteger q = rx.numerator.multiply(ry.denominator).divide( rx.denominator.multiply(ry.numerator)); - return reduce(q); + return reduceBigInteger(q); } public Number remainder(Number x, Number y){ @@ -911,18 +654,10 @@ final static class BigIntegerOps implements Ops{ return y.opsWith(this); } - final public Ops opsWith(IntegerOps x){ - return this; - } - final public Ops opsWith(LongOps x){ return this; } - final public Ops opsWith(FloatOps x){ - return FLOAT_OPS; - } - final public Ops opsWith(DoubleOps x){ return DOUBLE_OPS; } @@ -955,11 +690,11 @@ final static class BigIntegerOps implements Ops{ } final public Number add(Number x, Number y){ - return reduce(toBigInteger(x).add(toBigInteger(y))); + return reduceBigInteger(toBigInteger(x).add(toBigInteger(y))); } final public Number multiply(Number x, Number y){ - return reduce(toBigInteger(x).multiply(toBigInteger(y))); + return reduceBigInteger(toBigInteger(x).multiply(toBigInteger(y))); } public Number divide(Number x, Number y){ @@ -989,12 +724,12 @@ final static class BigIntegerOps implements Ops{ public Number inc(Number x){ BigInteger bx = toBigInteger(x); - return reduce(bx.add(BigInteger.ONE)); + return reduceBigInteger(bx.add(BigInteger.ONE)); } public Number dec(Number x){ BigInteger bx = toBigInteger(x); - return reduce(bx.subtract(BigInteger.ONE)); + return reduceBigInteger(bx.subtract(BigInteger.ONE)); } } @@ -1005,18 +740,10 @@ final static class BigDecimalOps implements Ops{ return y.opsWith(this); } - final public Ops opsWith(IntegerOps x){ - return this; - } - final public Ops opsWith(LongOps x){ return this; } - final public Ops opsWith(FloatOps x){ - return FLOAT_OPS; - } - final public Ops opsWith(DoubleOps x){ return DOUBLE_OPS; } @@ -1116,107 +843,11 @@ final static class BigDecimalOps implements Ops{ } } -final static class IntegerBitOps implements BitOps{ - public BitOps combine(BitOps y){ - return y.bitOpsWith(this); - } - - final public BitOps bitOpsWith(IntegerBitOps x){ - return this; - } - - final public BitOps bitOpsWith(LongBitOps x){ - return LONG_BITOPS; - } - - final public BitOps bitOpsWith(BigIntegerBitOps x){ - return BIGINTEGER_BITOPS; - } - - - public Number not(Number x){ - return ~x.intValue(); - } - - public Number and(Number x, Number y){ - return x.intValue() & y.intValue(); - } - - public Number or(Number x, Number y){ - return x.intValue() | y.intValue(); - } - - public Number xor(Number x, Number y){ - return x.intValue() ^ y.intValue(); - } - - public Number andNot(Number x, Number y){ - return x.intValue() & ~y.intValue(); - } - - public Number clearBit(Number x, int n){ - if(n < 31) - return x.intValue() & ~(1 << n); - else if(n < 63) - return x.longValue() & ~(1L << n); - else - return toBigInteger(x).clearBit(n); - } - - public Number setBit(Number x, int n){ - if(n < 31) - return x.intValue() | (1 << n); - else if(n < 63) - return x.longValue() | (1L << n); - else - return toBigInteger(x).setBit(n); - } - - public Number flipBit(Number x, int n){ - if(n < 31) - return x.intValue() ^ (1 << n); - else if(n < 63) - return x.longValue() ^ (1L << n); - else - return toBigInteger(x).flipBit(n); - } - - public boolean testBit(Number x, int n){ - if(n < 32) - return (x.intValue() & (1 << n)) != 0; - else if(n < 64) - return (x.longValue() & (1L << n)) != 0; - else - return toBigInteger(x).testBit(n); - } - - public Number shiftLeft(Number x, int n){ - if(n < 32) - { - if(n < 0) - return shiftRight(x, -n); - return reduce(x.longValue() << n); - } - else - return reduce(toBigInteger(x).shiftLeft(n)); - } - - public Number shiftRight(Number x, int n){ - if(n < 0) - return shiftLeft(x, -n); - return x.intValue() >> n; - } -} - final static class LongBitOps implements BitOps{ public BitOps combine(BitOps y){ return y.bitOpsWith(this); } - final public BitOps bitOpsWith(IntegerBitOps x){ - return this; - } - final public BitOps bitOpsWith(LongBitOps x){ return this; } @@ -1276,7 +907,7 @@ final static class LongBitOps implements BitOps{ public Number shiftLeft(Number x, int n){ if(n < 0) return shiftRight(x, -n); - return reduce(toBigInteger(x).shiftLeft(n)); + return reduceBigInteger(toBigInteger(x).shiftLeft(n)); } public Number shiftRight(Number x, int n){ @@ -1291,10 +922,6 @@ final static class BigIntegerBitOps implements BitOps{ return y.bitOpsWith(this); } - final public BitOps bitOpsWith(IntegerBitOps x){ - return this; - } - final public BitOps bitOpsWith(LongBitOps x){ return this; } @@ -1348,52 +975,49 @@ final static class BigIntegerBitOps implements BitOps{ } } -static final IntegerOps INTEGER_OPS = new IntegerOps(); static final LongOps LONG_OPS = new LongOps(); -static final FloatOps FLOAT_OPS = new FloatOps(); static final DoubleOps DOUBLE_OPS = new DoubleOps(); static final RatioOps RATIO_OPS = new RatioOps(); static final BigIntegerOps BIGINTEGER_OPS = new BigIntegerOps(); static final BigDecimalOps BIGDECIMAL_OPS = new BigDecimalOps(); -static final IntegerBitOps INTEGER_BITOPS = new IntegerBitOps(); static final LongBitOps LONG_BITOPS = new LongBitOps(); static final BigIntegerBitOps BIGINTEGER_BITOPS = new BigIntegerBitOps(); static Ops ops(Object x){ Class xc = x.getClass(); - if(xc == Integer.class) - return INTEGER_OPS; + if(xc == Long.class) + return LONG_OPS; else if(xc == Double.class) return DOUBLE_OPS; + else if(xc == Integer.class) + return LONG_OPS; else if(xc == Float.class) - return FLOAT_OPS; + return DOUBLE_OPS; else if(xc == BigInteger.class) return BIGINTEGER_OPS; - else if(xc == Long.class) - return LONG_OPS; else if(xc == Ratio.class) return RATIO_OPS; else if(xc == BigDecimal.class) return BIGDECIMAL_OPS; else - return INTEGER_OPS; + return LONG_OPS; } static BitOps bitOps(Object x){ Class xc = x.getClass(); - if(xc == Integer.class) - return INTEGER_BITOPS; - else if(xc == Long.class) + if(xc == Long.class) + return LONG_BITOPS; + else if(xc == Integer.class) return LONG_BITOPS; else if(xc == BigInteger.class) return BIGINTEGER_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 INTEGER_BITOPS; + return LONG_BITOPS; } //final static ExecutorService executor = Executors.newCachedThreadPool(); @@ -1876,18 +1500,33 @@ static public int not(int x){ return ~x; } +static public long not(long x){ + return ~x; +} static public int and(int x, int y){ return x & 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 int xor(int x, int y){ return x ^ y; } +static public long xor(long x, long y){ + return x ^ y; +} + static public int minus(int x, int y){ int ret = x - y; if (((ret ^ x) < 0 && (ret ^ ~y) < 0)) diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 9aea629f..18a770b8 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -1399,6 +1399,10 @@ static public void print(Object x, Writer w) throws Exception{ w.write(x.toString()); w.write('M'); } + else if(x instanceof BigInteger && readably) { + w.write(x.toString()); + w.write('N'); + } else if(x instanceof Var) { Var v = (Var) x; w.write("#=(var " + v.ns.name + "/" + v.sym + ")"); |