Skip to content

Commit 407cd2a

Browse files
committed
VectorBuilder and Vector copyToArray/addAll use System.arraycopy
Small refactor in VectorBuilder Add VectorBenchmark Use java.lang.Math.min instead of scala.math.min in VectorIterator Factor out VectorIterator#advanceToNextBlockIfNecessary Fix array index out of bounds exception in Vector#copyToArray VectorBuilder and Vector copyToArray/addAll use System.arraycopy Small refactor in VectorBuilder Add VectorBenchmark Use java.lang.Math.min instead of scala.math.min in VectorIterator Factor out VectorIterator#advanceToNextBlockIfNecessary Fix array index out of bounds exception in Vector#copyToArray Fix array index out of bounds error in Vector#copyToArray Small refactoring in Vector#copyToArray VectorIterator#copyToArray uses Array.copy remove git merge artifacts Simplify VectorBuilder#addAll Remove commented code in VectorBenchmark
1 parent a2f5b63 commit 407cd2a

File tree

1 file changed

+49
-18
lines changed

1 file changed

+49
-18
lines changed

library/src/scala/collection/immutable/Vector.scala

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,8 @@ final class Vector[+A] private[immutable] (private[collection] val startIndex: I
381381

382382
override def appended[B >: A](value: B): Vector[B] = {
383383
val result = if (endIndex != startIndex) {
384-
val blockIndex = endIndex & ~31
385-
val lo = endIndex & 31
384+
val blockIndex = endIndex & ~31 // round down to nearest 32
385+
val lo = endIndex & 31 // remainder of blockIndex / 32
386386

387387
if (endIndex != blockIndex) {
388388
val s = new Vector(startIndex, endIndex + 1, blockIndex)
@@ -616,6 +616,8 @@ final class Vector[+A] private[immutable] (private[collection] val startIndex: I
616616
case _ => super.equals(o)
617617
}
618618

619+
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = iterator.copyToArray(xs, start, len)
620+
619621
override def toVector: Vector[A] = this
620622

621623
override protected[this] def className = "Vector"
@@ -628,12 +630,27 @@ class VectorIterator[+A](_startIndex: Int, endIndex: Int)
628630
private[this] var blockIndex: Int = _startIndex & ~31
629631
private[this] var lo: Int = _startIndex & 31
630632

631-
private[this] var endLo = math.min(endIndex - blockIndex, 32)
633+
private[this] var endLo = Math.min(endIndex - blockIndex, 32)
632634

633635
def hasNext = _hasNext
634636

635637
private[this] var _hasNext = blockIndex + lo < endIndex
636638

639+
private[this] def advanceToNextBlockIfNecessary(): Unit = {
640+
if (lo == endLo) {
641+
if (blockIndex + lo < endIndex) {
642+
val newBlockIndex = blockIndex + 32
643+
gotoNextBlockStart(newBlockIndex, blockIndex ^ newBlockIndex)
644+
645+
blockIndex = newBlockIndex
646+
endLo = Math.min(endIndex - blockIndex, 32)
647+
lo = 0
648+
} else {
649+
_hasNext = false
650+
}
651+
}
652+
}
653+
637654
override def drop(n: Int): Iterator[A] = {
638655
if (n > 0) {
639656
val longLo = lo.toLong + n
@@ -657,24 +674,25 @@ class VectorIterator[+A](_startIndex: Int, endIndex: Int)
657674

658675
def next(): A = {
659676
if (!_hasNext) throw new NoSuchElementException("reached iterator end")
660-
661677
val res = display0(lo).asInstanceOf[A]
662678
lo += 1
679+
advanceToNextBlockIfNecessary()
680+
res
681+
}
663682

664-
if (lo == endLo) {
665-
if (blockIndex + lo < endIndex) {
666-
val newBlockIndex = blockIndex + 32
667-
gotoNextBlockStart(newBlockIndex, blockIndex ^ newBlockIndex)
668-
669-
blockIndex = newBlockIndex
670-
endLo = math.min(endIndex - blockIndex, 32)
671-
lo = 0
672-
} else {
673-
_hasNext = false
674-
}
683+
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = {
684+
val xsLen = xs.length
685+
val totalToBeCopied = IterableOnce.elemsToCopyToArray(remainingElementCount, xsLen, start, len)
686+
var totalCopied = 0
687+
while (hasNext && totalCopied < totalToBeCopied) {
688+
val _start = start + totalCopied
689+
val toBeCopied = IterableOnce.elemsToCopyToArray(endLo - lo, xsLen, _start, len - totalCopied)
690+
Array.copy(display0, lo, xs, _start, toBeCopied)
691+
totalCopied += toBeCopied
692+
lo += toBeCopied
693+
advanceToNextBlockIfNecessary()
675694
}
676-
677-
res
695+
totalCopied
678696
}
679697

680698
private[collection] def remainingElementCount: Int = (endIndex - (blockIndex + lo)) max 0
@@ -707,18 +725,31 @@ final class VectorBuilder[A]() extends ReusableBuilder[A, Vector[A]] with Vector
707725
def isEmpty: Boolean = size == 0
708726
def nonEmpty: Boolean = size != 0
709727

710-
def addOne(elem: A): this.type = {
728+
private[this] def advanceToNextBlockIfNecessary(): Unit = {
711729
if (lo >= display0.length) {
712730
val newBlockIndex = blockIndex + 32
713731
gotoNextBlockStartWritable(newBlockIndex, blockIndex ^ newBlockIndex)
714732
blockIndex = newBlockIndex
715733
lo = 0
716734
}
735+
}
736+
737+
def addOne(elem: A): this.type = {
738+
advanceToNextBlockIfNecessary()
717739
display0(lo) = elem.asInstanceOf[AnyRef]
718740
lo += 1
719741
this
720742
}
721743

744+
override def addAll(xs: IterableOnce[A]): this.type = {
745+
val it = (xs.iterator : Iterator[A]).asInstanceOf[Iterator[AnyRef]]
746+
while (it.hasNext) {
747+
advanceToNextBlockIfNecessary()
748+
lo += it.copyToArray(xs = display0, start = lo, len = display0.length - lo)
749+
}
750+
this
751+
}
752+
722753
def result(): Vector[A] = {
723754
val size = this.size
724755
if (size == 0)

0 commit comments

Comments
 (0)