From 946414cf8b2fa9ef198ef6cded019c2d187c229e Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Fri, 2 Aug 2019 19:54:12 +0200 Subject: [PATCH] More efficient ArraySeq iteration - Use `ArrayIterator` for `ArraySeq`: As discovered in https://github.com/scala/bug/issues/11658, `ArraySeq` (both mutable and immutable) used the generic `IndexedSeqView`-based iterators even though the more efficient `ArrayIterator` is available. - Avoid runtime type checks for `ArraySeq` steppers: `ArraySeq.stepper` had to perform a runtime type check for the array. Now there are separate implementations for all specialized `ArraySeq` types that avoid the extra checks. - Add a useful `knownSize` implementation to `ArrayIterator`. --- build.sbt | 26 ++++++ src/library/scala/collection/ArrayOps.scala | 10 ++- .../scala/collection/immutable/ArraySeq.scala | 83 +++++++++++++------ .../scala/collection/mutable/ArraySeq.scala | 83 +++++++++++++------ 4 files changed, 145 insertions(+), 57 deletions(-) diff --git a/build.sbt b/build.sbt index 7fb0a35f114b..413c986f1ea2 100644 --- a/build.sbt +++ b/build.sbt @@ -95,6 +95,32 @@ val mimaFilterSettings = Seq( ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.api.TypeTags.TypeTagImpl"), ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.api.Universe.TypeTagImpl"), ProblemFilters.exclude[MissingClassProblem]("scala.reflect.macros.Attachments$"), + ProblemFilters.exclude[DirectAbstractMethodProblem]("scala.collection.immutable.ArraySeq.stepper"), + ProblemFilters.exclude[ReversedAbstractMethodProblem]("scala.collection.immutable.ArraySeq.stepper"), + ProblemFilters.exclude[DirectAbstractMethodProblem]("scala.collection.mutable.ArraySeq.stepper"), + ProblemFilters.exclude[ReversedAbstractMethodProblem]("scala.collection.mutable.ArraySeq.stepper"), + ProblemFilters.exclude[FinalClassProblem]("scala.collection.ArrayOps$GroupedIterator"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcB$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcZ$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcV$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcD$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcJ$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcV$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcB$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$GroupedIterator"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcF$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcC$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcF$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcS$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcI$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcC$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcJ$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcD$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ReverseIterator$mcZ$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcI$sp"), + ProblemFilters.exclude[MissingTypesProblem]("scala.collection.ArrayOps$ArrayIterator$mcS$sp"), ), ) diff --git a/src/library/scala/collection/ArrayOps.scala b/src/library/scala/collection/ArrayOps.scala index 04d78608b40e..626dec4e41a5 100644 --- a/src/library/scala/collection/ArrayOps.scala +++ b/src/library/scala/collection/ArrayOps.scala @@ -119,9 +119,11 @@ object ArrayOps { def withFilter(q: A => Boolean): WithFilter[A] = new WithFilter[A](a => p(a) && q(a), xs) } - private final class ArrayIterator[@specialized(Specializable.Everything) A](xs: Array[A]) extends AbstractIterator[A] { + @SerialVersionUID(3L) + private[collection] final class ArrayIterator[@specialized(Specializable.Everything) A](xs: Array[A]) extends AbstractIterator[A] with Serializable { private[this] var pos = 0 private[this] val len = xs.length + override def knownSize = len - pos def hasNext: Boolean = pos < len def next(): A = try { val r = xs(pos) @@ -134,7 +136,8 @@ object ArrayOps { } } - private final class ReverseIterator[@specialized(Specializable.Everything) A](xs: Array[A]) extends AbstractIterator[A] { + @SerialVersionUID(3L) + private final class ReverseIterator[@specialized(Specializable.Everything) A](xs: Array[A]) extends AbstractIterator[A] with Serializable { private[this] var pos = xs.length-1 def hasNext: Boolean = pos >= 0 def next(): A = try { @@ -149,7 +152,8 @@ object ArrayOps { } } - private class GroupedIterator[A](xs: Array[A], groupSize: Int) extends AbstractIterator[Array[A]] { + @SerialVersionUID(3L) + private final class GroupedIterator[A](xs: Array[A], groupSize: Int) extends AbstractIterator[Array[A]] with Serializable { private[this] var pos = 0 def hasNext: Boolean = pos < xs.length def next(): Array[A] = { diff --git a/src/library/scala/collection/immutable/ArraySeq.scala b/src/library/scala/collection/immutable/ArraySeq.scala index edd0e3485e2d..9460148955c6 100644 --- a/src/library/scala/collection/immutable/ArraySeq.scala +++ b/src/library/scala/collection/immutable/ArraySeq.scala @@ -18,6 +18,7 @@ import java.util.Arrays import scala.annotation.unchecked.uncheckedVariance import scala.collection.Stepper.EfficientSplit import scala.collection.mutable.{ArrayBuffer, ArrayBuilder, Builder, ArraySeq => MutableArraySeq} +import scala.collection.convert.impl._ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime import scala.util.Sorting @@ -55,33 +56,7 @@ sealed abstract class ArraySeq[+A] protected def evidenceIterableFactory: ArraySeq.type = ArraySeq protected def iterableEvidence: ClassTag[A @uncheckedVariance] = elemTag.asInstanceOf[ClassTag[A]] - override def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S with EfficientSplit = { - import scala.collection.convert.impl._ - val isRefShape = shape.shape == StepperShape.ReferenceShape - val s = if (isRefShape) unsafeArray match { - case a: Array[Int] => AnyStepper.ofParIntStepper (new IntArrayStepper(a, 0, a.length)) - case a: Array[Long] => AnyStepper.ofParLongStepper (new LongArrayStepper(a, 0, a.length)) - case a: Array[Double] => AnyStepper.ofParDoubleStepper(new DoubleArrayStepper(a, 0, a.length)) - case a: Array[Byte] => AnyStepper.ofParIntStepper (new WidenedByteArrayStepper(a, 0, a.length)) - case a: Array[Short] => AnyStepper.ofParIntStepper (new WidenedShortArrayStepper(a, 0, a.length)) - case a: Array[Char] => AnyStepper.ofParIntStepper (new WidenedCharArrayStepper(a, 0, a.length)) - case a: Array[Float] => AnyStepper.ofParDoubleStepper(new WidenedFloatArrayStepper(a, 0, a.length)) - case a: Array[Boolean] => new BoxedBooleanArrayStepper(a, 0, a.length) - case a: Array[AnyRef] => new ObjectArrayStepper(a, 0, a.length) - } else { - unsafeArray match { - case a: Array[AnyRef] => shape.parUnbox(new ObjectArrayStepper(a, 0, a.length).asInstanceOf[AnyStepper[A] with EfficientSplit]) - case a: Array[Int] => new IntArrayStepper(a, 0, a.length) - case a: Array[Long] => new LongArrayStepper(a, 0, a.length) - case a: Array[Double] => new DoubleArrayStepper(a, 0, a.length) - case a: Array[Byte] => new WidenedByteArrayStepper(a, 0, a.length) - case a: Array[Short] => new WidenedShortArrayStepper(a, 0, a.length) - case a: Array[Char] => new WidenedCharArrayStepper(a, 0, a.length) - case a: Array[Float] => new WidenedFloatArrayStepper(a, 0, a.length) - } - } - s.asInstanceOf[S with EfficientSplit] - } + def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S with EfficientSplit @throws[ArrayIndexOutOfBoundsException] def apply(i: Int): A @@ -276,6 +251,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => new ArraySeq.ofRef(a) } } + override def iterator: Iterator[T] = new ArrayOps.ArrayIterator[T](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[T, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + new ObjectArrayStepper(unsafeArray, 0, unsafeArray.length) + else shape.parUnbox(new ObjectArrayStepper(unsafeArray, 0, unsafeArray.length).asInstanceOf[AnyStepper[T] with EfficientSplit]) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -296,6 +277,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => Arrays.sort(a) new ArraySeq.ofByte(a) } else super.sorted[B] + override def iterator: Iterator[Byte] = new ArrayOps.ArrayIterator[Byte](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Byte, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new WidenedByteArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new WidenedByteArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -316,6 +303,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => Arrays.sort(a) new ArraySeq.ofShort(a) } else super.sorted[B] + override def iterator: Iterator[Short] = new ArrayOps.ArrayIterator[Short](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Short, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new WidenedShortArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new WidenedShortArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -336,6 +329,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => Arrays.sort(a) new ArraySeq.ofChar(a) } else super.sorted[B] + override def iterator: Iterator[Char] = new ArrayOps.ArrayIterator[Char](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Char, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new WidenedCharArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new WidenedCharArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] override def addString(sb: StringBuilder, start: String, sep: String, end: String): StringBuilder = (new MutableArraySeq.ofChar(unsafeArray)).addString(sb, start, sep, end) @@ -359,6 +358,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => Arrays.sort(a) new ArraySeq.ofInt(a) } else super.sorted[B] + override def iterator: Iterator[Int] = new ArrayOps.ArrayIterator[Int](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Int, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new IntArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new IntArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -379,6 +384,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => Arrays.sort(a) new ArraySeq.ofLong(a) } else super.sorted[B] + override def iterator: Iterator[Long] = new ArrayOps.ArrayIterator[Long](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Long, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParLongStepper(new LongArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new LongArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -392,6 +403,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofFloat => Arrays.equals(unsafeArray, that.unsafeArray) case _ => super.equals(that) } + override def iterator: Iterator[Float] = new ArrayOps.ArrayIterator[Float](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Float, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParDoubleStepper(new WidenedFloatArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new WidenedFloatArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -405,6 +422,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofDouble => Arrays.equals(unsafeArray, that.unsafeArray) case _ => super.equals(that) } + override def iterator: Iterator[Double] = new ArrayOps.ArrayIterator[Double](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Double, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParDoubleStepper(new DoubleArrayStepper(unsafeArray, 0, unsafeArray.length)) + else new DoubleArrayStepper(unsafeArray, 0, unsafeArray.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -425,6 +448,9 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => Sorting.stableSort(a) new ArraySeq.ofBoolean(a) } else super.sorted[B] + override def iterator: Iterator[Boolean] = new ArrayOps.ArrayIterator[Boolean](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Boolean, S]): S with EfficientSplit = + new BoxedBooleanArrayStepper(unsafeArray, 0, unsafeArray.length).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -438,5 +464,8 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofUnit => unsafeArray.length == that.unsafeArray.length case _ => super.equals(that) } + override def iterator: Iterator[Unit] = new ArrayOps.ArrayIterator[Unit](unsafeArray) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Unit, S]): S with EfficientSplit = + new ObjectArrayStepper[AnyRef](unsafeArray.asInstanceOf[Array[AnyRef]], 0, unsafeArray.length).asInstanceOf[S with EfficientSplit] } } diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala index 7ed2dea53d6d..6f2596a66f2f 100644 --- a/src/library/scala/collection/mutable/ArraySeq.scala +++ b/src/library/scala/collection/mutable/ArraySeq.scala @@ -16,6 +16,7 @@ package mutable import java.util.Arrays import scala.collection.Stepper.EfficientSplit +import scala.collection.convert.impl._ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime import scala.util.hashing.MurmurHash3 @@ -66,33 +67,7 @@ sealed abstract class ArraySeq[T] * or subtype of the element type. */ def array: Array[_] - override def stepper[S <: Stepper[_]](implicit shape: StepperShape[T, S]): S with EfficientSplit = { - import scala.collection.convert.impl._ - val isRefShape = shape.shape == StepperShape.ReferenceShape - val s = if (isRefShape) array match { - case a: Array[Int] => AnyStepper.ofParIntStepper (new IntArrayStepper(a, 0, a.length)) - case a: Array[Long] => AnyStepper.ofParLongStepper (new LongArrayStepper(a, 0, a.length)) - case a: Array[Double] => AnyStepper.ofParDoubleStepper(new DoubleArrayStepper(a, 0, a.length)) - case a: Array[Byte] => AnyStepper.ofParIntStepper (new WidenedByteArrayStepper(a, 0, a.length)) - case a: Array[Short] => AnyStepper.ofParIntStepper (new WidenedShortArrayStepper(a, 0, a.length)) - case a: Array[Char] => AnyStepper.ofParIntStepper (new WidenedCharArrayStepper(a, 0, a.length)) - case a: Array[Float] => AnyStepper.ofParDoubleStepper(new WidenedFloatArrayStepper(a, 0, a.length)) - case a: Array[Boolean] => new BoxedBooleanArrayStepper(a, 0, a.length) - case a: Array[AnyRef] => new ObjectArrayStepper(a, 0, a.length) - } else { - array match { - case a: Array[AnyRef] => shape.parUnbox(new ObjectArrayStepper(a, 0, a.length).asInstanceOf[AnyStepper[T] with EfficientSplit]) - case a: Array[Int] => new IntArrayStepper(a, 0, a.length) - case a: Array[Long] => new LongArrayStepper(a, 0, a.length) - case a: Array[Double] => new DoubleArrayStepper(a, 0, a.length) - case a: Array[Byte] => new WidenedByteArrayStepper(a, 0, a.length) - case a: Array[Short] => new WidenedShortArrayStepper(a, 0, a.length) - case a: Array[Char] => new WidenedCharArrayStepper(a, 0, a.length) - case a: Array[Float] => new WidenedFloatArrayStepper(a, 0, a.length) - } - } - s.asInstanceOf[S with EfficientSplit] - } + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[T, S]): S with EfficientSplit override protected[this] def className = "ArraySeq" @@ -191,6 +166,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => that.array.asInstanceOf[Array[AnyRef]]) case _ => super.equals(that) } + override def iterator: Iterator[T] = new ArrayOps.ArrayIterator[T](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[T, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + new ObjectArrayStepper(array, 0, array.length) + else shape.parUnbox(new ObjectArrayStepper(array, 0, array.length).asInstanceOf[AnyStepper[T] with EfficientSplit]) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -204,6 +185,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofByte => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Byte] = new ArrayOps.ArrayIterator[Byte](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Byte, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new WidenedByteArrayStepper(array, 0, array.length)) + else new WidenedByteArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -217,6 +204,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofShort => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Short] = new ArrayOps.ArrayIterator[Short](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Short, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new WidenedShortArrayStepper(array, 0, array.length)) + else new WidenedShortArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -230,6 +223,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofChar => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Char] = new ArrayOps.ArrayIterator[Char](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Char, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new WidenedCharArrayStepper(array, 0, array.length)) + else new WidenedCharArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] override def addString(sb: StringBuilder, start: String, sep: String, end: String): StringBuilder = { val jsb = sb.underlying @@ -264,6 +263,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofInt => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Int] = new ArrayOps.ArrayIterator[Int](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Int, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParIntStepper(new IntArrayStepper(array, 0, array.length)) + else new IntArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -277,6 +282,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofLong => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Long] = new ArrayOps.ArrayIterator[Long](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Long, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParLongStepper(new LongArrayStepper(array, 0, array.length)) + else new LongArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -290,6 +301,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofFloat => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Float] = new ArrayOps.ArrayIterator[Float](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Float, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParDoubleStepper(new WidenedFloatArrayStepper(array, 0, array.length)) + else new WidenedFloatArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -303,6 +320,12 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofDouble => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Double] = new ArrayOps.ArrayIterator[Double](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Double, S]): S with EfficientSplit = ( + if(shape.shape == StepperShape.ReferenceShape) + AnyStepper.ofParDoubleStepper(new DoubleArrayStepper(array, 0, array.length)) + else new DoubleArrayStepper(array, 0, array.length) + ).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -316,6 +339,9 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofBoolean => Arrays.equals(array, that.array) case _ => super.equals(that) } + override def iterator: Iterator[Boolean] = new ArrayOps.ArrayIterator[Boolean](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Boolean, S]): S with EfficientSplit = + new BoxedBooleanArrayStepper(array, 0, array.length).asInstanceOf[S with EfficientSplit] } @SerialVersionUID(3L) @@ -329,5 +355,8 @@ object ArraySeq extends StrictOptimizedClassTagSeqFactory[ArraySeq] { self => case that: ofUnit => array.length == that.array.length case _ => super.equals(that) } + override def iterator: Iterator[Unit] = new ArrayOps.ArrayIterator[Unit](array) + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[Unit, S]): S with EfficientSplit = + new ObjectArrayStepper[AnyRef](array.asInstanceOf[Array[AnyRef]], 0, array.length).asInstanceOf[S with EfficientSplit] } }