summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-03-28 16:07:04 +0000
committerRich Hickey <richhickey@gmail.com>2006-03-28 16:07:04 +0000
commite63b0c3f98628dce4a9a829466ab67d175dd4414 (patch)
treea8a591387d9c8fbe146936782f4ce12457fdd125 /src
parent3d18eff96403ddee6c3a82307c255dff3500c94a (diff)
first cut of numbers
Diffstat (limited to 'src')
-rw-r--r--src/org/clojure/runtime/DoubleNum.java176
-rw-r--r--src/org/clojure/runtime/FloatNum.java17
-rw-r--r--src/org/clojure/runtime/IntegerNum.java17
-rw-r--r--src/org/clojure/runtime/Num.java164
-rw-r--r--src/org/clojure/runtime/RatioNum.java171
-rw-r--r--src/org/clojure/runtime/Rational.java17
-rw-r--r--src/org/clojure/runtime/RealNum.java17
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 {
+
+}