diff options
author | Paul Phillips <paulp@improving.org> | 2010-04-13 18:24:48 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-04-13 18:24:48 +0000 |
commit | 382dd00508882f15ffd086588903380d7980b35c (patch) | |
tree | 157c4c41e2ac7f2418c45fd5db91a06af761879f /src/library | |
parent | 27288e3ffe2224bb206e79204542c26a2779223b (diff) | |
download | scala-382dd00508882f15ffd086588903380d7980b35c.tar.gz scala-382dd00508882f15ffd086588903380d7980b35c.tar.bz2 scala-382dd00508882f15ffd086588903380d7980b35c.zip |
Some mopping up in equality.
way equals was being handled, and hammered it out. New ==/## tests which
covers all types and values. Review by odersky.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/math/BigDecimal.scala | 6 | ||||
-rw-r--r-- | src/library/scala/math/BigInt.scala | 2 | ||||
-rw-r--r-- | src/library/scala/math/ScalaNumericConversions.scala | 21 |
3 files changed, 22 insertions, 7 deletions
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index bb6965fcdc..c4cccd1f52 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -30,6 +30,9 @@ object BigDecimal private val minCached = -512 private val maxCached = 512 + val MinLong = BigDecimal(Long.MinValue) + val MaxLong = BigDecimal(Long.MaxValue) + /** Cache ony for defaultMathContext using BigDecimals in a small range. */ private lazy val cache = new Array[BigDecimal](maxCached - minCached + 1) @@ -173,12 +176,11 @@ extends ScalaNumber with ScalaNumericConversions else doubleValue.hashCode() /** Compares this BigDecimal with the specified value for equality. - * Will only claim equality with scala.BigDecimal and java.math.BigDecimal. */ override def equals (that: Any): Boolean = that match { case that: BigDecimal => this equals that case that: BigInt => this.toBigIntExact exists (that equals _) - case x => unifiedPrimitiveEquals(x) + case x => (this <= BigDecimal.MaxLong && this >= BigDecimal.MinLong) && unifiedPrimitiveEquals(x) } protected[math] def isWhole = (this remainder 1) == BigDecimal(0) diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala index 5267ad8b95..f0988f2934 100644 --- a/src/library/scala/math/BigInt.scala +++ b/src/library/scala/math/BigInt.scala @@ -124,7 +124,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo override def equals(that: Any): Boolean = that match { case that: BigInt => this equals that case that: BigDecimal => that.toBigIntExact exists (this equals _) - case x => unifiedPrimitiveEquals(x) + case x => (this <= BigInt.MaxLong && this >= BigInt.MinLong) && unifiedPrimitiveEquals(x) } protected[math] def isWhole = true diff --git a/src/library/scala/math/ScalaNumericConversions.scala b/src/library/scala/math/ScalaNumericConversions.scala index d983595c17..2e754c2584 100644 --- a/src/library/scala/math/ScalaNumericConversions.scala +++ b/src/library/scala/math/ScalaNumericConversions.scala @@ -33,15 +33,28 @@ trait ScalaNumericConversions extends ScalaNumber { else lv.hashCode } + /** Should only be called after all known non-primitive + * types have been excluded. This method won't dispatch + * anywhere else after checking against the primitives + * to avoid infinite recursion between equals and this on + * unknown "Number" variants. + * + * Additionally, this should only be called if the numeric + * type is happy to be converted to Long, Float, and Double. + * If for instance a BigInt much larger than the Long range is + * sent here, it will claim equality with whatever Long is left + * in its lower 64 bits. Or a BigDecimal with more precision + * than Double can hold: same thing. There's no way given the + * interface available here to prevent this error. + */ protected def unifiedPrimitiveEquals(x: Any) = x match { case x: Char => isValidChar && (toInt == x.toInt) case x: Byte => isValidByte && (toByte == x) case x: Short => isValidShort && (toShort == x) case x: Int => isValidInt && (toInt == x) - case x: Long => toLong == x // XXX - case x: Float => toFloat == x // XXX - case x: Double => toDouble == x // XXX - case x: Number => this equals x + case x: Long => toLong == x + case x: Float => toFloat == x + case x: Double => toDouble == x case _ => false } } |