summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/Enumeration.scala4
-rw-r--r--src/library/scala/Predef.scala2
-rw-r--r--src/library/scala/StringContext.scala5
-rw-r--r--src/library/scala/collection/generic/ImmutableSetFactory.scala3
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala4
-rw-r--r--src/library/scala/collection/immutable/ListSet.scala3
-rw-r--r--src/library/scala/collection/immutable/Set.scala4
-rw-r--r--src/library/scala/collection/immutable/Stream.scala18
-rw-r--r--src/library/scala/collection/immutable/StringLike.scala4
-rw-r--r--src/library/scala/collection/mutable/AVLTree.scala10
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala52
-rw-r--r--src/library/scala/io/Position.scala4
-rw-r--r--src/library/scala/math/BigDecimal.scala479
-rw-r--r--src/library/scala/math/BigInt.scala2
-rw-r--r--src/library/scala/reflect/package.scala15
-rw-r--r--src/library/scala/util/matching/Regex.scala8
16 files changed, 499 insertions, 118 deletions
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index 59be0cdfa3..d4b9c17eab 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -11,7 +11,7 @@ package scala
import scala.collection.{ mutable, immutable, generic, SortedSetLike, AbstractSet }
import java.lang.reflect.{ Modifier, Method => JMethod, Field => JField }
import scala.reflect.NameTransformer._
-import java.util.regex.Pattern
+import scala.util.matching.Regex
/** Defines a finite set of values specific to the enumeration. Typically
* these values enumerate all possible forms something can take and provide
@@ -64,7 +64,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
*/
override def toString =
((getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.').last split
- Pattern.quote(NAME_JOIN_STRING)).last
+ Regex.quote(NAME_JOIN_STRING)).last
/** The mapping from the integer used to identify values to the actual
* values. */
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 8900450fa3..ec587c158d 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -95,8 +95,6 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
type Set[A] = immutable.Set[A]
val Map = immutable.Map
val Set = immutable.Set
- // @deprecated("Use scala.AnyRef instead", "2.10.0")
- // def AnyRef = scala.AnyRef
// Manifest types, companions, and incantations for summoning
@annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.")
diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala
index 70f95750da..2d79452c5d 100644
--- a/src/library/scala/StringContext.scala
+++ b/src/library/scala/StringContext.scala
@@ -157,9 +157,8 @@ case class StringContext(parts: String*) {
* If a formatting position does not refer to a `%` character (which is assumed to
* start a format specifier), then the string format specifier `%s` is inserted.
*
- * 2. Any `%` characters not in formatting positions are left in the resulting
- * string literally. This is achieved by replacing each such occurrence by the
- * format specifier `%%`.
+ * 2. Any `%` characters not in formatting positions must begin one of the conversions
+ * `%%` (the literal percent) or `%n` (the platform-specific line separator).
*/
// The implementation is hardwired to `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f`
// Using the mechanism implemented in `scala.tools.reflect.FastTrack`
diff --git a/src/library/scala/collection/generic/ImmutableSetFactory.scala b/src/library/scala/collection/generic/ImmutableSetFactory.scala
index f4d4e061bb..a72caf2633 100644
--- a/src/library/scala/collection/generic/ImmutableSetFactory.scala
+++ b/src/library/scala/collection/generic/ImmutableSetFactory.scala
@@ -15,6 +15,7 @@ import scala.language.higherKinds
abstract class ImmutableSetFactory[CC[X] <: immutable.Set[X] with SetLike[X, CC[X]]]
extends SetFactory[CC] {
-
+ private[collection] def emptyInstance: CC[Any]
+ override def empty[A] = emptyInstance.asInstanceOf[CC[A]]
def newBuilder[A]: Builder[A, CC[A]] = new SetBuilder[A, CC[A]](empty[A])
}
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 062fe7c158..127b22185a 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -137,10 +137,10 @@ object HashSet extends ImmutableSetFactory[HashSet] {
/** $setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, HashSet[A]] = setCanBuildFrom[A]
- override def empty[A]: HashSet[A] = EmptyHashSet.asInstanceOf[HashSet[A]]
private object EmptyHashSet extends HashSet[Any] { }
-
+ private[collection] def emptyInstance: HashSet[Any] = EmptyHashSet
+
// utility method to create a HashTrieSet from two leaf HashSets (HashSet1 or HashSetCollision1) with non-colliding hash code)
private def makeHashTrieSet[A](hash0:Int, elem0:HashSet[A], hash1:Int, elem1:HashSet[A], level:Int) : HashTrieSet[A] = {
val index0 = (hash0 >>> level) & 0x1f
diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala
index 7ebaa26d26..1bb07eb02d 100644
--- a/src/library/scala/collection/immutable/ListSet.scala
+++ b/src/library/scala/collection/immutable/ListSet.scala
@@ -22,10 +22,11 @@ import mutable.{ ListBuffer, Builder }
object ListSet extends ImmutableSetFactory[ListSet] {
/** setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ListSet[A]] = setCanBuildFrom[A]
- override def empty[A] = EmptyListSet.asInstanceOf[ListSet[A]]
+
override def newBuilder[A]: Builder[A, ListSet[A]] = new ListSetBuilder[A]
private object EmptyListSet extends ListSet[Any] { }
+ private[collection] def emptyInstance: ListSet[Any] = EmptyListSet
/** A custom builder because forgetfully adding elements one at
* a time to a list backed set puts the "squared" in N^2. There is a
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
index a888955bb2..e21a8dfa8a 100644
--- a/src/library/scala/collection/immutable/Set.scala
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -53,8 +53,7 @@ trait Set[A] extends Iterable[A]
object Set extends ImmutableSetFactory[Set] {
/** $setCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
- override def empty[A]: Set[A] = EmptySet.asInstanceOf[Set[A]]
-
+
/** An optimized representation for immutable empty sets */
private object EmptySet extends AbstractSet[Any] with Set[Any] with Serializable {
override def size: Int = 0
@@ -64,6 +63,7 @@ object Set extends ImmutableSetFactory[Set] {
def iterator: Iterator[Any] = Iterator.empty
override def foreach[U](f: Any => U): Unit = {}
}
+ private[collection] def emptyInstance: Set[Any] = EmptySet
/** An optimized representation for immutable sets of size 1 */
@SerialVersionUID(1233385750652442003L)
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index a82e31f5da..49c3b4c3cd 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -960,14 +960,16 @@ self =>
* }}}
*/
override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): Stream[B] = {
- def flatten1(t: Traversable[B]): Stream[B] =
- if (!t.isEmpty)
- cons(t.head, flatten1(t.tail))
- else
- tail.flatten
-
- if (isEmpty) Stream.empty
- else flatten1(asTraversable(head).seq.toTraversable)
+ var st: Stream[A] = this
+ while (st.nonEmpty) {
+ val h = asTraversable(st.head)
+ if (h.isEmpty) {
+ st = st.tail
+ } else {
+ return h.toStream #::: st.tail.flatten
+ }
+ }
+ Stream.empty
}
override def view = new StreamView[A, Stream[A]] {
diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala
index 5a0d24ddd2..43d46cf4d0 100644
--- a/src/library/scala/collection/immutable/StringLike.scala
+++ b/src/library/scala/collection/immutable/StringLike.scala
@@ -164,8 +164,8 @@ self =>
* @return the resulting string
*/
def replaceAllLiterally(literal: String, replacement: String): String = {
- val arg1 = java.util.regex.Pattern.quote(literal)
- val arg2 = java.util.regex.Matcher.quoteReplacement(replacement)
+ val arg1 = Regex.quote(literal)
+ val arg2 = Regex.quoteReplacement(replacement)
toString.replaceAll(arg1, arg2)
}
diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala
index d2205f9994..de09bb2040 100644
--- a/src/library/scala/collection/mutable/AVLTree.scala
+++ b/src/library/scala/collection/mutable/AVLTree.scala
@@ -11,10 +11,10 @@ package collection
package mutable
/**
- * An immutable AVL Tree implementation used by mutable.TreeSet
+ * An immutable AVL Tree implementation formerly used by mutable.TreeSet
*
* @author Lucien Pereira
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11")
+ * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
*/
private[mutable] sealed trait AVLTree[+A] extends Serializable {
def balance: Int
@@ -65,7 +65,7 @@ private[mutable] sealed trait AVLTree[+A] extends Serializable {
}
/**
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11")
+ * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
*/
private case object Leaf extends AVLTree[Nothing] {
override val balance: Int = 0
@@ -74,7 +74,7 @@ private case object Leaf extends AVLTree[Nothing] {
}
/**
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11")
+ * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
*/
private case class Node[A](data: A, left: AVLTree[A], right: AVLTree[A]) extends AVLTree[A] {
override val balance: Int = right.depth - left.depth
@@ -211,7 +211,7 @@ private case class Node[A](data: A, left: AVLTree[A], right: AVLTree[A]) extends
}
/**
- * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11")
+ * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0")
*/
private class AVLIterator[A](root: Node[A]) extends Iterator[A] {
val stack = mutable.ArrayStack[Node[A]](root)
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index e1f18a7036..e342e134b4 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -53,14 +53,14 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza
super.toArray[U]
}
- def :+[B >: T: scala.reflect.ClassTag](elem: B): Array[B] = {
+ def :+[B >: T: ClassTag](elem: B): Array[B] = {
val result = Array.ofDim[B](repr.length + 1)
Array.copy(repr, 0, result, 0, repr.length)
result(repr.length) = elem
result
}
- def +:[B >: T: scala.reflect.ClassTag](elem: B): Array[B] = {
+ def +:[B >: T: ClassTag](elem: B): Array[B] = {
val result = Array.ofDim[B](repr.length + 1)
result(0) = elem
Array.copy(repr, 0, result, 1, repr.length)
@@ -107,6 +107,54 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza
bb.result()
}
}
+
+ /** Converts an array of pairs into an array of first elements and an array of second elements.
+ *
+ * @tparam T1 the type of the first half of the element pairs
+ * @tparam T2 the type of the second half of the element pairs
+ * @param asPair an implicit conversion which asserts that the element type
+ * of this Array is a pair.
+ * @return a pair of Arrays, containing, respectively, the first and second half
+ * of each element pair of this Array.
+ */
+ def unzip[T1: ClassTag, T2: ClassTag](implicit asPair: T => (T1, T2)): (Array[T1], Array[T2]) = {
+ val a1 = new Array[T1](length)
+ val a2 = new Array[T2](length)
+ var i = 0
+ while (i < length) {
+ val e = apply(i)
+ a1(i) = e._1
+ a2(i) = e._2
+ i += 1
+ }
+ (a1, a2)
+ }
+
+ /** Converts an array of triples into three arrays, one containing the elements from each position of the triple.
+ *
+ * @tparam T1 the type of the first of three elements in the triple
+ * @tparam T2 the type of the second of three elements in the triple
+ * @tparam T3 the type of the third of three elements in the triple
+ * @param asTriple an implicit conversion which asserts that the element type
+ * of this Array is a triple.
+ * @return a triple of Arrays, containing, respectively, the first, second, and third
+ * elements from each element triple of this Array.
+ */
+ def unzip3[T1: ClassTag, T2: ClassTag, T3: ClassTag](implicit asTriple: T => (T1, T2, T3)): (Array[T1], Array[T2], Array[T3]) = {
+ val a1 = new Array[T1](length)
+ val a2 = new Array[T2](length)
+ val a3 = new Array[T3](length)
+ var i = 0
+ while (i < length) {
+ val e = apply(i)
+ a1(i) = e._1
+ a2(i) = e._2
+ a3(i) = e._3
+ i += 1
+ }
+ (a1, a2, a3)
+ }
+
def seq = thisCollection
diff --git a/src/library/scala/io/Position.scala b/src/library/scala/io/Position.scala
index 85149223ee..011d0f17af 100644
--- a/src/library/scala/io/Position.scala
+++ b/src/library/scala/io/Position.scala
@@ -34,7 +34,7 @@ package io
* @author Burak Emir (translated from work by Matthias Zenger and others)
*/
@deprecated("This class will be removed.", "2.10.0")
-abstract class Position {
+private[scala] abstract class Position {
/** Definable behavior for overflow conditions.
*/
def checkInput(line: Int, column: Int): Unit
@@ -68,7 +68,7 @@ abstract class Position {
def toString(pos: Int): String = line(pos) + ":" + column(pos)
}
-object Position extends Position {
+private[scala] object Position extends Position {
def checkInput(line: Int, column: Int) {
if (line < 0)
throw new IllegalArgumentException(line + " < 0")
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index d783dd29f5..bcbed645a7 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -16,36 +16,165 @@ import scala.collection.immutable.NumericRange
import scala.language.implicitConversions
-/**
+/**
* @author Stephane Micheloud
- * @version 1.0
+ * @author Rex Kerr
+ * @version 1.1
* @since 2.7
*/
object BigDecimal {
+ private final val maximumHashScale = 4934 // Quit maintaining hash identity with BigInt beyond this scale
+ private final val hashCodeNotComputed = 0x5D50690F // Magic value (happens to be "BigDecimal" old MurmurHash3 value)
+ private final val deci2binary = 3.3219280948873626 // Ratio of log(10) to log(2)
private val minCached = -512
private val maxCached = 512
val defaultMathContext = MathContext.DECIMAL128
- /** Cache ony for defaultMathContext using BigDecimals in a small range. */
+ /** Cache only for defaultMathContext using BigDecimals in a small range. */
private lazy val cache = new Array[BigDecimal](maxCached - minCached + 1)
object RoundingMode extends Enumeration {
+ // Annoying boilerplate to ensure consistency with java.math.RoundingMode
+ import java.math.{RoundingMode => RM}
type RoundingMode = Value
- // These are supposed to be the same as java.math.RoundingMode.values,
- // though it seems unwise to rely on the correspondence.
- val UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, UNNECESSARY = Value
+ val UP = Value(RM.UP.ordinal)
+ val DOWN = Value(RM.DOWN.ordinal)
+ val CEILING = Value(RM.CEILING.ordinal)
+ val FLOOR = Value(RM.FLOOR.ordinal)
+ val HALF_UP = Value(RM.HALF_UP.ordinal)
+ val HALF_DOWN = Value(RM.HALF_DOWN.ordinal)
+ val HALF_EVEN = Value(RM.HALF_EVEN.ordinal)
+ val UNNECESSARY = Value(RM.UNNECESSARY.ordinal)
+ }
+
+ /** Constructs a `BigDecimal` using the decimal text representation of `Double` value `d`, rounding if necessary. */
+ def decimal(d: Double, mc: MathContext): BigDecimal =
+ new BigDecimal(new BigDec(java.lang.Double.toString(d), mc))
+
+ /** Constructs a `BigDecimal` using the decimal text representation of `Double` value `d`. */
+ def decimal(d: Double): BigDecimal = decimal(d, defaultMathContext)
+
+ /** Constructs a `BigDecimal` using the decimal text representation of `Float` value `f`, rounding if necessary.
+ * Note that `BigDecimal.decimal(0.1f) != 0.1f` since equality agrees with the `Double` representation, and
+ * `0.1 != 0.1f`.
+ */
+ def decimal(f: Float, mc: MathContext): BigDecimal =
+ new BigDecimal(new BigDec(java.lang.Float.toString(f), mc))
+
+ /** Constructs a `BigDecimal` using the decimal text representation of `Float` value `f`.
+ * Note that `BigDecimal.decimal(0.1f) != 0.1f` since equality agrees with the `Double` representation, and
+ * `0.1 != 0.1f`.
+ */
+ def decimal(f: Float): BigDecimal = decimal(f, defaultMathContext)
+
+ // This exists solely to avoid conversion from Int/Long to Float, screwing everything up.
+ /** Constructs a `BigDecimal` from a `Long`, rounding if necessary. This is identical to `BigDecimal(l, mc)`. */
+ def decimal(l: Long, mc: MathContext): BigDecimal = apply(l, mc)
+
+ // This exists solely to avoid conversion from Int/Long to Float, screwing everything up.
+ /** Constructs a `BigDecimal` from a `Long`. This is identical to `BigDecimal(l)`. */
+ def decimal(l: Long): BigDecimal = apply(l)
+
+ /** Constructs a `BigDecimal` using a `java.math.BigDecimal`, rounding if necessary. */
+ def decimal(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd.round(mc), mc)
+
+ /** Constructs a `BigDecimal` by expanding the binary fraction
+ * contained by `Double` value `d` into a decimal representation,
+ * rounding if necessary. When a `Float` is converted to a
+ * `Double`, the binary fraction is preserved, so this method
+ * also works for converted `Float`s.
+ */
+ def binary(d: Double, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(d, mc), mc)
+
+ /** Constructs a `BigDecimal` by expanding the binary fraction
+ * contained by `Double` value `d` into a decimal representation.
+ * Note: this also works correctly on converted `Float`s.
+ */
+ def binary(d: Double): BigDecimal = binary(d, defaultMathContext)
+
+ /** Constructs a `BigDecimal` from a `java.math.BigDecimal`. The
+ * precision is the default for `BigDecimal` or enough to represent
+ * the `java.math.BigDecimal` exactly, whichever is greater.
+ */
+ def exact(repr: BigDec): BigDecimal = {
+ val mc =
+ if (repr.precision <= defaultMathContext.getPrecision) defaultMathContext
+ else new MathContext(repr.precision, java.math.RoundingMode.HALF_EVEN)
+ new BigDecimal(repr, mc)
}
+
+ /** Constructs a `BigDecimal` by fully expanding the binary fraction
+ * contained by `Double` value `d`, adjusting the precision as
+ * necessary. Note: this works correctly on converted `Float`s also.
+ */
+ def exact(d: Double): BigDecimal = exact(new BigDec(d))
+
+ /** Constructs a `BigDecimal` that exactly represents a `BigInt`.
+ */
+ def exact(bi: BigInt): BigDecimal = exact(new BigDec(bi.bigInteger))
+
+ /** Constructs a `BigDecimal` that exactly represents a `Long`. Note that
+ * all creation methods for `BigDecimal` that do not take a `MathContext`
+ * represent a `Long`; this is equivalent to `apply`, `valueOf`, etc..
+ */
+ def exact(l: Long): BigDecimal = apply(l)
+
+ /** Constructs a `BigDecimal` that exactly represents the number
+ * specified in a `String`.
+ */
+ def exact(s: String): BigDecimal = exact(new BigDec(s))
+
+ /** Constructs a 'BigDecimal` that exactly represents the number
+ * specified in base 10 in a character array.
+ */
+ def exact(cs: Array[Char]): BigDecimal = exact(new BigDec(cs))
+
/** Constructs a `BigDecimal` using the java BigDecimal static
- * valueOf constructor.
+ * valueOf constructor. Equivalent to `BigDecimal.decimal`.
*
* @param d the specified double value
* @return the constructed `BigDecimal`
*/
def valueOf(d: Double): BigDecimal = apply(BigDec valueOf d)
+
+ /** Constructs a `BigDecimal` using the java BigDecimal static
+ * valueOf constructor, specifying a `MathContext` that is
+ * used for computations but isn't used for rounding. Use
+ * `BigDecimal.decimal` to use `MathContext` for rounding,
+ * or `BigDecimal(java.math.BigDecimal.valueOf(d), mc)` for
+ * no rounding.
+ *
+ * @param d the specified double value
+ * @param mc the `MathContext` used for future computations
+ * @return the constructed `BigDecimal`
+ */
+ @deprecated("MathContext is not applied to Doubles in valueOf. Use BigDecimal.decimal to use rounding, or java.math.BigDecimal.valueOf to avoid it.","2.11")
def valueOf(d: Double, mc: MathContext): BigDecimal = apply(BigDec valueOf d, mc)
- def valueOf(x: Long): BigDecimal = apply(x.toDouble)
+
+ /** Constructs a `BigDecimal` using the java BigDecimal static
+ * valueOf constructor.
+ *
+ * @param x the specified `Long` value
+ * @return the constructed `BigDecimal`
+ */
+ def valueOf(x: Long): BigDecimal = apply(x)
+
+ /** Constructs a `BigDecimal` using the java BigDecimal static
+ * valueOf constructor. This is unlikely to do what you want;
+ * use `valueOf(f.toDouble)` or `decimal(f)` instead.
+ */
+ @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).","2.11")
+ def valueOf(f: Float): BigDecimal = valueOf(f.toDouble)
+
+ /** Constructs a `BigDecimal` using the java BigDecimal static
+ * valueOf constructor. This is unlikely to do what you want;
+ * use `valueOf(f.toDouble)` or `decimal(f)` instead.
+ */
+ @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).","2.11")
+ def valueOf(f: Float, mc: MathContext): BigDecimal = valueOf(f.toDouble, mc)
+
/** Constructs a `BigDecimal` whose value is equal to that of the
* specified `Integer` value.
*
@@ -53,6 +182,14 @@ object BigDecimal {
* @return the constructed `BigDecimal`
*/
def apply(i: Int): BigDecimal = apply(i, defaultMathContext)
+
+ /** Constructs a `BigDecimal` whose value is equal to that of the
+ * specified `Integer` value, rounding if necessary.
+ *
+ * @param i the specified integer value
+ * @param mc the precision and rounding mode for creation of this value and future operations on it
+ * @return the constructed `BigDecimal`
+ */
def apply(i: Int, mc: MathContext): BigDecimal =
if (mc == defaultMathContext && minCached <= i && i <= maxCached) {
val offset = i - minCached
@@ -60,7 +197,7 @@ object BigDecimal {
if (n eq null) { n = new BigDecimal(BigDec.valueOf(i.toLong), mc); cache(offset) = n }
n
}
- else new BigDecimal(BigDec.valueOf(i.toLong), mc)
+ else apply(i.toLong, mc)
/** Constructs a `BigDecimal` whose value is equal to that of the
* specified long value.
@@ -72,6 +209,13 @@ object BigDecimal {
if (minCached <= l && l <= maxCached) apply(l.toInt)
else new BigDecimal(BigDec.valueOf(l), defaultMathContext)
+ /** Constructs a `BigDecimal` whose value is equal to that of the
+ * specified long value, but rounded if necessary.
+ *
+ * @param l the specified long value
+ * @param mc the precision and rounding mode for creation of this value and future operations on it
+ * @return the constructed `BigDecimal`
+ */
def apply(l: Long, mc: MathContext): BigDecimal =
new BigDecimal(new BigDec(l, mc), mc)
@@ -85,35 +229,62 @@ object BigDecimal {
def apply(unscaledVal: Long, scale: Int): BigDecimal =
apply(BigInt(unscaledVal), scale)
+ /** Constructs a `BigDecimal` whose unscaled value is equal to that
+ * of the specified long value, but rounded if necessary.
+ *
+ * @param unscaledVal the value
+ * @param scale the scale
+ * @param mc the precision and rounding mode for creation of this value and future operations on it
+ * @return the constructed `BigDecimal`
+ */
def apply(unscaledVal: Long, scale: Int, mc: MathContext): BigDecimal =
apply(BigInt(unscaledVal), scale, mc)
/** Constructs a `BigDecimal` whose value is equal to that of the
- * specified double value.
+ * specified double value. Equivalent to `BigDecimal.decimal`.
*
* @param d the specified `Double` value
* @return the constructed `BigDecimal`
*/
- def apply(d: Double): BigDecimal = apply(d, defaultMathContext)
+ def apply(d: Double): BigDecimal = decimal(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(jl.Double.toString(d), mc), mc)
+ /** Constructs a `BigDecimal` whose value is equal to that of the
+ * specified double value, but rounded if necessary. Equivalent to
+ * `BigDecimal.decimal`.
+ *
+ * @param d the specified `Double` value
+ * @param mc the precision and rounding mode for creation of this value and future operations on it
+ * @return the constructed `BigDecimal`
+ */
+ def apply(d: Double, mc: MathContext): BigDecimal = decimal(d, mc)
+ @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11")
def apply(x: Float): BigDecimal = apply(x.toDouble)
+
+ @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11")
def apply(x: Float, mc: MathContext): BigDecimal = apply(x.toDouble, mc)
/** Translates a character array representation of a `BigDecimal`
* into a `BigDecimal`.
*/
- def apply(x: Array[Char]): BigDecimal = apply(x, defaultMathContext)
+ def apply(x: Array[Char]): BigDecimal = exact(x)
+
+ /** Translates a character array representation of a `BigDecimal`
+ * into a `BigDecimal`, rounding if necessary.
+ */
def apply(x: Array[Char], mc: MathContext): BigDecimal =
- new BigDecimal(new BigDec(x.mkString, mc), mc)
+ new BigDecimal(new BigDec(x, mc), mc)
/** Translates the decimal String representation of a `BigDecimal`
* into a `BigDecimal`.
*/
- def apply(x: String): BigDecimal = apply(x, defaultMathContext)
+ def apply(x: String): BigDecimal = exact(x)
+
+ /** Translates the decimal String representation of a `BigDecimal`
+ * into a `BigDecimal`, rounding if necessary.
+ */
def apply(x: String, mc: MathContext): BigDecimal =
new BigDecimal(new BigDec(x, mc), mc)
@@ -123,7 +294,15 @@ object BigDecimal {
* @param x the specified `BigInt` value
* @return the constructed `BigDecimal`
*/
- def apply(x: BigInt): BigDecimal = apply(x, defaultMathContext)
+ def apply(x: BigInt): BigDecimal = exact(x)
+
+ /** Constructs a `BigDecimal` whose value is equal to that of the
+ * specified `BigInt` value, rounding if necessary.
+ *
+ * @param x the specified `BigInt` value
+ * @param mc the precision and rounding mode for creation of this value and future operations on it
+ * @return the constructed `BigDecimal`
+ */
def apply(x: BigInt, mc: MathContext): BigDecimal =
new BigDecimal(new BigDec(x.bigInteger, mc), mc)
@@ -134,11 +313,24 @@ object BigDecimal {
* @param scale the scale
* @return the constructed `BigDecimal`
*/
- def apply(unscaledVal: BigInt, scale: Int): BigDecimal = apply(unscaledVal, scale, defaultMathContext)
+ def apply(unscaledVal: BigInt, scale: Int): BigDecimal =
+ exact(new BigDec(unscaledVal.bigInteger, scale))
+
+ /** Constructs a `BigDecimal` whose unscaled value is equal to that
+ * of the specified `BigInt` value.
+ *
+ * @param unscaledVal the specified `BigInt` value
+ * @param scale the scale
+ * @param mc the precision and rounding mode for creation of this value and future operations on it
+ * @return the constructed `BigDecimal`
+ */
def apply(unscaledVal: BigInt, scale: Int, mc: MathContext): BigDecimal =
new BigDecimal(new BigDec(unscaledVal.bigInteger, scale, mc), mc)
+ /** Constructs a `BigDecimal` from a `java.math.BigDecimal`. */
def apply(bd: BigDec): BigDecimal = apply(bd, defaultMathContext)
+
+ @deprecated("This method appears to round a java.math.BigDecimal but actually doesn't. Use new BigDecimal(bd, mc) instead for no rounding, or BigDecimal.decimal(bd, mc) for rounding.", "2.11")
def apply(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd, mc)
/** Implicit conversion from `Int` to `BigDecimal`. */
@@ -148,43 +340,123 @@ object BigDecimal {
implicit def long2bigDecimal(l: Long): BigDecimal = apply(l)
/** Implicit conversion from `Double` to `BigDecimal`. */
- implicit def double2bigDecimal(d: Double): BigDecimal = valueOf(d, defaultMathContext)
+ implicit def double2bigDecimal(d: Double): BigDecimal = decimal(d)
/** Implicit conversion from `java.math.BigDecimal` to `scala.BigDecimal`. */
implicit def javaBigDecimal2bigDecimal(x: BigDec): BigDecimal = apply(x)
}
/**
+ * `BigDecimal` represents decimal floating-point numbers of arbitrary precision.
+ * By default, the precision approximately matches that of IEEE 128-bit floating
+ * point numbers (34 decimal digits, `HALF_EVEN` rounding mode). Within the range
+ * of IEEE binary128 numbers, `BigDecimal` will agree with `BigInt` for both
+ * equality and hash codes (and will agree with primitive types as well). Beyond
+ * that range--numbers with more than 4934 digits when written out in full--the
+ * `hashCode` of `BigInt` and `BigDecimal` is allowed to diverge due to difficulty
+ * in efficiently computing both the decimal representation in `BigDecimal` and the
+ * binary representation in `BigInt`.
+ *
+ * When creating a `BigDecimal` from a `Double` or `Float`, care must be taken as
+ * the binary fraction representation of `Double` and `Float` does not easily
+ * convert into a decimal representation. Three explicit schemes are available
+ * for conversion. `BigDecimal.decimal` will convert the floating-point number
+ * to a decimal text representation, and build a `BigDecimal` based on that.
+ * `BigDecimal.binary` will expand the binary fraction to the requested or default
+ * precision. `BigDecimal.exact` will expand the binary fraction to the
+ * full number of digits, thus producing the exact decimal value corrsponding to
+ * the binary fraction of that floating-point number. `BigDecimal` equality
+ * matches the decimal expansion of `Double`: `BigDecimal.decimal(0.1) == 0.1`.
+ * Note that since `0.1f != 0.1`, the same is not true for `Float`. Instead,
+ * `0.1f == BigDecimal.decimal((0.1f).toDouble)`.
+ *
+ * To test whether a `BigDecimal` number can be converted to a `Double` or
+ * `Float` and then back without loss of information by using one of these
+ * methods, test with `isDecimalDouble`, `isBinaryDouble`, or `isExactDouble`
+ * or the corresponding `Float` versions. Note that `BigInt`'s `isValidDouble`
+ * will agree with `isExactDouble`, not the `isDecimalDouble` used by default.
+ *
+ * `BigDecimal` uses the decimal representation of binary floating-point numbers
+ * to determine equality and hash codes. This yields different answers than
+ * conversion between `Long` and `Double` values, where the exact form is used.
+ * As always, since floating-point is a lossy representation, it is advisable to
+ * take care when assuming identity will be maintained across multiple conversions.
+ *
+ * `BigDecimal` maintains a `MathContext` that determines the rounding that
+ * is applied to certain calculations. In most cases, the value of the
+ * `BigDecimal` is also rounded to the precision specified by the `MathContext`.
+ * To create a `BigDecimal` with a different precision than its `MathContext`,
+ * use `new BigDecimal(new java.math.BigDecimal(...), mc)`. Rounding will
+ * be applied on those mathematical operations that can dramatically change the
+ * number of digits in a full representation, namely multiplication, division,
+ * and powers. The left-hand argument's `MathContext` always determines the
+ * degree of rounding, if any, and is the one propagated through arithmetic
+ * operations that do not apply rounding themselves.
+ *
* @author Stephane Micheloud
- * @version 1.0
+ * @author Rex Kerr
+ * @version 1.1
*/
-final class BigDecimal(
- val bigDecimal: BigDec,
- val mc: MathContext)
+final class BigDecimal(val bigDecimal: BigDec, val mc: MathContext)
extends ScalaNumber with ScalaNumericConversions with Serializable {
def this(bigDecimal: BigDec) = this(bigDecimal, BigDecimal.defaultMathContext)
import BigDecimal.RoundingMode._
-
- /** Cuts way down on the wrapper noise. */
- private implicit def bigdec2BigDecimal(x: BigDec): BigDecimal = new BigDecimal(x, mc)
-
+ import BigDecimal.{decimal, binary, exact}
+
+ if (bigDecimal eq null) throw new IllegalArgumentException("null value for BigDecimal")
+ if (mc eq null) throw new IllegalArgumentException("null MathContext for BigDecimal")
+
+ // There was an implicit to cut down on the wrapper noise for BigDec -> BigDecimal.
+ // However, this may mask introduction of surprising behavior (e.g. lack of rounding
+ // where one might expect it). Wrappers should be applied explicitly with an
+ // eye to correctness.
+
+ // Sane hash code computation (which is surprisingly hard).
+ // Note--not lazy val because we can't afford the extra space.
+ private final var computedHashCode: Int = BigDecimal.hashCodeNotComputed
+ private final def computeHashCode(): Unit = {
+ computedHashCode =
+ if (isWhole && (precision - scale) < BigDecimal.maximumHashScale) toBigInt.hashCode
+ else if (isValidDouble) doubleValue.##
+ else {
+ val temp = bigDecimal.stripTrailingZeros
+ scala.util.hashing.MurmurHash3.mixLast( temp.scaleByPowerOfTen(temp.scale).toBigInteger.hashCode, temp.scale )
+ }
+ }
+
/** Returns the hash code for this BigDecimal.
- * Note that this does not use the underlying java object's
- * hashCode because we compare BigDecimals with compareTo
+ * Note that this does not merely use the underlying java object's
+ * `hashCode` because we compare `BigDecimal`s with `compareTo`
* which deems 2 == 2.00, whereas in java these are unequal
- * with unequal hashCodes.
- */
- override def hashCode(): Int =
- if (isWhole()) unifiedPrimitiveHashcode()
- else doubleValue.##
+ * with unequal `hashCode`s. These hash codes agree with `BigInt`
+ * for whole numbers up ~4934 digits (the range of IEEE 128 bit floating
+ * point). Beyond this, hash codes will disagree; this prevents the
+ * explicit represention of the `BigInt` form for `BigDecimal` values
+ * with large exponents.
+ */
+ override def hashCode(): Int = {
+ if (computedHashCode == BigDecimal.hashCodeNotComputed) computeHashCode
+ computedHashCode
+ }
- /** Compares this BigDecimal with the specified value for equality.
+ /** Compares this BigDecimal with the specified value for equality. Where `Float` and `Double`
+ * disagree, `BigDecimal` will agree with the `Double` value
*/
override def equals (that: Any): Boolean = that match {
case that: BigDecimal => this equals that
- case that: BigInt => this.toBigIntExact exists (that equals _)
- case that: Double => isValidDouble && toDouble == that
- case that: Float => isValidFloat && toFloat == that
+ case that: BigInt =>
+ that.bitLength > (precision-scale-2)*BigDecimal.deci2binary &&
+ this.toBigIntExact.exists(that equals _)
+ case that: Double =>
+ !that.isInfinity && {
+ val d = toDouble
+ !d.isInfinity && d == that && equals(decimal(d))
+ }
+ case that: Float =>
+ !that.isInfinity && {
+ val f = toFloat
+ !f.isInfinity && f == that && equals(decimal(f.toDouble))
+ }
case _ => isValidLong && unifiedPrimitiveEquals(that)
}
override def isValidByte = noArithmeticException(toByteExact)
@@ -192,26 +464,71 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
override def isValidChar = isValidInt && toIntExact >= Char.MinValue && toIntExact <= Char.MaxValue
override def isValidInt = noArithmeticException(toIntExact)
def isValidLong = noArithmeticException(toLongExact)
- /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`.
+ /** Tests whether the value is a valid Float. "Valid" has several distinct meanings, however. Use
+ * `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat`, depending on the intended meaning.
+ * By default, `decimal` creation is used, so `isDecimalFloat` is probably what you want.
*/
+ @deprecated("What constitutes validity is unclear. Use `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat` instead.", "2.11")
def isValidFloat = {
val f = toFloat
- !f.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(f.toDouble)) == 0
+ !f.isInfinity && bigDecimal.compareTo(new BigDec(f.toDouble)) == 0
}
- /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`.
+ /** Tests whether the value is a valid Double. "Valid" has several distinct meanings, however. Use
+ * `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble`, depending on the intended meaning.
+ * By default, `decimal` creation is used, so `isDecimalDouble` is probably what you want.
*/
+ @deprecated("Validity has two distinct meanings. Use `isExactBinaryDouble` or `equivalentToDouble` instead.", "2.11")
def isValidDouble = {
val d = toDouble
- !d.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(d)) == 0
+ !d.isInfinity && bigDecimal.compareTo(new BigDec(d)) == 0
+ }
+
+ /** Tests whether this `BigDecimal` holds the decimal representation of a `Double`. */
+ def isDecimalDouble = {
+ val d = toDouble
+ !d.isInfinity && equals(decimal(d))
+ }
+
+ /** Tests whether this `BigDecimal` holds the decimal representation of a `Float`. */
+ def isDecimalFloat = {
+ val f = toFloat
+ !f.isInfinity && equals(decimal(f))
+ }
+
+ /** Tests whether this `BigDecimal` holds, to within precision, the binary representation of a `Double`. */
+ def isBinaryDouble = {
+ val d = toDouble
+ !d.isInfinity && equals(binary(d,mc))
+ }
+
+ /** Tests whether this `BigDecimal` holds, to within precision, the binary representation of a `Float`. */
+ def isBinaryFloat = {
+ val f = toFloat
+ !f.isInfinity && equals(binary(f,mc))
+ }
+
+ /** Tests whether this `BigDecimal` holds the exact expansion of a `Double`'s binary fractional form into base 10. */
+ def isExactDouble = {
+ val d = toDouble
+ !d.isInfinity && equals(exact(d))
+ }
+
+ /** Tests whether this `BigDecimal` holds the exact expansion of a `Float`'s binary fractional form into base 10. */
+ def isExactFloat = {
+ val f = toFloat
+ !f.isInfinity && equals(exact(f.toDouble))
}
+
private def noArithmeticException(body: => Unit): Boolean = {
try { body ; true }
catch { case _: ArithmeticException => false }
}
- def isWhole() = (this remainder 1) == BigDecimal(0)
+ def isWhole() = scale <= 0 || bigDecimal.stripTrailingZeros.scale <= 0
+
def underlying = bigDecimal
+
/** Compares this BigDecimal with the specified BigDecimal for equality.
*/
@@ -239,60 +556,66 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
/** Addition of BigDecimals
*/
- def + (that: BigDecimal): BigDecimal = this.bigDecimal.add(that.bigDecimal)
+ def + (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal add that.bigDecimal, mc)
/** Subtraction of BigDecimals
*/
- def - (that: BigDecimal): BigDecimal = this.bigDecimal.subtract(that.bigDecimal)
+ def - (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal subtract that.bigDecimal, mc)
/** Multiplication of BigDecimals
*/
- def * (that: BigDecimal): BigDecimal = this.bigDecimal.multiply(that.bigDecimal, mc)
+ def * (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.multiply(that.bigDecimal, mc), mc)
/** Division of BigDecimals
*/
- def / (that: BigDecimal): BigDecimal = this.bigDecimal.divide(that.bigDecimal, mc)
+ def / (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.divide(that.bigDecimal, mc), mc)
/** Division and Remainder - returns tuple containing the result of
- * divideToIntegralValue and the remainder.
+ * divideToIntegralValue and the remainder. The computation is exact: no rounding is applied.
*/
def /% (that: BigDecimal): (BigDecimal, BigDecimal) =
this.bigDecimal.divideAndRemainder(that.bigDecimal) match {
- case Array(q, r) => (q, r)
+ case Array(q, r) => (new BigDecimal(q, mc), new BigDecimal(r, mc))
}
/** Divide to Integral value.
*/
def quot (that: BigDecimal): BigDecimal =
- this.bigDecimal.divideToIntegralValue(that.bigDecimal)
+ new BigDecimal(this.bigDecimal divideToIntegralValue that.bigDecimal, mc)
- /** Returns the minimum of this and that
+ /** Returns the minimum of this and that, or this if the two are equal
*/
- def min (that: BigDecimal): BigDecimal = this.bigDecimal min that.bigDecimal
-
- /** Returns the maximum of this and that
+ def min (that: BigDecimal): BigDecimal = (this compare that) match {
+ case x if x <= 0 => this
+ case _ => that
+ }
+
+ /** Returns the maximum of this and that, or this if the two are equal
*/
- def max (that: BigDecimal): BigDecimal = this.bigDecimal max that.bigDecimal
-
+ def max (that: BigDecimal): BigDecimal = (this compare that) match {
+ case x if x >= 0 => this
+ case _ => that
+ }
+
/** Remainder after dividing this by that.
*/
- def remainder (that: BigDecimal): BigDecimal = this.bigDecimal.remainder(that.bigDecimal)
+ def remainder (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal remainder that.bigDecimal, mc)
/** Remainder after dividing this by that.
*/
- def % (that: BigDecimal): BigDecimal = this.remainder(that)
+ def % (that: BigDecimal): BigDecimal = this remainder that
/** Returns a BigDecimal whose value is this ** n.
*/
- def pow (n: Int): BigDecimal = this.bigDecimal.pow(n, mc)
+ def pow (n: Int): BigDecimal = new BigDecimal(this.bigDecimal.pow(n, mc), mc)
/** Returns a BigDecimal whose value is the negation of this BigDecimal
*/
- def unary_- : BigDecimal = this.bigDecimal.negate()
+ def unary_- : BigDecimal = new BigDecimal(this.bigDecimal.negate(), mc)
/** Returns the absolute value of this BigDecimal
*/
- def abs: BigDecimal = this.bigDecimal.abs
+ def abs: BigDecimal = if (signum < 0) unary_- else this
/** Returns the sign of this BigDecimal, i.e.
* -1 if it is less than 0,
@@ -305,9 +628,19 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
*/
def precision: Int = this.bigDecimal.precision()
- /** Returns a BigDecimal rounded according to the MathContext settings.
+ /** Returns a BigDecimal rounded according to the supplied MathContext settings, but
+ * preserving its own MathContext for future operations.
*/
- def round(mc: MathContext): BigDecimal = this.bigDecimal round mc
+ def round(mc: MathContext): BigDecimal = {
+ val r = this.bigDecimal round mc
+ if (r eq bigDecimal) this else new BigDecimal(r, this.mc)
+ }
+
+ /** Returns a `BigDecimal` rounded according to its own `MathContext` */
+ def rounded: BigDecimal = {
+ val r = bigDecimal round mc
+ if (r eq bigDecimal) this else new BigDecimal(r, mc)
+ }
/** Returns the scale of this `BigDecimal`.
*/
@@ -315,19 +648,22 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
/** Returns the size of an ulp, a unit in the last place, of this BigDecimal.
*/
- def ulp: BigDecimal = this.bigDecimal.ulp
+ def ulp: BigDecimal = new BigDecimal(this.bigDecimal.ulp, mc)
- /** Returns a new BigDecimal based on the supplied MathContext.
+ /** Returns a new BigDecimal based on the supplied MathContext, rounded as needed.
*/
- def apply(mc: MathContext): BigDecimal = BigDecimal(this.bigDecimal.toString, mc)
+ def apply(mc: MathContext): BigDecimal = new BigDecimal(this.bigDecimal round mc, mc)
/** Returns a `BigDecimal` whose scale is the specified value, and whose value is
* numerically equal to this BigDecimal's.
*/
- def setScale(scale: Int): BigDecimal = this.bigDecimal setScale scale
+ def setScale(scale: Int): BigDecimal =
+ if (this.scale == scale) this
+ else new BigDecimal(this.bigDecimal setScale scale, mc)
def setScale(scale: Int, mode: RoundingMode): BigDecimal =
- this.bigDecimal.setScale(scale, mode.id)
+ if (this.scale == scale) this
+ else new BigDecimal(this.bigDecimal.setScale(scale, mode.id), mc)
/** 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.
@@ -442,8 +778,11 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
* can be done losslessly, returning Some(BigInt) or None.
*/
def toBigIntExact(): Option[BigInt] =
- try Some(new BigInt(this.bigDecimal.toBigIntegerExact()))
- catch { case _: ArithmeticException => None }
+ if (isWhole()) {
+ try Some(new BigInt(this.bigDecimal.toBigIntegerExact()))
+ catch { case _: ArithmeticException => None }
+ }
+ else None
/** Returns the decimal String representation of this BigDecimal.
*/
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 5e70bdc2f6..689fc0c3e1 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -119,7 +119,7 @@ final class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNum
*/
override def equals(that: Any): Boolean = that match {
case that: BigInt => this equals that
- case that: BigDecimal => that.toBigIntExact exists (this equals _)
+ case that: BigDecimal => that equals this
case that: Double => isValidDouble && toDouble == that
case that: Float => isValidFloat && toFloat == that
case x => isValidLong && unifiedPrimitiveEquals(x)
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 74c1f2172c..509d181d87 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -61,21 +61,6 @@ package object reflect {
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
// todo. once we have implicit macros for tag generation, we can remove this anchor
private[scala] def materializeClassTag[T](): ClassTag[T] = macro ???
-
- @deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0")
- type BeanDescription = scala.beans.BeanDescription
- @deprecated("Use `@scala.beans.BeanDisplayName` instead", "2.10.0")
- type BeanDisplayName = scala.beans.BeanDisplayName
- @deprecated("Use `@scala.beans.BeanInfo` instead", "2.10.0")
- type BeanInfo = scala.beans.BeanInfo
- @deprecated("Use `@scala.beans.BeanInfoSkip` instead", "2.10.0")
- type BeanInfoSkip = scala.beans.BeanInfoSkip
- @deprecated("Use `@scala.beans.BeanProperty` instead", "2.10.0")
- type BeanProperty = scala.beans.BeanProperty
- @deprecated("Use `@scala.beans.BooleanBeanProperty` instead", "2.10.0")
- type BooleanBeanProperty = scala.beans.BooleanBeanProperty
- @deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0")
- type ScalaBeanInfo = scala.beans.ScalaBeanInfo
}
/** An exception that indicates an error during Scala reflection */
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 22dbb37789..86132bb876 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -704,6 +704,14 @@ object Regex {
def replace(rs: String) = matcher.appendReplacement(sb, rs)
}
+ /** Quotes strings to be used literally in regex patterns.
+ *
+ * All regex metacharacters in the input match themselves literally in the output.
+ *
+ * @example {{{List("US$", "CAN$").map(Regex.quote).mkString("|").r}}}
+ */
+ def quote(text: String): String = Pattern quote text
+
/** Quotes replacement strings to be used in replacement methods.
*
* Replacement methods give special meaning to backslashes (`\`) and