diff options
-rw-r--r-- | src/library/scala/BigDecimal.scala | 90 | ||||
-rw-r--r-- | src/library/scala/BigInt.scala | 26 |
2 files changed, 87 insertions, 29 deletions
diff --git a/src/library/scala/BigDecimal.scala b/src/library/scala/BigDecimal.scala index 54409bfa32..27d1c19b26 100644 --- a/src/library/scala/BigDecimal.scala +++ b/src/library/scala/BigDecimal.scala @@ -37,13 +37,14 @@ object BigDecimal * @param i the specified integer value * @return the constructed <code>BigDecimal</code> */ - def apply(i: Int): BigDecimal = + def apply(i: Int): BigDecimal = apply(i, defaultMathContext) + def apply(i: Int, mc: MathContext): 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 } + if (n eq null) { n = new BigDecimal(BigDec.valueOf(i), mc); cache(offset) = n } n - } else new BigDecimal(BigDec.valueOf(i)) + } else new BigDecimal(BigDec.valueOf(i), mc) /** Constructs a <code>BigDecimal</code> whose value is equal to that of the * specified long value. @@ -53,11 +54,23 @@ object BigDecimal */ def apply(l: Long): BigDecimal = if (minCached <= l && l <= maxCached) apply(l.toInt) - else new BigDecimal(BigDec.valueOf(l)) + else new BigDecimal(BigDec.valueOf(l), defaultMathContext) + def apply(l: Long, mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(l, mc), mc) + + /** Constructs a <code>BigDecimal</code> whose unscaled value is equal to that + * of the specified long value. + * + * @param unscaledVal the value + * @param scale the scale + * @return the constructed <code>BigDecimal</code> + */ def apply(unscaledVal: Long, scale: Int): BigDecimal = - if (scale == 0) apply(unscaledVal) - else new BigDecimal(BigDec.valueOf(unscaledVal, scale)) + apply(BigInt(unscaledVal), scale) + + def apply(unscaledVal: Long, scale: Int, mc: MathContext): BigDecimal = + apply(BigInt(unscaledVal), scale, mc) /** Constructs a <code>BigDecimal</code> whose value is equal to that of the * specified double value. @@ -65,21 +78,23 @@ object BigDecimal * @param d the specified <code>Double</code> value * @return the constructed <code>BigDecimal</code> */ - def apply(d: Double): BigDecimal = - new BigDecimal(BigDec.valueOf(d)) + def apply(d: Double): BigDecimal = apply(d, defaultMathContext) + // note we don't use the static valueOf because it doesn't let us supply + // a MathContext, but we should be duplicating its logic, modulo caching. + def apply(d: Double, mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(java.lang.Double.toString(d), mc), mc) /** Translates a character array representation of a <code>BigDecimal</code> * into a <code>BigDecimal</code>. */ - def apply(x: Array[Char]): BigDecimal = - new BigDecimal(new BigDec(x.toString)) + def apply(x: Array[Char]): BigDecimal = apply(x, defaultMathContext) + def apply(x: Array[Char], mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(x.toString, mc), mc) /** Translates the decimal String representation of a <code>BigDecimal</code> * into a <code>BigDecimal</code>. */ - def apply(x: String): BigDecimal = - new BigDecimal(new BigDec(x)) - + def apply(x: String): BigDecimal = apply(x, defaultMathContext) def apply(x: String, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(x, mc), mc) @@ -89,8 +104,23 @@ object BigDecimal * @param x the specified <code>BigInt</code> value * @return the constructed <code>BigDecimal</code> */ - def apply(x: BigInt): BigDecimal = - new BigDecimal(new BigDec(x.bigInteger)) + def apply(x: BigInt): BigDecimal = apply(x, defaultMathContext) + def apply(x: BigInt, mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(x.bigInteger, mc), mc) + + /** Constructs a <code>BigDecimal</code> whose unscaled value is equal to that + * of the specified <code>BigInt</code> value. + * + * @param unscaledVal the specified <code>BigInt</code> value + * @param scale the scale + * @return the constructed <code>BigDecimal</code> + */ + def apply(unscaledVal: BigInt, scale: Int): BigDecimal = apply(unscaledVal, scale, defaultMathContext) + def apply(unscaledVal: BigInt, scale: Int, mc: MathContext): BigDecimal = + new BigDecimal(new BigDec(unscaledVal.bigInteger, scale, mc), mc) + + def apply(bd: BigDec): BigDecimal = apply(bd, defaultMathContext) + def apply(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd, mc) /** Implicit conversion from <code>Int</code> to <code>BigDecimal</code>. */ implicit def int2bigDecimal(i: Int): BigDecimal = apply(i) @@ -115,6 +145,11 @@ object BigDecimal * @since 2.8 */ implicit def bigInt2bigDecimal(x: BigInt): BigDecimal = apply(x) + + // Anyone can subclass Number, so we can't just assume .longValue is an unrounded + // representation (as it cannot be for anything larger than Long.) So we also confirm + // that at least x thinks it's equal to x.longValue. + private[scala] def equalsOwnLongValue(that: Number): Boolean = that == that.longValue } /** @@ -129,6 +164,7 @@ extends java.lang.Number { def this(bigDecimal: BigDec) = this(bigDecimal, BigDecimal.defaultMathContext) import BigDecimal.RoundingMode._ + import BigDecimal.equalsOwnLongValue /** Cuts way down on the wrapper noise. */ private implicit def bigdec2BigDecimal(x: BigDec): BigDecimal = new BigDecimal(x, mc) @@ -138,13 +174,16 @@ extends java.lang.Number /** 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 + override def equals (that: Any): Boolean = that match { + case that: BigDecimal => this equals that + case that: BigDec => this equals BigDecimal(that) + case that: BigInt => this equals BigDecimal(that) + case that: java.math.BigInteger => this equals BigDecimal(new BigInt(that), mc) + case that: java.lang.Double => this equals BigDecimal(that.doubleValue) + case that: java.lang.Float => this equals BigDecimal(that.floatValue) + case that: java.lang.Number => equalsOwnLongValue(that) && (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. @@ -327,6 +366,13 @@ extends java.lang.Number */ def toBigInt(): BigInt = new BigInt(this.bigDecimal.toBigInteger()) + /** Converts this <code>BigDecimal</code> to a scala.BigInt if it + * can be done losslessly, returning Some(BigInt) or None. + */ + def toBigIntExact(): Option[BigInt] = + try Some(new BigInt(this.bigDecimal.toBigIntegerExact())) + catch { case _: ArithmeticException => None } + /** Returns the decimal String representation of this BigDecimal. */ override def toString(): String = this.bigDecimal.toString() diff --git a/src/library/scala/BigInt.scala b/src/library/scala/BigInt.scala index ac8b4c40a7..abed8c748d 100644 --- a/src/library/scala/BigInt.scala +++ b/src/library/scala/BigInt.scala @@ -108,7 +108,9 @@ object BigInt { * @version 1.0, 15/07/2003 */ @serializable -class BigInt(val bigInteger: BigInteger) extends java.lang.Number { +class BigInt(val bigInteger: BigInteger) extends java.lang.Number +{ + import BigDecimal.equalsOwnLongValue /** Returns the hash code for this BigInt. */ override def hashCode(): Int = this.bigInteger.hashCode() @@ -116,12 +118,15 @@ class BigInt(val bigInteger: BigInteger) extends java.lang.Number { /** Compares this BigInt with the specified value for equality. */ override def equals (that: Any): Boolean = that match { - case that: BigInt => this equals that - case that: java.lang.Double => this.bigInteger.doubleValue == that.doubleValue - case that: java.lang.Float => this.bigInteger.floatValue == that.floatValue - case that: java.lang.Number => this equals BigInt(that.longValue) - case that: java.lang.Character => this equals BigInt(that.charValue.asInstanceOf[Int]) - case _ => false + case that: BigInt => this equals that + case that: BigInteger => this equals new BigInt(that) + case that: BigDecimal => this equals that + case that: java.math.BigDecimal => this equals BigDecimal(that) + case that: java.lang.Double => this equals BigDecimal(that.doubleValue) + case that: java.lang.Float => this equals BigDecimal(that.floatValue) + case that: java.lang.Number => equalsOwnLongValue(that) && (this equals BigInt(that.longValue)) + case that: java.lang.Character => this equals BigInt(that.charValue.asInstanceOf[Int]) + case _ => false } /** Compares this BigInt with the specified BigInt for equality. @@ -129,6 +134,13 @@ class BigInt(val bigInteger: BigInteger) extends java.lang.Number { def equals (that: BigInt): Boolean = this.bigInteger.compareTo(that.bigInteger) == 0 + /** Compares this BigInt with the specified BigDecimal for equality. + */ + def equals(that: BigDecimal): Boolean = that.toBigIntExact match { + case None => false + case Some(x) => this equals x + } + /** Compares this BigInt with the specified BigInt */ def compare (that: BigInt): Int = this.bigInteger.compareTo(that.bigInteger) |