diff options
author | Paul Phillips <paulp@improving.org> | 2011-12-30 11:01:41 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-01-24 14:49:25 -0800 |
commit | 969e2587c2d6c5f5c17d550d3192f68c4b342f45 (patch) | |
tree | e3ac3ae7adb4b18cf1f17bdc6256d83909cb51f9 /src/library/scala/collection/immutable/Range.scala | |
parent | 72cda2b44092ea9ab67df8a6f6c8fbf63f830c10 (diff) | |
download | scala-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.scala | 36 |
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) |