From 6736ca07f22a8da42604a27bda84f71b720b54ed Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 23 Apr 2010 22:13:41 +0000 Subject: Added size hints to Array.{ iterate, range, tab... Added size hints to Array.{ iterate, range, tabulate, fill }. Probably closes #3331, but it would be nice if someone would measure whether it makes much difference to skip the builder entirely in those cases where that could be done. No review. --- src/library/scala/Array.scala | 5 +++++ src/library/scala/collection/immutable/Range.scala | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index f89e8b48a5..c9d929b88c 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -207,6 +207,7 @@ object Array extends FallbackArrayBuilding { */ def fill[T: ClassManifest](n: Int)(elem: => T): Array[T] = { val b = newBuilder[T] + b.sizeHint(n) var i = 0 while (i < n) { b += elem @@ -270,6 +271,7 @@ object Array extends FallbackArrayBuilding { */ def tabulate[T: ClassManifest](n: Int)(f: Int => T): Array[T] = { val b = newBuilder[T] + b.sizeHint(n) var i = 0 while (i < n) { b += f(i) @@ -343,6 +345,8 @@ object Array extends FallbackArrayBuilding { def range(start: Int, end: Int, step: Int): Array[Int] = { if (step == 0) throw new IllegalArgumentException("zero step") val b = newBuilder[Int] + b.sizeHint(Range.count(start, end, step, false)) + var i = start while (if (step < 0) end < i else i < end) { b += i @@ -360,6 +364,7 @@ object Array extends FallbackArrayBuilding { */ def iterate[T: ClassManifest](start: T, len: Int)(f: T => T): Array[T] = { val b = newBuilder[T] + b.sizeHint(len) var acc = start var i = 0 while (i < len) { diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 8f1f7d58a6..0f20b1ea04 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -219,6 +219,23 @@ class Range(val start: Int, val end: Int, val step: Int) extends IndexedSeq[Int] object Range { private[immutable] val MAX_PRINT = 512 // some arbitrary value + /** Calculates the number of elements in a range given start, end, step, and + * whether or not it is inclusive. Returns -1 if parameters are invalid. + */ + 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 = { + def last = + if (isInclusive && step < 0) end - 1 + else if (isInclusive && step > 0) end + 1 + else end + + if (step == 0) -1 + else if (start == end) { if (isInclusive) 1 else 0 } + else if (end > start != step > 0) -1 + else if (step == 1 || step == -1) last - start + else ((last - start - 1) / step) + 1 + } + class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) { override def isInclusive = true override protected def copy(start: Int, end: Int, step: Int): Range = new Inclusive(start, end, step) -- cgit v1.2.3