diff options
-rw-r--r-- | src/library/scala/collection/immutable/NumericRange.scala | 18 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Range.scala | 9 | ||||
-rw-r--r-- | test/files/specialized/fft.check | 2 |
3 files changed, 16 insertions, 13 deletions
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala index e4b539f962..0e32118696 100644 --- a/src/library/scala/collection/immutable/NumericRange.scala +++ b/src/library/scala/collection/immutable/NumericRange.scala @@ -192,24 +192,22 @@ extends IndexedSeq[T] with Serializable { /** A companion object for numeric ranges. */ object NumericRange { - import Ordering.Implicits._ - import math.Integral.Implicits._ - /** Calculates the number of elements in a range given start, end, step, and * whether or not it is inclusive. Throws an exception if step == 0 or * the number of elements exceeds the maximum Int. */ - def count[T: Integral](start: T, end: T, step: T, isInclusive: Boolean): Int = { - val zero = implicitly[Integral[T]].zero - val upward = start < end - val posStep = step > zero + def count[T](start: T, end: T, step: T, isInclusive: Boolean)(implicit num: Integral[T]): Int = { + val zero = num.zero + val upward = num.lt(start, end) + val posStep = num.gt(step, zero) if (step == zero) throw new IllegalArgumentException("step cannot be 0.") else if (start == end) if (isInclusive) 1 else 0 else if (upward != posStep) 0 else { - val jumps = ((end - start) / step).toLong - val remainder = ((end - start) % step).toLong + val diff = num.minus(end, start) + val jumps = num.toLong(num.quot(diff, step)) + val remainder = num.toLong(num.rem(diff, step)) val longCount = jumps + ( if (!isInclusive && zero == remainder) 0 else 1 ) @@ -220,7 +218,7 @@ object NumericRange { * overflow turn up as an empty range. */ // The second condition contradicts an empty result. - val isOverflow = longCount == 0 && (start + step < end) == upward + val isOverflow = longCount == 0 && num.lt(num.plus(start, step), end) == upward if (longCount > scala.Int.MaxValue || longCount < 0L || isOverflow) { val word = if (isInclusive) "to" else "until" diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index b22998fb4b..ed4f4615c2 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -243,8 +243,13 @@ object Range { 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 = - NumericRange.count[Long](start, end, step, isInclusive) + 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) + } class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) { // override def par = new ParRange(this) diff --git a/test/files/specialized/fft.check b/test/files/specialized/fft.check index 69a3a61f36..845729084d 100644 --- a/test/files/specialized/fft.check +++ b/test/files/specialized/fft.check @@ -1,4 +1,4 @@ Processing 65536 items Boxed doubles: 0 Boxed ints: 2 -Boxed longs: 1310921 +Boxed longs: 1245366 |