summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-05-13 19:53:43 +0000
committerPaul Phillips <paulp@improving.org>2009-05-13 19:53:43 +0000
commite9a2726b588273bd9d126f58a23048c14f7d35cb (patch)
tree9a34fa59d9f4731a2e40e34edade3dc8811e3de0 /src/library
parent1d744e7e93347bda7c4d9483a202151556ac8b2d (diff)
downloadscala-e9a2726b588273bd9d126f58a23048c14f7d35cb.tar.gz
scala-e9a2726b588273bd9d126f58a23048c14f7d35cb.tar.bz2
scala-e9a2726b588273bd9d126f58a23048c14f7d35cb.zip
Added to/until methods to RichLong and BigInt.
Created Inclusive and Exclusive subclasses of GenericRange. Moved factories for GenericRanges inside the Range object. They are now created by calling e.g. Range.Long(1,10,1) or Range.BigInt(0, BigInt(1) << 128, BigInt(1) << 124) .
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/BigInt.scala12
-rw-r--r--src/library/scala/Range.scala90
-rw-r--r--src/library/scala/runtime/RichLong.scala12
3 files changed, 76 insertions, 38 deletions
diff --git a/src/library/scala/BigInt.scala b/src/library/scala/BigInt.scala
index a3d1545e2a..c03238680e 100644
--- a/src/library/scala/BigInt.scala
+++ b/src/library/scala/BigInt.scala
@@ -348,6 +348,18 @@ class BigInt(val bigInteger: BigInteger) extends java.lang.Number {
*/
def doubleValue = this.bigInteger.doubleValue
+ /** See <code>Iterator.range</code>. */
+ def until(end: BigInt) = Range.BigInt(this, end, BigInt(1))
+
+ /** See <code>Iterator.range</code>. */
+ def until(end: BigInt, step: BigInt) = Range.BigInt(this, end, step)
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: BigInt) = Range.BigInt.inclusive(this, end, BigInt(1))
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: BigInt, step: BigInt) = Range.BigInt.inclusive(this, end, step)
+
/** Returns the decimal String representation of this BigInt.
*/
override def toString(): String = this.bigInteger.toString()
diff --git a/src/library/scala/Range.scala b/src/library/scala/Range.scala
index dbd4f82f69..b2cb8c07c4 100644
--- a/src/library/scala/Range.scala
+++ b/src/library/scala/Range.scala
@@ -19,24 +19,30 @@ import collection.generic.VectorView
* It must be supplied with Integral and Ordering implementations
* of the range type.
*
- * Built-in incarnations include BigIntRange and LongRange.
+ * Factories for likely types include Range.BigInt and Range.Long.
+ * Range.Int exists for completeness, but the Int-based scala.Range
+ * should be more performant.
* </p><pre>
* <b>val</b> r1 = new Range(0, 100, 1)
* <b>val</b> veryBig = Math.MAX_INT.toLong + 1
- * <b>val</b> r2 = new LongRange(veryBig, veryBig + 100, 1)
+ * <b>val</b> r2 = Range.Long(veryBig, veryBig + 100, 1)
* assert(r1 sameElements r2.map(_ - veryBig))
* </pre>
*
* @author Paul Phillips
* @version 2.8
*/
-class GenericRange[T]
+abstract class GenericRange[T]
(val start: T, val end: T, val step: T)
(implicit num: Integral[T], ord: Ordering[T])
extends VectorView[T, Vector[T]] with RangeToString[T] {
import num._
import ord._
+ // 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.)
@@ -48,17 +54,19 @@ extends VectorView[T, Vector[T]] with RangeToString[T] {
/** Create a new range with the start and end values of this range and
* a new <code>step</code>.
*/
- def by(step: T): GenericRange[T] = new GenericRange(start, end, step)
+ def by(step: T): GenericRange[T] =
+ if (isInclusive) GenericRange.inclusive(start, end, step)
+ else GenericRange(start, end, step)
override def foreach[U](f: T => U) {
var i = start
if (step > zero) {
- while (i < end) {
+ while (i < trueEnd) {
f(i)
i = i + step
}
} else {
- while (i > end) {
+ while (i > trueEnd) {
f(i)
i = i + step
}
@@ -67,13 +75,11 @@ extends VectorView[T, Vector[T]] with RangeToString[T] {
lazy val genericLength: T = {
def plen(start: T, end: T, step: T) =
- if (end <= start) zero
- else (end - start - one) / step + one
- // if (lteq(end, start)) zero
- // else plus(quot((minus(minus(end, start), one)), step), one)
+ if (trueEnd <= start) zero
+ else (trueEnd - start - one) / step + one
- if (step > zero) plen(start, end, step)
- else plen(end, start, -step)
+ if (step > zero) plen(start, trueEnd, step)
+ else plen(trueEnd, start, -step)
}
lazy val length: Int = toInt(genericLength)
@@ -91,11 +97,9 @@ extends VectorView[T, Vector[T]] with RangeToString[T] {
try { _x.asInstanceOf[T] }
catch { case _: ClassCastException => return false }
- if (step > zero) start <= x && x < end
- else start >= x && x > end
+ if (step > zero) start <= x && x < trueEnd
+ else start >= x && x > trueEnd
}
-
- def inclusive = GenericRange.inclusive(start, end, step)
}
private[scala] trait RangeToString[T] extends VectorView[T, Vector[T]] {
@@ -110,39 +114,31 @@ private[scala] trait RangeToString[T] extends VectorView[T, Vector[T]] {
}
}
+
object GenericRange {
import Numeric._
import Ordering._
- // This is very ugly, but modelled on the existing range class for now
- private class Inclusive[T](start: T, end0: T, step: T)(implicit num: Integral[T], ord: Ordering[T])
- extends GenericRange(
- start,
- if (ord.gt(step, num.zero)) num.plus(end0, num.one) else num.minus(end0, num.one),
- step)
+ class Inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T])
+ extends GenericRange(start, end, step)
{
- self =>
- override def by(step: T): GenericRange[T] = new Inclusive(start, end0, step)
+ val isInclusive = true
+ def exclusive: Exclusive[T] = new Exclusive(start, end, step)
+ }
+ class Exclusive[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T])
+ extends GenericRange(start, end, step)
+ {
+ val isInclusive = false
+ def inclusive: Inclusive[T] = new Inclusive(start, end, step)
}
def apply[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T]) =
- new GenericRange(start, end, step)
+ new Exclusive(start, end, step)
- def inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T]): GenericRange[T] =
- new GenericRange.Inclusive(start, end, step)
+ def inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T], ord: Ordering[T]) =
+ new Inclusive(start, end, step)
}
-class BigIntRange(start: BigInt, end: BigInt, step: BigInt)
-extends GenericRange(start, end, step)(Numeric.BigIntIsIntegral, Ordering.BigInt) {}
-class LongRange(start: Long, end: Long, step: Long)
-extends GenericRange(start, end, step)(Numeric.LongIsIntegral, Ordering.Long) {}
-
-// Illustrating genericity with IntRange, which should have the same behavior
-// as the original Range class. However we leave the original Range
-// indefinitely, for performance and because the compiler seems to bootstrap
-// off it and won't do so with our parameterized version without modifications.
-class IntRange(start: Int, end: Int, step: Int)
-extends GenericRange(start, end, step)(Numeric.IntIsIntegral, Ordering.Int) {}
/** <p>
* The <code>Range</code> class represents integer values in range
@@ -217,4 +213,22 @@ object Range {
def inclusive(start: Int, end: Int, step: Int): Range =
new Range.Inclusive(start, end, step)
+
+ object BigInt {
+ 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)
+ }
+ 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)
+ }
+
+ // Illustrating genericity with Int Range, which should have the same behavior
+ // as the original Range class. However we leave the original Range
+ // indefinitely, for performance and because the compiler seems to bootstrap
+ // off it and won't do so with our parameterized version without modifications.
+ object Int {
+ def apply(start: Int, end: Int, step: Int) = GenericRange(start, end, step)
+ def inclusive(start: Int, end: Int, step: Int) = GenericRange.inclusive(start, end, step)
+ }
}
diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala
index 78784170f3..5eddaf0ec3 100644
--- a/src/library/scala/runtime/RichLong.scala
+++ b/src/library/scala/runtime/RichLong.scala
@@ -20,6 +20,18 @@ final class RichLong(x: Long) extends Proxy with Ordered[Long] {
// Ordered[Long].compare
def compare(y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0
+ /** See <code>Iterator.range</code>. */
+ def until(end: Long) = Range.Long(x, end, 1L)
+
+ /** See <code>Iterator.range</code>. */
+ def until(end: Long, step: Long) = Range.Long(x, end, step)
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: Long) = Range.Long.inclusive(x, end, 1L)
+
+ /** like <code>until</code>, but includes the last index */
+ def to(end: Long, step: Long) = Range.Long.inclusive(x, end, step)
+
def min(y: Long): Long = if (x < y) x else y
def max(y: Long): Long = if (x > y) x else y
def abs: Long = if (x < 0) -x else x