From 411793e1ba329a47eb692617ff37f9fcc22341f8 Mon Sep 17 00:00:00 2001 From: michelou Date: Wed, 6 Feb 2008 14:45:52 +0000 Subject: added class BigDecimal --- src/library/scala/BigDecimal.scala | 322 +++++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 src/library/scala/BigDecimal.scala (limited to 'src') diff --git a/src/library/scala/BigDecimal.scala b/src/library/scala/BigDecimal.scala new file mode 100644 index 0000000000..3905c44cfd --- /dev/null +++ b/src/library/scala/BigDecimal.scala @@ -0,0 +1,322 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: $ + +package scala + +import java.math.{BigDecimal => BigDec, MathContext} + +/** + * @author Stephane Micheloud + * @version 1.0 + */ +object BigDecimal { + + private val minCached = -256 + private val maxCached = 256 + private lazy val cache = new Array[BigDecimal](maxCached - minCached + 1) + private lazy val cacheP = new Array[Array[BigDecimal]](maxCached - minCached + 1) + + object Precision extends Enumeration { + type Precision = Value + val DECIMAL128, DECIMAL32, DECIMAL64, UNLIMITED = Value + } + type Precision = Precision.Precision + + private val mc = collection.immutable.ListMap.empty[Precision, MathContext] + + (Precision.DECIMAL128 -> MathContext.DECIMAL128) + + (Precision.DECIMAL32 -> MathContext.DECIMAL32) + + (Precision.DECIMAL64 -> MathContext.DECIMAL64) + + (Precision.UNLIMITED -> MathContext.UNLIMITED) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified Integer value. + * + * @param i the specified Integer value + * @param p the specified precision p + * @return the constructed BigDecimal + */ + def apply(i: Int, p: Precision): BigDecimal = + if (minCached <= i && i <= maxCached) { + val offset = i - minCached + var a = cacheP(offset) + if (a eq null) { a = new Array[BigDecimal](mc.size); cacheP(offset) = a } + var n = a(p.id) + if (n eq null) { n = new BigDecimal(BigDec.valueOf(i)); a(p.id) = n } + n + } else new BigDecimal(BigDec.valueOf(i)) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified Integer value. + * + * @param i the specified integer value + * @return the constructed BigDecimal + */ + def apply(i: Int): BigDecimal = + if (minCached <= i && i <= maxCached) { + val offset = i - minCached + var n = cache(offset) + if (n eq null) { n = new BigDecimal(BigDec.valueOf(i)); cache(offset) = n } + n + } else new BigDecimal(BigDec.valueOf(i)) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified Long value. + * + * @param l the specified long value + * @param p the specified precision + * @return the constructed BigDecimal + */ + def apply(l: Long, p: Precision): BigDecimal = + if (minCached <= l && l <= maxCached) apply(l.toInt, p) + else new BigDecimal(BigDec.valueOf(l)) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified long value. + * + * @param l the specified long value + * @return the constructed BigDecimal + */ + def apply(l: Long): BigDecimal = + if (minCached <= l && l <= maxCached) apply(l.toInt) + else new BigDecimal(BigDec.valueOf(l)) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified Double value. + * + * @param d the specified Double value + * @param p the specified precision + * @return the constructed BigDecimal + */ + def apply(d: Double, p: Precision): BigDecimal = + new BigDecimal(new BigDec(d, mc(p))) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified double value. + * + * @param d the specified Double value + * @return the constructed BigDecimal + */ + def apply(d: Double): BigDecimal = + new BigDecimal(BigDec.valueOf(d)) + + /** Translates a character array representation of a BigDecimal + * into a BigDecimal. + */ + def apply(x: Array[Char]): BigDecimal = + new BigDecimal(new BigDec(x)) + + /** Translates the decimal String representation of a BigDecimal + * into a BigDecimal. + */ + def apply(x: String, p: Precision): BigDecimal = + new BigDecimal(new BigDec(x, mc(p))) + + /** Translates the decimal String representation of a BigDecimal + * into a BigDecimal. + */ + def apply(x: String): BigDecimal = + new BigDecimal(new BigDec(x)) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified BigInt value. + * + * @param x the specified BigInt value + * @param p the specified precision p + * @return the constructed BigDecimal + */ + def apply(x: BigInt, p: Precision): BigDecimal = + new BigDecimal(new BigDec(x.bigInteger, mc(p))) + + /** Constructs a BigDecimal whose value is equal to that of the + * specified BigInt value. + * + * @param x the specified BigInt value + * @return the constructed BigDecimal + */ + def apply(x: BigInt): BigDecimal = + new BigDecimal(new BigDec(x.bigInteger)) + + /** Implicit conversion from Int to BigDecimal. */ + implicit def int2bigDecimal(i: Int): BigDecimal = apply(i) + + /** Implicit copnversion from Long to BigDecimal. */ + implicit def long2bigDecimal(l: Long): BigDecimal = apply(l) + + /** Implicit copnversion from Double to BigDecimal. */ + implicit def double2bigDecimal(d: Double): BigDecimal = apply(d) + + /** Implicit conversion from BigDecimal to Ordered. */ + implicit def bigDecimal2ordered(x: BigDecimal): Ordered[BigDecimal] = + new Ordered[BigDecimal] with Proxy { + def self: Any = x; + def compare (y: BigDecimal): Int = x.bigDecimal.compareTo(y.bigDecimal) + } +} + +/** + * @author Stephane Micheloud + * @version 1.0 + */ +@serializable +class BigDecimal(val bigDecimal: BigDec) extends java.lang.Number { + + /** Returns the hash code for this BigDecimal. */ + override def hashCode(): Int = this.bigDecimal.hashCode() + + /** Compares this BigDecimal with the specified value for equality. + */ + override def equals (that: Any): Boolean = that match { + case that: BigDecimal => this equals that + case that: java.lang.Double => this.bigDecimal.doubleValue == that.doubleValue + case that: java.lang.Float => this.bigDecimal.floatValue == that.floatValue + case that: java.lang.Number => this equals BigDecimal(that.longValue) + case that: java.lang.Character => this equals BigDecimal(that.charValue.asInstanceOf[Int]) + case _ => false + } + + /** Compares this BigDecimal with the specified BigDecimal for equality. + */ + def equals (that: BigDecimal): Boolean = + this.bigDecimal.compareTo(that.bigDecimal) == 0 + + /** Compares this BigDecimal with the specified BigDecimal + */ + def compare (that: BigDecimal): Int = this.bigDecimal.compareTo(that.bigDecimal) + + /** Less-than-or-equals comparison of BigDecimals + */ + def <= (that: BigDecimal): Boolean = this.bigDecimal.compareTo(that.bigDecimal) <= 0 + + /** Greater-than-or-equals comparison of BigDecimals + */ + def >= (that: BigDecimal): Boolean = this.bigDecimal.compareTo(that.bigDecimal) >= 0 + + /** Less-than of BigDecimals + */ + def < (that: BigDecimal): Boolean = this.bigDecimal.compareTo(that.bigDecimal) < 0 + + /** Greater-than comparison of BigDecimals + */ + def > (that: BigDecimal): Boolean = this.bigDecimal.compareTo(that.bigDecimal) > 0 + + /** Addition of BigDecimals + */ + def + (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.add(that.bigDecimal)) + + /** Subtraction of BigDecimals + */ + def - (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.subtract(that.bigDecimal)) + + /** Multiplication of BigDecimals + */ + def * (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.multiply(that.bigDecimal)) + + /** Division of BigDecimals + */ + def / (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.divide(that.bigDecimal)) + + /** Remainder of BigDecimals + */ + def % (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.remainder(that.bigDecimal)) + + /** Returns a pair of two BigDecimals containing (this / that) and (this % that). + */ + def /% (that: BigDecimal): (BigDecimal, BigDecimal) = { + val dr = this.bigDecimal.divideAndRemainder(that.bigDecimal) + (new BigDecimal(dr(0)), new BigDecimal(dr(1))) + } + + /** Returns the minimum of this and that + */ + def min (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.min(that.bigDecimal)) + + /** Returns the maximum of this and that + */ + def max (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.max(that.bigDecimal)) + + /** Returns a BigDecimal whose value is (this raised to the power of exp). + */ + def pow (exp: Int): BigDecimal = new BigDecimal(this.bigDecimal.pow(exp)) + + /** Returns a BigDecimal whose value is the negation of this BigDecimal + */ + def unary_- : BigDecimal = new BigDecimal(this.bigDecimal.negate()) + + /** Returns the absolute value of this BigDecimal + */ + def abs: BigDecimal = new BigDecimal(this.bigDecimal.abs()) + + /** Returns the sign of this BigDecimal, i.e. + * -1 if it is less than 0, + * +1 if it is greater than 0 + * 0 if it is equal to 0 + */ + def signum: Int = this.bigDecimal.signum() + + /** Converts this BigDecimal to a byte. + * If the BigDecimal is too big to fit in a byte, only the low-order 8 bits are returned. + * Note that this conversion can lose information about the overall magnitude of the + * BigDecimal value as well as return a result with the opposite sign. + */ + override def byteValue = intValue.toByte + + /** Converts this BigDecimal to a short. + * If the BigDecimal is too big to fit in a byte, only the low-order 16 bits are returned. + * Note that this conversion can lose information about the overall magnitude of the + * BigDecimal value as well as return a result with the opposite sign. + */ + override def shortValue = intValue.toShort + + /** Converts this BigDecimal to a char. + * If the BigDecimal is too big to fit in a char, only the low-order 16 bits are returned. + * Note that this conversion can lose information about the overall magnitude of the + * BigDecimal value and that it always returns a positive result. + */ + def charValue = intValue.toChar + + /** Converts this BigDecimal to an int. + * If the BigDecimal is too big to fit in a char, only the low-order 32 bits + * are returned. Note that this conversion can lose information about the + * overall magnitude of the BigDecimal value as well as return a result with + * the opposite sign. + */ + def intValue = this.bigDecimal.intValue + + /** Converts this BigDecimal to a Long. + * If the BigDecimal is too big to fit in a char, only the low-order 64 bits + * are returned. Note that this conversion can lose information about the + * overall magnitude of the BigDecimal value as well as return a result with + * the opposite sign. + */ + def longValue = this.bigDecimal.longValue + + /** Converts this BigDecimal to a float. + * if this BigDecimal has too great a magnitude to represent as a float, + * it will be converted to Float.NEGATIVE_INFINITY or + * Float.POSITIVE_INFINITY as appropriate. + */ + def floatValue = this.bigDecimal.floatValue + + /** Converts this BigDecimal to a Double. + * if this BigDecimal has too great a magnitude to represent as a float, + * it will be converted to Float.NEGATIVE_INFINITY or + * Float.POSITIVE_INFINITY as appropriate. + */ + def doubleValue = this.bigDecimal.doubleValue + + /** Returns the decimal String representation of this BigDecimal. + */ + override def toString(): String = this.bigDecimal.toString() + + /** Returns a string representation of this BigDecimal without an exponent field. + */ + def toPlainString(): String = this.bigDecimal.toPlainString() + +} -- cgit v1.2.3