summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/BigDecimal.scala6
-rwxr-xr-xsrc/library/scala/Numeric.scala26
-rw-r--r--src/library/scala/Range.scala42
-rw-r--r--src/library/scala/runtime/RichDouble.scala6
4 files changed, 62 insertions, 18 deletions
diff --git a/src/library/scala/BigDecimal.scala b/src/library/scala/BigDecimal.scala
index a5faf979e1..9bae9feb01 100644
--- a/src/library/scala/BigDecimal.scala
+++ b/src/library/scala/BigDecimal.scala
@@ -266,6 +266,12 @@ class BigDecimal(val bigDecimal: BigDec) extends java.lang.Number {
*/
def doubleValue = this.bigDecimal.doubleValue
+ /** See <code>Iterator.range</code>. */
+ def until(end: BigDecimal, step: BigDecimal) = Range.BigDecimal(this, end, step)
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: BigDecimal, step: BigDecimal) = Range.BigDecimal.inclusive(this, end, step)
+
/** Converts this <code>BigDecimal</code> to a BigInteger.
*/
def toBigInt(): BigInt = new BigInt(this.bigDecimal.toBigInteger())
diff --git a/src/library/scala/Numeric.scala b/src/library/scala/Numeric.scala
index cd563609c9..a9fc0c08f8 100755
--- a/src/library/scala/Numeric.scala
+++ b/src/library/scala/Numeric.scala
@@ -73,6 +73,32 @@ object Numeric {
def toDouble(x: Double): Double = x
}
implicit object DoubleIsFractional extends DoubleIsFractional with Ordering.DoubleOrdering
+
+ trait BigDecimalIsConflicted {
+ def plus(x: BigDecimal, y: BigDecimal): BigDecimal = x + y
+ def minus(x: BigDecimal, y: BigDecimal): BigDecimal = x - y
+ def times(x: BigDecimal, y: BigDecimal): BigDecimal = x * y
+ def negate(x: BigDecimal): BigDecimal = -x
+ def fromInt(x: Int): BigDecimal = BigDecimal(x)
+ def toInt(x: BigDecimal): Int = x.intValue
+ def toLong(x: BigDecimal): Long = x.longValue
+ def toFloat(x: BigDecimal): Float = x.floatValue
+ def toDouble(x: BigDecimal): Double = x.doubleValue
+ }
+
+ trait BigDecimalIsFractional extends BigDecimalIsConflicted with Fractional[BigDecimal] {
+ def div(x: BigDecimal, y: BigDecimal): BigDecimal = x / y
+ }
+ trait BigDecimalAsIfIntegral extends BigDecimalIsConflicted with Integral[BigDecimal] {
+ def quot(x: BigDecimal, y: BigDecimal): BigDecimal = x / y
+ // scala.BigDecimal doesn't give access to remainder, grr
+ def rem(x: BigDecimal, y: BigDecimal): BigDecimal =
+ new BigDecimal(x.bigDecimal remainder y.bigDecimal)
+ }
+
+ // The Fractional one is the implicit, but Integral is useful for GenericRange.
+ implicit object BigDecimalIsFractional extends BigDecimalIsFractional with Ordering.BigDecimalOrdering
+ object BigDecimalAsIfIntegral extends BigDecimalAsIfIntegral with Ordering.BigDecimalOrdering
}
trait Numeric[T] extends Ordering[T] {
diff --git a/src/library/scala/Range.scala b/src/library/scala/Range.scala
index 4cf8bac950..3c8138fb87 100644
--- a/src/library/scala/Range.scala
+++ b/src/library/scala/Range.scala
@@ -34,21 +34,19 @@ import util.control.Exception.catching
* @version 2.8
*/
abstract class GenericRange[T]
- (val start: T, val end: T, val step: T)
+ (val start: T, val end: T, val step: T, val isInclusive: Boolean = false)
(implicit num: Integral[T])
extends VectorView[T, Vector[T]] with RangeToString[T] {
import num._
- // this lets us pretend all ranges are exclusive
- val isInclusive: Boolean
- private val trueEnd = if (isInclusive) end + one else end
-
// todo? - we could lift the length restriction by implementing a range as a sequence of
// subranges and limiting the subranges to MAX_INT. There's no other way around it because
// the generics we inherit assume integer-based indexing (as well they should.)
require(!(step equiv zero))
require(genericLength <= fromInt(Math.MAX_INT), "Implementation restricts ranges to Math.MAX_INT elements.")
+ // By adjusting end based on isInclusive, we can treat all ranges as exclusive.
+ private lazy val trueEnd: T = if (isInclusive) end + step else end
protected def underlying = Vector.empty[T]
/** Create a new range with the start and end values of this range and
@@ -74,9 +72,8 @@ extends VectorView[T, Vector[T]] with RangeToString[T] {
}
lazy val genericLength: T = {
- def plen(start: T, end: T, step: T) =
- if (trueEnd <= start) zero
- else (trueEnd - start - one) / step + one
+ def plen(s: T, e: T, stp: T) =
+ if (e <= s) zero else ((e - s) / stp)
if (step > zero) plen(start, trueEnd, step)
else plen(trueEnd, start, -step)
@@ -88,7 +85,7 @@ extends VectorView[T, Vector[T]] with RangeToString[T] {
def apply(idx: Int): T = applyAt(fromInt(idx))
def applyAt(idx: T): T = {
if (idx < zero || idx >= genericLength) throw new IndexOutOfBoundsException(idx.toString)
- start + idx * step
+ start + (idx * step)
}
// The contains situation makes for some interesting code.
@@ -119,7 +116,7 @@ private[scala] trait RangeToString[T] extends VectorView[T, Vector[T]] {
// if the Range is unduly large. This interacts poorly with the REPL.
override def toString() = {
val MAX_PRINT = 512 // some arbitrary value
- val str = (this take MAX_PRINT).toString
+ val str = (this take MAX_PRINT).mkString(", ")
if (length > MAX_PRINT) str.replaceAll("""\)$""", ", ...)")
else str
@@ -128,18 +125,13 @@ private[scala] trait RangeToString[T] extends VectorView[T, Vector[T]] {
object GenericRange {
- import Numeric._
-
class Inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T])
- extends GenericRange(start, end, step)
- {
- val isInclusive = true
+ extends GenericRange(start, end, step, true) {
def exclusive: Exclusive[T] = new Exclusive(start, end, step)
}
+
class Exclusive[T](start: T, end: T, step: T)(implicit num: Integral[T])
- extends GenericRange(start, end, step)
- {
- val isInclusive = false
+ extends GenericRange(start, end, step, false) {
def inclusive: Inclusive[T] = new Inclusive(start, end, step)
}
@@ -229,10 +221,24 @@ object Range {
def apply(start: BigInt, end: BigInt, step: BigInt) = GenericRange(start, end, step)
def inclusive(start: BigInt, end: BigInt, step: BigInt) = GenericRange.inclusive(start, end, step)
}
+ // The BigDecimal and Double ranges will throw an exception if they cannot
+ // step exactly as requested.
+ object BigDecimal {
+ def apply(start: BigDecimal, end: BigDecimal, step: BigDecimal) =
+ GenericRange(start, end, step)(Numeric.BigDecimalAsIfIntegral)
+ def inclusive(start: BigDecimal, end: BigDecimal, step: BigDecimal) =
+ GenericRange.inclusive(start, end, step)(Numeric.BigDecimalAsIfIntegral)
+ }
object Long {
def apply(start: Long, end: Long, step: Long) = GenericRange(start, end, step)
def inclusive(start: Long, end: Long, step: Long) = GenericRange.inclusive(start, end, step)
}
+ object Double {
+ def apply(start: Double, end: Double, step: Double) =
+ BigDecimal(scala.BigDecimal(start), scala.BigDecimal(end), scala.BigDecimal(step))
+ def inclusive(start: Double, end: Double, step: Double) =
+ BigDecimal.inclusive(scala.BigDecimal(start), scala.BigDecimal(end), scala.BigDecimal(step))
+ }
// Illustrating genericity with Int Range, which should have the same behavior
// as the original Range class. However we leave the original Range
diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala
index 8f7d18d167..5c20745f60 100644
--- a/src/library/scala/runtime/RichDouble.scala
+++ b/src/library/scala/runtime/RichDouble.scala
@@ -29,6 +29,12 @@ final class RichDouble(x: Double) extends Proxy with Ordered[Double] {
def ceil: Double = Math.ceil(x)
def floor: Double = Math.floor(x)
+ /** See <code>Iterator.range</code>. */
+ def until(end: Double, step: Double) = Range.Double(x, end, step)
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: Double, step: Double) = Range.Double.inclusive(x, end, step)
+
/** Converts an angle measured in degrees to an approximately equivalent
* angle measured in radians.
*