summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/immutable/Range.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-12-30 11:01:41 -0800
committerPaul Phillips <paulp@improving.org>2012-01-24 14:49:25 -0800
commit969e2587c2d6c5f5c17d550d3192f68c4b342f45 (patch)
treee3ac3ae7adb4b18cf1f17bdc6256d83909cb51f9 /src/library/scala/collection/immutable/Range.scala
parent72cda2b44092ea9ab67df8a6f6c8fbf63f830c10 (diff)
downloadscala-969e2587c2d6c5f5c17d550d3192f68c4b342f45.tar.gz
scala-969e2587c2d6c5f5c17d550d3192f68c4b342f45.tar.bz2
scala-969e2587c2d6c5f5c17d550d3192f68c4b342f45.zip
Cleaner range counting.
Plus a big unit test I had lying around.
Diffstat (limited to 'src/library/scala/collection/immutable/Range.scala')
-rw-r--r--src/library/scala/collection/immutable/Range.scala36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index c92c0268b6..7537558f0b 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -286,18 +286,36 @@ extends collection.AbstractSeq[Int]
object Range {
private[immutable] val MAX_PRINT = 512 // some arbitrary value
- /** Counts in "Long arithmetic" so we can recognize overflow.
+ /** Counts the number of range elements.
+ * @pre step != 0
+ * If the size of the range exceeds Int.MaxValue, the
+ * result will be negative.
*/
- def count(start: Int, end: Int, step: Int): Int =
- count(start, end, step, false)
-
def count(start: Int, end: Int, step: Int, isInclusive: Boolean): Int = {
- // faster path for the common counting range
- if (start >= 0 && end > start && end < scala.Int.MaxValue && step == 1)
- (end - start) + ( if (isInclusive) 1 else 0 )
- else
- NumericRange.count[Long](start, end, step, isInclusive)
+ if (step == 0)
+ throw new IllegalArgumentException("step cannot be 0.")
+
+ val isEmpty = (
+ if (start == end) !isInclusive
+ else if (start < end) step < 0
+ else step > 0
+ )
+ if (isEmpty) 0
+ else {
+ // Counts with Longs so we can recognize too-large ranges.
+ val gap: Long = end.toLong - start.toLong
+ val jumps: Long = gap / step
+ // Whether the size of this range is one larger than the
+ // number of full-sized jumps.
+ val hasStub = isInclusive || (gap % step != 0)
+ val result: Long = jumps + ( if (hasStub) 1 else 0 )
+
+ if (result > scala.Int.MaxValue) -1
+ else result.toInt
+ }
}
+ def count(start: Int, end: Int, step: Int): Int =
+ count(start, end, step, false)
class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) {
// override def par = new ParRange(this)