diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-03-28 16:07:04 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-03-28 16:07:04 +0000 |
commit | e63b0c3f98628dce4a9a829466ab67d175dd4414 (patch) | |
tree | a8a591387d9c8fbe146936782f4ce12457fdd125 /src | |
parent | 3d18eff96403ddee6c3a82307c255dff3500c94a (diff) |
first cut of numbers
Diffstat (limited to 'src')
-rw-r--r-- | src/org/clojure/runtime/DoubleNum.java | 176 | ||||
-rw-r--r-- | src/org/clojure/runtime/FloatNum.java | 17 | ||||
-rw-r--r-- | src/org/clojure/runtime/IntegerNum.java | 17 | ||||
-rw-r--r-- | src/org/clojure/runtime/Num.java | 164 | ||||
-rw-r--r-- | src/org/clojure/runtime/RatioNum.java | 171 | ||||
-rw-r--r-- | src/org/clojure/runtime/Rational.java | 17 | ||||
-rw-r--r-- | src/org/clojure/runtime/RealNum.java | 17 |
7 files changed, 579 insertions, 0 deletions
diff --git a/src/org/clojure/runtime/DoubleNum.java b/src/org/clojure/runtime/DoubleNum.java new file mode 100644 index 00000000..3bbdc5bd --- /dev/null +++ b/src/org/clojure/runtime/DoubleNum.java @@ -0,0 +1,176 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:13:45 AM */ + +package org.clojure.runtime; + +import java.math.BigInteger; +import java.math.BigDecimal; + +public class DoubleNum extends FloatNum { + double val; + public DoubleNum(double val){ + this.val = val; + } + + public double doubleValue() { + return val; + } + public float floatValue() { + return (float)val; + } + public int intValue() { + return (int)val; + } + public long longValue() { + return (long)val; + } + + final static BigInteger BIGTEN = BigInteger.valueOf(10); + + public Num toRational(){ + BigDecimal d = new BigDecimal(val); + return Num.divide(d.unscaledValue(),BIGTEN.pow(d.scale())); + } + + public boolean equiv(Num rhs) { + if(rhs instanceof RatioNum) + return equivTo((RatioNum)rhs); + return val == rhs.doubleValue(); + } + public boolean equivTo(BigInteger x) { + return val == x.doubleValue(); + } + public boolean equivTo(int x) { + return x == val; + } + public boolean equivTo(RatioNum x) { + return toRational().equivTo(x); + } + + public boolean lt(Num rhs) throws Exception { + if(rhs instanceof RatioNum) + return toRational().lt(rhs); + return val < rhs.doubleValue(); + } + public boolean gt(BigInteger x) throws Exception { + return val > x.doubleValue(); + } + public boolean gt(int x) throws Exception { + return val > x; + } + public boolean gt(RatioNum x) throws Exception { + return toRational().gt(x); + } + + public Num add(Num rhs){ + return Num.from(val + rhs.doubleValue()); + } + public Num addTo(int x){ + return Num.from(val + x); + } + public Num addTo(BigInteger x){ + return Num.from(val + x.doubleValue()); + } + public Num addTo(RatioNum x){ + return Num.from(val + x.doubleValue()); + } + + public Num subtractFrom(Num x){ + return Num.from(x.doubleValue() - val); + } + + public Num multiplyBy(Num rhs){ + return Num.from(val * rhs.doubleValue()); + } + public Num multiply(int x){ + return Num.from(val * x); + } + public Num multiply(BigInteger x){ + return Num.from(val * x.doubleValue()); + } + public Num multiply(RatioNum x){ + return Num.from(val * x.doubleValue()); + } + + public Num divideBy(Num rhs){ + return Num.from(val / rhs.doubleValue()); + } + public Num divide(int x){ + return Num.from(x/val); + } + public Num divide(BigInteger x){ + return Num.from(x.doubleValue()/val); + } + public Num divide(RatioNum x){ + return Num.from(x.doubleValue()/val); + } + + static Object truncate(ThreadLocalData tld, double n, double d){ + double q = n/d; + if(q <= Integer.MAX_VALUE && q >= Integer.MIN_VALUE){ + return RT.setValues(tld,Num.from((int)q), + Num.from(n - ((int)q)*d)); + } + else{ //bigint quotient + Num bq = Num.from(new BigDecimal(q).toBigInteger()); + return RT.setValues(tld,bq, + Num.from(n - bq.doubleValue()*d)); + } + } + + public Object truncateBy(ThreadLocalData tld, BigInteger x) { + return truncate(tld, val,x.doubleValue()); + } + public Object truncateBy(ThreadLocalData tld, int x) { + return truncate(tld, val,x); + } + public Object truncateBy(ThreadLocalData tld, RatioNum x) { + return truncate(tld, val,x.doubleValue()); + } + public Object truncateDivide(ThreadLocalData tld, Num num) { + return truncate(tld, num.doubleValue(),val); + } + public Num negate() throws Exception{ + return Num.from(-val); + } + + public boolean equals(Object arg0) { + return arg0 != null + && arg0 instanceof DoubleNum + && Double.doubleToLongBits(((DoubleNum)arg0).val) == + Double.doubleToLongBits(val); + } + public int hashCode() { + long v = Double.doubleToLongBits(val); + return (int)(v^(v>>>32)); + } + + public String toString() { + return Double.toString(val); + } + public boolean minusp() { + return val < 0; + } + public boolean plusp() { + return val > 0; + } + + public Num oneMinus() { + return Num.from(val - 1); + } + + public Num onePlus() { + return Num.from(val + 1); + } + +} + diff --git a/src/org/clojure/runtime/FloatNum.java b/src/org/clojure/runtime/FloatNum.java new file mode 100644 index 00000000..8ea7b6de --- /dev/null +++ b/src/org/clojure/runtime/FloatNum.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:17:21 AM */ + +package org.clojure.runtime; + +public abstract class FloatNum extends RealNum { + +} diff --git a/src/org/clojure/runtime/IntegerNum.java b/src/org/clojure/runtime/IntegerNum.java new file mode 100644 index 00000000..6fa53219 --- /dev/null +++ b/src/org/clojure/runtime/IntegerNum.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:11:55 AM */ + +package org.clojure.runtime; + +public abstract class IntegerNum extends Rational { + +}
\ No newline at end of file diff --git a/src/org/clojure/runtime/Num.java b/src/org/clojure/runtime/Num.java new file mode 100644 index 00000000..688fb0b4 --- /dev/null +++ b/src/org/clojure/runtime/Num.java @@ -0,0 +1,164 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:07:33 AM */ + +package org.clojure.runtime; + +import java.math.BigInteger; + +public abstract class Num extends Number { + + public final static Num ZERO = from(0); + public final static Num ONE = from(1); + + static public Num from(int val){ + //todo - cache a bunch of small fixnums + return new FixNum(val); + } + + static public Num from(double val){ + return new DoubleNum(val); + } + + static public Num from(long val){ + if(val <= Integer.MAX_VALUE && val >= Integer.MIN_VALUE) + return from((int)val); + else + return new BigNum(val); + } + + static public Num from(BigInteger val){ + if(val.bitLength() < 32) + return from(val.intValue()); + else + return new BigNum(val); + } + + static public Num from(Object x){ + if(x instanceof Num) + return (Num)x; + else{ + Class c = x.getClass(); + if(c == Integer.class) + return Num.from(((Integer)x).intValue()); + else if(c == Double.class || c == Float.class) + return Num.from(((Number)x).doubleValue()); + else if(c == Long.class) + return Num.from(((Long)x).longValue()); + else if(c == BigInteger.class) + return Num.from((BigInteger)x); + else + return Num.from(((Number)x).intValue()); + } + } + + static public Num add(Object x,Object y){ + //if(x instanceof Num && y instanceof Num) + //return ((Num)x).add((Num) y); + return Num.from(x).add(Num.from(y)); + } + abstract public Num add(Num rhs); + abstract public Num addTo(int x); + abstract public Num addTo(BigInteger x); + abstract public Num addTo(RatioNum x); + + static public Num subtract(Object x,Object y){ + return Num.from(y).subtractFrom(Num.from(x)); + } + //this double-dispatches to addTo(-self) + abstract public Num subtractFrom(Num rhs); + + static public Num multiply(Object x,Object y) { + return Num.from(x).multiplyBy(Num.from(y)); + } + abstract public Num multiplyBy(Num rhs); + abstract public Num multiply(int x); + abstract public Num multiply(BigInteger x); + abstract public Num multiply(RatioNum x); + + static public Num divide(Object x,Object y){ + return Num.from(x).divideBy(Num.from(y)); + } + + abstract public Num divideBy(Num rhs); + abstract public Num divide(int x); + abstract public Num divide(BigInteger x); + abstract public Num divide(RatioNum x); + + static public Object truncate(ThreadLocalData tld, Object num, Object div) { + return Num.from(div).truncateDivide(tld, Num.from(num)); + } + + abstract public Object truncateDivide(ThreadLocalData tld, Num rhs) ; + abstract public Object truncateBy(ThreadLocalData tld, int x) ; + abstract public Object truncateBy(ThreadLocalData tld, BigInteger x) ; + abstract public Object truncateBy(ThreadLocalData tld, RatioNum x) ; + + static public Object truncateBigints(ThreadLocalData tld, BigInteger n, BigInteger d){ + BigInteger[] result = n.divideAndRemainder(d); + return RT.setValues(tld,Num.from(result[0]),Num.from(result[1])); + } + + static public Num divide(BigInteger n,BigInteger d) { + BigInteger gcd = n.gcd(d); + if(gcd.equals(BigInteger.ZERO)) + return Num.ZERO; + n = n.divide(gcd); + d = d.divide(gcd); + if(d.equals(BigInteger.ONE)) + return Num.from(n); + return new RatioNum((IntegerNum)Num.from(d.signum() < 0 ? n.negate():n), + (IntegerNum)Num.from(d.signum() < 0 ? d.negate():d)); + } + + static public boolean equiv(Object x,Object y) throws Exception{ + return Num.from(x).equiv(Num.from(y)); + } + abstract public boolean equiv(Num rhs) ; + abstract public boolean equivTo(int x) ; + abstract public boolean equivTo(BigInteger x) ; + abstract public boolean equivTo(RatioNum x) ; + + static public boolean lt(Object x,Object y) throws Exception{ + return Num.from(x).lt(Num.from(y)); + } + static public boolean lte(Object x,Object y) throws Exception{ + Num lx = Num.from(x); + Num ly = Num.from(y); + return lx.lt(ly) || lx.equiv(ly); + } + + static public boolean gt(Object x,Object y) throws Exception{ + return Num.from(y).lt(Num.from(x)); + } + + static public boolean gte(Object x,Object y) throws Exception{ + Num lx = Num.from(x); + Num ly = Num.from(y); + return ly.lt(lx) || lx.equiv(ly); + } + + abstract public boolean lt(Num rhs) throws Exception; + abstract public boolean gt(int x) throws Exception; + abstract public boolean gt(BigInteger x) throws Exception; + abstract public boolean gt(RatioNum x) throws Exception; + + static public Num negate(Object x) throws Exception{ + return Num.from(x).negate(); + } + abstract public Num negate() throws Exception; + + abstract public boolean minusp(); + abstract public boolean plusp(); + abstract public Num oneMinus(); + abstract public Num onePlus(); + +} diff --git a/src/org/clojure/runtime/RatioNum.java b/src/org/clojure/runtime/RatioNum.java new file mode 100644 index 00000000..d30c9d99 --- /dev/null +++ b/src/org/clojure/runtime/RatioNum.java @@ -0,0 +1,171 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:14:44 AM */ + +package org.clojure.runtime; + +import java.math.BigInteger; + +public class RatioNum extends Rational { + public boolean equals(Object arg0) { + return arg0 != null + && arg0 instanceof RatioNum + && ((RatioNum)arg0).numerator.equals(numerator) + && ((RatioNum)arg0).denominator.equals(denominator); + } + + public int hashCode() { + return numerator.hashCode() ^ denominator.hashCode(); + } + + public String toString() { + return numerator.toString() + "/" + denominator.toString(); + } + + public IntegerNum numerator; + public IntegerNum denominator; + + public RatioNum(IntegerNum n,IntegerNum d){ + this.numerator = n; + this.denominator = d; + } + + public double doubleValue() { + return numerator.doubleValue()/denominator.doubleValue(); + } + public float floatValue() { + return (float)doubleValue(); + } + public int intValue() { + return (int)doubleValue(); + } + public long longValue() { + return (long)doubleValue(); + } + + public boolean equiv(Num rhs) { + return rhs.equivTo(this); + } + public boolean equivTo(BigInteger x) { + return false; + } + public boolean equivTo(int x) { + return false; + } + public boolean equivTo(RatioNum x) { + return numerator.equiv(x.numerator) && denominator.equiv(x.denominator); + } + + public boolean lt(Num rhs) throws Exception { + return rhs.gt(this); + } + public boolean gt(BigInteger x) throws Exception { + return denominator.multiply(x).lt(numerator); + } + public boolean gt(int x) throws Exception { + return denominator.multiply(x).lt(numerator); + } + public boolean gt(RatioNum x) throws Exception { + return x.numerator.multiplyBy(denominator).lt(numerator.multiplyBy(x.denominator)); + } + + public Num add(Num rhs) { + return rhs.addTo(this); + } + + public Num addTo(BigInteger x) { + return Num.divide(numerator.add(denominator.multiply(x)),denominator); + } + public Num addTo(int x) { + return Num.divide(numerator.add(denominator.multiply(x)),denominator); + } + public Num addTo(RatioNum x) { + return Num.divide(numerator.multiplyBy(x.denominator) + .add(x.numerator.multiplyBy(denominator)) + ,denominator.multiplyBy(x.denominator)); + } + + public Num subtractFrom(Num x) { + return x.add(this.multiply(-1)); + } + + public Num multiplyBy(Num rhs) { + return rhs.multiply(this); + } + + public Num multiply(BigInteger x) { + return Num.divide(numerator.multiply(x),denominator); + } + public Num multiply(int x) { + return Num.divide(numerator.multiply(x),denominator); + } + public Num multiply(RatioNum x) { + return Num.divide(numerator.multiplyBy(x.numerator) + ,denominator.multiplyBy(x.denominator)); + } + + public Num divideBy(Num rhs) { + return rhs.divide(this); + } + + public Num divide(BigInteger n) { + return Num.divide(denominator.multiply(n),numerator); + } + public Num divide(int n) { + return Num.divide(denominator.multiply(n),numerator); + } + public Num divide(RatioNum n) { + return Num.divide(denominator.multiplyBy(n.numerator) + ,numerator.multiplyBy(n.denominator)); + } + + + public Object truncateDivide(ThreadLocalData tld, Num num) { + return num.truncateBy(tld, this); + } + + public Object truncateBy(ThreadLocalData tld, int div) { + Num q = (Num)Num.truncate(tld, numerator,denominator.multiply(div)); + return RT.setValues(tld,q,q.multiply(div).subtractFrom(this)); + } + + public Object truncateBy(ThreadLocalData tld, BigInteger div) { + Num q = (Num)Num.truncate(tld, numerator,denominator.multiply(div)); + return RT.setValues(tld,q,q.multiply(div).subtractFrom(this)); + } + + public Object truncateBy(ThreadLocalData tld, RatioNum div) { + Num q = (Num)Num.truncate(tld, numerator.multiplyBy(div.denominator), + denominator.multiplyBy(div.numerator)); + return RT.setValues(tld,q,q.multiplyBy(div).subtractFrom(this)); + } + + + public Num negate() throws Exception{ + return Num.divide(numerator.negate(),denominator); + } + + public boolean minusp() { + return numerator.minusp(); + } + public boolean plusp() { + return numerator.plusp(); + } + + public Num oneMinus() { + return addTo(-1); + } + public Num onePlus() { + return addTo(1); + } + +} + diff --git a/src/org/clojure/runtime/Rational.java b/src/org/clojure/runtime/Rational.java new file mode 100644 index 00000000..c3d2b545 --- /dev/null +++ b/src/org/clojure/runtime/Rational.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:12:30 AM */ + +package org.clojure.runtime; + +public abstract class Rational extends RealNum { + +} diff --git a/src/org/clojure/runtime/RealNum.java b/src/org/clojure/runtime/RealNum.java new file mode 100644 index 00000000..387f0a23 --- /dev/null +++ b/src/org/clojure/runtime/RealNum.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Mar 28, 2006 10:13:00 AM */ + +package org.clojure.runtime; + +public abstract class RealNum extends Num { + +} |