summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-04-23 22:13:41 +0000
committerPaul Phillips <paulp@improving.org>2010-04-23 22:13:41 +0000
commit6736ca07f22a8da42604a27bda84f71b720b54ed (patch)
treeb4e720c26ad1aab77cefa34ea345e11ebf35291d
parenteb1ee924dd922db2e967c8a38ec13410eeb7110f (diff)
downloadscala-6736ca07f22a8da42604a27bda84f71b720b54ed.tar.gz
scala-6736ca07f22a8da42604a27bda84f71b720b54ed.tar.bz2
scala-6736ca07f22a8da42604a27bda84f71b720b54ed.zip
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.
-rw-r--r--src/library/scala/Array.scala5
-rw-r--r--src/library/scala/collection/immutable/Range.scala17
2 files changed, 22 insertions, 0 deletions
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)