From 1562feb4f4d8e1b982863159b52b89a630277a1a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 29 Apr 2015 20:58:59 -0700 Subject: [PATCH 01/56] Basic implementation of Stepper which covers functionality of both Iterator and Spliterator and primitive versions thereof. (Will still need four implementations of some things, but this should reduce it a lot.) Also added Steppers for arrays to check performance. (Very good so far.) Have some terminal operations to Stepper. Trying to avoid the Stepper/StepperLike pattern, but I doubt I'll manage. --- .../scala/compat/java8/StepConverters.scala | 193 ++++++++++++++++++ .../scala/scala/compat/java8/Stepper.scala | 71 +++++++ 2 files changed, 264 insertions(+) create mode 100644 src/main/scala/scala/compat/java8/StepConverters.scala create mode 100644 src/main/scala/scala/compat/java8/Stepper.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala new file mode 100644 index 0000000..58e58ec --- /dev/null +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -0,0 +1,193 @@ +package scala.compat.java8 + +import language.implicitConversions + +package converterImpls { + import StepConverters.SplitFlags._ + + private[java8] abstract class StepperArrayAny[A, AA, STA >: Null <: StepperArrayAny[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) + extends StepperGeneric[A] { + def semiclone(half: Int): STA + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): StepperGeneric[A] = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } + } + + private[java8] class StepperArrayGenObject[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) + extends StepperArrayAny[A, Array[A], StepperArrayGenObject[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenObject[A](underlying, i0, half) + } + + private[java8] class StepperArrayGenAny[A](underlying: Array[A], _i0: Int, _iN: Int) + extends StepperArrayAny[A, Array[A], StepperArrayGenAny[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenAny[A](underlying, i0, half) + } + + private[java8] class StepperArrayGenUnit(underlying: Array[Unit], _i0: Int, _iN: Int) + extends StepperArrayAny[Unit, Array[Unit], StepperArrayGenUnit](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenUnit(underlying, i0, half) + } + + private[java8] class StepperArrayGenBoolean(underlying: Array[Boolean], _i0: Int, _iN: Int) + extends StepperArrayAny[Boolean, Array[Boolean], StepperArrayGenBoolean](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenBoolean(underlying, i0, half) + } + + private[java8] class StepperArrayGenByte(underlying: Array[Byte], _i0: Int, _iN: Int) + extends StepperArrayAny[Byte, Array[Byte], StepperArrayGenByte](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenByte(underlying, i0, half) + } + + private[java8] class StepperArrayGenChar(underlying: Array[Char], _i0: Int, _iN: Int) + extends StepperArrayAny[Char, Array[Char], StepperArrayGenChar](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenChar(underlying, i0, half) + } + + private[java8] class StepperArrayGenShort(underlying: Array[Short], _i0: Int, _iN: Int) + extends StepperArrayAny[Short, Array[Short], StepperArrayGenShort](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenShort(underlying, i0, half) + } + + private[java8] class StepperArrayGenFloat(underlying: Array[Float], _i0: Int, _iN: Int) + extends StepperArrayAny[Float, Array[Float], StepperArrayGenFloat](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenFloat(underlying, i0, half) + } + + private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends StepperDouble { + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def substep() = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = new StepperArrayDouble(underlying, i0, half) + i0 = half + ans + } + else null + } + } + + private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends StepperInt { + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def substep() = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = new StepperArrayInt(underlying, i0, half) + i0 = half + ans + } + else null + } + } + + private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends StepperLong { + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def substep() = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = new StepperArrayLong(underlying, i0, half) + i0 = half + ans + } + else null + } + } + + final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { + @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + } + + final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ + @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + } + + final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ + @inline def stepper: Stepper[Unit, StepperGeneric[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) + } + + final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ + @inline def stepper: Stepper[Boolean, StepperGeneric[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + } + + final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ + @inline def stepper: Stepper[Byte, StepperGeneric[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) + } + + final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ + @inline def stepper: Stepper[Char, StepperGeneric[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) + } + + final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ + @inline def stepper: Stepper[Short, StepperGeneric[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) + } + + final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ + @inline def stepper: Stepper[Float, StepperGeneric[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) + } + + trait Priority3StepConverters { + implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) + } + + trait Priority2StepConverters extends Priority3StepConverters { + implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) + implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) + implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) + implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) + implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) + implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) + implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + } +} + +object StepConverters extends converterImpls.Priority2StepConverters { + object SplitFlags { + final val Concurrent = java.util.Spliterator.CONCURRENT + final val Distinct = java.util.Spliterator.DISTINCT + final val Immutable = java.util.Spliterator.IMMUTABLE + final val NonNull = java.util.Spliterator.NONNULL + final val HasOrder = java.util.Spliterator.ORDERED + final val Sized = java.util.Spliterator.SIZED + final val Sorted = java.util.Spliterator.SORTED + final val Subsized = java.util.Spliterator.SUBSIZED + } + import SplitFlags._ + import converterImpls._ + + implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { + def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) + } + + implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { + def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) + } + + implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { + def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + } +} diff --git a/src/main/scala/scala/compat/java8/Stepper.scala b/src/main/scala/scala/compat/java8/Stepper.scala new file mode 100644 index 0000000..22fdd5c --- /dev/null +++ b/src/main/scala/scala/compat/java8/Stepper.scala @@ -0,0 +1,71 @@ +package scala.compat.java8 + +trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { + def characteristics: Int + def hasStep: Boolean + def knownSize: Long + def nextStep: A + def tryStep(f: A => Unit): Boolean + def substep(): Stepper[A, CC] + def typedPrecisely: CC + + // Terminal operations that do not produce another Stepper + def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } + def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } + def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } + def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None } + def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b } + def foreach(f: A => Unit) { while (hasStep) f(nextStep) } + def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } +} + +trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { + def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = next + def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false + def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely: StepperGeneric[A] = this +} + +trait StepperDouble extends Stepper[Double, StepperDouble] with java.util.PrimitiveIterator.OfDouble with java.util.Spliterator.OfDouble { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } + def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextDouble + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false + def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false + def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this +} + +trait StepperInt extends Stepper[Int, StepperInt] with java.util.PrimitiveIterator.OfInt with java.util.Spliterator.OfInt { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } + def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextInt + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false + def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false + def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this +} + +trait StepperLong extends Stepper[Long, StepperLong] with java.util.PrimitiveIterator.OfLong with java.util.Spliterator.OfLong { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } + def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextLong + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false + def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false + def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this +} + From f476c42bd61e155334f84f40a9789d702d4a81e1 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 1 May 2015 18:56:57 -0700 Subject: [PATCH 02/56] Further work on core stepper API. --- .../java8/Stepper.scala | 60 ++++++++++++++++++- .../scala/compat/java8/StepConverters.scala | 36 ++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) rename src/main/scala/scala/{compat => collection}/java8/Stepper.scala (68%) diff --git a/src/main/scala/scala/compat/java8/Stepper.scala b/src/main/scala/scala/collection/java8/Stepper.scala similarity index 68% rename from src/main/scala/scala/compat/java8/Stepper.scala rename to src/main/scala/scala/collection/java8/Stepper.scala index 22fdd5c..e433c9b 100644 --- a/src/main/scala/scala/compat/java8/Stepper.scala +++ b/src/main/scala/scala/collection/java8/Stepper.scala @@ -1,4 +1,4 @@ -package scala.compat.java8 +package scala.collection.java8 trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def characteristics: Int @@ -6,18 +6,72 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def knownSize: Long def nextStep: A def tryStep(f: A => Unit): Boolean - def substep(): Stepper[A, CC] + def substep(): CC def typedPrecisely: CC - // Terminal operations that do not produce another Stepper + // Terminal operations (do not produce another Stepper) def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None } def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b } + def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } def foreach(f: A => Unit) { while (hasStep) f(nextStep) } def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } } +object Stepper { + class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) extends StepperGeneric[A] with java.util.function.Consumer[A] { + private var cache: A = null.asInstanceOf[A] + private var cached: Boolean = false + def accept(a: A) { cache = a; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.Consumer[_ >: A]): Boolean = { + if (cached) { + c.accept(cache) + cache = null.asInstanceOf[A] + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def next = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cache = null.asInstanceOf[A] + cached = false + ans + } + def substep(): StepperGeneric[A] = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cache = null.asInstanceOf[A] + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) + } + def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) +} trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 58e58ec..ec5fd45 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -2,6 +2,8 @@ package scala.compat.java8 import language.implicitConversions +import scala.collection.java8._ + package converterImpls { import StepConverters.SplitFlags._ @@ -150,6 +152,30 @@ package converterImpls { @inline def stepper: Stepper[Float, StepperGeneric[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) } + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends StepperInt { + def characteristics() = NonNull + def estimateSize = iN - i0 + def hasNext = i0 < iN + def nextInt() = { + if (hasNext()) { + val cp = underlying.codePointAt(i0) + i0 += java.lang.Character.charCount(cp) + cp + } + else throw new NoSuchElementException("Empty Stepper") + } + def substep() = { + if (iN-3 > i0) { + var half = (i0+iN) >>> 1 + if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 + val ans = new StepperStringCodePoint(underlying, i0, half) + i0 = half + ans + } + else null + } + } + trait Priority3StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) } @@ -180,14 +206,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + } + + implicit class RichStringCanStep(val underlying: String) extends AnyVal { + @inline def stepper: Stepper[Int, StepperInt] = new StepperStringCodePoint(underlying, 0, underlying.length) } } From 1cf9ea2a904830f2aea341ec48dc0e9d1feaf578 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 23 Aug 2015 16:44:33 -0700 Subject: [PATCH 03/56] Basic conversion of Spliterator to Stepper works. --- .../compat/java8/SpliteratorConverters.scala | 29 ++++ .../scala/compat/java8/StepConverters.scala | 2 +- .../java8/collectionImpl}/Stepper.scala | 152 +++++++++++++++++- 3 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/SpliteratorConverters.scala rename src/main/scala/scala/{collection/java8 => compat/java8/collectionImpl}/Stepper.scala (56%) diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala new file mode 100644 index 0000000..a8bc6fb --- /dev/null +++ b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala @@ -0,0 +1,29 @@ +package scala.compat.java8 + +import language.implicitConversions + +import java.util._ +import scala.compat.java8.collectionImpl._ + +package SpliteratorConverters { + class SpliteratorToStepper[A] private[java8] (private val underlying: Spliterator[A]) extends AnyVal { + def stepper: StepperGeneric[A] = Stepper.ofSpliterator(underlying) + } + + trait Priority2SpliteratorConverters { + implicit def spliteratorToStepper[A](sp: Spliterator[A]) = new SpliteratorToStepper[A](sp) + } +} + + +package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters { + implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { + def stepper: StepperDouble = Stepper.ofSpliterator(underlying) + } + implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { + def stepper: StepperInt = Stepper.ofSpliterator(underlying) + } + implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { + def stepper: StepperLong = Stepper.ofSpliterator(underlying) + } +} diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ec5fd45..ec95c35 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -2,7 +2,7 @@ package scala.compat.java8 import language.implicitConversions -import scala.collection.java8._ +import scala.compat.java8.collectionImpl._ package converterImpls { import StepConverters.SplitFlags._ diff --git a/src/main/scala/scala/collection/java8/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala similarity index 56% rename from src/main/scala/scala/collection/java8/Stepper.scala rename to src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index e433c9b..8c7eb5f 100644 --- a/src/main/scala/scala/collection/java8/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,4 +1,4 @@ -package scala.collection.java8 +package scala.compat.java8.collectionImpl trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def characteristics: Int @@ -20,7 +20,8 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } } object Stepper { - class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) extends StepperGeneric[A] with java.util.function.Consumer[A] { + class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) + extends StepperGeneric[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] private var cached: Boolean = false def accept(a: A) { cache = a; cached = true } @@ -70,7 +71,154 @@ object Stepper { } override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) } + class OfDoubleSpliterator private[java8] (sp: java.util.Spliterator.OfDouble) + extends StepperDouble with java.util.function.DoubleConsumer { + private var cache: Double = Double.NaN + private var cached: Boolean = false + def accept(d: Double) { cache = d; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.DoubleConsumer): Boolean = { + if (cached) { + c.accept(cache) + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.DoubleConsumer) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def nextDouble = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cached = false + ans + } + def substep(): StepperDouble = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfDoubleSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c) + } + class OfIntSpliterator private[java8] (sp: java.util.Spliterator.OfInt) + extends StepperInt with java.util.function.IntConsumer { + private var cache: Int = 0 + private var cached: Boolean = false + def accept(i: Int) { cache = i; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.IntConsumer): Boolean = { + if (cached) { + c.accept(cache) + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.IntConsumer) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def nextInt = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cached = false + ans + } + def substep(): StepperInt = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfIntSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c) + } + class OfLongSpliterator private[java8] (sp: java.util.Spliterator.OfLong) + extends StepperLong with java.util.function.LongConsumer { + private var cache: Long = 0L + private var cached: Boolean = false + def accept(l: Long) { cache = l; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.LongConsumer): Boolean = { + if (cached) { + c.accept(cache) + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.LongConsumer) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def nextLong = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cached = false + ans + } + def substep(): StepperLong = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfLongSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) + } def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) + def ofSpliterator(sp: java.util.Spliterator.OfDouble) = new OfDoubleSpliterator(sp) + def ofSpliterator(sp: java.util.Spliterator.OfInt) = new OfIntSpliterator(sp) + def ofSpliterator(sp: java.util.Spliterator.OfLong) = new OfLongSpliterator(sp) } trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { From ec8ebd12afe048074880c275ecaddebcaedb18b3 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 29 Aug 2015 19:44:13 -0700 Subject: [PATCH 04/56] Work in progress on Filter etc.. --- .../compat/java8/collectionImpl/Stepper.scala | 109 +++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 8c7eb5f..0d7d0b1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,15 +1,49 @@ package scala.compat.java8.collectionImpl +/** A Stepper is a specialized collection that can step through its + * contents once. It provides the same test-and-get methods as + * does `Iterator`, named `hasStep` and `nextStep` so they can + * coexist with iterator methods. However, like `java.util.Spliterator`, + * steppers provide a `tryStep` method to call a closure if another + * element exists, a `substep()` method to split into pieces, and + * `characteristics` and size-reporting methods that + * implement the subdivision and report what is known about the remaining + * size of the `Stepper`. `Stepper` thus naturally implements both + * `Iterator` and `Spliterator`. + * + * Subtraits `NextStepper` and `TryStepper` fill in the basic capability + * by either implementing `tryStep` in terms of `hasStep` and `nextStep`, + * or vice versa. + * + * `Stepper` implements four core intermediate operations that process + * the sequence of elements and return another `Stepper`, and six core + * terminal operations that consume the `Stepper` and produce a result. + * If additional functionality is needed, one can convert a `Stepper` to + * a Scala `Iterator` or a Java 8 `Stream`. + */ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def characteristics: Int - def hasStep: Boolean def knownSize: Long - def nextStep: A + def hasStep: Boolean + def nextStep(): A def tryStep(f: A => Unit): Boolean def substep(): CC def typedPrecisely: CC + + //// + // Intermediate operations (do produce another Stepper) + //// + def drop(n: Int): Stepper[A, CC] + def filter(p: A => Boolean): Stepper[A, CC] + def flatMap[@specialized(Double, Int, Long) B, DD](f: A => Stepper[B, DD])(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = + impl.flatmapOf(this, f) + def map[@specialized(Double, Int, Long) B, DD](f: A => B)(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = + impl.mapOf(this, f) + def take(n: Int): Stepper[A, CC] + //// // Terminal operations (do not produce another Stepper) + //// def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } @@ -19,7 +53,34 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def foreach(f: A => Unit) { while (hasStep) f(nextStep) } def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } } + +trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { + def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false +} + +trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { + private var myCache: A = null.asInstanceOf[A] + private var myCacheIsFull = false + private def load(): Boolean = { + myCacheIsFull = tryStep(myCache = _) + myCacheIsFull + } + def hasStep = myCacheIsFull || load() + def nextStep = { + if (!myCacheIsFull) { + load() + if (!myCacheIsFull) throw new NoSuchElementException("nextStep in TryStepper") + } + val ans = myCache + myCacheIsFull = false + myCache = null.asInstanceOf[A] + ans + } +} + + object Stepper { + class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) extends StepperGeneric[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] @@ -71,6 +132,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) } + class OfDoubleSpliterator private[java8] (sp: java.util.Spliterator.OfDouble) extends StepperDouble with java.util.function.DoubleConsumer { private var cache: Double = Double.NaN @@ -119,6 +181,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c) } + class OfIntSpliterator private[java8] (sp: java.util.Spliterator.OfInt) extends StepperInt with java.util.function.IntConsumer { private var cache: Int = 0 @@ -167,6 +230,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c) } + class OfLongSpliterator private[java8] (sp: java.util.Spliterator.OfLong) extends StepperLong with java.util.function.LongConsumer { private var cache: Long = 0L @@ -215,6 +279,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) } + def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) def ofSpliterator(sp: java.util.Spliterator.OfDouble) = new OfDoubleSpliterator(sp) def ofSpliterator(sp: java.util.Spliterator.OfInt) = new OfIntSpliterator(sp) @@ -230,6 +295,46 @@ trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Ite def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false def trySplit() = substep.typedPrecisely final def typedPrecisely: StepperGeneric[A] = this + + def filter(p: A => Boolean): StepperGeneric[A] = new FilteredStepperGeneric(this, p) +} + +trait FilteredStepperGeneric[A](orig: StepperGeneric[A], predicate: A => Boolean) extends StepperGeneric[A] { + private val knownComplete = false + private val myCache: A = null.asInstanceOf[A] + private val isCached = false + private var myOrig = orig + private var myPred = predicate + + private def loadCache(): Boolean = if (knownComplete) false else { + while (orig.hasNext) { + val temp = orig.next + if (predicate(temp)) { + isCached = true + myCache = temp + return true + } + } + false + } + + override def getExactSizeIfKnown = if (knownComplete) 0L else -1L + override def hasNext(): Boolean = isCached || loadCache + override def next(): A = + if (hasNext) { val ans = myCache; myCache = null.asInstanceOf[A]; isCached = false; ans } + else throw new NoSuchElementException("Out of elements in Stepper.next") + override def substep() = { + val ss = orig.substep() + if (ss == null) null + else { + val init = new FilteredStepperGeneric[A](ss, predicate) + init.myCache = myCache + init.isCached = isCached + myCache = null.asInstanceOf[A] + isCached = false + init + } + } } trait StepperDouble extends Stepper[Double, StepperDouble] with java.util.PrimitiveIterator.OfDouble with java.util.Spliterator.OfDouble { From bc909f4efff00cdc2b81bab04581c3cde8a5e342 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 2 Sep 2015 16:25:19 -0700 Subject: [PATCH 05/56] Refactored names a bit, tried to make interface work a little better. --- .../compat/java8/SpliteratorConverters.scala | 8 +- .../scala/compat/java8/StepConverters.scala | 36 +-- .../compat/java8/collectionImpl/Stepper.scala | 221 ++++++++---------- 3 files changed, 116 insertions(+), 149 deletions(-) diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala index a8bc6fb..1babaf3 100644 --- a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala +++ b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala @@ -7,7 +7,7 @@ import scala.compat.java8.collectionImpl._ package SpliteratorConverters { class SpliteratorToStepper[A] private[java8] (private val underlying: Spliterator[A]) extends AnyVal { - def stepper: StepperGeneric[A] = Stepper.ofSpliterator(underlying) + def stepper: AnyStepper[A] = Stepper.ofSpliterator(underlying) } trait Priority2SpliteratorConverters { @@ -18,12 +18,12 @@ package SpliteratorConverters { package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters { implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { - def stepper: StepperDouble = Stepper.ofSpliterator(underlying) + def stepper: DoubleStepper = Stepper.ofSpliterator(underlying) } implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { - def stepper: StepperInt = Stepper.ofSpliterator(underlying) + def stepper: IntStepper = Stepper.ofSpliterator(underlying) } implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { - def stepper: StepperLong = Stepper.ofSpliterator(underlying) + def stepper: LongStepper = Stepper.ofSpliterator(underlying) } } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ec95c35..2297a7d 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,12 +8,12 @@ package converterImpls { import StepConverters.SplitFlags._ private[java8] abstract class StepperArrayAny[A, AA, STA >: Null <: StepperArrayAny[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) - extends StepperGeneric[A] { + extends AnyStepper[A] { def semiclone(half: Int): STA def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def substep(): StepperGeneric[A] = { + def substep(): AnyStepper[A] = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 val ans = semiclone(half) @@ -72,7 +72,7 @@ package converterImpls { def semiclone(half: Int) = new StepperArrayGenFloat(underlying, i0, half) } - private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends StepperDouble { + private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN @@ -88,7 +88,7 @@ package converterImpls { } } - private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends StepperInt { + private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN @@ -104,7 +104,7 @@ package converterImpls { } } - private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends StepperLong { + private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN @@ -121,38 +121,38 @@ package converterImpls { } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { - @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) } final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ - @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) } final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: Stepper[Unit, StepperGeneric[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) + @inline def stepper: Stepper[Unit, AnyStepper[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) } final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: Stepper[Boolean, StepperGeneric[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + @inline def stepper: Stepper[Boolean, AnyStepper[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) } final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: Stepper[Byte, StepperGeneric[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) + @inline def stepper: Stepper[Byte, AnyStepper[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) } final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ - @inline def stepper: Stepper[Char, StepperGeneric[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) + @inline def stepper: Stepper[Char, AnyStepper[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) } final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: Stepper[Short, StepperGeneric[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) + @inline def stepper: Stepper[Short, AnyStepper[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) } final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ - @inline def stepper: Stepper[Float, StepperGeneric[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) + @inline def stepper: Stepper[Float, AnyStepper[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) } - private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends StepperInt { + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull def estimateSize = iN - i0 def hasNext = i0 < iN @@ -206,18 +206,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: Stepper[Double, DoubleStepper] = new StepperArrayDouble(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: Stepper[Int, IntStepper] = new StepperArrayInt(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: Stepper[Long, LongStepper] = new StepperArrayLong(underlying, 0, underlying.length) } implicit class RichStringCanStep(val underlying: String) extends AnyVal { - @inline def stepper: Stepper[Int, StepperInt] = new StepperStringCodePoint(underlying, 0, underlying.length) + @inline def stepper: Stepper[Int, IntStepper] = new StepperStringCodePoint(underlying, 0, underlying.length) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 0d7d0b1..8a3acc6 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,9 +1,11 @@ package scala.compat.java8.collectionImpl +import java.util.Spliterator + /** A Stepper is a specialized collection that can step through its * contents once. It provides the same test-and-get methods as * does `Iterator`, named `hasStep` and `nextStep` so they can - * coexist with iterator methods. However, like `java.util.Spliterator`, + * coexist with iterator methods. However, like `Spliterator`, * steppers provide a `tryStep` method to call a closure if another * element exists, a `substep()` method to split into pieces, and * `characteristics` and size-reporting methods that @@ -11,17 +13,21 @@ package scala.compat.java8.collectionImpl * size of the `Stepper`. `Stepper` thus naturally implements both * `Iterator` and `Spliterator`. * + * A `Stepper` can present itself as a Spliterator via the `spliterator` + * method, or as a Scala Iterator via the `iterator` method. The `Stepper` + * trait is compatible with both `Spliterator` and Java's generic and + * primitive iterators, so a `Stepper` may already be one or both. + * * Subtraits `NextStepper` and `TryStepper` fill in the basic capability * by either implementing `tryStep` in terms of `hasStep` and `nextStep`, * or vice versa. * - * `Stepper` implements four core intermediate operations that process - * the sequence of elements and return another `Stepper`, and six core - * terminal operations that consume the `Stepper` and produce a result. - * If additional functionality is needed, one can convert a `Stepper` to - * a Scala `Iterator` or a Java 8 `Stream`. + * Subtraits `AnyStepper`, `DoubleStepper`, `IntStepper`, and `LongStepper` + * implement both the `Stepper` trait and the corresponding Java + * `Spliterator` and `Iterator`/`PrimitiveIterator`. */ -trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { + +trait Stepper[@specialized(Double, Int, Long) A, CC] { self => def characteristics: Int def knownSize: Long def hasStep: Boolean @@ -30,17 +36,6 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def substep(): CC def typedPrecisely: CC - //// - // Intermediate operations (do produce another Stepper) - //// - def drop(n: Int): Stepper[A, CC] - def filter(p: A => Boolean): Stepper[A, CC] - def flatMap[@specialized(Double, Int, Long) B, DD](f: A => Stepper[B, DD])(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = - impl.flatmapOf(this, f) - def map[@specialized(Double, Int, Long) B, DD](f: A => B)(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = - impl.mapOf(this, f) - def take(n: Int): Stepper[A, CC] - //// // Terminal operations (do not produce another Stepper) //// @@ -52,13 +47,22 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } def foreach(f: A => Unit) { while (hasStep) f(nextStep) } def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } + + //// + // Operations that convert to another related type + //// + def spliterator: Spliterator[A] + def iterator: Iterator[A] = new scala.collection.AbstractIterator[A] { + def hasNext = self.hasStep + def next = self.nextStep + } } -trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { +trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false } -trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { +trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { private var myCache: A = null.asInstanceOf[A] private var myCacheIsFull = false private def load(): Boolean = { @@ -77,12 +81,66 @@ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper ans } } + +trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] with Spliterator[A] { + def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = next + def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false + def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely: AnyStepper[A] = this + override def spliterator: Spliterator[A] = this +} + +trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } + def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextDouble + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false + def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false + def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely: DoubleStepper = this + override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double +} + +trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } + def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextInt + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false + def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false + def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this + override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int +} + +trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } + def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextLong + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false + def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false + def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this + override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long +} object Stepper { - class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) - extends StepperGeneric[A] with java.util.function.Consumer[A] { + private class OfSpliterator[A](sp: Spliterator[A]) + extends AnyStepper[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] private var cached: Boolean = false def accept(a: A) { cache = a; cached = true } @@ -116,7 +174,7 @@ object Stepper { cached = false ans } - def substep(): StepperGeneric[A] = { + def substep(): AnyStepper[A] = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -133,8 +191,8 @@ object Stepper { override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) } - class OfDoubleSpliterator private[java8] (sp: java.util.Spliterator.OfDouble) - extends StepperDouble with java.util.function.DoubleConsumer { + private class OfDoubleSpliterator(sp: Spliterator.OfDouble) + extends DoubleStepper with java.util.function.DoubleConsumer { private var cache: Double = Double.NaN private var cached: Boolean = false def accept(d: Double) { cache = d; cached = true } @@ -166,7 +224,7 @@ object Stepper { cached = false ans } - def substep(): StepperDouble = { + def substep(): DoubleStepper = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -182,8 +240,8 @@ object Stepper { override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c) } - class OfIntSpliterator private[java8] (sp: java.util.Spliterator.OfInt) - extends StepperInt with java.util.function.IntConsumer { + private class OfIntSpliterator(sp: Spliterator.OfInt) + extends IntStepper with java.util.function.IntConsumer { private var cache: Int = 0 private var cached: Boolean = false def accept(i: Int) { cache = i; cached = true } @@ -215,7 +273,7 @@ object Stepper { cached = false ans } - def substep(): StepperInt = { + def substep(): IntStepper = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -231,8 +289,8 @@ object Stepper { override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c) } - class OfLongSpliterator private[java8] (sp: java.util.Spliterator.OfLong) - extends StepperLong with java.util.function.LongConsumer { + private class OfLongSpliterator(sp: Spliterator.OfLong) + extends LongStepper with java.util.function.LongConsumer { private var cache: Long = 0L private var cached: Boolean = false def accept(l: Long) { cache = l; cached = true } @@ -264,7 +322,7 @@ object Stepper { cached = false ans } - def substep(): StepperLong = { + def substep(): LongStepper = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -280,99 +338,8 @@ object Stepper { override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) } - def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) - def ofSpliterator(sp: java.util.Spliterator.OfDouble) = new OfDoubleSpliterator(sp) - def ofSpliterator(sp: java.util.Spliterator.OfInt) = new OfIntSpliterator(sp) - def ofSpliterator(sp: java.util.Spliterator.OfLong) = new OfLongSpliterator(sp) -} - -trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { - def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = next - def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false - def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely: StepperGeneric[A] = this - - def filter(p: A => Boolean): StepperGeneric[A] = new FilteredStepperGeneric(this, p) -} - -trait FilteredStepperGeneric[A](orig: StepperGeneric[A], predicate: A => Boolean) extends StepperGeneric[A] { - private val knownComplete = false - private val myCache: A = null.asInstanceOf[A] - private val isCached = false - private var myOrig = orig - private var myPred = predicate - - private def loadCache(): Boolean = if (knownComplete) false else { - while (orig.hasNext) { - val temp = orig.next - if (predicate(temp)) { - isCached = true - myCache = temp - return true - } - } - false - } - - override def getExactSizeIfKnown = if (knownComplete) 0L else -1L - override def hasNext(): Boolean = isCached || loadCache - override def next(): A = - if (hasNext) { val ans = myCache; myCache = null.asInstanceOf[A]; isCached = false; ans } - else throw new NoSuchElementException("Out of elements in Stepper.next") - override def substep() = { - val ss = orig.substep() - if (ss == null) null - else { - val init = new FilteredStepperGeneric[A](ss, predicate) - init.myCache = myCache - init.isCached = isCached - myCache = null.asInstanceOf[A] - isCached = false - init - } - } + def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = new OfSpliterator[A](sp) + def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = new OfDoubleSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfInt): IntStepper = new OfIntSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfLong): LongStepper = new OfLongSpliterator(sp) } - -trait StepperDouble extends Stepper[Double, StepperDouble] with java.util.PrimitiveIterator.OfDouble with java.util.Spliterator.OfDouble { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } - def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextDouble - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false - def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false - def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely = this -} - -trait StepperInt extends Stepper[Int, StepperInt] with java.util.PrimitiveIterator.OfInt with java.util.Spliterator.OfInt { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } - def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextInt - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false - def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false - def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely = this -} - -trait StepperLong extends Stepper[Long, StepperLong] with java.util.PrimitiveIterator.OfLong with java.util.Spliterator.OfLong { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } - def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextLong - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false - def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false - def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely = this -} - From 7b6e1180ec1fd21c8874d0bad2dc51c009024aab Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 6 Sep 2015 20:48:39 -0700 Subject: [PATCH 06/56] Added outline of a test for Stepper. --- .../compat/java8/collectionImpl/Stepper.scala | 121 +++++++++++++++++- .../scala/compat/java8/StepperTest.scala | 55 ++++++++ 2 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/scala/compat/java8/StepperTest.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 8a3acc6..9fdf613 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -25,43 +25,132 @@ import java.util.Spliterator * Subtraits `AnyStepper`, `DoubleStepper`, `IntStepper`, and `LongStepper` * implement both the `Stepper` trait and the corresponding Java * `Spliterator` and `Iterator`/`PrimitiveIterator`. + * + * Example: + * {{{ + * val s = Stepper.of(Vector(1,2,3,4)) + * if (s.hasStep) println(s.nextStep) // Prints 1 + * println(s.tryStep(i => println(i*i))) // Prints 4, then true + * s.substep.foreach(println) // Prints 3 + * println(s.count(_ > 3)) // Prints 4 + * println(s.hasStep) // Prints `false` + * }}} */ trait Stepper[@specialized(Double, Int, Long) A, CC] { self => + /** Characteristics are bit flags that indicate runtime characteristics of this Stepper. + * + * - `Distinct` means that no duplicates exist + * - `Immutable` means that the underlying collection is guaranteed not to change during traversal + * - `NonNull` means that no nulls will be returned during traversal + * - `Sized` means that the collection knows its exact size + * - `SubSized` means that sub-Steppers created with `substep()` will also know their own size. `SubSized` steppers must also be `Sized`. + * + * The Java flags `CONCURRENT` and `SORTED` are not supported; modification of a concurrency-aware underlying collection is not + * guaranteed to be any safer than modification of any generic mutable collection, and if the underlying collection is ordered by + * virtue of sorting, `Stepper` will not keep track of that fact. + */ def characteristics: Int + + /** Returns the size of the collection, if known exactly, or `-1` if not. */ def knownSize: Long + + /** `true` if there are more elements to step through, `false` if not. */ def hasStep: Boolean + + /** The next element traversed by this Stepper. + * `nextStep()` throws an exception if no elements exist, so check `hasStep` immediately prior + * to calling. Note that `tryStep` also consumes an element, so the result of `hasStep` will + * be invalid after `tryStep` is called. + */ def nextStep(): A + + /** If another element exists, apply `f` to it and return `true`; otherwise, return `false`. */ def tryStep(f: A => Unit): Boolean + + /** Attempt to split this `Stepper` in half, with the new (returned) copy taking the first half + * of the collection, and this one advancing to cover the second half. If subdivision is not + * possible or not advisable, `substep()` will return `null`. + */ def substep(): CC + + /** Returns the precise underlying type of this `Stepper`. */ def typedPrecisely: CC + //// // Terminal operations (do not produce another Stepper) //// + + /** Consumes all remaining elements in this `Stepper` and counts how many there are. + * This is a terminal operation. + */ def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } + + /** Consumes all remaining elements in this `Stepper` and counts how many satisfy condition `p`. + * This is a terminal operation. + */ def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } + + /** Searches for an element that satisfies condition `p`. If none are found, it returns `false`. + * This is a terminal operation. + */ def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } + + /** Searches for an element that satisifes condition `p`, returning it wrapped in `Some` if one is found, or `None` otherwise. + * This is a terminal operation. + */ def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None } + + /** Repeatedly applies `op` to propagate an initial value `zero` through all elements of the collection. + * Traversal order is left-to-right. + * This is a terminal operation. + */ def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b } + + /** Repeatedly applies `op` to propagate an initial value `zero` through the collection until a condition `p` is met. + * If `p` is never met, the result of the last operation is returned. + * This is a terminal operation. + */ def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } + + /** Applies `f` to every remaining element in the collection. + * This is a terminal operation. + */ def foreach(f: A => Unit) { while (hasStep) f(nextStep) } - def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } + + /** Repeatedly merges elements with `op` until only a single element remains. + * Throws an exception if the `Stepper` is empty. + * Merging occurs from left to right. + * This is a terminal operation. + */ + def reduce(op: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = op(a, nextStep) }; a } + //// // Operations that convert to another related type //// + + /** Returns this `Stepper` as a `java.util.Spliterator`. + * This is a terminal operation. + */ def spliterator: Spliterator[A] + + /** Returns this `Stepper` as a Scala `Iterator`. + * This is a terminal operation. + */ def iterator: Iterator[A] = new scala.collection.AbstractIterator[A] { def hasNext = self.hasStep def next = self.nextStep } } +/** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false } +/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { private var myCache: A = null.asInstanceOf[A] private var myCacheIsFull = false @@ -80,8 +169,10 @@ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { myCache = null.asInstanceOf[A] ans } + override def foreach(f: A => Unit) { while(tryStep(f)) {} } } +/** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] with Spliterator[A] { def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } def hasStep = hasNext() @@ -94,6 +185,7 @@ trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] override def spliterator: Spliterator[A] = this } +/** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } @@ -108,6 +200,7 @@ trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.Primit override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double } +/** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } @@ -122,6 +215,7 @@ trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterat override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int } +/** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } @@ -138,6 +232,24 @@ trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIte object Stepper { + /** Indicates that a Stepper delivers distinct values (e.g. is backed by a `Set`) */ + val Distinct = Spliterator.DISTINCT + + /** Indicates that a Stepper runs over an immutable collection */ + val Immutable = Spliterator.IMMUTABLE + + /** Indicates that a Stepper will not return any `null` values */ + val NonNull = Spliterator.NONNULL + + /** Indicates that a Stepper delivers elements in a particular order that should be maintained */ + val Ordered = Spliterator.ORDERED + + /** Indicates that a Stepper knows exactly how many elements it contains */ + val Sized = Spliterator.SIZED + + /** Indicates that a Stepper's children (created with substep()) will all know their size. Steppers that are SubSized must also be Sized. */ + val SubSized = Spliterator.SUBSIZED + private class OfSpliterator[A](sp: Spliterator[A]) extends AnyStepper[A] with java.util.function.Consumer[A] { @@ -338,8 +450,15 @@ object Stepper { override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) } + /** Creates a `Stepper` over a generic `Spliterator`. */ def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = new OfSpliterator[A](sp) + + /** Creates a `Stepper` over a `DoubleSpliterator`. */ def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = new OfDoubleSpliterator(sp) + + /** Creates a `Stepper` over an `IntSpliterator`. */ def ofSpliterator(sp: Spliterator.OfInt): IntStepper = new OfIntSpliterator(sp) + + /** Creates a `Stepper` over a `LongSpliterator`. */ def ofSpliterator(sp: Spliterator.OfLong): LongStepper = new OfLongSpliterator(sp) } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala new file mode 100644 index 0000000..1887cc8 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -0,0 +1,55 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StepperTest { + class IncStepperA(private val size0: Long) extends NextStepper[Int, IncStepperA] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def hasStep = i < knownSize + def nextStep() = { i += 1; (i - 1).toInt } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new FakeStepper1(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + def typedPrecisely = this + } + + class IncStepperB(private val size0: Long) extends TryStepper[Int, IncStepperB] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i); i += 1; true } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new FakeStepper1(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + def typedPrecisely = this + } + + def subs[Z, A, CC](zero: Z)(s: Stepper[A, CC], f: Stepper[A, CC] => Z, op: (Z, Z) => Z): Z = { + val ss = s.substep() + if (ss == null) op(zero, f(s)) + else { + val left = subs(zero)(ss, f, op) + subs(left)(s, f, op) + } + } + + val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) + def sources = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) + + @Test + def count_only() { + sources.foreach{ case (i, s) => assertEquals(i, s.count) } + sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s, _.count, _ + _)) } + } +} From 5f7d2d7f132bf0e6c4a16725834210f9dad1994d Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 7 Sep 2015 23:23:17 -0700 Subject: [PATCH 07/56] Converted to covariant 2nd arg in Stepper, introduced StepperLike. --- .../scala/compat/java8/StepConverters.scala | 24 +++++++++---------- .../compat/java8/collectionImpl/Stepper.scala | 17 +++++++------ .../scala/compat/java8/StepperTest.scala | 24 +++++++++++-------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 2297a7d..21b0eeb 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -121,35 +121,35 @@ package converterImpls { } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { - @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepperArrayGenAny[A](underlying, 0, underlying.length) } final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ - @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepperArrayGenObject[A](underlying, 0, underlying.length) } final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: Stepper[Unit, AnyStepper[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Unit] = new StepperArrayGenUnit(underlying, 0, underlying.length) } final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: Stepper[Boolean, AnyStepper[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Boolean] = new StepperArrayGenBoolean(underlying, 0, underlying.length) } final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: Stepper[Byte, AnyStepper[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Byte] = new StepperArrayGenByte(underlying, 0, underlying.length) } final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ - @inline def stepper: Stepper[Char, AnyStepper[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Char] = new StepperArrayGenChar(underlying, 0, underlying.length) } final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: Stepper[Short, AnyStepper[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Short] = new StepperArrayGenShort(underlying, 0, underlying.length) } final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ - @inline def stepper: Stepper[Float, AnyStepper[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Float] = new StepperArrayGenFloat(underlying, 0, underlying.length) } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { @@ -206,18 +206,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: Stepper[Double, DoubleStepper] = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: DoubleStepper = new StepperArrayDouble(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: Stepper[Int, IntStepper] = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: IntStepper = new StepperArrayInt(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: Stepper[Long, LongStepper] = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: LongStepper = new StepperArrayLong(underlying, 0, underlying.length) } implicit class RichStringCanStep(val underlying: String) extends AnyVal { - @inline def stepper: Stepper[Int, IntStepper] = new StepperStringCodePoint(underlying, 0, underlying.length) + @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 9fdf613..301138a 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -36,8 +36,11 @@ import java.util.Spliterator * println(s.hasStep) // Prints `false` * }}} */ +trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {} -trait Stepper[@specialized(Double, Int, Long) A, CC] { self => +/** Provides functionality for Stepper while keeping track of a more precise type of the collection. + */ +trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => /** Characteristics are bit flags that indicate runtime characteristics of this Stepper. * * - `Distinct` means that no duplicates exist @@ -146,12 +149,12 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] { self => } /** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ -trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { +trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false } /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ -trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { +trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { private var myCache: A = null.asInstanceOf[A] private var myCacheIsFull = false private def load(): Boolean = { @@ -173,7 +176,7 @@ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { } /** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ -trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] with Spliterator[A] { +trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterator[A] with StepperLike[A, AnyStepper[A]] { def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown @@ -186,7 +189,7 @@ trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] } /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ -trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble { +trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } def hasStep = hasNext() @@ -201,7 +204,7 @@ trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.Primit } /** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ -trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt { +trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt with StepperLike[Int, IntStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } def hasStep = hasNext() @@ -216,7 +219,7 @@ trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterat } /** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ -trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong { +trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong with StepperLike[Long, LongStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } def hasStep = hasNext() diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 1887cc8..57f9a36 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -3,8 +3,10 @@ package scala.compat.java8 import org.junit.Test import org.junit.Assert._ +import collectionImpl._ + class StepperTest { - class IncStepperA(private val size0: Long) extends NextStepper[Int, IncStepperA] { + class IncStepperA(private val size0: Long) extends NextStepper[Int] with StepperLike[Int, IncStepperA] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics = 0 @@ -12,44 +14,46 @@ class StepperTest { def hasStep = i < knownSize def nextStep() = { i += 1; (i - 1).toInt } def substep() = if ((knownSize - i) <= 1) null else { - val sub = new FakeStepper1(size0 - (size0 - i)/2) + val sub = new IncStepperA(size0 - (size0 - i)/2) sub.i = i i = sub.size0 sub } def typedPrecisely = this + def spliterator = ??? } - class IncStepperB(private val size0: Long) extends TryStepper[Int, IncStepperB] { + class IncStepperB(private val size0: Long) extends TryStepper[Int] with StepperLike[Int, IncStepperB] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics = 0 def knownSize = math.max(0L, size0 - i) - def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i); i += 1; true } + def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } def substep() = if ((knownSize - i) <= 1) null else { - val sub = new FakeStepper1(size0 - (size0 - i)/2) + val sub = new IncStepperB(size0 - (size0 - i)/2) sub.i = i i = sub.size0 sub } def typedPrecisely = this + def spliterator = ??? } - def subs[Z, A, CC](zero: Z)(s: Stepper[A, CC], f: Stepper[A, CC] => Z, op: (Z, Z) => Z): Z = { + def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { val ss = s.substep() if (ss == null) op(zero, f(s)) else { - val left = subs(zero)(ss, f, op) - subs(left)(s, f, op) + val left = subs(zero)(ss)(f, op) + subs(left)(s)(f, op) } } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } - sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s, _.count, _ + _)) } + sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count.toInt, _ + _)) } } } From 649dec44f2174348a7f12e14038cc6d0331a72ff Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 7 Sep 2015 23:42:46 -0700 Subject: [PATCH 08/56] Moved classes outside of StepperTest to see if this helps exception. --- .../scala/compat/java8/StepperTest.scala | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 57f9a36..f028bc5 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -5,40 +5,40 @@ import org.junit.Assert._ import collectionImpl._ -class StepperTest { - class IncStepperA(private val size0: Long) extends NextStepper[Int] with StepperLike[Int, IncStepperA] { - if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") - private var i = 0L - def characteristics = 0 - def knownSize = math.max(0L, size0 - i) - def hasStep = i < knownSize - def nextStep() = { i += 1; (i - 1).toInt } - def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperA(size0 - (size0 - i)/2) - sub.i = i - i = sub.size0 - sub - } - def typedPrecisely = this - def spliterator = ??? +class IncStepperA(private val size0: Long) extends NextStepper[Int] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def hasStep = i < knownSize + def nextStep() = { i += 1; (i - 1).toInt } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new IncStepperA(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub } + def typedPrecisely = this + def spliterator = ??? +} - class IncStepperB(private val size0: Long) extends TryStepper[Int] with StepperLike[Int, IncStepperB] { - if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") - private var i = 0L - def characteristics = 0 - def knownSize = math.max(0L, size0 - i) - def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } - def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperB(size0 - (size0 - i)/2) - sub.i = i - i = sub.size0 - sub - } - def typedPrecisely = this - def spliterator = ??? +class IncStepperB(private val size0: Long) extends TryStepper[Int] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new IncStepperB(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub } + def typedPrecisely = this + def spliterator = ??? +} +class StepperTest { def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { val ss = s.substep() if (ss == null) op(zero, f(s)) From e6c8ffa98cd0b360f223a0efd549ce3777086eb8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 8 Sep 2015 00:24:50 -0700 Subject: [PATCH 09/56] Fixed TryStepper impl to avoid specialization bug. Added tests. --- .../compat/java8/collectionImpl/Stepper.scala | 3 +- .../scala/compat/java8/StepperTest.scala | 45 ++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 301138a..5fb23d4 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -155,7 +155,8 @@ trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Ste /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { - private var myCache: A = null.asInstanceOf[A] + protected def myCache: A + protected def myCache_=(a: A): Unit private var myCacheIsFull = false private def load(): Boolean = { myCacheIsFull = tryStep(myCache = _) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index f028bc5..78c26e4 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -5,15 +5,16 @@ import org.junit.Assert._ import collectionImpl._ + class IncStepperA(private val size0: Long) extends NextStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics = 0 def knownSize = math.max(0L, size0 - i) - def hasStep = i < knownSize + def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperA(size0 - (size0 - i)/2) + val sub = new IncStepperA(i + (size0 - i)/2) sub.i = i i = sub.size0 sub @@ -24,6 +25,7 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { class IncStepperB(private val size0: Long) extends TryStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + protected var myCache: Int = 0 private var i = 0L def characteristics = 0 def knownSize = math.max(0L, size0 - i) @@ -56,4 +58,43 @@ class StepperTest { sources.foreach{ case (i, s) => assertEquals(i, s.count) } sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count.toInt, _ + _)) } } + + @Test + def count_conditionally() { + sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), s.count(_ % 3 == 0)) } + sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), subs(0)(s)(_.count(_ % 3 == 0).toInt, _ + _)) } + } + + @Test + def existence() { + sources.foreach{ case (i, s) => assert(i > 0 == s.exists(_ >= 0)) } + sources.foreach{ case (i, s) => assert(i > 16 == s.exists(_ % 17 == 16)) } + sources.foreach{ case (i, s) => assert(i > 0 == subs(false)(s)(_.exists(_ >= 0), _ || _)) } + sources.foreach{ case (i, s) => assert(i > 16 == subs(false)(s)(_.exists(_ % 17 == 16), _ || _)) } + } + + @Test + def finding() { + for (k <- 0 until 100) { + (sources zip sources).foreach{ case ((i,s), (j,t)) => + val x = util.Random.nextInt(math.min(i,j)+3) + val a = s.find(_ == x) + val b = subs(None: Option[Int])(t)(_.find(_ == x), _ orElse _) + assertEquals(a, b) + assertEquals(a.isDefined, x < math.min(i,j)) + } + } + } + + @Test + def folding() { + sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, s.fold("")(_ + _.toString)) } + sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, subs("")(s)(_.fold("")(_ + _.toString), _ + _)) } + sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, s.fold(0.0)(_ + _), 1e-10) } + sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, subs(0.0)(s)(_.fold(0.0)(_ + _), _ + _), 1e-10) } + } + + @Test + def partialFolding() { + } } From 2550aff2fcbe1587ae51a5db8ae11f50ba638962 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 9 Sep 2015 15:10:44 -0700 Subject: [PATCH 10/56] Finished testing terminal operations for Stepper, save spliterator which isn't written. --- .../compat/java8/collectionImpl/Stepper.scala | 2 +- .../scala/compat/java8/StepperTest.scala | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 5fb23d4..ee426c7 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -115,7 +115,7 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => * If `p` is never met, the result of the last operation is returned. * This is a terminal operation. */ - def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } + def foldTo[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (!p(b) && hasStep) { b = op(b, nextStep) }; b } /** Applies `f` to every remaining element in the collection. * This is a terminal operation. diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 78c26e4..565190a 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -95,6 +95,45 @@ class StepperTest { } @Test - def partialFolding() { + def foldingUntil() { + def expected(i: Int) = (0 until i).scan(0)(_ + _).dropWhile(_ < 6*i).headOption.getOrElse((0 until i).sum) + sources.foreach{ case (i,s) => assertEquals(expected(i), s.foldTo(0)(_ + _)(_ >= 6*i)) } + sources.foreach{ case (_,s) => assertEquals(-1, s.foldTo(-1)(_ * _)(_ => true)) } + sources.foreach{ case (i,s) => + val ss = s.substep + val x = s.foldTo( if (ss == null) 0 else ss.foldTo(0)(_ + _)(_ >= 6*i) )(_ + _)(_ >= 6*i) + assertEquals(expected(i), x) + } + } + + @Test + def foreaching() { + sources.foreach{ case (i,s) => + val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] + s.foreach( clq add _.toString ) + assertEquals((0 until i).map(_.toString).toSet, Iterator.continually(if (!clq.isEmpty) Some(clq.poll) else None).takeWhile(_.isDefined).toSet.flatten) + } + sources.foreach{ case (i,s) => + val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] + subs(())(s)(_.foreach( clq add _.toString ), (_, _) => ()) + assertEquals((0 until i).map(_.toString).toSet, Iterator.continually(if (!clq.isEmpty) Some(clq.poll) else None).takeWhile(_.isDefined).toSet.flatten) + } + } + + @Test + def reducing() { + sources.foreach{ case (i,s) => + if (i==0) assertEquals(s.hasStep, false) + else assertEquals((0 until i).sum, s.reduce(_ + _)) + } + sources.foreach{ case (i,s) => + assertEquals((0 until i).sum, subs(0)(s)(x => if (!x.hasStep) 0 else x.reduce(_ + _), _ + _)) + } + } + + @Test + def iterating() { + sources.foreach{ case (i, s) => assert(Iterator.range(0,i) sameElements s.iterator) } } } + From 6ee09efd79fc2b64a089928ff4f85530b944da35 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 11:48:51 -0700 Subject: [PATCH 11/56] Added proxy-to-spliterator to default Stepper trait. (Should overrride everywhere important.) --- .../compat/java8/collectionImpl/Stepper.scala | 19 +++++++++++++++++-- .../scala/compat/java8/StepperTest.scala | 15 +++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index ee426c7..096eef4 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -149,12 +149,19 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => } /** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ -trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { +trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false + def spliterator: Spliterator[A] = new ProxySpliteratorViaNext[A](this) +} +private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper[A]) extends Spliterator[A] { + def characteristics() = underlying.characteristics + def estimateSize() = underlying.knownSize + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = if (underlying.hasStep) { f.accept(underlying.nextStep()); true } else false + def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaNext[A](x) } } /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ -trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { +trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { protected def myCache: A protected def myCache_=(a: A): Unit private var myCacheIsFull = false @@ -174,6 +181,14 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step ans } override def foreach(f: A => Unit) { while(tryStep(f)) {} } + def spliterator: Spliterator[A] = new ProxySpliteratorViaTry[A](this) +} +private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A]) extends Spliterator[A] { + def characteristics() = underlying.characteristics + def estimateSize() = underlying.knownSize + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryStep(a => f.accept(a)) + override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { underlying.foreach(a => f.accept(a)) } + def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaTry[A](x) } } /** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 565190a..abde749 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -20,7 +20,6 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { sub } def typedPrecisely = this - def spliterator = ??? } class IncStepperB(private val size0: Long) extends TryStepper[Int] { @@ -37,7 +36,6 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { sub } def typedPrecisely = this - def spliterator = ??? } class StepperTest { @@ -135,5 +133,18 @@ class StepperTest { def iterating() { sources.foreach{ case (i, s) => assert(Iterator.range(0,i) sameElements s.iterator) } } + + @Test + def spliterating() { + sources.foreach{ case (i,s) => + var sum = 0 + s.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int) { sum += i } }) + assertEquals(sum, (0 until i).sum) + } + sources.foreach{ case (i,s) => + val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int) { sm += i } }); sm }, _ + _) + assertEquals(sum, (0 until i).sum) + } + } } From 37ea39cc478092c4b036de35f4da97e8f91d7dbb Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 13:22:24 -0700 Subject: [PATCH 12/56] Tests on all the various permutations of Stepper-Spliterator converters. --- .../scala/compat/java8/StepperTest.scala | 88 ++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index abde749..75070c3 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -3,13 +3,15 @@ package scala.compat.java8 import org.junit.Test import org.junit.Assert._ +import java.util.Spliterator + import collectionImpl._ class IncStepperA(private val size0: Long) extends NextStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L - def characteristics = 0 + def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def knownSize = math.max(0L, size0 - i) def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } @@ -26,7 +28,7 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") protected var myCache: Int = 0 private var i = 0L - def characteristics = 0 + def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def knownSize = math.max(0L, size0 - i) def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } def substep() = if ((knownSize - i) <= 1) null else { @@ -38,6 +40,78 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { def typedPrecisely = this } +class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { + private var i = 0L + def characteristics() = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + def estimateSize() = math.max(0L, size0 - i) + def tryAdvance(f: java.util.function.IntConsumer): Boolean = if (i >= size0) false else { f.accept(i.toInt); i += 1; true } + def trySplit(): Spliterator.OfInt = if (i+1 >= size0) null else { + val sub = new IncSpliterator(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + override def forEachRemaining(f: java.util.function.IntConsumer) { while (i < size0) { f.accept(i.toInt); i += 1 } } +} + +class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, Int, Long) B](underlying: Stepper[A], mapping: A => B) extends Stepper[B] { + def characteristics = underlying.characteristics + def knownSize = underlying.knownSize + def hasStep = underlying.hasStep + def nextStep() = mapping(underlying.nextStep()) + def tryStep(f: B => Unit): Boolean = underlying.tryStep(a => f(mapping(a))) + override def foreach(f: B => Unit) { underlying.foreach(a => f(mapping(a))) } + def substep() = { + val undersub = underlying.substep() + if (undersub == null) null + else new MappingStepper(undersub, mapping) + } + def typedPrecisely = this + def spliterator: Spliterator[B] = new MappingSpliterator[A, B](underlying.spliterator, mapping) +} + +class MappingSpliterator[A, B](private val underlying: Spliterator[A], mapping: A => B) extends Spliterator[B] { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.Consumer[_ >: B]): Boolean = underlying.tryAdvance(new java.util.function.Consumer[A]{ def accept(a: A) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator[B] = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new MappingSpliterator(undersplit, mapping) + } +} +class IntToGenericSpliterator[A](private val underlying: Spliterator.OfInt, mapping: Int => A) extends Spliterator[A] { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator[A] = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToGenericSpliterator[A](undersplit, mapping) + } +} +class IntToDoubleSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Double) extends Spliterator.OfDouble { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator.OfDouble = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToDoubleSpliterator(undersplit, mapping) + } +} +class IntToLongSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Long) extends Spliterator.OfLong { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.LongConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator.OfLong = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToLongSpliterator(undersplit, mapping) + } +} + + class StepperTest { def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { val ss = s.substep() @@ -49,7 +123,15 @@ class StepperTest { } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector( + i -> new IncStepperA(i), + i -> new IncStepperB(i), + i -> Stepper.ofSpliterator(new IncSpliterator(i)), + i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), + i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), + i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), + i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) + )) @Test def count_only() { From 04bc02ae7823eb67f19d23502cfe3df396e0db1f Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 16:54:14 -0700 Subject: [PATCH 13/56] Fixed a bug in tryStep of TryStepper by adding a protected tryUncached method. --- .../compat/java8/collectionImpl/Stepper.scala | 39 ++++++++++---- .../scala/compat/java8/StepperTest.scala | 52 ++++++++++++++++++- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 096eef4..6f2edc1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -160,17 +160,20 @@ private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaNext[A](x) } } -/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ +/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. + * Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected. + * For speed, `foreachUncached` may also be overridden. + */ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { protected def myCache: A protected def myCache_=(a: A): Unit - private var myCacheIsFull = false + protected final var myCacheIsFull = false private def load(): Boolean = { myCacheIsFull = tryStep(myCache = _) myCacheIsFull } - def hasStep = myCacheIsFull || load() - def nextStep = { + final def hasStep = myCacheIsFull || load() + final def nextStep = { if (!myCacheIsFull) { load() if (!myCacheIsFull) throw new NoSuchElementException("nextStep in TryStepper") @@ -180,7 +183,10 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step myCache = null.asInstanceOf[A] ans } - override def foreach(f: A => Unit) { while(tryStep(f)) {} } + final def tryStep(f: A => Unit): Boolean = if (myCacheIsFull) { f(myCache); myCacheIsFull = false; true } else tryUncached(f) + protected def tryUncached(f: A => Unit): Boolean + final override def foreach(f: A => Unit) { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } + protected def foreachUncached(f: A => Unit) { while (tryUncached(f)) {} } def spliterator: Spliterator[A] = new ProxySpliteratorViaTry[A](this) } private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A]) extends Spliterator[A] { @@ -470,14 +476,29 @@ object Stepper { } /** Creates a `Stepper` over a generic `Spliterator`. */ - def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = new OfSpliterator[A](sp) + def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = sp match { + case as: AnyStepper[A] => as + case _ => new OfSpliterator[A](sp) + } + /** Creates a `Stepper` over a `DoubleSpliterator`. */ - def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = new OfDoubleSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = sp match { + case ds: DoubleStepper => ds + case _ => new OfDoubleSpliterator(sp) + } /** Creates a `Stepper` over an `IntSpliterator`. */ - def ofSpliterator(sp: Spliterator.OfInt): IntStepper = new OfIntSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfInt): IntStepper = sp match { + case is: IntStepper => is + case _ => new OfIntSpliterator(sp) + } + /** Creates a `Stepper` over a `LongSpliterator`. */ - def ofSpliterator(sp: Spliterator.OfLong): LongStepper = new OfLongSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfLong): LongStepper = sp match { + case ls: LongStepper => ls + case _ => new OfLongSpliterator(sp) + } + } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 75070c3..bae0d72 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -30,7 +30,7 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { private var i = 0L def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def knownSize = math.max(0L, size0 - i) - def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } + protected def tryUncached(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } def substep() = if ((knownSize - i) <= 1) null else { val sub = new IncStepperB(size0 - (size0 - i)/2) sub.i = i @@ -133,6 +133,56 @@ class StepperTest { i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) )) + @Test + def stepping() { + sources.foreach{ case (i, s) => assert((0 until i).forall{ j => s.hasStep && s.nextStep == j } && !s.hasStep) } + sources.foreach{ case (i, s) => + val set = collection.mutable.BitSet.empty + subs(0)(s)( + { x => + while (x.hasStep) { val y = x.nextStep; assert(!(set contains y)); set += y } + 0 + }, + _ + _ + ) + assert((0 until i).toSet == set) + } + } + + @Test + def trying() { + sources.foreach{ case (i,s) => + val set = collection.mutable.BitSet.empty + while (s.tryStep{ y => assert(!(set contains y)); set += y }) {} + assert((0 until i).toSet == set) + } + sources.foreach{ case (i,s) => + val set = collection.mutable.BitSet.empty + subs(0)(s)( + { x => + while(x.tryStep{ y => assert(!(set contains y)); set += y }) {} + 0 + }, + _ + _ + ) + assertTrue(s.getClass.getName + s" said [0, $i) was " + set.mkString("{", " ", "}"), (0 until i).toSet == set) + } + } + + @Test + def substepping() { + sources.foreach{ case (i,s) => + val ss = s.substep + assertEquals(ss == null, i < 2) + if (ss != null) { + assertTrue(s.hasStep) + assertTrue(ss.hasStep) + assertEquals(i, s.count + ss.count) + } + else assertEquals(i, s.count) + } + } + @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } From e7033e34c075cd7ce447667576b8ab7fdfd0f8c8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 18:55:51 -0700 Subject: [PATCH 14/56] Finished tests of basic steppers and fixed bugs in TryStepper. --- .../compat/java8/collectionImpl/Stepper.scala | 15 +++-- .../scala/compat/java8/StepperTest.scala | 62 ++++++++++++++----- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 6f2edc1..3e09ee5 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -86,9 +86,13 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => //// /** Consumes all remaining elements in this `Stepper` and counts how many there are. - * This is a terminal operation. + * This is a terminal operation, though if `knownSize` is non-negative, it won't actually + * iterate over the elements. */ - def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } + def count(): Long = knownSize match { + case x if x < 0 => var n = 0L; while (hasStep) { nextStep; n += 1 }; n + case x => x + } /** Consumes all remaining elements in this `Stepper` and counts how many satisfy condition `p`. * This is a terminal operation. @@ -161,8 +165,9 @@ private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper } /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. - * Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected. - * For speed, `foreachUncached` may also be overridden. + * Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected, and must implement + * `knownUncachedSize` instead of `knownSize`. For speed, `foreachUncached` may also be overridden. It is recommended + * that all of the `Uncached` methods be left protected. */ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { protected def myCache: A @@ -183,6 +188,8 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step myCache = null.asInstanceOf[A] ans } + final def knownSize = knownUncachedSize + (if (myCacheIsFull) 1 else 0) + protected def knownUncachedSize: Long final def tryStep(f: A => Unit): Boolean = if (myCacheIsFull) { f(myCache); myCacheIsFull = false; true } else tryUncached(f) protected def tryUncached(f: A => Unit): Boolean final override def foreach(f: A => Unit) { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index bae0d72..18cbc10 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -15,8 +15,8 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { def knownSize = math.max(0L, size0 - i) def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } - def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperA(i + (size0 - i)/2) + def substep() = if (knownSize <= 1) null else { + val sub = new IncStepperA(size0 - (size0 - i)/2) sub.i = i i = sub.size0 sub @@ -29,9 +29,9 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { protected var myCache: Int = 0 private var i = 0L def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered - def knownSize = math.max(0L, size0 - i) + def knownUncachedSize = math.max(0L, size0 - i) protected def tryUncached(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } - def substep() = if ((knownSize - i) <= 1) null else { + def substep() = if (knownSize <= 1) null else { val sub = new IncStepperB(size0 - (size0 - i)/2) sub.i = i i = sub.size0 @@ -41,6 +41,7 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { } class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics() = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def estimateSize() = math.max(0L, size0 - i) @@ -123,15 +124,27 @@ class StepperTest { } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector( - i -> new IncStepperA(i), - i -> new IncStepperB(i), - i -> Stepper.ofSpliterator(new IncSpliterator(i)), - i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), - i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), - i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), - i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) - )) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap{ i => + Vector( + i -> new IncStepperA(i), + i -> new IncStepperB(i), + i -> Stepper.ofSpliterator(new IncSpliterator(i)), + i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), + i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), + i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), + i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) + ) ++ + { + // Implicitly converted instead of explicitly + import SpliteratorConverters._ + Vector[(Int, Stepper[Int])]( + i -> (new IncSpliterator(i)).stepper, + i -> new MappingStepper[Long, Int]((new IntToLongSpliterator(new IncSpliterator(i), _.toLong)).stepper, _.toInt), + i -> new MappingStepper[Double, Int]((new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)).stepper, _.toInt), + i -> new MappingStepper[String, Int]((new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)).stepper, _.toInt) + ) + } + } @Test def stepping() { @@ -177,12 +190,33 @@ class StepperTest { if (ss != null) { assertTrue(s.hasStep) assertTrue(ss.hasStep) - assertEquals(i, s.count + ss.count) + val c1 = s.count + val c2 = ss.count + assertEquals(s"$i != $c1 + $c2 from ${s.getClass.getName}", i, c1 + c2) } else assertEquals(i, s.count) } } + @Test + def characteristically() { + val expected = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + sources.foreach{ case (_,s) => assertEquals(s.characteristics, expected)} + sources.foreach{ case (_,s) => subs(0)(s)(x => { assertEquals(x.characteristics, expected); 0 }, _ + _) } + } + + @Test + def knownSizes() { + sources.foreach{ case (i,s) => assertEquals(i.toLong, s.knownSize) } + sources.foreach{ case (i,s) => if (i > 0) subs(0)(s)(x => { assertEquals(x.knownSize, 1L); 0 }, _ + _) } + } + + @Test + def consistentPrecision() { + sources.foreach{ case (_,s) => assert(s eq s.typedPrecisely) } + sources.foreach{ case (_,s) => subs(0)(s)(x => { assert(x eq x.typedPrecisely); 0}, _ + _) } + } + @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } From 6baf83269e509160b2d7cb90daaf61c921ff73a0 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 13 Jul 2015 16:13:56 -0700 Subject: [PATCH 15/56] Basic interoperability between Java8 Streams and Scala collections. This consists of (1) toScala[Coll] extension methods for Java8 Streams (2) seqStream and parStream extension methods for Scala collections (3) A manually specialized set of Accumulators that let you quickly save a stream for multiple re-use. (a) accumulate and accumulatePrimitive methods on Java8 Streams (b) to[Coll] on Accumulators (c) .iterator, .toArray, .toList also There is a lot of redundant code in the Accumulators since it is difficult to pull out common functionality without endangering performance of the manually specialized cases. Everything goes through the new Stepper trait to partially tame the Spliterator hierarchy. At this point, Scala collections all go through Accumulator. Need to write something custom for the more important collections. Tests written. Scaladocs written for the new classes. --- .../scala/compat/java8/StreamConverters.scala | 226 ++++++++++++ .../java8/collectionImpl/Accumulator.scala | 337 +++++++++++++++++ .../collectionImpl/AccumulatorLike.scala | 41 +++ .../collectionImpl/DoubleAccumulator.scala | 332 +++++++++++++++++ .../java8/collectionImpl/IntAccumulator.scala | 339 ++++++++++++++++++ .../collectionImpl/LongAccumulator.scala | 333 +++++++++++++++++ .../compat/java8/StreamConvertersTest.scala | 145 ++++++++ 7 files changed, 1753 insertions(+) create mode 100644 src/main/scala/scala/compat/java8/StreamConverters.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala create mode 100644 src/test/scala/scala/compat/java8/StreamConvertersTest.scala diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala new file mode 100644 index 0000000..0b9b644 --- /dev/null +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -0,0 +1,226 @@ +package scala.compat.java8 + +import language.implicitConversions + +import java.util.stream._ +import scala.compat.java8.collectionImpl._ + +trait PrimitiveStreamAccumulator[S, AA] { + def streamAccumulate(stream: S): AA +} + +trait PrimitiveStreamUnboxer[A, S] { + def apply(boxed: Stream[A]): S +} + +trait Priority2StreamConverters { + implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { + private def mkAcc() = { + val acc = new Accumulator[A] + t.foreach{ acc += _ } + acc + } + + def seqStream: Stream[A] = mkAcc().seqStream + + def parStream: Stream[A] = mkAcc().parStream + } + + implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { + private def mkAcc() = { + val acc = new Accumulator[A] + var i = 0 + while (i < a.length) { + acc += a(i) + i += 1 + } + acc + } + + def seqStream: Stream[A] = mkAcc().seqStream + + def parStream: Stream[A] = mkAcc().parStream + } +} + +trait Priority1StreamConverters extends Priority2StreamConverters { + implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { + private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { + if (t.isTraversableAgain && t.hasDefiniteSize) { + val sz = t.size + val a = new Array[A](sz) + t.copyToArray(a, 0, sz) + a + } + else t.toArray[A] + } + + def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = + java.util.Arrays.stream(mkArr()) + + def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel + } + + implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { + def seqStream: Stream[A] = java.util.Arrays.stream(a) + def parStream: Stream[A] = seqStream.parallel + } + + implicit class RichStream[A](stream: Stream[A]) { + def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.Consumer[A]{ def accept(a: A) { b += a } }) + b.result() + } + } + + def unboxed[S](implicit ubx: PrimitiveStreamUnboxer[A, S]): S = ubx(stream) + } + + implicit class RichStreamCanAccumulatePrimitive[S](stream: S) { + def accumulatePrimitive[AA](implicit psa: PrimitiveStreamAccumulator[S, AA]) = psa.streamAccumulate(stream) + } +} + +/** `StreamConverters` provides extension methods and other functionality to + * ease interoperability of Scala collections with `java.util.stream` classes. + * + * Scala collections gain extension methods `seqStream` and + * `parStream` that allow them to be used as the source of a `Stream`. + * + * `Array` also gains `seqStream` and `parStream` methods, and calling those + * on `Array[Double]`, `Array[Int]`, or `Array[Long]` will produce the + * corresponding primitive stream. + * + * Streams gain `accumulate` and `toScala[_]` methods, which collect the stream + * into a custom high-performance `scala.collection.mutable.java8.Accumulator`, + * which is not part of the standard collections hierarchy, or into a named + * Scala collection, respectively. + * + * Generic streams also gain an `unboxed` method that will convert to the + * corresponding unboxed primitive stream, if appropriate. Unboxed streams + * have custom accumulators with improved performance. + * + * Accumulators have `toArray`, `toList`, `iterator`, and `to[_]` methods + * to convert to standard Scala collections. + * + * Example: + * ``` + * import scala.compat.java8.StreamConverers._ + * + * val s = Vector(1,2,3,4).parStream // Stream[Int] + * val si = s.unboxed // Stream.OfInt + * val ai = si.accumulate // IntAccumulator + * val v = ai.to[Vector] // Vector[Int] again + * + * val t = Array(2.0, 3.0, 4.0).parStream // DoubleStream + * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] + * ``` + */ +object StreamConverters extends Priority1StreamConverters { + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { + def seqStream: DoubleStream = java.util.Arrays.stream(a) + def parStream: DoubleStream = seqStream.parallel + } + + implicit class EnrichIntArrayWithStream(a: Array[Int]) { + def seqStream: IntStream = java.util.Arrays.stream(a) + def parStream: IntStream = seqStream.parallel + } + + implicit class EnrichLongArrayWithStream(a: Array[Long]) { + def seqStream: LongStream = java.util.Arrays.stream(a) + def parStream: LongStream = seqStream.parallel + } + + implicit val primitiveAccumulateDoubleStream = new PrimitiveStreamAccumulator[Stream[Double], DoubleAccumulator] { + def streamAccumulate(stream: Stream[Double]): DoubleAccumulator = + stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger) + } + + implicit val primitiveAccumulateDoubleStream2 = + primitiveAccumulateDoubleStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Double], DoubleAccumulator]] + + implicit val primitiveUnboxDoubleStream = new PrimitiveStreamUnboxer[Double, DoubleStream] { + def apply(boxed: Stream[Double]): DoubleStream = + boxed.mapToDouble(new java.util.function.ToDoubleFunction[Double]{ def applyAsDouble(d: Double) = d }) + } + + implicit val primitiveUnboxDoubleStream2 = + primitiveUnboxDoubleStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Double, DoubleStream]] + + implicit val primitiveAccumulateIntStream = new PrimitiveStreamAccumulator[Stream[Int], IntAccumulator] { + def streamAccumulate(stream: Stream[Int]): IntAccumulator = + stream.collect(IntAccumulator.supplier, IntAccumulator.boxedAdder, IntAccumulator.merger) + } + + implicit val primitiveAccumulateIntStream2 = + primitiveAccumulateIntStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Integer], IntAccumulator]] + + implicit val primitiveUnboxIntStream = new PrimitiveStreamUnboxer[Int, IntStream] { + def apply(boxed: Stream[Int]): IntStream = + boxed.mapToInt(new java.util.function.ToIntFunction[Int]{ def applyAsInt(d: Int) = d }) + } + + implicit val primitiveUnboxIntStream2 = + primitiveUnboxIntStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Integer, IntStream]] + + implicit val primitiveAccumulateLongStream = new PrimitiveStreamAccumulator[Stream[Long], LongAccumulator] { + def streamAccumulate(stream: Stream[Long]): LongAccumulator = + stream.collect(LongAccumulator.supplier, LongAccumulator.boxedAdder, LongAccumulator.merger) + } + + implicit val primitiveAccumulateLongStream2 = + primitiveAccumulateLongStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Long], LongAccumulator]] + + implicit val primitiveUnboxLongStream = new PrimitiveStreamUnboxer[Long, LongStream] { + def apply(boxed: Stream[Long]): LongStream = + boxed.mapToLong(new java.util.function.ToLongFunction[Long]{ def applyAsLong(d: Long) = d }) + } + + implicit val primitiveUnboxLongStream2 = + primitiveUnboxLongStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Long, LongStream]] + + implicit class RichDoubleStream(stream: DoubleStream) { + def accumulate = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.adder, DoubleAccumulator.merger) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.DoubleConsumer{ def accept(d: Double) { b += d } }) + b.result() + } + } + } + + implicit class RichIntStream(stream: IntStream) { + def accumulate = stream.collect(IntAccumulator.supplier, IntAccumulator.adder, IntAccumulator.merger) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.IntConsumer{ def accept(d: Int) { b += d } }) + b.result() + } + } + } + + implicit class RichLongStream(stream: LongStream) { + def accumulate = stream.collect(LongAccumulator.supplier, LongAccumulator.adder, LongAccumulator.merger) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.LongConsumer{ def accept(d: Long) { b += d } }) + b.result() + } + } + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala new file mode 100644 index 0000000..b28790c --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -0,0 +1,337 @@ +package scala.compat.java8.collectionImpl + +/** An `Accumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging Accumulators. + * Accumulators can contain more than `Int.MaxValue` elements. + */ +final class Accumulator[A] extends AccumulatorLike[A, Accumulator[A]] { self => + private[java8] var current: Array[AnyRef] = Accumulator.emptyAnyRefArray + private[java8] var history: Array[Array[AnyRef]] = Accumulator.emptyAnyRefArrayArray + private[java8] var cumul: Array[Long] = Accumulator.emptyLongArray + + private[java8] def cumulative(i: Int) = cumul(i) + + private def expand(): Unit = { + if (index > 0) { + if (hIndex >= history.length) hExpand() + history(hIndex) = current + cumul(hIndex) = (if (hIndex > 0) cumulative(hIndex-1) else 0) + index + hIndex += 1 + } + current = new Array[AnyRef](nextBlockSize) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) { + history = new Array[Array[AnyRef]](4) + cumul = new Array[Long](4) + } + else { + history = java.util.Arrays.copyOf(history, history.length << 1) + cumul = java.util.Arrays.copyOf(cumul, cumul.length << 1) + } + } + + /** Appends an element to this `Accumulator`. */ + final def +=(a: A): Unit = { + totalSize += 1 + if (index >= current.length) expand() + current(index) = a.asInstanceOf[AnyRef] + index += 1 + } + + /** Removes all elements from `that` and appends them to this `Accumulator`. */ + final def drain[A1 <: A](that: Accumulator[A1]): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val n = (that.cumulative(h) - prev).toInt + if (current.length - index >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = that.cumulative(h) + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index >= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + cumul = java.util.Arrays.copyOf(cumul, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + pv += index + cumul(hIndex) = pv + history(hIndex) = (if (index < (current.length >>> 3) && current.length > 32) java.util.Arrays.copyOf(current, index) else current) + hIndex += 1 + } + while (h < that.hIndex) { + pv += that.cumulative(h) - prev + prev = that.cumulative(h) + cumul(hIndex) = pv + history(hIndex) = that.history(h) + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = Accumulator.emptyAnyRefArray + history = Accumulator.emptyAnyRefArrayArray + cumul = Accumulator.emptyLongArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): A = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt).asInstanceOf[A] + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt).asInstanceOf[A] + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): A = apply(i.toLong) + + /** Returns a `Stepper` over the contents of this `Accumulator`*/ + final def stepper: AnyStepper[A] = new AccumulatorStepper[A](this) + + /** Returns an `Iterator` over the contents of this `Accumulator`. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator` over the contents of this `Accumulator`*/ + final def spliterator: java.util.Spliterator[A] = stepper.spliterator + + /** Produces a sequential Java 8 Stream over the elements of this `Accumulator`*/ + final def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(spliterator, false) + + /** Produces a parallel Java 8 Stream over the elements of this `Accumulator`*/ + final def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(spliterator, true) + + /** Copies the elements in this `Accumulator` into an `Array` */ + final def toArray(implicit tag: reflect.ClassTag[A]) = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[A](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + a(j) = x(i).asInstanceOf[A] + i += 1 + j += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + a(j) = current(i).asInstanceOf[A] + i += 1 + j += 1 + } + a + } + + /** Copies the elements in this `Accumulator` to a `List` */ + final def toList: List[A] = { + var ans: List[A] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i).asInstanceOf[A] :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i).asInstanceOf[A] :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `Accumulator` to a specified collection. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + b += x(i).asInstanceOf[A] + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i).asInstanceOf[A] + i += 1 + } + b.result + } +} + +object Accumulator { + private val emptyAnyRefArray = new Array[AnyRef](0) + private val emptyAnyRefArrayArray = new Array[Array[AnyRef]](0) + private val emptyLongArray = new Array[Long](0) + + /** A `Supplier` of `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def supplier[A] = new java.util.function.Supplier[Accumulator[A]]{ def get: Accumulator[A] = new Accumulator[A] } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def adder[A] = new java.util.function.BiConsumer[Accumulator[A], A]{ def accept(ac: Accumulator[A], a: A) { ac += a } } + + /** A `BiConsumer` that merges `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]) { a1 drain a2 } } +} + +private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) extends AnyStepper[A] { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): AccumulatorStepper[A] = { + val ans = new AccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def next: A = + if (N <= 0) throw new NoSuchElementException("Next in empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i).asInstanceOf[A] + i += 1 + N -= 1 + ans + } + + // Overidden for efficiency + override def tryStep(f: A => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i).asInstanceOf[A]) + i += 1 + N -= 1 + true + } + + // Overidden for efficiency + override def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i).asInstanceOf[A]) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: A => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i).asInstanceOf[A]) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i).asInstanceOf[A]) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): AnyStepper[A] = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } + + override def toString = s"$h $i ${a.mkString("{",",","}")} $n $N" +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala new file mode 100644 index 0000000..8201ac3 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.collectionImpl + +/** An accumulator that works with Java 8 streams; it accepts elements of type `A`, + * is itself an `AC`. Accumulators can handle more than `Int.MaxValue` elements. + */ +trait AccumulatorLike[@specialized(Double, Int, Long) A, AC] { + private[java8] var index: Int = 0 + private[java8] var hIndex: Int = 0 + private[java8] var totalSize: Long = 0L + private[java8] def cumulative(i: Int): Long + + private[java8] def nextBlockSize: Int = { + if (totalSize < 32) 16 + else if (totalSize <= Int.MaxValue) { + val bit = (64 - java.lang.Long.numberOfLeadingZeros(totalSize)) + 1 << (bit - (bit >> 2)) + } + else 1 << 24 + } + + /** Size of the accumulated collection, as a `Long` */ + final def size = totalSize + + /** Remove all accumulated elements from this accumulator. */ + def clear(): Unit = { + index = 0 + hIndex = 0 + totalSize = 0L + } + + private[java8] def seekSlot(ix: Long): Long = { + var lo = -1 + var hi = hIndex + while (lo + 1 < hi) { + val m = (lo + hi) >>> 1 // Shift allows division-as-unsigned, prevents overflow + if (cumulative(m) > ix) hi = m + else lo = m + } + (hi.toLong << 32) | (if (hi==0) ix else (ix - cumulative(hi-1))).toInt + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala new file mode 100644 index 0000000..9703fe9 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -0,0 +1,332 @@ +package scala.compat.java8.collectionImpl + +/** A `DoubleAccumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging them. + * This is a manually specialized variant of `Accumulator` with no actual + * subclassing relationship with `Accumulator`. + */ +final class DoubleAccumulator extends AccumulatorLike[Double, DoubleAccumulator] { self => + private[java8] var current: Array[Double] = DoubleAccumulator.emptyDoubleArray + private[java8] var history: Array[Array[Double]] = DoubleAccumulator.emptyDoubleArrayArray + + private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-1).toLong } + + private def expand(): Unit = { + if (index > 0) { + current(current.length-1) = (if (hIndex > 0) { val x = history(hIndex-1); x(x.length-1) } else 0) + index + if (hIndex >= history.length) hExpand() + history(hIndex) = current + hIndex += 1 + } + current = new Array[Double](nextBlockSize+1) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) history = new Array[Array[Double]](4) + else history = java.util.Arrays.copyOf(history, history.length << 1) + } + + /** Appends an element to this `DoubleAccumulator`. */ + final def +=(a: Double): Unit = { + totalSize += 1 + if (index+1 >= current.length) expand() + current(index) = a + index += 1 + } + + /** Removes all elements from `that` and appends them to this `DoubleAccumulator`. */ + final def drain(that: DoubleAccumulator): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val cuml = that.cumulative(h) + val n = (cuml - prev).toInt + if (current.length - index - 1 >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = cuml + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index - 1>= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + val x = + if (index < (current.length >>> 3) && current.length - 1 > 32) { + val ans = java.util.Arrays.copyOf(current, index + 1) + ans(ans.length - 1) = current(current.length - 1) + ans + } + else current + pv = pv + index + x(x.length - 1) = pv + history(hIndex) = x + hIndex += 1 + } + while (h < that.hIndex) { + val cuml = that.cumulative(h) + pv = pv + cuml - prev + prev = cuml + val x = that.history(h) + x(x.length - 1) = pv + history(hIndex) = x + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = DoubleAccumulator.emptyDoubleArray + history = DoubleAccumulator.emptyDoubleArrayArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): Double = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): Double = apply(i.toLong) + + /** Returns a `DoubleStepper` over the contents of this `DoubleAccumulator`. */ + final def stepper: DoubleStepper = new DoubleAccumulatorStepper(this) + + /** Returns an `Iterator` over the contents of this `DoubleAccumulator`. The `Iterator` is not specialized. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator.OfDouble` over the contents of this `DoubleAccumulator`*/ + final def spliterator: java.util.Spliterator.OfDouble = stepper + + /** Produces a sequential Java 8 `DoubleStream` over the elements of this `DoubleAccumulator`*/ + final def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(spliterator, false) + + /** Produces a parallel Java 8 `DoubleStream` over the elements of this `DoubleAccumulator`*/ + final def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(spliterator, true) + + /** Copies the elements in this `DoubleAccumulator` into an `Array[Double]` */ + final def toArray = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[Double](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = x(x.length-1).toLong + val n = (cuml - pv).toInt + pv = cuml + System.arraycopy(x, 0, a, j, n) + j += n + h += 1 + } + System.arraycopy(current, 0, a, j, index) + j += index + a + } + + /** Copies the elements in this `DoubleAccumulator` to a `List` */ + final def toList: List[Double] = { + var ans: List[Double] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i) :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i) :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `DoubleAccumulator` to a specified collection. + * Note that the target collection is not specialized. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + b += x(i) + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i) + i += 1 + } + b.result + } +} +object DoubleAccumulator { + private val emptyDoubleArray = new Array[Double](0) + private val emptyDoubleArrayArray = new Array[Array[Double]](0) + + /** A `Supplier` of `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ + def supplier = new java.util.function.Supplier[DoubleAccumulator]{ def get: DoubleAccumulator = new DoubleAccumulator } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. */ + def adder = new java.util.function.ObjDoubleConsumer[DoubleAccumulator]{ def accept(ac: DoubleAccumulator, a: Double) { ac += a } } + + /** A `BiConsumer` that adds a boxed `Double` to an `DoubleAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def boxedAdder = new java.util.function.BiConsumer[DoubleAccumulator, Double]{ def accept(ac: DoubleAccumulator, a: Double) { ac += a } } + + /** A `BiConsumer` that merges `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ + def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator) { a1 drain a2 } } +} + +private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator) extends DoubleStepper { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): DoubleAccumulatorStepper = { + val ans = new DoubleAccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def nextDouble: Double = + if (n <= 0) throw new NoSuchElementException("next on empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i) + i += 1 + N -= 1 + ans + } + + // Overridden for efficiency + override def tryStep(f: Double => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: Double => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.DoubleConsumer) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): DoubleStepper = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala new file mode 100644 index 0000000..69a13d1 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -0,0 +1,339 @@ +package scala.compat.java8.collectionImpl + +/** A `IntAccumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging them. + * This is a manually specialized variant of `Accumulator` with no actual + * subclassing relationship with `Accumulator`. + */ +final class IntAccumulator extends AccumulatorLike[Int, IntAccumulator] { self => + private[java8] var current: Array[Int] = IntAccumulator.emptyIntArray + private[java8] var history: Array[Array[Int]] = IntAccumulator.emptyIntArrayArray + + private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-2).toLong << 32 | (x(x.length-1)&0xFFFFFFFFL) } + + private def expand(): Unit = { + if (index > 0) { + val cuml = (if (hIndex > 0) cumulative(hIndex-1) else 0) + index + current(current.length-2) = (cuml >>> 32).toInt + current(current.length-1) = (cuml & 0xFFFFFFFFL).toInt + if (hIndex >= history.length) hExpand() + history(hIndex) = current + hIndex += 1 + } + current = new Array[Int](nextBlockSize+1) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) history = new Array[Array[Int]](4) + else history = java.util.Arrays.copyOf(history, history.length << 1) + } + + /** Appends an element to this `IntAccumulator`. */ + final def +=(a: Int): Unit = { + totalSize += 1 + if (index+2 >= current.length) expand() + current(index) = a + index += 1 + } + + /** Removes all elements from `that` and appends them to this `IntAccumulator`. */ + final def drain(that: IntAccumulator): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val cuml = that.cumulative(h) + val n = (cuml - prev).toInt + if (current.length - index - 2 >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = cuml + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index - 2 >= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + val x = + if (index < (current.length >>> 3) && current.length - 1 > 32) { + val ans = java.util.Arrays.copyOf(current, index + 2) + ans(ans.length - 2) = current(current.length - 2) + ans(ans.length - 1) = current(current.length - 1) + ans + } + else current + pv = pv + index + x(x.length - 2) = (pv >>> 32).toInt + x(x.length - 1) = (pv & 0xFFFFFFFFL).toInt + history(hIndex) = x + hIndex += 1 + } + while (h < that.hIndex) { + val cuml = that.cumulative(h) + pv = pv + cuml - prev + prev = cuml + val x = that.history(h) + x(x.length - 2) = (pv >>> 32).toInt + x(x.length - 1) = (pv & 0xFFFFFFFFL).toInt + history(hIndex) = x + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = IntAccumulator.emptyIntArray + history = IntAccumulator.emptyIntArrayArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): Int = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): Int = apply(i.toLong) + + /** Returns an `IntStepper` over the contents of this `IntAccumulator` */ + final def stepper: IntStepper = new IntAccumulatorStepper(this) + + /** Returns an `Iterator` over the contents of this `IntAccumulator`. The `Iterator` is not specialized. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator.OfInt` over the contents of this `IntAccumulator`*/ + final def spliterator: java.util.Spliterator.OfInt = stepper + + /** Produces a sequential Java 8 `IntStream` over the elements of this `IntAccumulator`*/ + final def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(spliterator, false) + + /** Produces a parallel Java 8 `IntStream` over the elements of this `IntAccumulator`*/ + final def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(spliterator, true) + + /** Copies the elements in this `IntAccumulator` into an `Array[Int]` */ + final def toArray = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[Int](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = cumulative(h) + val n = (cuml - pv).toInt + pv = cuml + System.arraycopy(x, 0, a, j, n) + j += n + h += 1 + } + System.arraycopy(current, 0, a, j, index) + j += index + a + } + + /** Copies the elements in this `IntAccumulator` to a `List` */ + final def toList: List[Int] = { + var ans: List[Int] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i) :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i) :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `IntAccumulator` to a specified collection. + * Note that the target collection is not specialized. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = cumulative(h) + val n = cuml - pv + pv = cuml + var i = 0 + while (i < n) { + b += x(i) + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i) + i += 1 + } + b.result + } +} + +object IntAccumulator { + private val emptyIntArray = new Array[Int](0) + private val emptyIntArrayArray = new Array[Array[Int]](0) + + /** A `Supplier` of `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ + def supplier = new java.util.function.Supplier[IntAccumulator]{ def get: IntAccumulator = new IntAccumulator } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.IntStream`'s `collect` method. */ + def adder = new java.util.function.ObjIntConsumer[IntAccumulator]{ def accept(ac: IntAccumulator, a: Int) { ac += a } } + + /** A `BiConsumer` that adds a boxed `Int` to an `IntAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def boxedAdder = new java.util.function.BiConsumer[IntAccumulator, Int]{ def accept(ac: IntAccumulator, a: Int) { ac += a } } + + /** A `BiConsumer` that merges `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ + def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator) { a1 drain a2 } } +} + +private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) extends IntStepper { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): IntAccumulatorStepper = { + val ans = new IntAccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def nextInt: Int = + if (N <= 0) throw new NoSuchElementException("next on empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i) + i += 1 + N -= 1 + ans + } + + // Overridden for efficiency + override def tryStep(f: Int => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def tryAdvance(f: java.util.function.IntConsumer): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: Int => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.IntConsumer) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): IntStepper = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala new file mode 100644 index 0000000..8cf770c --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -0,0 +1,333 @@ +package scala.compat.java8.collectionImpl + +/** A `LongAccumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging them. + * This is a manually specialized variant of `Accumulator` with no actual + * subclassing relationship with `Accumulator`. + */ +final class LongAccumulator extends AccumulatorLike[Long, LongAccumulator] { self => + private[java8] var current: Array[Long] = LongAccumulator.emptyLongArray + private[java8] var history: Array[Array[Long]] = LongAccumulator.emptyLongArrayArray + + private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-1) } + + private def expand(): Unit = { + if (index > 0) { + current(current.length-1) = (if (hIndex > 0) { val x = history(hIndex-1); x(x.length-1) } else 0) + index + if (hIndex >= history.length) hExpand() + history(hIndex) = current + hIndex += 1 + } + current = new Array[Long](nextBlockSize+1) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) history = new Array[Array[Long]](4) + else history = java.util.Arrays.copyOf(history, history.length << 1) + } + + /** Appends an element to this `LongAccumulator`. */ + final def +=(a: Long): Unit = { + totalSize += 1 + if (index+1 >= current.length) expand() + current(index) = a + index += 1 + } + + /** Removes all elements from `that` and appends them to this `LongAccumulator`. */ + final def drain(that: LongAccumulator): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val cuml = that.cumulative(h) + val n = (cuml - prev).toInt + if (current.length - index - 1 >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = cuml + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index - 1>= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + val x = + if (index < (current.length >>> 3) && current.length - 1 > 32) { + val ans = java.util.Arrays.copyOf(current, index + 1) + ans(ans.length - 1) = current(current.length - 1) + ans + } + else current + pv = pv + index + x(x.length - 1) = pv + history(hIndex) = x + hIndex += 1 + } + while (h < that.hIndex) { + val cuml = that.cumulative(h) + pv = pv + cuml - prev + prev = cuml + val x = that.history(h) + x(x.length - 1) = pv + history(hIndex) = x + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = LongAccumulator.emptyLongArray + history = LongAccumulator.emptyLongArrayArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): Long = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): Long = apply(i.toLong) + + /** Returns a `LongStepper` over the contents of this `LongAccumulator`. */ + final def stepper: LongStepper = new LongAccumulatorStepper(this) + + /** Returns an `Iterator` over the contents of this `LongAccumulator`. The `Iterator` is not specialized. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator.OfLong` over the contents of this `LongAccumulator`*/ + final def spliterator: java.util.Spliterator.OfLong = stepper + + /** Produces a sequential Java 8 `LongStream` over the elements of this `LongAccumulator`*/ + final def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(spliterator, false) + + /** Produces a parallel Java 8 `LongStream` over the elements of this `LongAccumulator`*/ + final def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(spliterator, true) + + /** Copies the elements in this `LongAccumulator` into an `Array[Long]` */ + final def toArray = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[Long](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = x(x.length-1) + val n = (cuml - pv).toInt + pv = cuml + System.arraycopy(x, 0, a, j, n) + j += n + h += 1 + } + System.arraycopy(current, 0, a, j, index) + j += index + a + } + + /** Copies the elements in this `LongAccumulator` to a `List` */ + final def toList: List[Long] = { + var ans: List[Long] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i) :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i) :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `LongAccumulator` to a specified collection. + * Note that the target collection is not specialized. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + b += x(i) + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i) + i += 1 + } + b.result + } +} + +object LongAccumulator { + private val emptyLongArray = new Array[Long](0) + private val emptyLongArrayArray = new Array[Array[Long]](0) + + /** A `Supplier` of `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ + def supplier = new java.util.function.Supplier[LongAccumulator]{ def get: LongAccumulator = new LongAccumulator } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.LongStream`'s `collect` method. */ + def adder = new java.util.function.ObjLongConsumer[LongAccumulator]{ def accept(ac: LongAccumulator, a: Long) { ac += a } } + + /** A `BiConsumer` that adds a boxed `Long` to an `LongAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def boxedAdder = new java.util.function.BiConsumer[LongAccumulator, Long]{ def accept(ac: LongAccumulator, a: Long) { ac += a } } + + /** A `BiConsumer` that merges `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ + def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator) { a1 drain a2 } } +} + +private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) extends LongStepper { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): LongAccumulatorStepper = { + val ans = new LongAccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def nextLong: Long = + if (n <= 0) throw new NoSuchElementException("next on empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i) + i += 1 + N -= 1 + ans + } + + // Overridden for efficiency + override def tryStep(f: Long => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def tryAdvance(f: java.util.function.LongConsumer): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: Long => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.LongConsumer) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): LongStepper = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } +} diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala new file mode 100644 index 0000000..879b219 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -0,0 +1,145 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StreamConvertersTest { + import java.util.stream._ + import StreamConverters._ + + def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! + def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } + + def arrayO(n: Int) = (1 to n).map(_.toString).toArray + def arrayD(n: Int) = (1 to n).map(_.toDouble).toArray + def arrayI(n: Int) = (1 to n).toArray + def arrayL(n: Int) = (1 to n).map(_.toLong).toArray + + def newStream(n: Int) = java.util.Arrays.stream(arrayO(n)) + def newDoubleStream(n: Int) = java.util.Arrays.stream(arrayD(n)) + def newIntStream(n: Int) = java.util.Arrays.stream(arrayI(n)) + def newLongStream(n: Int) = java.util.Arrays.stream(arrayL(n)) + + val ns = Vector(0, 1, 2, 12, 15, 16, 17, 31, 32, 33, 151, 1298, 7159) + + @Test + def streamAccumulate() { + for (n <- ns) { + val vecO = arrayO(n).toVector + val accO = newStream(n).parallel.accumulate + assertEq(vecO, newStream(n).accumulate.to[Vector], s"stream $n to vector") + assertEq(vecO, accO.to[Vector], s"stream $n to vector in parallel") + assertEq(vecO, accO.toArray.toVector, s"stream $n to vector via array in parallel") + assertEq(vecO, accO.iterator.toVector, s"stream $n to vector via iterator in parallel") + assertEq(vecO, accO.toList.toVector, s"stream $n to vector via list in parallel") + assert((0 until accO.size.toInt).forall(i => vecO(i) == accO(i)), s"stream $n indexed via accumulator") + assert(accO.isInstanceOf[scala.compat.java8.collectionImpl.Accumulator[_]], s"stream $n to generic accumulator") + + for (boxless <- Seq(false, true)) { + val sbox = (if (boxless) "" else "(boxed)") + val vecD = arrayD(n).toVector + val accD = + if (boxless) newDoubleStream(n).parallel.accumulate + else newDoubleStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecD, newDoubleStream(n).accumulate.to[Vector], s"double stream $n to vector $sbox") + assertEq(vecD, accD.to[Vector], s"double stream $n to vector in parallel $sbox") + assertEq(vecD, accD.toArray.toVector, s"double stream $n to vector via array in parallel $sbox") + assertEq(vecD, accD.iterator.toVector, s"double stream $n to vector via iterator in parallel $sbox") + assertEq(vecD, accD.toList.toVector, s"double stream $n to vector via list in parallel $sbox") + assert((0 until accD.size.toInt).forall(i => vecD(i) == accD(i)), s"double stream $n indexed via accumulator $sbox") + assert(accD.isInstanceOf[scala.compat.java8.collectionImpl.DoubleAccumulator], s"double stream $n to generic accumulator $sbox") + + val vecI = arrayI(n).toVector + val accI = + if (boxless) newIntStream(n).parallel.accumulate + else newIntStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecI, newIntStream(n).accumulate.to[Vector], s"int stream $n to vector $sbox") + assertEq(vecI, accI.to[Vector], s"int stream $n to vector in parallel $sbox") + assertEq(vecI, accI.toArray.toVector, s"int stream $n to vector via array in parallel $sbox") + assertEq(vecI, accI.iterator.toVector, s"int stream $n to vector via iterator in parallel $sbox") + assertEq(vecI, accI.toList.toVector, s"int stream $n to vector via list in parallel $sbox") + assert((0 until accI.size.toInt).forall(i => vecI(i) == accI(i)), s"int stream $n indexed via accumulator $sbox") + assert(accI.isInstanceOf[scala.compat.java8.collectionImpl.IntAccumulator], s"int stream $n to generic accumulator $sbox") + + val vecL = arrayL(n).toVector + val accL = + if (boxless) newLongStream(n).parallel.accumulate + else newLongStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecL, newLongStream(n).accumulate.to[Vector], s"long stream $n to vector $sbox") + assertEq(vecL, accL.to[Vector], s"long stream $n to vector in parallel $sbox") + assertEq(vecL, accL.toArray.toVector, s"long stream $n to vector via array in parallel $sbox") + assertEq(vecL, accL.iterator.toVector, s"long stream $n to vector via iterator in parallel $sbox") + assertEq(vecL, accL.toList.toVector, s"long stream $n to vector via list in parallel $sbox") + assert((0 until accL.size.toInt).forall(i => vecL(i) == accL(i)), s"long stream $n indexed via accumulator $sbox") + assert(accL.isInstanceOf[scala.compat.java8.collectionImpl.LongAccumulator], s"long stream $n to generic accumulator $sbox") + } + } + } + + @Test + def streamToScala() { + for (n <- ns) { + val vecO = arrayO(n).toVector + assertEq(vecO, newStream(n).toScala[Vector]) + assertEq(vecO, newStream(n).parallel.toScala[Vector]) + + val vecD = arrayD(n).toVector + assertEq(vecD, newDoubleStream(n).toScala[Vector]) + assertEq(vecD, newDoubleStream(n).parallel.toScala[Vector]) + + val vecI = arrayI(n).toVector + assertEq(vecI, newIntStream(n).toScala[Vector]) + assertEq(vecI, newIntStream(n).parallel.toScala[Vector]) + + val vecL = arrayL(n).toVector + assertEq(vecL, newLongStream(n).toScala[Vector]) + assertEq(vecL, newLongStream(n).parallel.toScala[Vector]) + } + } + + @Test + def streamUnbox() { + assert(newDoubleStream(1).boxed.unboxed.isInstanceOf[DoubleStream]) + assert(newIntStream(1).boxed.unboxed.isInstanceOf[IntStream]) + assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) + } + + @Test + def scalaToStream() { + for (n <- ns) { + val arrO = arrayO(n) + val seqO = arrO.toSeq + assertEq(seqO, seqO.seqStream.toScala[Seq]) + assertEq(seqO, seqO.parStream.toScala[Seq]) + assertEq(seqO, arrO.seqStream.toScala[Seq]) + assertEq(seqO, arrO.parStream.toScala[Seq]) + + val arrD = arrayD(n) + val seqD = arrD.toSeq + assertEq(seqD, seqD.seqStream.toScala[Seq]) + assertEq(seqD, seqD.parStream.toScala[Seq]) + assertEq(seqD, arrD.seqStream.toScala[Seq]) + assertEq(seqD, arrD.parStream.toScala[Seq]) + assert(arrD.seqStream.isInstanceOf[DoubleStream]) + assert(arrD.parStream.isInstanceOf[DoubleStream]) + + val arrI = arrayI(n) + val seqI = arrI.toSeq + assertEq(seqI, seqI.seqStream.toScala[Seq]) + assertEq(seqI, seqI.parStream.toScala[Seq]) + assertEq(seqI, arrI.seqStream.toScala[Seq]) + assertEq(seqI, arrI.parStream.toScala[Seq]) + assert(arrI.seqStream.isInstanceOf[IntStream]) + assert(arrI.parStream.isInstanceOf[IntStream]) + + val arrL = arrayL(n) + val seqL = arrL.toSeq + assertEq(seqL, seqL.seqStream.toScala[Seq]) + assertEq(seqL, seqL.parStream.toScala[Seq]) + assertEq(seqL, arrL.seqStream.toScala[Seq]) + assertEq(seqL, arrL.parStream.toScala[Seq]) + assert(arrL.seqStream.isInstanceOf[LongStream]) + assert(arrL.parStream.isInstanceOf[LongStream]) + } + } +} From 302fd15d5b2d4936f8a572bb4eea4b1ac959ff41 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 27 Sep 2015 12:31:13 -0700 Subject: [PATCH 16/56] Pulled out abstractable part of Array steppers for use by any Indexed. --- .../scala/compat/java8/StepConverters.scala | 145 +++++++----------- .../compat/java8/collectionImpl/Stepper.scala | 12 +- .../collectionImpl/StepsLikeIndexed.scala | 19 +++ 3 files changed, 85 insertions(+), 91 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 21b0eeb..4f429ee 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -5,82 +5,65 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ package converterImpls { - import StepConverters.SplitFlags._ - - private[java8] abstract class StepperArrayAny[A, AA, STA >: Null <: StepperArrayAny[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) - extends AnyStepper[A] { - def semiclone(half: Int): STA - def characteristics() = NonNull + Sized + Subsized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): AnyStepper[A] = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } - } - - private[java8] class StepperArrayGenObject[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) - extends StepperArrayAny[A, Array[A], StepperArrayGenObject[A]](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenObject[A](underlying, i0, half) + import Stepper._ + + private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, Array[A], StepsObjectArray[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) } - private[java8] class StepperArrayGenAny[A](underlying: Array[A], _i0: Int, _iN: Int) - extends StepperArrayAny[A, Array[A], StepperArrayGenAny[A]](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenAny[A](underlying, i0, half) + private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, Array[A], StepsAnyArray[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) } - private[java8] class StepperArrayGenUnit(underlying: Array[Unit], _i0: Int, _iN: Int) - extends StepperArrayAny[Unit, Array[Unit], StepperArrayGenUnit](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenUnit(underlying, i0, half) + private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Unit, Array[Unit], StepsUnitArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE + def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) } - private[java8] class StepperArrayGenBoolean(underlying: Array[Boolean], _i0: Int, _iN: Int) - extends StepperArrayAny[Boolean, Array[Boolean], StepperArrayGenBoolean](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenBoolean(underlying, i0, half) + private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Boolean, Array[Boolean], StepsBoxedBooleanArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) } - private[java8] class StepperArrayGenByte(underlying: Array[Byte], _i0: Int, _iN: Int) - extends StepperArrayAny[Byte, Array[Byte], StepperArrayGenByte](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenByte(underlying, i0, half) + private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Byte, Array[Byte], StepsBoxedByteArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) } - private[java8] class StepperArrayGenChar(underlying: Array[Char], _i0: Int, _iN: Int) - extends StepperArrayAny[Char, Array[Char], StepperArrayGenChar](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenChar(underlying, i0, half) + private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Char, Array[Char], StepsBoxedCharArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) } - private[java8] class StepperArrayGenShort(underlying: Array[Short], _i0: Int, _iN: Int) - extends StepperArrayAny[Short, Array[Short], StepperArrayGenShort](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenShort(underlying, i0, half) + private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Short, Array[Short], StepsBoxedShortArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) } - private[java8] class StepperArrayGenFloat(underlying: Array[Float], _i0: Int, _iN: Int) - extends StepperArrayAny[Float, Array[Float], StepperArrayGenFloat](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenFloat(underlying, i0, half) + private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Float, Array[Float], StepsBoxedFloatArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) } - private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { - def characteristics() = NonNull + Sized + Subsized + private[java8] class StepsDoubleArray(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { + def characteristics() = NonNull + Sized + SubSized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def substep() = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 - val ans = new StepperArrayDouble(underlying, i0, half) + val ans = new StepsDoubleArray(underlying, i0, half) i0 = half ans } @@ -88,15 +71,15 @@ package converterImpls { } } - private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { - def characteristics() = NonNull + Sized + Subsized + private[java8] class StepsIntArray(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { + def characteristics() = NonNull + Sized + SubSized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def substep() = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 - val ans = new StepperArrayInt(underlying, i0, half) + val ans = new StepsIntArray(underlying, i0, half) i0 = half ans } @@ -104,15 +87,15 @@ package converterImpls { } } - private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { - def characteristics() = NonNull + Sized + Subsized + private[java8] class StepsLongArray(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { + def characteristics() = NonNull + Sized + SubSized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def substep() = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 - val ans = new StepperArrayLong(underlying, i0, half) + val ans = new StepsLongArray(underlying, i0, half) i0 = half ans } @@ -121,35 +104,35 @@ package converterImpls { } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ - @inline def stepper: AnyStepper[A] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepsObjectArray[A](underlying, 0, underlying.length) } final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: AnyStepper[Unit] = new StepperArrayGenUnit(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Unit] = new StepsUnitArray(underlying, 0, underlying.length) } final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: AnyStepper[Boolean] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Boolean] = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: AnyStepper[Byte] = new StepperArrayGenByte(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Byte] = new StepsBoxedByteArray(underlying, 0, underlying.length) } final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ - @inline def stepper: AnyStepper[Char] = new StepperArrayGenChar(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Char] = new StepsBoxedCharArray(underlying, 0, underlying.length) } final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: AnyStepper[Short] = new StepperArrayGenShort(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Short] = new StepsBoxedShortArray(underlying, 0, underlying.length) } final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ - @inline def stepper: AnyStepper[Float] = new StepperArrayGenFloat(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { @@ -162,7 +145,7 @@ package converterImpls { i0 += java.lang.Character.charCount(cp) cp } - else throw new NoSuchElementException("Empty Stepper") + else throwNSEE } def substep() = { if (iN-3 > i0) { @@ -192,29 +175,19 @@ package converterImpls { } object StepConverters extends converterImpls.Priority2StepConverters { - object SplitFlags { - final val Concurrent = java.util.Spliterator.CONCURRENT - final val Distinct = java.util.Spliterator.DISTINCT - final val Immutable = java.util.Spliterator.IMMUTABLE - final val NonNull = java.util.Spliterator.NONNULL - final val HasOrder = java.util.Spliterator.ORDERED - final val Sized = java.util.Spliterator.SIZED - final val Sorted = java.util.Spliterator.SORTED - final val Subsized = java.util.Spliterator.SUBSIZED - } - import SplitFlags._ import converterImpls._ + import Stepper._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: DoubleStepper = new StepsDoubleArray(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: IntStepper = new StepsIntArray(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: LongStepper = new StepsLongArray(underlying, 0, underlying.length) } implicit class RichStringCanStep(val underlying: String) extends AnyVal { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 3e09ee5..af5c22a 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -181,7 +181,7 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step final def nextStep = { if (!myCacheIsFull) { load() - if (!myCacheIsFull) throw new NoSuchElementException("nextStep in TryStepper") + if (!myCacheIsFull) Stepper.throwNSEE } val ans = myCache myCacheIsFull = false @@ -282,6 +282,8 @@ object Stepper { /** Indicates that a Stepper's children (created with substep()) will all know their size. Steppers that are SubSized must also be Sized. */ val SubSized = Spliterator.SUBSIZED + private[java8] final def throwNSEE: Nothing = throw new NoSuchElementException("Empty Stepper") + private class OfSpliterator[A](sp: Spliterator[A]) extends AnyStepper[A] with java.util.function.Consumer[A] { @@ -312,7 +314,7 @@ object Stepper { } def hasNext = cached || loadCache def next = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cache = null.asInstanceOf[A] cached = false @@ -363,7 +365,7 @@ object Stepper { } def hasNext = cached || loadCache def nextDouble = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cached = false ans @@ -412,7 +414,7 @@ object Stepper { } def hasNext = cached || loadCache def nextInt = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cached = false ans @@ -461,7 +463,7 @@ object Stepper { } def hasNext = cached || loadCache def nextLong = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cached = false ans diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala new file mode 100644 index 0000000..4b7c1d5 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -0,0 +1,19 @@ +package scala.compat.java8.collectionImpl + +import Stepper._ + +abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) extends AnyStepper[A] { + def semiclone(half: Int): STA + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): AnyStepper[A] = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} From ecf85a38ff278de5ca3f90ee50250e359fe24489 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 27 Sep 2015 12:50:38 -0700 Subject: [PATCH 17/56] Abstracted indexed stepping over Double, Int, Long specialized versions. --- .../scala/compat/java8/StepConverters.scala | 48 ++++-------------- .../collectionImpl/StepsLikeIndexed.scala | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 4f429ee..6385502 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -55,52 +55,22 @@ package converterImpls { def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) } - private[java8] class StepsDoubleArray(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN + private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[Array[Double], StepsDoubleArray](underlying, _i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def substep() = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = new StepsDoubleArray(underlying, i0, half) - i0 = half - ans - } - else null - } + def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) } - private[java8] class StepsIntArray(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN + private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[Array[Int], StepsIntArray](underlying, _i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def substep() = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = new StepsIntArray(underlying, i0, half) - i0 = half - ans - } - else null - } + def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) } - private[java8] class StepsLongArray(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN + private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[Array[Long], StepsLongArray](underlying, _i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def substep() = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = new StepsLongArray(underlying, i0, half) - i0 = half - ans - } - else null - } + def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index 4b7c1d5..6d82050 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -17,3 +17,52 @@ abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _] else null } } + +abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, var i0: Int, var iN: Int) extends DoubleStepper { + def semiclone(half: Int): STD + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): DoubleStepper = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} + + +abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, var i0: Int, var iN: Int) extends IntStepper { + def semiclone(half: Int): STI + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): IntStepper = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} + +abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, var i0: Int, var iN: Int) extends LongStepper { + def semiclone(half: Int): STL + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): LongStepper = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} From e5624514f0d58f87536ea9adda6e08da315bb071 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 27 Sep 2015 15:03:28 -0700 Subject: [PATCH 18/56] IndexedSeqOptimized added to Stream compat via Stepper. Includes everything through StreamConverters and tests. --- .../scala/compat/java8/StepConverters.scala | 63 +++++++++++++++--- .../scala/compat/java8/StreamConverters.scala | 66 ++++++++++++++----- .../compat/java8/StreamConvertersTest.scala | 24 +++++++ 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 6385502..859c14f 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -72,38 +72,78 @@ package converterImpls { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } + + private[java8] class StepsAnyIndexedSeqOptimized[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, CC, StepsAnyIndexedSeqOptimized[A, CC]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A, CC](underlying, i0, half) + } + + private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[CC, StepsDoubleIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsDoubleIndexedSeqOptimized[CC](underlying, i0, half) + } + + private[java8] class StepsIntIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[CC, StepsIntIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntIndexedSeqOptimized[CC](underlying, i0, half) + } + + private[java8] class StepsLongIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[CC, StepsLongIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) + } - final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } - final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ + final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal{ @inline def stepper: AnyStepper[A] = new StepsObjectArray[A](underlying, 0, underlying.length) } - final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ + final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal{ @inline def stepper: AnyStepper[Unit] = new StepsUnitArray(underlying, 0, underlying.length) } - final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ + final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal{ @inline def stepper: AnyStepper[Boolean] = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } - final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ + final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal{ @inline def stepper: AnyStepper[Byte] = new StepsBoxedByteArray(underlying, 0, underlying.length) } - final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ + final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal { @inline def stepper: AnyStepper[Char] = new StepsBoxedCharArray(underlying, 0, underlying.length) } - final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ + final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal{ @inline def stepper: AnyStepper[Short] = new StepsBoxedShortArray(underlying, 0, underlying.length) } - final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ + final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal { @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } + + final class RichIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A, CC](underlying, 0, underlying.length) + } + + final class RichDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeqOptimized[CC](underlying, 0, underlying.length) + } + + final class RichIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntIndexedSeqOptimized[CC](underlying, 0, underlying.length) + } + + final class RichLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) + } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull @@ -131,6 +171,7 @@ package converterImpls { trait Priority3StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) + implicit def richIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC) = new RichIndexedSeqOptimizedCanStep[A, CC](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -141,6 +182,12 @@ package converterImpls { implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + implicit def richDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC) = + new RichDoubleIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC) = + new RichIntIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = + new RichLongIndexedSeqOptimizedCanStep[CC](underlying) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 0b9b644..f04e848 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -13,7 +13,7 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority2StreamConverters { +trait Priority3StreamConverters { implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { private def mkAcc() = { val acc = new Accumulator[A] @@ -24,8 +24,27 @@ trait Priority2StreamConverters { def seqStream: Stream[A] = mkAcc().seqStream def parStream: Stream[A] = mkAcc().parStream + } +} + +trait Priority2StreamConverters extends Priority3StreamConverters { + implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { + private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { + if (t.isTraversableAgain && t.hasDefiniteSize) { + val sz = t.size + val a = new Array[A](sz) + t.copyToArray(a, 0, sz) + a + } + else t.toArray[A] + } + + def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = + java.util.Arrays.stream(mkArr()) + + def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel } - + implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { private def mkAcc() = { val acc = new Accumulator[A] @@ -44,23 +63,13 @@ trait Priority2StreamConverters { } trait Priority1StreamConverters extends Priority2StreamConverters { - implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { - private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { - if (t.isTraversableAgain && t.hasDefiniteSize) { - val sz = t.size - val a = new Array[A](sz) - t.copyToArray(a, 0, sz) - a - } - else t.toArray[A] - } - - def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = - java.util.Arrays.stream(mkArr()) - - def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel + implicit class EnrichGenericIndexedSeqOptimizedWithStream[A, CC <: collection.IndexedSeqOptimized[A, _]](c: CC) { + private def someStream(parallel: Boolean): Stream[A] = + StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A, CC](c, 0, c.length), parallel) + def seqStream: Stream[A] = someStream(false) + def parStream: Stream[A] = someStream(true) } - + implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { def seqStream: Stream[A] = java.util.Arrays.stream(a) def parStream: Stream[A] = seqStream.parallel @@ -122,6 +131,27 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * ``` */ object StreamConverters extends Priority1StreamConverters { + implicit class EnrichDoubleIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Double, _]](c: CC) { + private def someStream(parallel: Boolean): DoubleStream = + StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeqOptimized[CC](c, 0, c.length), parallel) + def seqStream: DoubleStream = someStream(false) + def parStream: DoubleStream = someStream(true) + } + + implicit class EnrichIntIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Int, _]](c: CC) { + private def someStream(parallel: Boolean): IntStream = + StreamSupport.intStream(new converterImpls.StepsIntIndexedSeqOptimized[CC](c, 0, c.length), parallel) + def seqStream: IntStream = someStream(false) + def parStream: IntStream = someStream(true) + } + + implicit class EnrichLongIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Long, _]](c: CC) { + private def someStream(parallel: Boolean): LongStream = + StreamSupport.longStream(new converterImpls.StepsLongIndexedSeqOptimized[CC](c, 0, c.length), parallel) + def seqStream: LongStream = someStream(false) + def parStream: LongStream = someStream(true) + } + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 879b219..284f79a 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -103,43 +103,67 @@ class StreamConvertersTest { assert(newIntStream(1).boxed.unboxed.isInstanceOf[IntStream]) assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) } + + import collection.mutable.{ArrayBuffer, WrappedArray } + def abufO(n: Int) = { val ab = new ArrayBuffer[String]; arrayO(n).foreach(ab += _); ab } + def abufD(n: Int) = { val ab = new ArrayBuffer[Double]; arrayD(n).foreach(ab += _); ab } + def abufI(n: Int) = { val ab = new ArrayBuffer[Int]; arrayI(n).foreach(ab += _); ab } + def abufL(n: Int) = { val ab = new ArrayBuffer[Long]; arrayL(n).foreach(ab += _); ab } @Test def scalaToStream() { for (n <- ns) { val arrO = arrayO(n) val seqO = arrO.toSeq + val abO = abufO(n) assertEq(seqO, seqO.seqStream.toScala[Seq]) assertEq(seqO, seqO.parStream.toScala[Seq]) assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) + assertEq(seqO, abO.seqStream.toScala[Seq]) + assertEq(seqO, abO.parStream.toScala[Seq]) val arrD = arrayD(n) val seqD = arrD.toSeq + val abD = abufD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) assertEq(seqD, seqD.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) assertEq(seqD, arrD.parStream.toScala[Seq]) assert(arrD.seqStream.isInstanceOf[DoubleStream]) assert(arrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, abD.seqStream.toScala[Seq]) + assertEq(seqD, abD.parStream.toScala[Seq]) + assert(abD.seqStream.isInstanceOf[DoubleStream]) + assert(abD.parStream.isInstanceOf[DoubleStream]) val arrI = arrayI(n) val seqI = arrI.toSeq + val abI = abufI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) assertEq(seqI, seqI.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) assertEq(seqI, arrI.parStream.toScala[Seq]) assert(arrI.seqStream.isInstanceOf[IntStream]) assert(arrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, abI.seqStream.toScala[Seq]) + assertEq(seqI, abI.parStream.toScala[Seq]) + assert(abI.seqStream.isInstanceOf[IntStream]) + assert(abI.parStream.isInstanceOf[IntStream]) val arrL = arrayL(n) val seqL = arrL.toSeq + val abL = abufL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) assertEq(seqL, seqL.parStream.toScala[Seq]) assertEq(seqL, arrL.seqStream.toScala[Seq]) assertEq(seqL, arrL.parStream.toScala[Seq]) assert(arrL.seqStream.isInstanceOf[LongStream]) assert(arrL.parStream.isInstanceOf[LongStream]) + assertEq(seqL, abL.seqStream.toScala[Seq]) + assertEq(seqL, abL.parStream.toScala[Seq]) + assert(abL.seqStream.isInstanceOf[LongStream]) + assert(abL.parStream.isInstanceOf[LongStream]) } } } From 390bbabc8d836f3aacfa45000fb5b50b5c58239a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 30 Sep 2015 14:56:45 -0700 Subject: [PATCH 19/56] FlatHashTable-based collections have steppers and can be converted to streams. --- .../java8/runtime/CollectionInternals.java | 5 ++ .../scala/compat/java8/StepConverters.scala | 58 +++++++++++++- .../scala/compat/java8/StreamConverters.scala | 42 +++++++++- .../collectionImpl/StepsLikeIndexed.scala | 79 +++++++------------ .../compat/java8/StreamConvertersTest.scala | 48 ++++++++++- 5 files changed, 176 insertions(+), 56 deletions(-) create mode 100644 src/main/java/scala/compat/java8/runtime/CollectionInternals.java diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java new file mode 100644 index 0000000..82af37b --- /dev/null +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -0,0 +1,5 @@ +package scala.compat.java8.runtime; + +public class CollectionInternals { + public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } +} diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 859c14f..6b82ac6 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -96,7 +96,31 @@ package converterImpls { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } - + + private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) + } + + private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) + } + + private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) + } + + private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -144,6 +168,34 @@ package converterImpls { final class RichLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](private val underlying: CC) extends AnyVal { @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) } + + final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsAnyFlatHashTable(tbl, 0, tbl.length) + } + } + + final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsDoubleFlatHashTable(tbl, 0, tbl.length) + } + } + + final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal { + @inline def stepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsIntFlatHashTable(tbl, 0, tbl.length) + } + } + + final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal { + @inline def stepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsLongFlatHashTable(tbl, 0, tbl.length) + } + } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull @@ -172,6 +224,7 @@ package converterImpls { trait Priority3StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) implicit def richIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC) = new RichIndexedSeqOptimizedCanStep[A, CC](underlying) + implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -188,6 +241,9 @@ package converterImpls { new RichIntIndexedSeqOptimizedCanStep[CC](underlying) implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = new RichLongIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) + implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) + implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index f04e848..435248c 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -63,6 +63,11 @@ trait Priority2StreamConverters extends Priority3StreamConverters { } trait Priority1StreamConverters extends Priority2StreamConverters { + implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { + def seqStream: Stream[A] = java.util.Arrays.stream(a) + def parStream: Stream[A] = seqStream.parallel + } + implicit class EnrichGenericIndexedSeqOptimizedWithStream[A, CC <: collection.IndexedSeqOptimized[A, _]](c: CC) { private def someStream(parallel: Boolean): Stream[A] = StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A, CC](c, 0, c.length), parallel) @@ -70,9 +75,13 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = someStream(true) } - implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { - def seqStream: Stream[A] = java.util.Arrays.stream(a) - def parStream: Stream[A] = seqStream.parallel + implicit class EnrichGenericFlatHashTableWithStream[A](fht: collection.mutable.FlatHashTable[A]) { + private def someStream(parallel: Boolean): Stream[A] = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.stream(new converterImpls.StepsAnyFlatHashTable[A](tbl, 0, tbl.length), parallel) + } + def seqStream: Stream[A] = someStream(false) + def parStream: Stream[A] = someStream(true) } implicit class RichStream[A](stream: Stream[A]) { @@ -152,6 +161,33 @@ object StreamConverters extends Priority1StreamConverters { def parStream: LongStream = someStream(true) } + implicit class EnrichDoubleFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Double]) { + private def someStream(parallel: Boolean): DoubleStream = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.doubleStream(new converterImpls.StepsDoubleFlatHashTable(tbl, 0, tbl.length), parallel) + } + def seqStream: DoubleStream = someStream(false) + def parStream: DoubleStream = someStream(true) + } + + implicit class EnrichIntFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Int]) { + private def someStream(parallel: Boolean): IntStream = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.intStream(new converterImpls.StepsIntFlatHashTable(tbl, 0, tbl.length), parallel) + } + def seqStream: IntStream = someStream(false) + def parStream: IntStream = someStream(true) + } + + implicit class EnrichLongFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Long]) { + private def someStream(parallel: Boolean): LongStream = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.longStream(new converterImpls.StepsLongFlatHashTable(tbl, 0, tbl.length), parallel) + } + def seqStream: LongStream = someStream(false) + def parStream: LongStream = someStream(true) + } + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index 6d82050..208af7c 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -1,13 +1,15 @@ package scala.compat.java8.collectionImpl +import java.util.Spliterator import Stepper._ -abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) extends AnyStepper[A] { - def semiclone(half: Int): STA - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): AnyStepper[A] = { +/** Abstracts all the generic operations of stepping over an indexable collection */ +abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { + def semiclone(half: Int): Semi + def characteristics(): Int = Ordered + Sized + SubSized + def estimateSize(): Long = iN - i0 + def hasNext(): Boolean = i0 < iN + def substep(): Sub = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 val ans = semiclone(half) @@ -18,51 +20,26 @@ abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _] } } -abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, var i0: Int, var iN: Int) extends DoubleStepper { - def semiclone(half: Int): STD - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): DoubleStepper = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} +/** Abstracts the operation of stepping over a generic indexable collection */ +abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) + with AnyStepper[A] +{} +/** Abstracts the operation of stepping over an indexable collection of Doubles */ +abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) + with DoubleStepper +{} -abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, var i0: Int, var iN: Int) extends IntStepper { - def semiclone(half: Int): STI - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): IntStepper = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} +/** Abstracts the operation of stepping over an indexable collection of Ints */ +abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) + with IntStepper +{} -abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, var i0: Int, var iN: Int) extends LongStepper { - def semiclone(half: Int): STL - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): LongStepper = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} +/** Abstracts the operation of stepping over an indexable collection of Longs */ +abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 284f79a..4c4c0ad 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -104,11 +104,20 @@ class StreamConvertersTest { assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) } - import collection.mutable.{ArrayBuffer, WrappedArray } + import collection.mutable.{ ArrayBuffer, WrappedArray } def abufO(n: Int) = { val ab = new ArrayBuffer[String]; arrayO(n).foreach(ab += _); ab } def abufD(n: Int) = { val ab = new ArrayBuffer[Double]; arrayD(n).foreach(ab += _); ab } def abufI(n: Int) = { val ab = new ArrayBuffer[Int]; arrayI(n).foreach(ab += _); ab } def abufL(n: Int) = { val ab = new ArrayBuffer[Long]; arrayL(n).foreach(ab += _); ab } + def wrapO(n: Int): WrappedArray[String] = arrayO(n) + def wrapD(n: Int): WrappedArray[Double] = arrayD(n) + def wrapI(n: Int): WrappedArray[Int] = arrayI(n) + def wrapL(n: Int): WrappedArray[Long] = arrayL(n) + def genhset[A](aa: Array[A]) = { val hs = new collection.mutable.HashSet[A]; aa.foreach(hs += _); hs } + def hsetO(n: Int) = genhset(arrayO(n)) + def hsetD(n: Int) = genhset(arrayD(n)) + def hsetI(n: Int) = genhset(arrayI(n)) + def hsetL(n: Int) = genhset(arrayL(n)) @Test def scalaToStream() { @@ -116,16 +125,25 @@ class StreamConvertersTest { val arrO = arrayO(n) val seqO = arrO.toSeq val abO = abufO(n) + val wrO = wrapO(n) + val hsO = hsetO(n) + // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) assertEq(seqO, seqO.parStream.toScala[Seq]) assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) assertEq(seqO, abO.seqStream.toScala[Seq]) assertEq(seqO, abO.parStream.toScala[Seq]) + assertEq(seqO, wrO.seqStream.toScala[Seq]) + assertEq(seqO, wrO.parStream.toScala[Seq]) + assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) + assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) val arrD = arrayD(n) val seqD = arrD.toSeq val abD = abufD(n) + val wrD = wrapD(n) + val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) assertEq(seqD, seqD.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) @@ -136,10 +154,20 @@ class StreamConvertersTest { assertEq(seqD, abD.parStream.toScala[Seq]) assert(abD.seqStream.isInstanceOf[DoubleStream]) assert(abD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(wrD.seqStream.isInstanceOf[DoubleStream]) + assert(wrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, hsD.seqStream.toScala[Seq].sorted) + assertEq(seqD, hsD.parStream.toScala[Seq].sorted) + assert(hsD.seqStream.isInstanceOf[DoubleStream]) + assert(hsD.parStream.isInstanceOf[DoubleStream]) val arrI = arrayI(n) val seqI = arrI.toSeq val abI = abufI(n) + val wrI = wrapI(n) + val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) assertEq(seqI, seqI.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) @@ -150,10 +178,20 @@ class StreamConvertersTest { assertEq(seqI, abI.parStream.toScala[Seq]) assert(abI.seqStream.isInstanceOf[IntStream]) assert(abI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, wrI.seqStream.toScala[Seq]) + assertEq(seqI, wrI.parStream.toScala[Seq]) + assert(wrI.seqStream.isInstanceOf[IntStream]) + assert(wrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, hsI.seqStream.toScala[Seq].sorted) + assertEq(seqI, hsI.parStream.toScala[Seq].sorted) + assert(hsI.seqStream.isInstanceOf[IntStream]) + assert(hsI.parStream.isInstanceOf[IntStream]) val arrL = arrayL(n) val seqL = arrL.toSeq val abL = abufL(n) + val wrL = wrapL(n) + val hsL = hsetL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) assertEq(seqL, seqL.parStream.toScala[Seq]) assertEq(seqL, arrL.seqStream.toScala[Seq]) @@ -164,6 +202,14 @@ class StreamConvertersTest { assertEq(seqL, abL.parStream.toScala[Seq]) assert(abL.seqStream.isInstanceOf[LongStream]) assert(abL.parStream.isInstanceOf[LongStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(wrL.seqStream.isInstanceOf[LongStream]) + assert(wrL.parStream.isInstanceOf[LongStream]) + assertEq(seqL, hsL.seqStream.toScala[Seq].sorted) + assertEq(seqL, hsL.parStream.toScala[Seq].sorted) + assert(hsL.seqStream.isInstanceOf[LongStream]) + assert(hsL.parStream.isInstanceOf[LongStream]) } } } From a482301da344b53f643796fe4b05ffa0264ccc71 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 3 Oct 2015 18:30:07 -0700 Subject: [PATCH 20/56] Vector works with Stepper, and if you use the raw Stepper interface it's 10% faster than Iterator. --- .../java8/runtime/CollectionInternals.java | 6 + .../scala/compat/java8/StepConverters.scala | 137 ++++++++++++++++++ .../scala/compat/java8/StreamConverters.scala | 28 ++++ .../compat/java8/StreamConvertersTest.scala | 24 ++- 4 files changed, 194 insertions(+), 1 deletion(-) diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index 82af37b..1f30ea3 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -2,4 +2,10 @@ public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } + public static Object[] getDisplay0(scala.collection.immutable.Vector v) { return v.display0(); } + public static Object[] getDisplay1(scala.collection.immutable.Vector v) { return v.display1(); } + public static Object[] getDisplay2(scala.collection.immutable.Vector v) { return v.display2(); } + public static Object[] getDisplay3(scala.collection.immutable.Vector v) { return v.display3(); } + public static Object[] getDisplay4(scala.collection.immutable.Vector v) { return v.display4(); } + public static Object[] getDisplay5(scala.collection.immutable.Vector v) { return v.display5(); } } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 6b82ac6..e68686e 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -3,6 +3,7 @@ package scala.compat.java8 import language.implicitConversions import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ package converterImpls { import Stepper._ @@ -97,6 +98,125 @@ package converterImpls { def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } + private[java8] trait StepsVectorLike[A] { + protected def myVector: Vector[A] + protected var index: Int = 32 + protected var data: Array[AnyRef] = null + protected var index1: Int = 32 + protected var data1: Array[AnyRef] = null + protected final def advanceData(iX: Int) { + index1 += 1 + if (index >= 32) initTo(iX) + else { + data = data1(index1).asInstanceOf[Array[AnyRef]] + index = 0 + } + } + protected final def initTo(iX: Int) { + myVector.length match { + case x if x <= 0x20 => + index = iX + data = CollectionInternals.getDisplay0(myVector) + case x if x <= 0x400 => + index1 = iX >>> 5 + data1 = CollectionInternals.getDisplay1(myVector) + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + case x => + var N = 0 + var dataN: Array[AnyRef] = + if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } + else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } + else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } + else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } + while (N > 2) { + dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] + N -= 1 + } + index1 = (iX >>> 5) & 0x1F + data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + } + } + } + + private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, Vector[A], StepsAnyVector[A]](underlying, _i0, _iN) + with StepsVectorLike[A] { + protected def myVector = underlying + def next() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[A] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsAnyVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + + private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[Vector[Double], StepsDoubleVector](underlying, _i0, _iN) + with StepsVectorLike[Double] { + protected def myVector = underlying + def nextDouble() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Double] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsDoubleVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + + private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[Vector[Int], StepsIntVector](underlying, _i0, _iN) + with StepsVectorLike[Int] { + protected def myVector = underlying + def nextInt() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Int] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsIntVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + + private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[Vector[Long], StepsLongVector](underlying, _i0, _iN) + with StepsVectorLike[Long] { + protected def myVector = underlying + def nextLong() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Long] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsLongVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } @@ -169,6 +289,10 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) } + final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyVector[A](underlying, 0, underlying.length) + } + final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = { val tbl = runtime.CollectionInternals.getTable(underlying) @@ -244,6 +368,7 @@ package converterImpls { implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) + implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) } } @@ -263,6 +388,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: LongStepper = new StepsLongArray(underlying, 0, underlying.length) } + implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) + } + + implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntVector(underlying, 0, underlying.length) + } + + implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongVector(underlying, 0, underlying.length) + } + implicit class RichStringCanStep(val underlying: String) extends AnyVal { @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 435248c..80e0da1 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -75,6 +75,13 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = someStream(true) } + implicit class EnrichAnyVectorWithStream[A](c: Vector[A]) { + private def someStream(parallel: Boolean): Stream[A] = + StreamSupport.stream(new converterImpls.StepsAnyVector[A](c, 0, c.length), parallel) + def seqStream: Stream[A] = someStream(false) + def parStream: Stream[A] = someStream(true) + } + implicit class EnrichGenericFlatHashTableWithStream[A](fht: collection.mutable.FlatHashTable[A]) { private def someStream(parallel: Boolean): Stream[A] = { val tbl = runtime.CollectionInternals.getTable(fht) @@ -161,6 +168,27 @@ object StreamConverters extends Priority1StreamConverters { def parStream: LongStream = someStream(true) } + implicit class EnrichDoubleVectorWithStream(c: Vector[Double]) { + private def someStream(parallel: Boolean): DoubleStream = + StreamSupport.doubleStream(new converterImpls.StepsDoubleVector(c, 0, c.length), parallel) + def seqStream: DoubleStream = someStream(false) + def parStream: DoubleStream = someStream(true) + } + + implicit class EnrichIntVectorWithStream(c: Vector[Int]) { + private def someStream(parallel: Boolean): IntStream = + StreamSupport.intStream(new converterImpls.StepsIntVector(c, 0, c.length), parallel) + def seqStream: IntStream = someStream(false) + def parStream: IntStream = someStream(true) + } + + implicit class EnrichLongVectorWithStream(c: Vector[Long]) { + private def someStream(parallel: Boolean): LongStream = + StreamSupport.longStream(new converterImpls.StepsLongVector(c, 0, c.length), parallel) + def seqStream: LongStream = someStream(false) + def parStream: LongStream = someStream(true) + } + implicit class EnrichDoubleFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Double]) { private def someStream(parallel: Boolean): DoubleStream = { val tbl = runtime.CollectionInternals.getTable(fht) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 4c4c0ad..9a5b7f9 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -113,12 +113,16 @@ class StreamConvertersTest { def wrapD(n: Int): WrappedArray[Double] = arrayD(n) def wrapI(n: Int): WrappedArray[Int] = arrayI(n) def wrapL(n: Int): WrappedArray[Long] = arrayL(n) + def vectO(n: Int) = arrayO(n).toVector + def vectD(n: Int) = arrayD(n).toVector + def vectI(n: Int) = arrayI(n).toVector + def vectL(n: Int) = arrayL(n).toVector def genhset[A](aa: Array[A]) = { val hs = new collection.mutable.HashSet[A]; aa.foreach(hs += _); hs } def hsetO(n: Int) = genhset(arrayO(n)) def hsetD(n: Int) = genhset(arrayD(n)) def hsetI(n: Int) = genhset(arrayI(n)) def hsetL(n: Int) = genhset(arrayL(n)) - + @Test def scalaToStream() { for (n <- ns) { @@ -126,6 +130,7 @@ class StreamConvertersTest { val seqO = arrO.toSeq val abO = abufO(n) val wrO = wrapO(n) + val vecO = vectO(n) val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) @@ -136,6 +141,8 @@ class StreamConvertersTest { assertEq(seqO, abO.parStream.toScala[Seq]) assertEq(seqO, wrO.seqStream.toScala[Seq]) assertEq(seqO, wrO.parStream.toScala[Seq]) + assertEq(seqO, vecO.seqStream.toScala[Seq]) + assertEq(seqO, vecO.parStream.toScala[Seq]) assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) @@ -143,6 +150,7 @@ class StreamConvertersTest { val seqD = arrD.toSeq val abD = abufD(n) val wrD = wrapD(n) + val vecD = vectD(n) val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) assertEq(seqD, seqD.parStream.toScala[Seq]) @@ -158,6 +166,10 @@ class StreamConvertersTest { assertEq(seqD, wrD.parStream.toScala[Seq]) assert(wrD.seqStream.isInstanceOf[DoubleStream]) assert(wrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, vecD.seqStream.toScala[Seq]) + assertEq(seqD, vecD.parStream.toScala[Seq]) + assert(vecD.seqStream.isInstanceOf[DoubleStream]) + assert(vecD.parStream.isInstanceOf[DoubleStream]) assertEq(seqD, hsD.seqStream.toScala[Seq].sorted) assertEq(seqD, hsD.parStream.toScala[Seq].sorted) assert(hsD.seqStream.isInstanceOf[DoubleStream]) @@ -167,6 +179,7 @@ class StreamConvertersTest { val seqI = arrI.toSeq val abI = abufI(n) val wrI = wrapI(n) + val vecI = vectI(n) val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) assertEq(seqI, seqI.parStream.toScala[Seq]) @@ -182,6 +195,10 @@ class StreamConvertersTest { assertEq(seqI, wrI.parStream.toScala[Seq]) assert(wrI.seqStream.isInstanceOf[IntStream]) assert(wrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, vecI.seqStream.toScala[Seq]) + assertEq(seqI, vecI.parStream.toScala[Seq]) + assert(vecI.seqStream.isInstanceOf[IntStream]) + assert(vecI.parStream.isInstanceOf[IntStream]) assertEq(seqI, hsI.seqStream.toScala[Seq].sorted) assertEq(seqI, hsI.parStream.toScala[Seq].sorted) assert(hsI.seqStream.isInstanceOf[IntStream]) @@ -191,6 +208,7 @@ class StreamConvertersTest { val seqL = arrL.toSeq val abL = abufL(n) val wrL = wrapL(n) + val vecL = vectL(n) val hsL = hsetL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) assertEq(seqL, seqL.parStream.toScala[Seq]) @@ -206,6 +224,10 @@ class StreamConvertersTest { assertEq(seqD, wrD.parStream.toScala[Seq]) assert(wrL.seqStream.isInstanceOf[LongStream]) assert(wrL.parStream.isInstanceOf[LongStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(vecL.seqStream.isInstanceOf[LongStream]) + assert(vecL.parStream.isInstanceOf[LongStream]) assertEq(seqL, hsL.seqStream.toScala[Seq].sorted) assertEq(seqL, hsL.parStream.toScala[Seq].sorted) assert(hsL.seqStream.isInstanceOf[LongStream]) From 4c72bd92afc1fef696a97f05701a8976d9173b46 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 6 Oct 2015 18:26:29 -0700 Subject: [PATCH 21/56] Added a bunch of comprehensiveness tests to StepConvertersTests. (Right now we don't do so well at covering them, though.) --- .../scala/compat/java8/StepConverters.scala | 22 ++- .../compat/java8/StepConvertersTest.scala | 151 ++++++++++++++++++ 2 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 src/test/scala/scala/compat/java8/StepConvertersTest.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index e68686e..8951fc2 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -344,10 +344,28 @@ package converterImpls { else null } } + + final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { + def stepper: Stepper[A] = { + val acc = new Accumulator[A] + underlying.foreach(acc += _) + acc.stepper + } + } + + trait Priority5StepConverters { + implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) + } + + trait Priority4StepConverters extends Priority5StepConverters { + implicit def richLikeIndexedSeqOptimizedCanStep[A, DD, CC[A, DD] <: collection.IndexedSeqOptimized[A, DD]](underlying: CC[A, DD]) = + new RichIndexedSeqOptimizedCanStep[A, CC[A, DD]](underlying) + } - trait Priority3StepConverters { + trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC) = new RichIndexedSeqOptimizedCanStep[A, CC](underlying) + implicit def richIndexedSeqOptimizedCanStep[A, CC[A] <: collection.IndexedSeqOptimized[A, CC[A]]](underlying: CC[A]) = + new RichIndexedSeqOptimizedCanStep[A, CC[A]](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala new file mode 100644 index 0000000..3df0297 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -0,0 +1,151 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StepConvertersTest { + import java.util._ + import collectionImpl._ + import StepConverters._ + import scala.{ collection => co } + import collection.{ mutable => cm, immutable => ci, generic => cg } + + def isAcc[X](x: X) = x match { + case _: AccumulatorStepper[_] => true + case _: DoubleAccumulatorStepper => true + case _: IntAccumulatorStepper => true + case _: LongAccumulatorStepper => true + case _ => false + } + + def _eh_[X](x: => X) { IFFY(x) } + + def IFFY[X](x: => X) { + assert(x.isInstanceOf[Stepper[_]]) + assert(isAcc(x)) + } + + def good[X](x: => X) { + assert(x.isInstanceOf[Stepper[_]]) + assert(!isAcc(x)) + } + + @Test + def comprehensivelyGeneric() { + // Collection section + IFFY( co.Iterator[String]("salmon").buffered.stepper ) + IFFY( co.IndexedSeq[String]("salmon").stepper ) + IFFY( co.Iterable[String]("salmon").stepper ) + IFFY( co.Iterable[String]("salmon").view.stepper ) + IFFY( co.Iterator[String]("salmon").stepper ) + IFFY( co.LinearSeq[String]("salmon").stepper ) + IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) + IFFY( co.Seq[String]("salmon").stepper ) + IFFY( co.Seq[String]("salmon").view.stepper ) + IFFY( co.Set[String]("salmon").stepper ) + IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + IFFY( co.SortedSet[String]("salmon").stepper ) + IFFY( co.Traversable[String]("salmon").stepper ) + IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) + IFFY( co.Traversable[String]("salmon").view.stepper ) + + // Generic section + + // Immutable section + IFFY( ci.::("salmon", Nil).stepper ) + IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.HashSet[String]("salmon").stepper ) + IFFY( ci.IndexedSeq[String]("salmon").stepper ) + IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) + IFFY( ci.Iterable[String]("salmon").stepper ) + IFFY( ci.LinearSeq[String]("salmon").stepper ) + IFFY( ci.List[String]("salmon").stepper ) + IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.ListSet[String]("salmon").stepper ) + IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) + IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.Queue[String]("salmon").stepper ) + IFFY( ci.Seq[String]("salmon").stepper ) + IFFY( ci.Set[String]("salmon").stepper ) + IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.SortedSet[String]("salmon").stepper ) + IFFY( ci.Stack[String]("salmon").stepper ) + IFFY( ci.Stream[String]("salmon").stepper ) + IFFY( ci.Stream[String]("salmon").view.stepper ) + IFFY( ci.Traversable[String]("salmon").stepper ) + IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.TreeSet[String]("salmon").stepper ) + good( ci.Vector[String]("salmon").stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) + IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) + IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) + IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) + IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + good( cm.ArrayBuffer[String]("salmon").stepper ) + good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) + good( (Array("salmon"): cm.ArrayOps[String]).stepper ) + good( cm.ArraySeq[String]("salmon").stepper ) + _eh_( cm.ArrayStack[String]("salmon").stepper ) + IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) + IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashSet[String]("salmon").stepper ) + IFFY( cm.IndexedSeq[String]("salmon").stepper ) + IFFY( cm.IndexedSeq[String]("salmon").view.stepper ) + IFFY( cm.Iterable[String]("salmon").stepper ) + IFFY( cm.LinearSeq[String]("salmon").stepper ) + IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.LinkedHashSet[String]("salmon").stepper ) + IFFY( cm.ListBuffer[String]("salmon").stepper ) + IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) + IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.MutableList[String]("salmon").stepper ) + IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.PriorityQueue[String]("salmon").stepper ) + IFFY( cm.Queue[String]("salmon").stepper ) + good( cm.ResizableArray[String]("salmon").stepper ) + IFFY( cm.Seq[String]("salmon").stepper ) + IFFY( cm.Set[String]("salmon").stepper ) + IFFY( cm.SortedSet[String]("salmon").stepper ) + IFFY( cm.Stack[String]("salmon").stepper ) + IFFY( cm.Traversable[String]("salmon").stepper ) + IFFY( cm.TreeSet[String]("salmon").stepper ) + IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) + IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + good( (Array("salmon"): cm.WrappedArray[String]).stepper ) + + // Java 6 converters section + + // Concurrent section + } + + @Test + def comprehensivelyDouble() { + } + + @Test + def comprehensivelyInt() { + // Int-specific tests + IFFY( co.BitSet(42).stepper ) + IFFY( ci.BitSet(42).stepper ) + IFFY( cm.BitSet(42).stepper ) + IFFY( (1 until 2).stepper ) + } + + @Test + def comprehensivelyLong() { + // Long-specific tests + IFFY( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + } + + @Test + def comprehensivelySpecific() { + IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) + good( ("salmon": ci.StringOps).stepper ) + good( ("salmon": ci.WrappedString).stepper ) + } +} From 40c0117cf4be435016b59357ff5162d8c8857616 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 6 Oct 2015 20:53:07 -0700 Subject: [PATCH 22/56] Ranges step quickly. Nearly complete coverage testing for generics. --- .../scala/compat/java8/StepConverters.scala | 43 ++++++++++++++++++- .../compat/java8/StepConvertersTest.scala | 13 +++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 8951fc2..56373f6 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -98,6 +98,30 @@ package converterImpls { def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } + private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[Range, StepsIntRange](underlying, _i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) + } + + private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) + extends StepsLikeIndexed[T, collection.immutable.NumericRange[T], StepsAnyNumericRange[T]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) + } + + private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[collection.immutable.NumericRange[Int], StepsIntNumericRange](underlying, _i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) + } + + private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[collection.immutable.NumericRange[Long], StepsLongNumericRange](underlying, _i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) + } + private[java8] trait StepsVectorLike[A] { protected def myVector: Vector[A] protected var index: Int = 32 @@ -289,6 +313,10 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) } + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { + @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) + } + final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyVector[A](underlying, 0, underlying.length) } @@ -383,10 +411,11 @@ package converterImpls { new RichIntIndexedSeqOptimizedCanStep[CC](underlying) implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = new RichLongIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) + implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) - implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) } } @@ -410,6 +439,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) } + implicit final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntNumericRange(underlying, 0, underlying.length) + } + + implicit final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongNumericRange(underlying, 0, underlying.length) + } + + implicit final class RichRangeCanStep(private val underlying: Range) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntRange(underlying, 0, underlying.length) + } + implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal { @inline def stepper: IntStepper = new StepsIntVector(underlying, 0, underlying.length) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 3df0297..9d7d66a 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -8,7 +8,7 @@ class StepConvertersTest { import collectionImpl._ import StepConverters._ import scala.{ collection => co } - import collection.{ mutable => cm, immutable => ci, generic => cg } + import collection.{ mutable => cm, immutable => ci, concurrent => cc } def isAcc[X](x: X) = x match { case _: AccumulatorStepper[_] => true @@ -49,8 +49,6 @@ class StepConvertersTest { IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) IFFY( co.Traversable[String]("salmon").view.stepper ) - // Generic section - // Immutable section IFFY( ci.::("salmon", Nil).stepper ) IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) @@ -121,10 +119,13 @@ class StepConvertersTest { // Java 6 converters section // Concurrent section + IFFY( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + IFFY( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) } @Test def comprehensivelyDouble() { + //Double-specific tests } @Test @@ -132,18 +133,20 @@ class StepConvertersTest { // Int-specific tests IFFY( co.BitSet(42).stepper ) IFFY( ci.BitSet(42).stepper ) + good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) - IFFY( (1 until 2).stepper ) + good( (1 until 2).stepper ) } @Test def comprehensivelyLong() { // Long-specific tests - IFFY( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) } @Test def comprehensivelySpecific() { + good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) good( ("salmon": ci.WrappedString).stepper ) From 4013be65f1233404adfc3311583dec4536c47954 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 7 Oct 2015 17:52:53 -0700 Subject: [PATCH 23/56] Filled in all the stepper tests and simplifed IndexedSeqOptimized dispatching. --- .../scala/compat/java8/StepConverters.scala | 45 ++- .../scala/compat/java8/StreamConverters.scala | 4 +- .../compat/java8/StepConvertersTest.scala | 302 +++++++++++++++++- 3 files changed, 334 insertions(+), 17 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 56373f6..767d218 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -74,10 +74,10 @@ package converterImpls { def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } - private[java8] class StepsAnyIndexedSeqOptimized[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, CC, StepsAnyIndexedSeqOptimized[A, CC]](underlying, _i0, _iN) { + private[java8] class StepsAnyIndexedSeqOptimized[A](underlying: collection.IndexedSeqOptimized[A, _], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, collection.IndexedSeqOptimized[A, _], StepsAnyIndexedSeqOptimized[A]](underlying, _i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A, CC](underlying, i0, half) + def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A](underlying, i0, half) } private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) @@ -297,8 +297,8 @@ package converterImpls { @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } - final class RichIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A, CC](underlying, 0, underlying.length) + final class RichIndexedSeqOptimizedCanStep[A](private val underlying: collection.IndexedSeqOptimized[A, _]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A](underlying, 0, underlying.length) } final class RichDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](private val underlying: CC) extends AnyVal { @@ -374,26 +374,51 @@ package converterImpls { } final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def stepper: Stepper[A] = { + def stepper: AnyStepper[A] = { val acc = new Accumulator[A] underlying.foreach(acc += _) acc.stepper } } + final class RichDoubleTraversableOnceCanStep(private val underlying: TraversableOnce[Double]) extends AnyVal { + def stepper: DoubleStepper = { + val acc = new DoubleAccumulator + underlying.foreach(acc += _) + acc.stepper + } + } + + final class RichIntTraversableOnceCanStep(private val underlying: TraversableOnce[Int]) extends AnyVal { + def stepper: IntStepper = { + val acc = new IntAccumulator + underlying.foreach(acc += _) + acc.stepper + } + } + + final class RichLongTraversableOnceCanStep(private val underlying: TraversableOnce[Long]) extends AnyVal { + def stepper: LongStepper = { + val acc = new LongAccumulator + underlying.foreach(acc += _) + acc.stepper + } + } + trait Priority5StepConverters { implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) } trait Priority4StepConverters extends Priority5StepConverters { - implicit def richLikeIndexedSeqOptimizedCanStep[A, DD, CC[A, DD] <: collection.IndexedSeqOptimized[A, DD]](underlying: CC[A, DD]) = - new RichIndexedSeqOptimizedCanStep[A, CC[A, DD]](underlying) + implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) + implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) + implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) } trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqOptimizedCanStep[A, CC[A] <: collection.IndexedSeqOptimized[A, CC[A]]](underlying: CC[A]) = - new RichIndexedSeqOptimizedCanStep[A, CC[A]](underlying) + implicit def richIndexedSeqOptimizedCanStep[A](underlying: collection.IndexedSeqOptimized[A, _]) = + new RichIndexedSeqOptimizedCanStep[A](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 80e0da1..6a21437 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -68,9 +68,9 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = seqStream.parallel } - implicit class EnrichGenericIndexedSeqOptimizedWithStream[A, CC <: collection.IndexedSeqOptimized[A, _]](c: CC) { + implicit class EnrichGenericIndexedSeqOptimizedWithStream[A](c: collection.IndexedSeqOptimized[A, _]) { private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A, CC](c, 0, c.length), parallel) + StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A](c, 0, c.length), parallel) def seqStream: Stream[A] = someStream(false) def parStream: Stream[A] = someStream(true) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 9d7d66a..eb65c97 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -18,20 +18,35 @@ class StepConvertersTest { case _ => false } - def _eh_[X](x: => X) { IFFY(x) } + trait SpecCheck { def apply[X](x: X): Boolean } + object SpecCheck { + def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } + } + + def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { IFFY(x)(correctSpec) } - def IFFY[X](x: => X) { + def IFFY[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) assert(isAcc(x)) } - def good[X](x: => X) { + def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) assert(!isAcc(x)) } + def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { + println(x.getClass.getName + " -> " + isAcc(x)) + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + } + @Test def comprehensivelyGeneric() { + implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + // Collection section IFFY( co.Iterator[String]("salmon").buffered.stepper ) IFFY( co.IndexedSeq[String]("salmon").stepper ) @@ -92,7 +107,7 @@ class StepConvertersTest { IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) good( cm.HashSet[String]("salmon").stepper ) IFFY( cm.IndexedSeq[String]("salmon").stepper ) - IFFY( cm.IndexedSeq[String]("salmon").view.stepper ) + good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) IFFY( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) @@ -125,27 +140,304 @@ class StepConvertersTest { @Test def comprehensivelyDouble() { + implicit val spec = SpecCheck(_.isInstanceOf[DoubleStepper]) //Double-specific tests + + // Collection section + IFFY( co.Iterator[Double](3.14159).buffered.stepper ) + IFFY( co.IndexedSeq[Double](3.14159).stepper ) + IFFY( co.Iterable[Double](3.14159).stepper ) + IFFY( co.Iterable[Double](3.14159).view.stepper ) + IFFY( co.Iterator[Double](3.14159).stepper ) + IFFY( co.LinearSeq[Double](3.14159).stepper ) + //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( co.Seq[Double](3.14159).stepper ) + IFFY( co.Seq[Double](3.14159).view.stepper ) + IFFY( co.Set[Double](3.14159).stepper ) + //IFFY( co.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( co.SortedSet[Double](3.14159).stepper ) + IFFY( co.Traversable[Double](3.14159).stepper ) + IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) + IFFY( co.Traversable[Double](3.14159).view.stepper ) + + // Immutable section + IFFY( ci.::(3.14159, Nil).stepper ) + //IFFY( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).stepper ) + //IFFY( ci.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.HashSet[Double](3.14159).stepper ) + IFFY( ci.IndexedSeq[Double](3.14159).stepper ) + //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) + IFFY( ci.Iterable[Double](3.14159).stepper ) + IFFY( ci.LinearSeq[Double](3.14159).stepper ) + IFFY( ci.List[Double](3.14159).stepper ) + //IFFY( ci.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.ListSet[Double](3.14159).stepper ) + //IFFY( ci.LongMap[Double](9876543210L -> 3.14159).stepper ) + //IFFY( ci.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.Queue[Double](3.14159).stepper ) + IFFY( ci.Seq[Double](3.14159).stepper ) + IFFY( ci.Set[Double](3.14159).stepper ) + //IFFY( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.SortedSet[Double](3.14159).stepper ) + IFFY( ci.Stack[Double](3.14159).stepper ) + IFFY( ci.Stream[Double](3.14159).stepper ) + IFFY( ci.Stream[Double](3.14159).view.stepper ) + IFFY( ci.Traversable[Double](3.14159).stepper ) + //IFFY( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.TreeSet[Double](3.14159).stepper ) + good( ci.Vector[Double](3.14159).stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) + IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) + //IFFY( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).stepper ) + IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) + IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) + //IFFY( cm.AnyRefMap[Double,Double](2.718281828 -> 3.14159).stepper ) + good( cm.ArrayBuffer[Double](3.14159).stepper ) + good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) + good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) + good( cm.ArraySeq[Double](3.14159).stepper ) + _eh_( cm.ArrayStack[Double](3.14159).stepper ) + IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) + //IFFY( cm.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.HashSet[Double](3.14159).stepper ) + IFFY( cm.IndexedSeq[Double](3.14159).stepper ) + good( cm.IndexedSeq[Double](3.14159).view.stepper ) + IFFY( cm.Iterable[Double](3.14159).stepper ) + IFFY( cm.LinearSeq[Double](3.14159).stepper ) + //IFFY( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) + IFFY( cm.ListBuffer[Double](3.14159).stepper ) + //IFFY( cm.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) + //IFFY( cm.LongMap[Double](9876543210L -> 3.14159).stepper ) + //IFFY( cm.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( cm.MutableList[Double](3.14159).stepper ) + //IFFY( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( cm.PriorityQueue[Double](3.14159).stepper ) + IFFY( cm.Queue[Double](3.14159).stepper ) + good( cm.ResizableArray[Double](3.14159).stepper ) + IFFY( cm.Seq[Double](3.14159).stepper ) + IFFY( cm.Set[Double](3.14159).stepper ) + IFFY( cm.SortedSet[Double](3.14159).stepper ) + IFFY( cm.Stack[Double](3.14159).stepper ) + IFFY( cm.Traversable[Double](3.14159).stepper ) + IFFY( cm.TreeSet[Double](3.14159).stepper ) + IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) + //IFFY( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) + + // Java 6 converters section + + // Concurrent section + //IFFY( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).stepper ) + //IFFY( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).stepper ) } @Test def comprehensivelyInt() { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) + // Int-specific tests IFFY( co.BitSet(42).stepper ) IFFY( ci.BitSet(42).stepper ) good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) + + // Collection section + IFFY( co.Iterator[Int](654321).buffered.stepper ) + IFFY( co.IndexedSeq[Int](654321).stepper ) + IFFY( co.Iterable[Int](654321).stepper ) + IFFY( co.Iterable[Int](654321).view.stepper ) + IFFY( co.Iterator[Int](654321).stepper ) + IFFY( co.LinearSeq[Int](654321).stepper ) + //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( co.Seq[Int](654321).stepper ) + IFFY( co.Seq[Int](654321).view.stepper ) + IFFY( co.Set[Int](654321).stepper ) + //IFFY( co.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( co.SortedSet[Int](654321).stepper ) + IFFY( co.Traversable[Int](654321).stepper ) + IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) + IFFY( co.Traversable[Int](654321).view.stepper ) + + // Immutable section + IFFY( ci.::(654321, Nil).stepper ) + //IFFY( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).stepper ) + //IFFY( ci.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.HashSet[Int](654321).stepper ) + IFFY( ci.IndexedSeq[Int](654321).stepper ) + //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) + IFFY( ci.Iterable[Int](654321).stepper ) + IFFY( ci.LinearSeq[Int](654321).stepper ) + IFFY( ci.List[Int](654321).stepper ) + //IFFY( ci.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.ListSet[Int](654321).stepper ) + //IFFY( ci.LongMap[Int](9876543210L -> 654321).stepper ) + //IFFY( ci.Map[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.Queue[Int](654321).stepper ) + IFFY( ci.Seq[Int](654321).stepper ) + IFFY( ci.Set[Int](654321).stepper ) + //IFFY( ci.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.SortedSet[Int](654321).stepper ) + IFFY( ci.Stack[Int](654321).stepper ) + IFFY( ci.Stream[Int](654321).stepper ) + IFFY( ci.Stream[Int](654321).view.stepper ) + IFFY( ci.Traversable[Int](654321).stepper ) + //IFFY( ci.TreeMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.TreeSet[Int](654321).stepper ) + good( ci.Vector[Int](654321).stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) + IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) + //IFFY( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).stepper ) + IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) + IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) + //IFFY( cm.AnyRefMap[Int,Int](0xDEEDED -> 654321).stepper ) + good( cm.ArrayBuffer[Int](654321).stepper ) + good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) + good( (Array(654321): cm.ArrayOps[Int]).stepper ) + good( cm.ArraySeq[Int](654321).stepper ) + _eh_( cm.ArrayStack[Int](654321).stepper ) + IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) + //IFFY( cm.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.HashSet[Int](654321).stepper ) + IFFY( cm.IndexedSeq[Int](654321).stepper ) + good( cm.IndexedSeq[Int](654321).view.stepper ) + IFFY( cm.Iterable[Int](654321).stepper ) + IFFY( cm.LinearSeq[Int](654321).stepper ) + //IFFY( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( cm.LinkedHashSet[Int](654321).stepper ) + IFFY( cm.ListBuffer[Int](654321).stepper ) + //IFFY( cm.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) + //IFFY( cm.LongMap[Int](9876543210L -> 654321).stepper ) + //IFFY( cm.Map[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( cm.MutableList[Int](654321).stepper ) + //IFFY( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( cm.PriorityQueue[Int](654321).stepper ) + IFFY( cm.Queue[Int](654321).stepper ) + good( cm.ResizableArray[Int](654321).stepper ) + IFFY( cm.Seq[Int](654321).stepper ) + IFFY( cm.Set[Int](654321).stepper ) + IFFY( cm.SortedSet[Int](654321).stepper ) + IFFY( cm.Stack[Int](654321).stepper ) + IFFY( cm.Traversable[Int](654321).stepper ) + IFFY( cm.TreeSet[Int](654321).stepper ) + IFFY( cm.UnrolledBuffer[Int](654321).stepper ) + //IFFY( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( (Array(654321): cm.WrappedArray[Int]).stepper ) + + // Java 6 converters section + + // Concurrent section + //IFFY( cc.TrieMap[Int, Int](0xDEEDED -> 654321).stepper ) + //IFFY( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).stepper ) } @Test def comprehensivelyLong() { + implicit val spec = SpecCheck(_.isInstanceOf[LongStepper]) + // Long-specific tests good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) - } + + // Collection section + IFFY( co.Iterator[Long](0x123456789L).buffered.stepper ) + IFFY( co.IndexedSeq[Long](0x123456789L).stepper ) + IFFY( co.Iterable[Long](0x123456789L).stepper ) + IFFY( co.Iterable[Long](0x123456789L).view.stepper ) + IFFY( co.Iterator[Long](0x123456789L).stepper ) + IFFY( co.LinearSeq[Long](0x123456789L).stepper ) + //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( co.Seq[Long](0x123456789L).stepper ) + IFFY( co.Seq[Long](0x123456789L).view.stepper ) + IFFY( co.Set[Long](0x123456789L).stepper ) + //IFFY( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( co.SortedSet[Long](0x123456789L).stepper ) + IFFY( co.Traversable[Long](0x123456789L).stepper ) + IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) + IFFY( co.Traversable[Long](0x123456789L).view.stepper ) + + // Immutable section + IFFY( ci.::(0x123456789L, Nil).stepper ) + //IFFY( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).stepper ) + //IFFY( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.HashSet[Long](0x123456789L).stepper ) + IFFY( ci.IndexedSeq[Long](0x123456789L).stepper ) + //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) + IFFY( ci.Iterable[Long](0x123456789L).stepper ) + IFFY( ci.LinearSeq[Long](0x123456789L).stepper ) + IFFY( ci.List[Long](0x123456789L).stepper ) + //IFFY( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.ListSet[Long](0x123456789L).stepper ) + //IFFY( ci.LongMap[Long](9876543210L -> 0x123456789L).stepper ) + //IFFY( ci.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.Queue[Long](0x123456789L).stepper ) + IFFY( ci.Seq[Long](0x123456789L).stepper ) + IFFY( ci.Set[Long](0x123456789L).stepper ) + //IFFY( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.SortedSet[Long](0x123456789L).stepper ) + IFFY( ci.Stack[Long](0x123456789L).stepper ) + IFFY( ci.Stream[Long](0x123456789L).stepper ) + IFFY( ci.Stream[Long](0x123456789L).view.stepper ) + IFFY( ci.Traversable[Long](0x123456789L).stepper ) + //IFFY( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.TreeSet[Long](0x123456789L).stepper ) + good( ci.Vector[Long](0x123456789L).stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) + IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) + //IFFY( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).stepper ) + IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) + IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) + //IFFY( cm.AnyRefMap[Long,Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.ArrayBuffer[Long](0x123456789L).stepper ) + good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) + good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) + good( cm.ArraySeq[Long](0x123456789L).stepper ) + _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) + IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) + //IFFY( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.HashSet[Long](0x123456789L).stepper ) + IFFY( cm.IndexedSeq[Long](0x123456789L).stepper ) + good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) + IFFY( cm.Iterable[Long](0x123456789L).stepper ) + IFFY( cm.LinearSeq[Long](0x123456789L).stepper ) + //IFFY( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) + IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) + //IFFY( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + //IFFY( cm.LongMap[Long](9876543210L -> 0x123456789L).stepper ) + //IFFY( cm.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( cm.MutableList[Long](0x123456789L).stepper ) + //IFFY( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) + IFFY( cm.Queue[Long](0x123456789L).stepper ) + good( cm.ResizableArray[Long](0x123456789L).stepper ) + IFFY( cm.Seq[Long](0x123456789L).stepper ) + IFFY( cm.Set[Long](0x123456789L).stepper ) + IFFY( cm.SortedSet[Long](0x123456789L).stepper ) + IFFY( cm.Stack[Long](0x123456789L).stepper ) + IFFY( cm.Traversable[Long](0x123456789L).stepper ) + IFFY( cm.TreeSet[Long](0x123456789L).stepper ) + IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) + //IFFY( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) + + // Java 6 converters section + + // Concurrent section + //IFFY( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + //IFFY( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).stepper ) + } @Test def comprehensivelySpecific() { + implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) From e4c18a3a5c3ee4bca8a7b8e9f3140c9cffd1f671 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 7 Oct 2015 20:25:26 -0700 Subject: [PATCH 24/56] Simplified StepsLikeIndexed implementation. --- .../scala/compat/java8/StepConverters.scala | 46 +++++++++---------- .../collectionImpl/StepsLikeIndexed.scala | 8 ++-- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 767d218..531561b 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -9,115 +9,115 @@ package converterImpls { import Stepper._ private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, Array[A], StepsObjectArray[A]](underlying, _i0, _iN) { + extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) } private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, Array[A], StepsAnyArray[A]](underlying, _i0, _iN) { + extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) } private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Unit, Array[Unit], StepsUnitArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) } private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Boolean, Array[Boolean], StepsBoxedBooleanArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) } private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Byte, Array[Byte], StepsBoxedByteArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) } private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Char, Array[Char], StepsBoxedCharArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) } private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Short, Array[Short], StepsBoxedShortArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) } private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Float, Array[Float], StepsBoxedFloatArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) } private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[Array[Double], StepsDoubleArray](underlying, _i0, _iN) { + extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) } private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[Array[Int], StepsIntArray](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) } private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[Array[Long], StepsLongArray](underlying, _i0, _iN) { + extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } private[java8] class StepsAnyIndexedSeqOptimized[A](underlying: collection.IndexedSeqOptimized[A, _], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, collection.IndexedSeqOptimized[A, _], StepsAnyIndexedSeqOptimized[A]](underlying, _i0, _iN) { + extends StepsLikeIndexed[A, StepsAnyIndexedSeqOptimized[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A](underlying, i0, half) } private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[CC, StepsDoubleIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeqOptimized[CC]](_i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsDoubleIndexedSeqOptimized[CC](underlying, i0, half) } private[java8] class StepsIntIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[CC, StepsIntIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntIndexedSeqOptimized[CC]](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntIndexedSeqOptimized[CC](underlying, i0, half) } private[java8] class StepsLongIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[CC, StepsLongIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + extends StepsLongLikeIndexed[StepsLongIndexedSeqOptimized[CC]](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[Range, StepsIntRange](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) } private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) - extends StepsLikeIndexed[T, collection.immutable.NumericRange[T], StepsAnyNumericRange[T]](underlying, _i0, _iN) { + extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) } private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[collection.immutable.NumericRange[Int], StepsIntNumericRange](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) } private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[collection.immutable.NumericRange[Long], StepsLongNumericRange](underlying, _i0, _iN) { + extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) } @@ -166,7 +166,7 @@ package converterImpls { } private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, Vector[A], StepsAnyVector[A]](underlying, _i0, _iN) + extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) with StepsVectorLike[A] { protected def myVector = underlying def next() = if (hasNext()) { @@ -185,7 +185,7 @@ package converterImpls { } private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[Vector[Double], StepsDoubleVector](underlying, _i0, _iN) + extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) with StepsVectorLike[Double] { protected def myVector = underlying def nextDouble() = if (hasNext()) { @@ -204,7 +204,7 @@ package converterImpls { } private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[Vector[Int], StepsIntVector](underlying, _i0, _iN) + extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) with StepsVectorLike[Int] { protected def myVector = underlying def nextInt() = if (hasNext()) { @@ -223,7 +223,7 @@ package converterImpls { } private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[Vector[Long], StepsLongVector](underlying, _i0, _iN) + extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) with StepsVectorLike[Long] { protected def myVector = underlying def nextLong() = if (hasNext()) { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index 208af7c..b9dfa55 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -21,25 +21,25 @@ abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var } /** Abstracts the operation of stepping over a generic indexable collection */ -abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, _i0: Int, _iN: Int) +abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ -abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, _i0: Int, _iN: Int) +abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper {} /** Abstracts the operation of stepping over an indexable collection of Ints */ -abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, _i0: Int, _iN: Int) +abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper {} /** Abstracts the operation of stepping over an indexable collection of Longs */ -abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, _i0: Int, _iN: Int) +abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper {} From 27e72aa9f6f44bd55aedcc3f1ec041899b9f7c77 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 7 Oct 2015 20:46:14 -0700 Subject: [PATCH 25/56] Added missing file! Also covered all of IndexedSeqLike. Note that almost all of IndexedSeqLike is Optimized (or should be) or I already have a workaround (e.g. Vector). --- .../scala/compat/java8/StepConverters.scala | 56 ++++++++-------- .../scala/compat/java8/StreamConverters.scala | 16 ++--- .../collectionImpl/StepsLikeGapped.scala | 66 +++++++++++++++++++ .../compat/java8/StepConvertersTest.scala | 31 +++++---- 4 files changed, 119 insertions(+), 50 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 531561b..ea7093b 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -74,28 +74,28 @@ package converterImpls { def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } - private[java8] class StepsAnyIndexedSeqOptimized[A](underlying: collection.IndexedSeqOptimized[A, _], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyIndexedSeqOptimized[A]](_i0, _iN) { + private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A](underlying, i0, half) + def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) } - private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeqOptimized[CC]](_i0, _iN) { + private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleIndexedSeqOptimized[CC](underlying, i0, half) + def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) } - private[java8] class StepsIntIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntIndexedSeqOptimized[CC]](_i0, _iN) { + private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntIndexedSeqOptimized[CC](underlying, i0, half) + def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) } - private[java8] class StepsLongIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongIndexedSeqOptimized[CC]](_i0, _iN) { + private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) + def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) } private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) @@ -297,20 +297,20 @@ package converterImpls { @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } - final class RichIndexedSeqOptimizedCanStep[A](private val underlying: collection.IndexedSeqOptimized[A, _]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A](underlying, 0, underlying.length) + final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) } - final class RichDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeqOptimized[CC](underlying, 0, underlying.length) + final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntIndexedSeqOptimized[CC](underlying, 0, underlying.length) + final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) + final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { @@ -417,8 +417,8 @@ package converterImpls { trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqOptimizedCanStep[A](underlying: collection.IndexedSeqOptimized[A, _]) = - new RichIndexedSeqOptimizedCanStep[A](underlying) + implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = + new RichIndexedSeqCanStep[A](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } @@ -430,12 +430,12 @@ package converterImpls { implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) - implicit def richDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC) = - new RichDoubleIndexedSeqOptimizedCanStep[CC](underlying) - implicit def richIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC) = - new RichIntIndexedSeqOptimizedCanStep[CC](underlying) - implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = - new RichLongIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = + new RichDoubleIndexedSeqCanStep[CC](underlying) + implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = + new RichIntIndexedSeqCanStep[CC](underlying) + implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = + new RichLongIndexedSeqCanStep[CC](underlying) implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 6a21437..d45a205 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -68,9 +68,9 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = seqStream.parallel } - implicit class EnrichGenericIndexedSeqOptimizedWithStream[A](c: collection.IndexedSeqOptimized[A, _]) { + implicit class EnrichGenericIndexedSeqWithStream[A](c: collection.IndexedSeqLike[A, _]) { private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A](c, 0, c.length), parallel) + StreamSupport.stream(new converterImpls.StepsAnyIndexedSeq[A](c, 0, c.length), parallel) def seqStream: Stream[A] = someStream(false) def parStream: Stream[A] = someStream(true) } @@ -147,23 +147,23 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * ``` */ object StreamConverters extends Priority1StreamConverters { - implicit class EnrichDoubleIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Double, _]](c: CC) { + implicit class EnrichDoubleIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Double, _]](c: CC) { private def someStream(parallel: Boolean): DoubleStream = - StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeqOptimized[CC](c, 0, c.length), parallel) + StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeq[CC](c, 0, c.length), parallel) def seqStream: DoubleStream = someStream(false) def parStream: DoubleStream = someStream(true) } - implicit class EnrichIntIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Int, _]](c: CC) { + implicit class EnrichIntIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Int, _]](c: CC) { private def someStream(parallel: Boolean): IntStream = - StreamSupport.intStream(new converterImpls.StepsIntIndexedSeqOptimized[CC](c, 0, c.length), parallel) + StreamSupport.intStream(new converterImpls.StepsIntIndexedSeq[CC](c, 0, c.length), parallel) def seqStream: IntStream = someStream(false) def parStream: IntStream = someStream(true) } - implicit class EnrichLongIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Long, _]](c: CC) { + implicit class EnrichLongIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Long, _]](c: CC) { private def someStream(parallel: Boolean): LongStream = - StreamSupport.longStream(new converterImpls.StepsLongIndexedSeqOptimized[CC](c, 0, c.length), parallel) + StreamSupport.longStream(new converterImpls.StepsLongIndexedSeq[CC](c, 0, c.length), parallel) def seqStream: LongStream = someStream(false) def parStream: LongStream = someStream(true) } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala new file mode 100644 index 0000000..87bb295 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala @@ -0,0 +1,66 @@ +package scala.compat.java8.collectionImpl + +import annotation.tailrec + +import Stepper._ + +/** Abstracts all the generic operations of stepping over a backing array + * for some collection where the elements are stored generically and some + * may be missing. Subclasses should set `currentEntry` to `null` when it + * is used as a signal to look for more entries in the array. (This also + * allows a subclass to traverse a sublist by updating `currentEntry`.) + */ +abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { + protected var currentEntry: AnyRef = null + def semiclone(half: Int): Semi + def characteristics(): Int = Ordered + def estimateSize(): Long = if (!hasNext) 0 else iN - i0 + def hasNext(): Boolean = currentEntry != null || (i0 < iN && { + do { currentEntry = underlying(i0); i0 += 1 } while (currentEntry == null && i0 < iN) + currentEntry != null + }) + def substep(): Sub = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection. + */ +abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) + with AnyStepper[A] +{} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection of `Double`s. Subclasses + * are responsible for unboxing the `AnyRef` inside `nextDouble`. + */ +abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) + with DoubleStepper +{} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection of `Int`s. Subclasses + * are responsible for unboxing the `AnyRef` inside `nextInt`. + */ +abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) + with IntStepper +{} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection of `Long`s. Subclasses + * are responsible for unboxing the `AnyRef` inside `nextLong`. + */ +abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index eb65c97..054e93a 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -23,7 +23,10 @@ class StepConvertersTest { def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } } - def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { IFFY(x)(correctSpec) } + def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + } def IFFY[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) @@ -49,7 +52,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[String]("salmon").buffered.stepper ) - IFFY( co.IndexedSeq[String]("salmon").stepper ) + good( co.IndexedSeq[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) IFFY( co.Iterator[String]("salmon").stepper ) @@ -69,7 +72,7 @@ class StepConvertersTest { IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.HashSet[String]("salmon").stepper ) - IFFY( ci.IndexedSeq[String]("salmon").stepper ) + good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) IFFY( ci.Iterable[String]("salmon").stepper ) IFFY( ci.LinearSeq[String]("salmon").stepper ) @@ -106,7 +109,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) good( cm.HashSet[String]("salmon").stepper ) - IFFY( cm.IndexedSeq[String]("salmon").stepper ) + good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) IFFY( cm.LinearSeq[String]("salmon").stepper ) @@ -145,7 +148,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[Double](3.14159).buffered.stepper ) - IFFY( co.IndexedSeq[Double](3.14159).stepper ) + good( co.IndexedSeq[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) IFFY( co.Iterator[Double](3.14159).stepper ) @@ -165,7 +168,7 @@ class StepConvertersTest { //IFFY( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).stepper ) //IFFY( ci.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) - IFFY( ci.IndexedSeq[Double](3.14159).stepper ) + good( ci.IndexedSeq[Double](3.14159).stepper ) //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) IFFY( ci.LinearSeq[Double](3.14159).stepper ) @@ -202,7 +205,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) //IFFY( cm.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) good( cm.HashSet[Double](3.14159).stepper ) - IFFY( cm.IndexedSeq[Double](3.14159).stepper ) + good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) IFFY( cm.LinearSeq[Double](3.14159).stepper ) @@ -247,7 +250,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[Int](654321).buffered.stepper ) - IFFY( co.IndexedSeq[Int](654321).stepper ) + good( co.IndexedSeq[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) IFFY( co.Iterator[Int](654321).stepper ) @@ -267,7 +270,7 @@ class StepConvertersTest { //IFFY( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).stepper ) //IFFY( ci.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.HashSet[Int](654321).stepper ) - IFFY( ci.IndexedSeq[Int](654321).stepper ) + good( ci.IndexedSeq[Int](654321).stepper ) //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) IFFY( ci.Iterable[Int](654321).stepper ) IFFY( ci.LinearSeq[Int](654321).stepper ) @@ -304,7 +307,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) //IFFY( cm.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) good( cm.HashSet[Int](654321).stepper ) - IFFY( cm.IndexedSeq[Int](654321).stepper ) + good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) IFFY( cm.LinearSeq[Int](654321).stepper ) @@ -345,7 +348,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[Long](0x123456789L).buffered.stepper ) - IFFY( co.IndexedSeq[Long](0x123456789L).stepper ) + good( co.IndexedSeq[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) IFFY( co.Iterator[Long](0x123456789L).stepper ) @@ -365,7 +368,7 @@ class StepConvertersTest { //IFFY( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).stepper ) //IFFY( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) - IFFY( ci.IndexedSeq[Long](0x123456789L).stepper ) + good( ci.IndexedSeq[Long](0x123456789L).stepper ) //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) IFFY( ci.LinearSeq[Long](0x123456789L).stepper ) @@ -402,7 +405,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) //IFFY( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) good( cm.HashSet[Long](0x123456789L).stepper ) - IFFY( cm.IndexedSeq[Long](0x123456789L).stepper ) + good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) IFFY( cm.LinearSeq[Long](0x123456789L).stepper ) @@ -439,7 +442,7 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) - IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) + _eh_( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) good( ("salmon": ci.WrappedString).stepper ) } From ffeb369063f0362340c44e38b5e174e025b137ae Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 10 Oct 2015 18:25:40 -0700 Subject: [PATCH 26/56] LinearSeq conversions in. --- .../scala/compat/java8/StepConverters.scala | 55 ++++++++++++ .../java8/collectionImpl/StepsWithTail.scala | 86 +++++++++++++++++++ .../compat/java8/StepConvertersTest.scala | 80 ++++++++--------- 3 files changed, 181 insertions(+), 40 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ea7093b..b7b8f6d 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -98,6 +98,38 @@ package converterImpls { def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) } + private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) + extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) + } + + private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) + extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) + } + + private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) + extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) + } + + private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) + extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) + } + private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -313,6 +345,22 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } + final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) + } + + final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) + } + + final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) + } + + final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) + } + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } @@ -413,6 +461,7 @@ package converterImpls { implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) + implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) } trait Priority3StepConverters extends Priority4StepConverters { @@ -420,6 +469,12 @@ package converterImpls { implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = new RichIndexedSeqCanStep[A](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) + implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = + new RichDoubleLinearSeqCanStep[CC](underlying) + implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = + new RichIntLinearSeqCanStep[CC](underlying) + implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = + new RichLongLinearSeqCanStep[CC](underlying) } trait Priority2StepConverters extends Priority3StepConverters { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala new file mode 100644 index 0000000..464880b --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala @@ -0,0 +1,86 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over a collection with a fast tail operation. + * Because of how Java 8 streams subdivide their spliterators, we do this by chunking a bit at + * a time, generating a long chain of chunks. These won't necessarily all be the same size, + * but if there are enough hopefully it won't matter. + * + * Subclasses MUST decrement `maxN` when consuming elements, or this will not work! + */ +abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { + private var nextChunkSize: Int = 0 + protected def myIsEmpty(cc: CC): Boolean + protected def myTailOf(cc: CC): CC + def prepareParallelOperation(): this.type = { + if (maxN >= Int.MaxValue && nextChunkSize == 0) { + // Need parallel context to know whether to run this or not! + var u = underlying + var i = 0 + while (i < 1024 && !myIsEmpty(u)) { u = myTailOf(u); i += 1 } + if (i < 1024) maxN = i + else nextChunkSize = 64 // Guaranteed at least 16 chunks + } + this + } + def semiclone(chunk: Int): Semi + def characteristics(): Int = if (maxN < Int.MaxValue) Ordered | Sized | SubSized else Ordered + def estimateSize(): Long = if (maxN < Int.MaxValue) maxN else Long.MaxValue + def hasNext(): Boolean = if (maxN < Int.MaxValue) maxN > 0 else if (myIsEmpty(underlying)) { maxN = 0; false } else true + def substep(): Sub = { + prepareParallelOperation() + maxN match { + case x if x < 2 => null + case x if x >= Int.MaxValue => + var u = underlying + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) // Use bottom two bits to count up + while (i < n && !myIsEmpty(u)) { + u = myTailOf(u) + i += 1 + } + if (myIsEmpty(u)) { + maxN = i + substep() // Different branch now, recursion is an easy way to get it + } + else { + val sub = semiclone(n) + underlying = u + if ((nextChunkSize & 3) == 3) nextChunkSize = if (n < 0x40000000) 2*n else n else nextChunkSize += 1 + sub + } + case x => + var half = x.toInt >>> 1 + val sub = semiclone(half) + maxN -= half + while (half > 0) { underlying = myTailOf(underlying); half -= 1 } + sub + } + } +} + +/** Abstracts the operation of stepping over a generic indexable collection */ +abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, AnyStepper[A], STA](_underlying, _maxN) + with AnyStepper[A] +{} + +/** Abstracts the operation of stepping over an indexable collection of Doubles */ +abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, DoubleStepper, STD](_underlying, _maxN) + with DoubleStepper +{} + +/** Abstracts the operation of stepping over an indexable collection of Ints */ +abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, IntStepper, STI](_underlying, _maxN) + with IntStepper +{} + +/** Abstracts the operation of stepping over an indexable collection of Longs */ +abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, LongStepper, STL](_underlying, _maxN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 054e93a..2a19eb0 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -56,7 +56,7 @@ class StepConvertersTest { IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) IFFY( co.Iterator[String]("salmon").stepper ) - IFFY( co.LinearSeq[String]("salmon").stepper ) + good( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) IFFY( co.Seq[String]("salmon").stepper ) IFFY( co.Seq[String]("salmon").view.stepper ) @@ -75,20 +75,20 @@ class StepConvertersTest { good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) IFFY( ci.Iterable[String]("salmon").stepper ) - IFFY( ci.LinearSeq[String]("salmon").stepper ) - IFFY( ci.List[String]("salmon").stepper ) + good( ci.LinearSeq[String]("salmon").stepper ) + good( ci.List[String]("salmon").stepper ) IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.ListSet[String]("salmon").stepper ) IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) - IFFY( ci.Queue[String]("salmon").stepper ) + good( ci.Queue[String]("salmon").stepper ) IFFY( ci.Seq[String]("salmon").stepper ) IFFY( ci.Set[String]("salmon").stepper ) IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.SortedSet[String]("salmon").stepper ) - IFFY( ci.Stack[String]("salmon").stepper ) - IFFY( ci.Stream[String]("salmon").stepper ) - IFFY( ci.Stream[String]("salmon").view.stepper ) + good( ci.Stack[String]("salmon").stepper ) + good( ci.Stream[String]("salmon").stepper ) + _eh_( ci.Stream[String]("salmon").view.stepper ) IFFY( ci.Traversable[String]("salmon").stepper ) IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.TreeSet[String]("salmon").stepper ) @@ -112,17 +112,17 @@ class StepConvertersTest { good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) - IFFY( cm.LinearSeq[String]("salmon").stepper ) + good( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) - IFFY( cm.MutableList[String]("salmon").stepper ) + good( cm.MutableList[String]("salmon").stepper ) IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) IFFY( cm.PriorityQueue[String]("salmon").stepper ) - IFFY( cm.Queue[String]("salmon").stepper ) + good( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) IFFY( cm.Seq[String]("salmon").stepper ) IFFY( cm.Set[String]("salmon").stepper ) @@ -152,7 +152,7 @@ class StepConvertersTest { IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) IFFY( co.Iterator[Double](3.14159).stepper ) - IFFY( co.LinearSeq[Double](3.14159).stepper ) + good( co.LinearSeq[Double](3.14159).stepper ) //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( co.Seq[Double](3.14159).stepper ) IFFY( co.Seq[Double](3.14159).view.stepper ) @@ -171,20 +171,20 @@ class StepConvertersTest { good( ci.IndexedSeq[Double](3.14159).stepper ) //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) - IFFY( ci.LinearSeq[Double](3.14159).stepper ) - IFFY( ci.List[Double](3.14159).stepper ) + good( ci.LinearSeq[Double](3.14159).stepper ) + good( ci.List[Double](3.14159).stepper ) //IFFY( ci.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.ListSet[Double](3.14159).stepper ) //IFFY( ci.LongMap[Double](9876543210L -> 3.14159).stepper ) //IFFY( ci.Map[Double, Double](2.718281828 -> 3.14159).stepper ) - IFFY( ci.Queue[Double](3.14159).stepper ) + good( ci.Queue[Double](3.14159).stepper ) IFFY( ci.Seq[Double](3.14159).stepper ) IFFY( ci.Set[Double](3.14159).stepper ) //IFFY( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.SortedSet[Double](3.14159).stepper ) - IFFY( ci.Stack[Double](3.14159).stepper ) - IFFY( ci.Stream[Double](3.14159).stepper ) - IFFY( ci.Stream[Double](3.14159).view.stepper ) + good( ci.Stack[Double](3.14159).stepper ) + good( ci.Stream[Double](3.14159).stepper ) + _eh_( ci.Stream[Double](3.14159).view.stepper ) IFFY( ci.Traversable[Double](3.14159).stepper ) //IFFY( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.TreeSet[Double](3.14159).stepper ) @@ -208,17 +208,17 @@ class StepConvertersTest { good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) - IFFY( cm.LinearSeq[Double](3.14159).stepper ) + good( cm.LinearSeq[Double](3.14159).stepper ) //IFFY( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) //IFFY( cm.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) //IFFY( cm.LongMap[Double](9876543210L -> 3.14159).stepper ) //IFFY( cm.Map[Double, Double](2.718281828 -> 3.14159).stepper ) - IFFY( cm.MutableList[Double](3.14159).stepper ) + good( cm.MutableList[Double](3.14159).stepper ) //IFFY( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( cm.PriorityQueue[Double](3.14159).stepper ) - IFFY( cm.Queue[Double](3.14159).stepper ) + good( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) IFFY( cm.Seq[Double](3.14159).stepper ) IFFY( cm.Set[Double](3.14159).stepper ) @@ -254,7 +254,7 @@ class StepConvertersTest { IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) IFFY( co.Iterator[Int](654321).stepper ) - IFFY( co.LinearSeq[Int](654321).stepper ) + good( co.LinearSeq[Int](654321).stepper ) //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( co.Seq[Int](654321).stepper ) IFFY( co.Seq[Int](654321).view.stepper ) @@ -273,20 +273,20 @@ class StepConvertersTest { good( ci.IndexedSeq[Int](654321).stepper ) //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) IFFY( ci.Iterable[Int](654321).stepper ) - IFFY( ci.LinearSeq[Int](654321).stepper ) - IFFY( ci.List[Int](654321).stepper ) + good( ci.LinearSeq[Int](654321).stepper ) + good( ci.List[Int](654321).stepper ) //IFFY( ci.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.ListSet[Int](654321).stepper ) //IFFY( ci.LongMap[Int](9876543210L -> 654321).stepper ) //IFFY( ci.Map[Int, Int](0xDEEDED -> 654321).stepper ) - IFFY( ci.Queue[Int](654321).stepper ) + good( ci.Queue[Int](654321).stepper ) IFFY( ci.Seq[Int](654321).stepper ) IFFY( ci.Set[Int](654321).stepper ) //IFFY( ci.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.SortedSet[Int](654321).stepper ) - IFFY( ci.Stack[Int](654321).stepper ) - IFFY( ci.Stream[Int](654321).stepper ) - IFFY( ci.Stream[Int](654321).view.stepper ) + good( ci.Stack[Int](654321).stepper ) + good( ci.Stream[Int](654321).stepper ) + _eh_( ci.Stream[Int](654321).view.stepper ) IFFY( ci.Traversable[Int](654321).stepper ) //IFFY( ci.TreeMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.TreeSet[Int](654321).stepper ) @@ -310,17 +310,17 @@ class StepConvertersTest { good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) - IFFY( cm.LinearSeq[Int](654321).stepper ) + good( cm.LinearSeq[Int](654321).stepper ) //IFFY( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) //IFFY( cm.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) //IFFY( cm.LongMap[Int](9876543210L -> 654321).stepper ) //IFFY( cm.Map[Int, Int](0xDEEDED -> 654321).stepper ) - IFFY( cm.MutableList[Int](654321).stepper ) + good( cm.MutableList[Int](654321).stepper ) //IFFY( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( cm.PriorityQueue[Int](654321).stepper ) - IFFY( cm.Queue[Int](654321).stepper ) + good( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) IFFY( cm.Seq[Int](654321).stepper ) IFFY( cm.Set[Int](654321).stepper ) @@ -352,7 +352,7 @@ class StepConvertersTest { IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) IFFY( co.Iterator[Long](0x123456789L).stepper ) - IFFY( co.LinearSeq[Long](0x123456789L).stepper ) + good( co.LinearSeq[Long](0x123456789L).stepper ) //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).view.stepper ) @@ -371,20 +371,20 @@ class StepConvertersTest { good( ci.IndexedSeq[Long](0x123456789L).stepper ) //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) - IFFY( ci.LinearSeq[Long](0x123456789L).stepper ) - IFFY( ci.List[Long](0x123456789L).stepper ) + good( ci.LinearSeq[Long](0x123456789L).stepper ) + good( ci.List[Long](0x123456789L).stepper ) //IFFY( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.ListSet[Long](0x123456789L).stepper ) //IFFY( ci.LongMap[Long](9876543210L -> 0x123456789L).stepper ) //IFFY( ci.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) - IFFY( ci.Queue[Long](0x123456789L).stepper ) + good( ci.Queue[Long](0x123456789L).stepper ) IFFY( ci.Seq[Long](0x123456789L).stepper ) IFFY( ci.Set[Long](0x123456789L).stepper ) //IFFY( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.SortedSet[Long](0x123456789L).stepper ) - IFFY( ci.Stack[Long](0x123456789L).stepper ) - IFFY( ci.Stream[Long](0x123456789L).stepper ) - IFFY( ci.Stream[Long](0x123456789L).view.stepper ) + good( ci.Stack[Long](0x123456789L).stepper ) + good( ci.Stream[Long](0x123456789L).stepper ) + _eh_( ci.Stream[Long](0x123456789L).view.stepper ) IFFY( ci.Traversable[Long](0x123456789L).stepper ) //IFFY( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.TreeSet[Long](0x123456789L).stepper ) @@ -408,17 +408,17 @@ class StepConvertersTest { good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) - IFFY( cm.LinearSeq[Long](0x123456789L).stepper ) + good( cm.LinearSeq[Long](0x123456789L).stepper ) //IFFY( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) //IFFY( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) //IFFY( cm.LongMap[Long](9876543210L -> 0x123456789L).stepper ) //IFFY( cm.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) - IFFY( cm.MutableList[Long](0x123456789L).stepper ) + good( cm.MutableList[Long](0x123456789L).stepper ) //IFFY( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) - IFFY( cm.Queue[Long](0x123456789L).stepper ) + good( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) IFFY( cm.Seq[Long](0x123456789L).stepper ) IFFY( cm.Set[Long](0x123456789L).stepper ) From a221edc3312075cef4781f6316b52558126f84b8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 11 Oct 2015 17:37:33 -0700 Subject: [PATCH 27/56] Added iterator interface. Probably need to have it store initial segment like WithTail does. Leave that for speed tests later. --- .../scala/compat/java8/StepConverters.scala | 44 ++++++++ .../collectionImpl/StepsLikeIterator.scala | 106 ++++++++++++++++++ .../compat/java8/StepConvertersTest.scala | 16 +-- 3 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index b7b8f6d..01d9501 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -122,6 +122,30 @@ package converterImpls { def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) } + private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) + extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { + def semiclone() = new StepsAnyIterator(null) + def next() = if (proxied ne null) proxied.nextStep else underlying.next + } + + private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) + extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { + def semiclone() = new StepsDoubleIterator(null) + def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next + } + + private[java8] class StepsIntIterator(_underlying: Iterator[Int]) + extends StepsIntLikeIterator[StepsIntIterator](_underlying) { + def semiclone() = new StepsIntIterator(null) + def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next + } + + private[java8] class StepsLongIterator(_underlying: Iterator[Long]) + extends StepsLongLikeIterator[StepsLongIterator](_underlying) { + def semiclone() = new StepsLongIterator(null) + def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next + } + private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty @@ -361,6 +385,22 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) } + final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) + } + + final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) + } + + final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntIterator(underlying) + } + + final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongIterator(underlying) + } + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } @@ -475,6 +515,7 @@ package converterImpls { new RichIntLinearSeqCanStep[CC](underlying) implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = new RichLongLinearSeqCanStep[CC](underlying) + implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -496,6 +537,9 @@ package converterImpls { implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) + implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) + implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) + implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala new file mode 100644 index 0000000..972b989 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala @@ -0,0 +1,106 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Common functionality for Steppers that step through an Iterator, caching the results as needed when a split is requested. */ +abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { + final protected var nextChunkSize = 16 + final protected var proxied: SP = null + def semiclone(): Semi // Must initialize with null iterator! + def characteristics(): Int = if (proxied ne null) Ordered | Sized | SubSized else Ordered + def estimateSize(): Long = if (proxied ne null) proxied.knownSize else Long.MaxValue + def hasNext(): Boolean = if (proxied ne null) proxied.hasStep else underlying.hasNext +} + +/** Abstracts the operation of stepping over an iterator (that needs to be cached when splitting) */ +abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) + extends AbstractStepsLikeIterator[A, AnyStepper[A], SLI](_underlying) + with AnyStepper[A] +{ + override def substep(): AnyStepper[A] = if (proxied ne null) proxied.substep else { + val acc = new Accumulator[A] + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} + +/** Abstracts the operation of stepping over an iterator of Doubles (needs caching when split) */ +abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) + extends AbstractStepsLikeIterator[Double, DoubleStepper, SLI](_underlying) + with DoubleStepper +{ + override def substep(): DoubleStepper = if (proxied ne null) proxied.substep else { + val acc = new DoubleAccumulator + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} + +/** Abstracts the operation of stepping over an iterator of Ints (needs caching when split) */ +abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) + extends AbstractStepsLikeIterator[Int, IntStepper, SLI](_underlying) + with IntStepper +{ + override def substep(): IntStepper = if (proxied ne null) proxied.substep else { + val acc = new IntAccumulator + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} + +/** Abstracts the operation of stepping over an iterator of Longs (needs caching when split) */ +abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) + extends AbstractStepsLikeIterator[Long, LongStepper, SLI](_underlying) + with LongStepper +{ + override def substep: LongStepper = if (proxied ne null) proxied.substep else { + val acc = new LongAccumulator + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 2a19eb0..1104a11 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -51,11 +51,11 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) // Collection section - IFFY( co.Iterator[String]("salmon").buffered.stepper ) + good( co.Iterator[String]("salmon").buffered.stepper ) good( co.IndexedSeq[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) - IFFY( co.Iterator[String]("salmon").stepper ) + good( co.Iterator[String]("salmon").stepper ) good( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) IFFY( co.Seq[String]("salmon").stepper ) @@ -147,11 +147,11 @@ class StepConvertersTest { //Double-specific tests // Collection section - IFFY( co.Iterator[Double](3.14159).buffered.stepper ) + good( co.Iterator[Double](3.14159).buffered.stepper ) good( co.IndexedSeq[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) - IFFY( co.Iterator[Double](3.14159).stepper ) + good( co.Iterator[Double](3.14159).stepper ) good( co.LinearSeq[Double](3.14159).stepper ) //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( co.Seq[Double](3.14159).stepper ) @@ -249,11 +249,11 @@ class StepConvertersTest { good( (1 until 2).stepper ) // Collection section - IFFY( co.Iterator[Int](654321).buffered.stepper ) + good( co.Iterator[Int](654321).buffered.stepper ) good( co.IndexedSeq[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) - IFFY( co.Iterator[Int](654321).stepper ) + good( co.Iterator[Int](654321).stepper ) good( co.LinearSeq[Int](654321).stepper ) //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( co.Seq[Int](654321).stepper ) @@ -347,11 +347,11 @@ class StepConvertersTest { good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) // Collection section - IFFY( co.Iterator[Long](0x123456789L).buffered.stepper ) + good( co.Iterator[Long](0x123456789L).buffered.stepper ) good( co.IndexedSeq[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) - IFFY( co.Iterator[Long](0x123456789L).stepper ) + good( co.Iterator[Long](0x123456789L).stepper ) good( co.LinearSeq[Long](0x123456789L).stepper ) //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) From f9d4e35b340c592be64687ebb4a548058b72c2b9 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 11 Oct 2015 18:29:29 -0700 Subject: [PATCH 28/56] Added key and value steppers to maps. --- .../scala/compat/java8/StepConverters.scala | 36 +++ .../compat/java8/StepConvertersTest.scala | 224 +++++++++++++----- 2 files changed, 197 insertions(+), 63 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 01d9501..5033c97 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -461,6 +461,35 @@ package converterImpls { } } + final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal { + def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) + def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) + } + + final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal { + def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) + } + + final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal { + def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) + } + + final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal { + def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) + } + + final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal { + def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) + } + + final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal { + def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) + } + + final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal { + def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) + } + final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { def stepper: AnyStepper[A] = { val acc = new Accumulator[A] @@ -502,6 +531,7 @@ package converterImpls { implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) + implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } trait Priority3StepConverters extends Priority4StepConverters { @@ -516,6 +546,12 @@ package converterImpls { implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = new RichLongLinearSeqCanStep[CC](underlying) implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) + implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) + implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) + implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) + implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) + implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) + implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) } trait Priority2StepConverters extends Priority3StepConverters { diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 1104a11..72c9caa 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -58,10 +58,14 @@ class StepConvertersTest { good( co.Iterator[String]("salmon").stepper ) good( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) + good( co.Map[String, String]("fish" -> "salmon").keyStepper ) + good( co.Map[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.Seq[String]("salmon").stepper ) IFFY( co.Seq[String]("salmon").view.stepper ) IFFY( co.Set[String]("salmon").stepper ) IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + good( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + good( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.SortedSet[String]("salmon").stepper ) IFFY( co.Traversable[String]("salmon").stepper ) IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) @@ -70,27 +74,41 @@ class StepConvertersTest { // Immutable section IFFY( ci.::("salmon", Nil).stepper ) IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) + good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) + good( ci.IntMap[String](123456 -> "salmon").valueStepper ) IFFY( ci.Iterable[String]("salmon").stepper ) good( ci.LinearSeq[String]("salmon").stepper ) good( ci.List[String]("salmon").stepper ) IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + good( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.ListSet[String]("salmon").stepper ) IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) + good( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) + good( ci.Map[String, String]("fish" -> "salmon").keyStepper ) + good( ci.Map[String, String]("fish" -> "salmon").valueStepper ) good( ci.Queue[String]("salmon").stepper ) IFFY( ci.Seq[String]("salmon").stepper ) IFFY( ci.Set[String]("salmon").stepper ) IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + good( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.SortedSet[String]("salmon").stepper ) good( ci.Stack[String]("salmon").stepper ) good( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) IFFY( ci.Traversable[String]("salmon").stepper ) IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + good( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.TreeSet[String]("salmon").stepper ) good( ci.Vector[String]("salmon").stepper ) @@ -98,9 +116,13 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) + good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + good( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) + good( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) good( (Array("salmon"): cm.ArrayOps[String]).stepper ) @@ -108,19 +130,30 @@ class StepConvertersTest { _eh_( cm.ArrayStack[String]("salmon").stepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) good( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) + good( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) + good( cm.Map[String, String]("fish" -> "salmon").keyStepper ) + good( cm.Map[String, String]("fish" -> "salmon").valueStepper ) good( cm.MutableList[String]("salmon").stepper ) IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.PriorityQueue[String]("salmon").stepper ) good( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) @@ -132,6 +165,8 @@ class StepConvertersTest { IFFY( cm.TreeSet[String]("salmon").stepper ) IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) good( (Array("salmon"): cm.WrappedArray[String]).stepper ) // Java 6 converters section @@ -153,11 +188,13 @@ class StepConvertersTest { IFFY( co.Iterable[Double](3.14159).view.stepper ) good( co.Iterator[Double](3.14159).stepper ) good( co.LinearSeq[Double](3.14159).stepper ) - //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + good( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.Seq[Double](3.14159).stepper ) IFFY( co.Seq[Double](3.14159).view.stepper ) IFFY( co.Set[Double](3.14159).stepper ) - //IFFY( co.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.SortedSet[Double](3.14159).stepper ) IFFY( co.Traversable[Double](3.14159).stepper ) IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) @@ -165,58 +202,70 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(3.14159, Nil).stepper ) - //IFFY( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).stepper ) - //IFFY( ci.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) + good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) - //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) + good( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) good( ci.LinearSeq[Double](3.14159).stepper ) good( ci.List[Double](3.14159).stepper ) - //IFFY( ci.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.ListSet[Double](3.14159).stepper ) - //IFFY( ci.LongMap[Double](9876543210L -> 3.14159).stepper ) - //IFFY( ci.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + good( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( ci.Queue[Double](3.14159).stepper ) IFFY( ci.Seq[Double](3.14159).stepper ) IFFY( ci.Set[Double](3.14159).stepper ) - //IFFY( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.SortedSet[Double](3.14159).stepper ) good( ci.Stack[Double](3.14159).stepper ) good( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) IFFY( ci.Traversable[Double](3.14159).stepper ) - //IFFY( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.TreeSet[Double](3.14159).stepper ) good( ci.Vector[Double](3.14159).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) - //IFFY( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).stepper ) + good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) + good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) - //IFFY( cm.AnyRefMap[Double,Double](2.718281828 -> 3.14159).stepper ) + good( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) - //IFFY( cm.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) good( cm.LinearSeq[Double](3.14159).stepper ) - //IFFY( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) - //IFFY( cm.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) - //IFFY( cm.LongMap[Double](9876543210L -> 3.14159).stepper ) - //IFFY( cm.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + good( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.MutableList[Double](3.14159).stepper ) - //IFFY( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.PriorityQueue[Double](3.14159).stepper ) good( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) @@ -227,14 +276,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Double](3.14159).stepper ) IFFY( cm.TreeSet[Double](3.14159).stepper ) IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) - //IFFY( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) // Java 6 converters section // Concurrent section - //IFFY( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).stepper ) - //IFFY( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).stepper ) + good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) + good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) } @Test @@ -247,6 +299,9 @@ class StepConvertersTest { good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) + good( ci.IntMap[String](123456 -> "salmon").keyStepper ) + good( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) + good( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) // Collection section good( co.Iterator[Int](654321).buffered.stepper ) @@ -255,11 +310,13 @@ class StepConvertersTest { IFFY( co.Iterable[Int](654321).view.stepper ) good( co.Iterator[Int](654321).stepper ) good( co.LinearSeq[Int](654321).stepper ) - //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) + good( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.Seq[Int](654321).stepper ) IFFY( co.Seq[Int](654321).view.stepper ) IFFY( co.Set[Int](654321).stepper ) - //IFFY( co.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.SortedSet[Int](654321).stepper ) IFFY( co.Traversable[Int](654321).stepper ) IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) @@ -267,58 +324,71 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(654321, Nil).stepper ) - //IFFY( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).stepper ) - //IFFY( ci.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) + good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) - //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) + good( ci.IntMap[Int](123456 -> 654321).keyStepper ) + good( ci.IntMap[Int](123456 -> 654321).valueStepper ) IFFY( ci.Iterable[Int](654321).stepper ) good( ci.LinearSeq[Int](654321).stepper ) good( ci.List[Int](654321).stepper ) - //IFFY( ci.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.ListSet[Int](654321).stepper ) - //IFFY( ci.LongMap[Int](9876543210L -> 654321).stepper ) - //IFFY( ci.Map[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) + good( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) good( ci.Queue[Int](654321).stepper ) IFFY( ci.Seq[Int](654321).stepper ) IFFY( ci.Set[Int](654321).stepper ) - //IFFY( ci.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.SortedSet[Int](654321).stepper ) good( ci.Stack[Int](654321).stepper ) good( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) IFFY( ci.Traversable[Int](654321).stepper ) - //IFFY( ci.TreeMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.TreeSet[Int](654321).stepper ) good( ci.Vector[Int](654321).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) - //IFFY( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).stepper ) + good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) + good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) - //IFFY( cm.AnyRefMap[Int,Int](0xDEEDED -> 654321).stepper ) + good( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) good( (Array(654321): cm.ArrayOps[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) - //IFFY( cm.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) good( cm.LinearSeq[Int](654321).stepper ) - //IFFY( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) - //IFFY( cm.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) - //IFFY( cm.LongMap[Int](9876543210L -> 654321).stepper ) - //IFFY( cm.Map[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) + good( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.MutableList[Int](654321).stepper ) - //IFFY( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.PriorityQueue[Int](654321).stepper ) good( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) @@ -329,14 +399,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Int](654321).stepper ) IFFY( cm.TreeSet[Int](654321).stepper ) IFFY( cm.UnrolledBuffer[Int](654321).stepper ) - //IFFY( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( (Array(654321): cm.WrappedArray[Int]).stepper ) // Java 6 converters section // Concurrent section - //IFFY( cc.TrieMap[Int, Int](0xDEEDED -> 654321).stepper ) - //IFFY( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).stepper ) + good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) + good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) } @Test @@ -345,6 +418,12 @@ class StepConvertersTest { // Long-specific tests good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + good( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) + good( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) + good( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + good( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + good( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) + good( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) // Collection section good( co.Iterator[Long](0x123456789L).buffered.stepper ) @@ -353,11 +432,13 @@ class StepConvertersTest { IFFY( co.Iterable[Long](0x123456789L).view.stepper ) good( co.Iterator[Long](0x123456789L).stepper ) good( co.LinearSeq[Long](0x123456789L).stepper ) - //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).view.stepper ) IFFY( co.Set[Long](0x123456789L).stepper ) - //IFFY( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.SortedSet[Long](0x123456789L).stepper ) IFFY( co.Traversable[Long](0x123456789L).stepper ) IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) @@ -365,58 +446,72 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(0x123456789L, Nil).stepper ) - //IFFY( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).stepper ) - //IFFY( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) + good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) - //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) + good( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) good( ci.LinearSeq[Long](0x123456789L).stepper ) good( ci.List[Long](0x123456789L).stepper ) - //IFFY( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.ListSet[Long](0x123456789L).stepper ) - //IFFY( ci.LongMap[Long](9876543210L -> 0x123456789L).stepper ) - //IFFY( ci.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + good( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( ci.Queue[Long](0x123456789L).stepper ) IFFY( ci.Seq[Long](0x123456789L).stepper ) IFFY( ci.Set[Long](0x123456789L).stepper ) - //IFFY( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.SortedSet[Long](0x123456789L).stepper ) good( ci.Stack[Long](0x123456789L).stepper ) good( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) IFFY( ci.Traversable[Long](0x123456789L).stepper ) - //IFFY( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.TreeSet[Long](0x123456789L).stepper ) good( ci.Vector[Long](0x123456789L).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) - //IFFY( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).stepper ) + good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) + good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) - //IFFY( cm.AnyRefMap[Long,Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) - //IFFY( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) good( cm.LinearSeq[Long](0x123456789L).stepper ) - //IFFY( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) - //IFFY( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) - //IFFY( cm.LongMap[Long](9876543210L -> 0x123456789L).stepper ) - //IFFY( cm.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + good( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.MutableList[Long](0x123456789L).stepper ) - //IFFY( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) good( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) @@ -427,14 +522,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Long](0x123456789L).stepper ) IFFY( cm.TreeSet[Long](0x123456789L).stepper ) IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) - //IFFY( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) // Java 6 converters section // Concurrent section - //IFFY( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) - //IFFY( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).stepper ) + good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) + good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) } @Test From d5bb5895ff3948cdab76e73238f3a3c587a0e048 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 11 Oct 2015 18:51:48 -0700 Subject: [PATCH 29/56] Distinguish between good and sorta acceptable (sequential traversal) access for Stepper in tests. --- .../compat/java8/StepConvertersTest.scala | 430 +++++++++--------- 1 file changed, 223 insertions(+), 207 deletions(-) diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 72c9caa..681f16b 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -10,7 +10,7 @@ class StepConvertersTest { import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } - def isAcc[X](x: X) = x match { + def isAcc[X](x: X): Boolean = x match { case _: AccumulatorStepper[_] => true case _: DoubleAccumulatorStepper => true case _: IntAccumulatorStepper => true @@ -18,6 +18,12 @@ class StepConvertersTest { case _ => false } + def isLin[X](x: X): Boolean = x match { + case _: AbstractStepsLikeIterator[_, _, _] => true + case _: AbstractStepsWithTail[_, _, _] => true + case _ => false + } + trait SpecCheck { def apply[X](x: X): Boolean } object SpecCheck { def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } @@ -34,10 +40,16 @@ class StepConvertersTest { assert(isAcc(x)) } + def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + assert(!isAcc(x) && isLin(x)) + } + def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) - assert(!isAcc(x)) + assert(!isAcc(x) && !isLin(x)) } def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { @@ -51,21 +63,21 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) // Collection section - good( co.Iterator[String]("salmon").buffered.stepper ) + Okay( co.Iterator[String]("salmon").buffered.stepper ) good( co.IndexedSeq[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) - good( co.Iterator[String]("salmon").stepper ) - good( co.LinearSeq[String]("salmon").stepper ) + Okay( co.Iterator[String]("salmon").stepper ) + Okay( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) - good( co.Map[String, String]("fish" -> "salmon").keyStepper ) - good( co.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( co.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.Map[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.Seq[String]("salmon").stepper ) IFFY( co.Seq[String]("salmon").view.stepper ) IFFY( co.Set[String]("salmon").stepper ) IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) - good( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) - good( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.SortedSet[String]("salmon").stepper ) IFFY( co.Traversable[String]("salmon").stepper ) IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) @@ -74,41 +86,41 @@ class StepConvertersTest { // Immutable section IFFY( ci.::("salmon", Nil).stepper ) IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) - good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) - good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) - good( ci.IntMap[String](123456 -> "salmon").valueStepper ) + Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) IFFY( ci.Iterable[String]("salmon").stepper ) - good( ci.LinearSeq[String]("salmon").stepper ) - good( ci.List[String]("salmon").stepper ) + Okay( ci.LinearSeq[String]("salmon").stepper ) + Okay( ci.List[String]("salmon").stepper ) IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) - good( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.ListSet[String]("salmon").stepper ) IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) - good( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) - good( ci.Map[String, String]("fish" -> "salmon").keyStepper ) - good( ci.Map[String, String]("fish" -> "salmon").valueStepper ) - good( ci.Queue[String]("salmon").stepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.Queue[String]("salmon").stepper ) IFFY( ci.Seq[String]("salmon").stepper ) IFFY( ci.Set[String]("salmon").stepper ) IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) - good( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.SortedSet[String]("salmon").stepper ) - good( ci.Stack[String]("salmon").stepper ) - good( ci.Stream[String]("salmon").stepper ) + Okay( ci.Stack[String]("salmon").stepper ) + Okay( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) IFFY( ci.Traversable[String]("salmon").stepper ) IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) - good( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.TreeSet[String]("salmon").stepper ) good( ci.Vector[String]("salmon").stepper ) @@ -116,13 +128,13 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) - good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) - good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) - good( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) - good( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) good( (Array("salmon"): cm.ArrayOps[String]).stepper ) @@ -130,32 +142,32 @@ class StepConvertersTest { _eh_( cm.ArrayStack[String]("salmon").stepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) - good( cm.LinearSeq[String]("salmon").stepper ) + Okay( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) - good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) - good( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) - good( cm.Map[String, String]("fish" -> "salmon").keyStepper ) - good( cm.Map[String, String]("fish" -> "salmon").valueStepper ) - good( cm.MutableList[String]("salmon").stepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.MutableList[String]("salmon").stepper ) IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.PriorityQueue[String]("salmon").stepper ) - good( cm.Queue[String]("salmon").stepper ) + Okay( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) IFFY( cm.Seq[String]("salmon").stepper ) IFFY( cm.Set[String]("salmon").stepper ) @@ -165,15 +177,19 @@ class StepConvertersTest { IFFY( cm.TreeSet[String]("salmon").stepper ) IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) good( (Array("salmon"): cm.WrappedArray[String]).stepper ) // Java 6 converters section // Concurrent section IFFY( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) IFFY( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).keyStepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).valueStepper ) } @Test @@ -182,19 +198,19 @@ class StepConvertersTest { //Double-specific tests // Collection section - good( co.Iterator[Double](3.14159).buffered.stepper ) + Okay( co.Iterator[Double](3.14159).buffered.stepper ) good( co.IndexedSeq[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) - good( co.Iterator[Double](3.14159).stepper ) - good( co.LinearSeq[Double](3.14159).stepper ) - good( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( co.Iterator[Double](3.14159).stepper ) + Okay( co.LinearSeq[Double](3.14159).stepper ) + Okay( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.Seq[Double](3.14159).stepper ) IFFY( co.Seq[Double](3.14159).view.stepper ) IFFY( co.Set[Double](3.14159).stepper ) - good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.SortedSet[Double](3.14159).stepper ) IFFY( co.Traversable[Double](3.14159).stepper ) IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) @@ -202,72 +218,72 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(3.14159, Nil).stepper ) - good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) - good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) - good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) + Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) + Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) - good( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) - good( ci.LinearSeq[Double](3.14159).stepper ) - good( ci.List[Double](3.14159).stepper ) - good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.LinearSeq[Double](3.14159).stepper ) + Okay( ci.List[Double](3.14159).stepper ) + Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.ListSet[Double](3.14159).stepper ) - good( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) - good( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( ci.Queue[Double](3.14159).stepper ) + Okay( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.Queue[Double](3.14159).stepper ) IFFY( ci.Seq[Double](3.14159).stepper ) IFFY( ci.Set[Double](3.14159).stepper ) - good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.SortedSet[Double](3.14159).stepper ) - good( ci.Stack[Double](3.14159).stepper ) - good( ci.Stream[Double](3.14159).stepper ) + Okay( ci.Stack[Double](3.14159).stepper ) + Okay( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) IFFY( ci.Traversable[Double](3.14159).stepper ) - good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.TreeSet[Double](3.14159).stepper ) good( ci.Vector[Double](3.14159).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) - good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) - good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) + Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) + Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) - good( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) + Okay( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) - good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) - good( cm.LinearSeq[Double](3.14159).stepper ) - good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.LinearSeq[Double](3.14159).stepper ) + Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) - good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) - good( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( cm.MutableList[Double](3.14159).stepper ) - good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.MutableList[Double](3.14159).stepper ) + Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.PriorityQueue[Double](3.14159).stepper ) - good( cm.Queue[Double](3.14159).stepper ) + Okay( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) IFFY( cm.Seq[Double](3.14159).stepper ) IFFY( cm.Set[Double](3.14159).stepper ) @@ -276,17 +292,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Double](3.14159).stepper ) IFFY( cm.TreeSet[Double](3.14159).stepper ) IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) - good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) // Java 6 converters section // Concurrent section - good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) - good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) + Okay( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) + Okay( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) } @Test @@ -299,24 +315,24 @@ class StepConvertersTest { good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) - good( ci.IntMap[String](123456 -> "salmon").keyStepper ) - good( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) - good( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) + Okay( ci.IntMap[String](123456 -> "salmon").keyStepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) // Collection section - good( co.Iterator[Int](654321).buffered.stepper ) + Okay( co.Iterator[Int](654321).buffered.stepper ) good( co.IndexedSeq[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) - good( co.Iterator[Int](654321).stepper ) - good( co.LinearSeq[Int](654321).stepper ) - good( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( co.Iterator[Int](654321).stepper ) + Okay( co.LinearSeq[Int](654321).stepper ) + Okay( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.Seq[Int](654321).stepper ) IFFY( co.Seq[Int](654321).view.stepper ) IFFY( co.Set[Int](654321).stepper ) - good( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.SortedSet[Int](654321).stepper ) IFFY( co.Traversable[Int](654321).stepper ) IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) @@ -324,73 +340,73 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(654321, Nil).stepper ) - good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) - good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) - good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) + Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) + Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) - good( ci.IntMap[Int](123456 -> 654321).keyStepper ) - good( ci.IntMap[Int](123456 -> 654321).valueStepper ) + Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) + Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) IFFY( ci.Iterable[Int](654321).stepper ) - good( ci.LinearSeq[Int](654321).stepper ) - good( ci.List[Int](654321).stepper ) - good( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.LinearSeq[Int](654321).stepper ) + Okay( ci.List[Int](654321).stepper ) + Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.ListSet[Int](654321).stepper ) - good( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) - good( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( ci.Queue[Int](654321).stepper ) + Okay( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) + Okay( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.Queue[Int](654321).stepper ) IFFY( ci.Seq[Int](654321).stepper ) IFFY( ci.Set[Int](654321).stepper ) - good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.SortedSet[Int](654321).stepper ) - good( ci.Stack[Int](654321).stepper ) - good( ci.Stream[Int](654321).stepper ) + Okay( ci.Stack[Int](654321).stepper ) + Okay( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) IFFY( ci.Traversable[Int](654321).stepper ) - good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.TreeSet[Int](654321).stepper ) good( ci.Vector[Int](654321).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) - good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) - good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) + Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) + Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) - good( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) + Okay( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) good( (Array(654321): cm.ArrayOps[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) - good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) - good( cm.LinearSeq[Int](654321).stepper ) - good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.LinearSeq[Int](654321).stepper ) + Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) - good( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) - good( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( cm.MutableList[Int](654321).stepper ) - good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) + Okay( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.MutableList[Int](654321).stepper ) + Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.PriorityQueue[Int](654321).stepper ) - good( cm.Queue[Int](654321).stepper ) + Okay( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) IFFY( cm.Seq[Int](654321).stepper ) IFFY( cm.Set[Int](654321).stepper ) @@ -399,17 +415,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Int](654321).stepper ) IFFY( cm.TreeSet[Int](654321).stepper ) IFFY( cm.UnrolledBuffer[Int](654321).stepper ) - good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( (Array(654321): cm.WrappedArray[Int]).stepper ) // Java 6 converters section // Concurrent section - good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) - good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) + Okay( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) + Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) } @Test @@ -418,27 +434,27 @@ class StepConvertersTest { // Long-specific tests good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) - good( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) - good( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) - good( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) - good( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) - good( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) - good( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) + Okay( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + Okay( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + Okay( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) + Okay( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) // Collection section - good( co.Iterator[Long](0x123456789L).buffered.stepper ) + Okay( co.Iterator[Long](0x123456789L).buffered.stepper ) good( co.IndexedSeq[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) - good( co.Iterator[Long](0x123456789L).stepper ) - good( co.LinearSeq[Long](0x123456789L).stepper ) - good( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( co.Iterator[Long](0x123456789L).stepper ) + Okay( co.LinearSeq[Long](0x123456789L).stepper ) + Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).view.stepper ) IFFY( co.Set[Long](0x123456789L).stepper ) - good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.SortedSet[Long](0x123456789L).stepper ) IFFY( co.Traversable[Long](0x123456789L).stepper ) IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) @@ -446,74 +462,74 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(0x123456789L, Nil).stepper ) - good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) - good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) - good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) + Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) + Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) - good( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) - good( ci.LinearSeq[Long](0x123456789L).stepper ) - good( ci.List[Long](0x123456789L).stepper ) - good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.LinearSeq[Long](0x123456789L).stepper ) + Okay( ci.List[Long](0x123456789L).stepper ) + Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.ListSet[Long](0x123456789L).stepper ) - good( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) - good( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) - good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( ci.Queue[Long](0x123456789L).stepper ) + Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.Queue[Long](0x123456789L).stepper ) IFFY( ci.Seq[Long](0x123456789L).stepper ) IFFY( ci.Set[Long](0x123456789L).stepper ) - good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.SortedSet[Long](0x123456789L).stepper ) - good( ci.Stack[Long](0x123456789L).stepper ) - good( ci.Stream[Long](0x123456789L).stepper ) + Okay( ci.Stack[Long](0x123456789L).stepper ) + Okay( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) IFFY( ci.Traversable[Long](0x123456789L).stepper ) - good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.TreeSet[Long](0x123456789L).stepper ) good( ci.Vector[Long](0x123456789L).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) - good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) - good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) + Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) + Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) - good( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) + Okay( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) - good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) - good( cm.LinearSeq[Long](0x123456789L).stepper ) - good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.LinearSeq[Long](0x123456789L).stepper ) + Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) - good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) - good( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) - good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( cm.MutableList[Long](0x123456789L).stepper ) - good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.MutableList[Long](0x123456789L).stepper ) + Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) - good( cm.Queue[Long](0x123456789L).stepper ) + Okay( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) IFFY( cm.Seq[Long](0x123456789L).stepper ) IFFY( cm.Set[Long](0x123456789L).stepper ) @@ -522,17 +538,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Long](0x123456789L).stepper ) IFFY( cm.TreeSet[Long](0x123456789L).stepper ) IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) - good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) // Java 6 converters section // Concurrent section - good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) - good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) + Okay( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) + Okay( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) } @Test From f13b0f3d05b272aa9024db2f06a1ea735bfe202e Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 12 Oct 2015 20:50:07 -0700 Subject: [PATCH 30/56] Linked and regular HashMaps working. --- .../java8/runtime/CollectionInternals.java | 1 + .../scala/compat/java8/StepConverters.scala | 264 +++++++++++++++++- .../compat/java8/StepConvertersTest.scala | 42 +-- 3 files changed, 278 insertions(+), 29 deletions(-) diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index 1f30ea3..c5071bc 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -2,6 +2,7 @@ public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } + public static > scala.collection.mutable.HashEntry[] getTable(scala.collection.mutable.HashTable ht) { return ht.hashTableContents().table(); } public static Object[] getDisplay0(scala.collection.immutable.Vector v) { return v.display0(); } public static Object[] getDisplay1(scala.collection.immutable.Vector v) { return v.display1(); } public static Object[] getDisplay2(scala.collection.immutable.Vector v) { return v.display2(); } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 5033c97..65bc93c 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -321,6 +321,120 @@ package converterImpls { def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) } + private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) + extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) + } + + private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) + } + + private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) + } + + private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) + } + + private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) + } + + private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) + } + + private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) + } + + private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) + } + + private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) + } + + private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) + } + + private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) + } + + private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) + } + + private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) + } + + private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -436,7 +550,105 @@ package converterImpls { new StepsLongFlatHashTable(tbl, 0, tbl.length) } } + + final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) extends AnyVal { + @inline def keyStepper: AnyStepper[K] = { + val tbl = runtime.CollectionInternals.getTable[K, HE](underlying) + new StepsAnyHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) extends AnyVal { + @inline def keyStepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable[Double, HE](underlying) + new StepsDoubleHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) extends AnyVal { + @inline def keyStepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable[Int, HE](underlying) + new StepsIntHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) extends AnyVal { + @inline def keyStepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable[Long, HE](underlying) + new StepsLongHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { + @inline def stepper: AnyStepper[(K,V)] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTable(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { + @inline def valueStepper: AnyStepper[V] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) extends AnyVal { + @inline def valueStepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) + new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) extends AnyVal { + @inline def valueStepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) + new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) extends AnyVal { + @inline def valueStepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) + new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { + @inline def stepper: AnyStepper[(K,V)] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTable(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { + @inline def valueStepper: AnyStepper[V] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) extends AnyVal { + @inline def valueStepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) + new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) extends AnyVal { + @inline def valueStepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) + new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) + } + } + final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) extends AnyVal { + @inline def valueStepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) + new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) + } + } + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull def estimateSize = iN - i0 @@ -522,17 +734,39 @@ package converterImpls { } } - trait Priority5StepConverters { + trait Priority7StepConverters { implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) } - trait Priority4StepConverters extends Priority5StepConverters { + trait Priority6StepConverters extends Priority7StepConverters { implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) - implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } + + trait Priority5StepConverters extends Priority6StepConverters { + implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) + implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) + implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) + implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) + implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) + implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) + } + + trait Priority4StepConverters extends Priority5StepConverters { + implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) + implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = + new RichHashTableKeyCanStep[K, HE](underlying) + implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableCanStep[K, V](underlying) + implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableValueCanStep[K, V](underlying) + implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableCanStep[K, V](underlying) + implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableValueCanStep[K, V](underlying) + } trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) @@ -546,12 +780,24 @@ package converterImpls { implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = new RichLongLinearSeqCanStep[CC](underlying) implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) - implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) - implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) - implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) - implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) - implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) - implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) + implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = + new RichHashTableDoubleKeyCanStep[HE](underlying) + implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = + new RichHashTableIntKeyCanStep[HE](underlying) + implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = + new RichHashTableLongKeyCanStep[HE](underlying) + implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = + new RichDefaultHashTableDoubleValueCanStep[K](underlying) + implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = + new RichDefaultHashTableIntValueCanStep[K](underlying) + implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = + new RichDefaultHashTableLongValueCanStep[K](underlying) + implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = + new RichLinkedHashTableDoubleValueCanStep[K](underlying) + implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = + new RichLinkedHashTableIntValueCanStep[K](underlying) + implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = + new RichLinkedHashTableLongValueCanStep[K](underlying) } trait Priority2StepConverters extends Priority3StepConverters { diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 681f16b..855d9b9 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -43,13 +43,15 @@ class StepConvertersTest { def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) - assert(!isAcc(x) && isLin(x)) + assert(!isAcc(x)) + assert(isLin(x)) } def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) - assert(!isAcc(x) && !isLin(x)) + assert(!isAcc(x)) + assert(!isLin(x)) } def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { @@ -141,17 +143,17 @@ class StepConvertersTest { good( cm.ArraySeq[String]("salmon").stepper ) _eh_( cm.ArrayStack[String]("salmon").stepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) - IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) - Okay( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) - Okay( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) Okay( cm.LinearSeq[String]("salmon").stepper ) - IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) - Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) - Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) @@ -263,15 +265,15 @@ class StepConvertersTest { good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) - Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) Okay( cm.LinearSeq[Double](3.14159).stepper ) - Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) @@ -386,15 +388,15 @@ class StepConvertersTest { good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) - Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) Okay( cm.LinearSeq[Int](654321).stepper ) - Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) @@ -508,15 +510,15 @@ class StepConvertersTest { good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) - Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) Okay( cm.LinearSeq[Long](0x123456789L).stepper ) - Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) From fedc1eba242328f58e7281b85960860d5631a989 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 17 Oct 2015 20:40:25 -0700 Subject: [PATCH 31/56] Immutable HashMaps are now nicely steppable (and thus can be streamed). --- .../scala/compat/java8/StepConverters.scala | 147 ++++++++++++++++++ .../collectionImpl/StepsLikeImmHashMap.scala | 53 +++++++ .../collectionImpl/StepsLikeSliced.scala | 40 +++++ .../compat/java8/StepConvertersTest.scala | 18 +-- 4 files changed, 249 insertions(+), 9 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 65bc93c..c1bfbb0 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -435,6 +435,114 @@ package converterImpls { new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) } + private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) + def next(): (K, V) = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.iterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) + def next(): K = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) + def next(): V = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) + extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) + extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) + extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) + extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) + extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) + extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -648,6 +756,36 @@ package converterImpls { new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) } } + + final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal { + @inline def stepper: AnyStepper[(K, V)] = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) + @inline def keyStepper: AnyStepper[K] = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + @inline def valueStepper: AnyStepper[V] = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) + } + + final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal { + @inline def keyStepper: DoubleStepper = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) + } + + final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal { + @inline def valueStepper: DoubleStepper = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) + } + + final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal { + @inline def keyStepper: IntStepper = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) + } + + final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal { + @inline def valueStepper: IntStepper = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) + } + + final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal { + @inline def keyStepper: LongStepper = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) + } + + final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal { + @inline def valueStepper: LongStepper = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) + } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull @@ -798,6 +936,8 @@ package converterImpls { new RichLinkedHashTableIntValueCanStep[K](underlying) implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = new RichLinkedHashTableLongValueCanStep[K](underlying) + + implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -822,6 +962,13 @@ package converterImpls { implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) + + implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) + implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) + implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) + implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) + implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) + implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala new file mode 100644 index 0000000..169991c --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala @@ -0,0 +1,53 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over an immutable HashMap by slicing it into pieces. + * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the + * collection needs some sort of modification before transmission to the subclass. + */ +trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] +extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { + protected var theIterator: Iterator[A] = null + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int): Semi + override def characteristics() = Immutable + def hasNext(): Boolean = i < iN + def semiclone(halfHint: Int): Semi = + if (i >= iN) null + else underlying match { + case trie: collection.immutable.HashMap.HashTrieMap[K, V] => + val parts = if (i > i0) trie.drop(i-i0).split else trie.split + if (parts.length != 2) null + else { + val ans = demiclone(parts.head, 0, parts.head.size) + i = iN - parts.last.size + underlying = parts.last + ans.theIterator = theIterator + theIterator = null + i0 = i + ans + } + case _ => null + } +} + +abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeSliced[A, collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, A, AnyStepper[A], SIHM] +{} + +abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsDoubleLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, Double, DoubleStepper, SIHM] +{} + +abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsIntLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, Int, IntStepper, SIHM] +{} + +abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLongLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, Long, LongStepper, SIHM] +{} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala new file mode 100644 index 0000000..a6f2110 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala @@ -0,0 +1,40 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over a collection that can be sliced into pieces. + * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the + * collection needs some sort of modification before transmission to the subclass. + */ +abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { + protected var i0: Int = i + def semiclone(halfHint: Int): Semi // Must really do all the work for both this and cloned collection! + def characteristics(): Int = Ordered + def estimateSize(): Long = iN - i + def substep(): Sub = if (estimateSize > 0) semiclone((iN + i) >>> 1) else null +} + +/** Abstracts the operation of stepping over a generic collection that can be efficiently sliced or otherwise subdivided */ +abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) + with AnyStepper[A] +{} + +/** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ +abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) + with DoubleStepper +{} + +/** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ +abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) + with IntStepper +{} + +/** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ +abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 855d9b9..075e1eb 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -90,9 +90,9 @@ class StepConvertersTest { IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) - IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) - Okay( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) - Okay( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) @@ -222,8 +222,8 @@ class StepConvertersTest { IFFY( ci.::(3.14159, Nil).stepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) - Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) @@ -344,8 +344,8 @@ class StepConvertersTest { IFFY( ci.::(654321, Nil).stepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) - Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) @@ -466,8 +466,8 @@ class StepConvertersTest { IFFY( ci.::(0x123456789L, Nil).stepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) - Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) From 7413c0c52e667776addd08d90531977fcbd75eea Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 18 Oct 2015 17:56:08 -0700 Subject: [PATCH 32/56] BitSet added. --- .../java8/runtime/CollectionInternals.java | 11 ++ .../scala/compat/java8/StepConverters.scala | 102 +++++++++++++++++- .../StepsLikeTrieIterator.scala | 48 +++++++++ .../compat/java8/StepConvertersTest.scala | 14 +-- 4 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index c5071bc..ba6f6a6 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -1,5 +1,7 @@ package scala.compat.java8.runtime; +import scala.collection.immutable.*; // Don't rely on this! Refer to everything explicitly! + public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } public static > scala.collection.mutable.HashEntry[] getTable(scala.collection.mutable.HashTable ht) { return ht.hashTableContents().table(); } @@ -9,4 +11,13 @@ public class CollectionInternals { public static Object[] getDisplay3(scala.collection.immutable.Vector v) { return v.display3(); } public static Object[] getDisplay4(scala.collection.immutable.Vector v) { return v.display4(); } public static Object[] getDisplay5(scala.collection.immutable.Vector v) { return v.display5(); } + public static scala.Tuple2< scala.Tuple2< scala.collection.Iterator, Object >, scala.collection.Iterator > trieIteratorSplit(scala.collection.Iterator it) { + if (it instanceof scala.collection.immutable.TrieIterator) { + scala.collection.immutable.TrieIterator trie = (scala.collection.immutable.TrieIterator)it; + return trie.split(); + } + return null; + } + public static long[] getBitSetInternals(scala.collection.mutable.BitSet bitSet) { return bitSet.elems(); } } + diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index c1bfbb0..ef39d0c 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -543,6 +543,68 @@ package converterImpls { else throwNSEE } + private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) + extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { + protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) + def next(): A = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) + extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) + def nextDouble() = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) + extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) + def nextInt() = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) + extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) + def nextLong() = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) + extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { + private var mask: Long = (-1L) << (i & 0x3F) + private var cache: Long = underlying(i >>> 6) + private var found: Boolean = false + def semiclone(half: Int) = { + val ans = new StepsIntBitSet(underlying, i, half) + i = half + mask = (-1L) << (i & 0x3F) + cache = underlying(i >>> 6) + found = false + ans + } + def hasNext(): Boolean = found || ((i < iN) && { + while ((mask & cache) == 0) { + i += java.lang.Long.numberOfLeadingZeros(~mask) + if (i < 0 || i >= iN) { i = iN; return false } + mask = -1L + cache = underlying(i >>> 6) + } + var m = mask << 1 + while ((mask & cache) == (m & cache)) { + mask = m + m = mask << 1 + i += 1 + } + if (i < 0 || i >= iN) { + i = iN + false + } + else { + found = true + true + } + }) + def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -787,6 +849,25 @@ package converterImpls { @inline def valueStepper: LongStepper = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) } + final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyImmHashSet(underlying.iterator, underlying.size) + } + + final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal { + def stepper: IntStepper = { + val bits: Array[Long] = underlying match { + case m: collection.mutable.BitSet => runtime.CollectionInternals.getBitSetInternals(m) + case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) + case x => x.toBitMask + } + new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) + } + } + private[java8] object RichBitSetCanStep { + private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") + def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] + } + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull def estimateSize = iN - i0 @@ -938,6 +1019,7 @@ package converterImpls { new RichLinkedHashTableLongValueCanStep[K](underlying) implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) + implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -969,6 +1051,8 @@ package converterImpls { implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) + + implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) } } @@ -992,15 +1076,15 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) } - implicit final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { + implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { @inline def stepper: IntStepper = new StepsIntNumericRange(underlying, 0, underlying.length) } - implicit final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { + implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { @inline def stepper: LongStepper = new StepsLongNumericRange(underlying, 0, underlying.length) } - implicit final class RichRangeCanStep(private val underlying: Range) extends AnyVal { + implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal { @inline def stepper: IntStepper = new StepsIntRange(underlying, 0, underlying.length) } @@ -1012,6 +1096,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: LongStepper = new StepsLongVector(underlying, 0, underlying.length) } + implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + } + + implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntImmHashSet(underlying.iterator, underlying.size) + } + + implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongImmHashSet(underlying.iterator, underlying.size) + } + implicit class RichStringCanStep(val underlying: String) extends AnyVal { @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala new file mode 100644 index 0000000..631ed11 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala @@ -0,0 +1,48 @@ +package scala.compat.java8 +package collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over a TrieIterator by asking itself to + * slice itself into pieces. Note that `i` must be kept up to date in subclasses. + */ +trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] +extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { + protected def demiclone(it: Iterator[A], N: Int): Semi + override def characteristics() = Immutable + def hasNext(): Boolean = underlying.hasNext + def semiclone(halfHint: Int): Semi = + if (!underlying.hasNext || i > iN-2) null + else runtime.CollectionInternals.trieIteratorSplit(underlying) match { + case null => null + case ((pre: Iterator[A], pno), post: Iterator[A]) => + val pn = (pno: Any) match { case i: Int => i; case _ => throw new Exception("Unexpected type") } + val ans = demiclone(pre, pn) + i += pn + underlying = post + i0 = i + ans + case _ => null + } +} + +abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) + extends StepsLikeSliced[A, Iterator[A], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[A, AnyStepper[A], STI] +{} + +abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) + extends StepsDoubleLikeSliced[Iterator[Double], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[Double, DoubleStepper, STI] +{} + +abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) + extends StepsIntLikeSliced[Iterator[Int], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[Int, IntStepper, STI] +{} + +abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) + extends StepsLongLikeSliced[Iterator[Long], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[Long, LongStepper, STI] +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 075e1eb..c227463 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -93,7 +93,7 @@ class StepConvertersTest { good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.HashSet[String]("salmon").stepper ) + good( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) @@ -224,7 +224,7 @@ class StepConvertersTest { Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.HashSet[Double](3.14159).stepper ) + good( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) @@ -312,10 +312,10 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) // Int-specific tests - IFFY( co.BitSet(42).stepper ) - IFFY( ci.BitSet(42).stepper ) + good( co.BitSet(42).stepper ) + good( ci.BitSet(42).stepper ) good( ci.NumericRange(123456, 123458, 1).stepper ) - IFFY( cm.BitSet(42).stepper ) + good( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) Okay( ci.IntMap[String](123456 -> "salmon").keyStepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) @@ -346,7 +346,7 @@ class StepConvertersTest { Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.HashSet[Int](654321).stepper ) + good( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) @@ -468,7 +468,7 @@ class StepConvertersTest { Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.HashSet[Long](0x123456789L).stepper ) + good( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) From edf0644fb23e4f0348c9f27960b7dcb6d20bb34f Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 24 Oct 2015 17:14:59 -0700 Subject: [PATCH 33/56] Added marker trait to indicate when splits are efficient. --- .../scala/compat/java8/StepConverters.scala | 289 +++++++++++------- .../scala/compat/java8/StreamConverters.scala | 18 +- .../compat/java8/collectionImpl/Stepper.scala | 6 + .../collectionImpl/StepsLikeGapped.scala | 10 +- .../collectionImpl/StepsLikeIndexed.scala | 4 + .../collectionImpl/StepsLikeSliced.scala | 4 + 6 files changed, 213 insertions(+), 118 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ef39d0c..7117628 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -7,6 +7,54 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ + + trait MakesAnyStepper[A] extends Any { + def stepper: AnyStepper[A] with EfficientSubstep + } + + trait MakesAnyKeyStepper[A] extends Any { + def keyStepper: AnyStepper[A] with EfficientSubstep + } + + trait MakesAnyValueStepper[A] extends Any { + def valueStepper: AnyStepper[A] with EfficientSubstep + } + + trait MakesDoubleStepper extends Any { + def stepper: DoubleStepper with EfficientSubstep + } + + trait MakesDoubleKeyStepper extends Any { + def keyStepper: DoubleStepper with EfficientSubstep + } + + trait MakesDoubleValueStepper extends Any { + def valueStepper: DoubleStepper with EfficientSubstep + } + + trait MakesIntStepper extends Any { + def stepper: IntStepper with EfficientSubstep + } + + trait MakesIntKeyStepper extends Any { + def keyStepper: IntStepper with EfficientSubstep + } + + trait MakesIntValueStepper extends Any { + def valueStepper: IntStepper with EfficientSubstep + } + + trait MakesLongStepper extends Any { + def stepper: LongStepper with EfficientSubstep + } + + trait MakesLongKeyStepper extends Any { + def keyStepper: LongStepper with EfficientSubstep + } + + trait MakesLongValueStepper extends Any { + def valueStepper: LongStepper with EfficientSubstep + } private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { @@ -605,52 +653,52 @@ package converterImpls { def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE } - final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) } - final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal{ - @inline def stepper: AnyStepper[A] = new StepsObjectArray[A](underlying, 0, underlying.length) + final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) } - final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: AnyStepper[Unit] = new StepsUnitArray(underlying, 0, underlying.length) + final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { + @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) } - final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: AnyStepper[Boolean] = new StepsBoxedBooleanArray(underlying, 0, underlying.length) + final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { + @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } - final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: AnyStepper[Byte] = new StepsBoxedByteArray(underlying, 0, underlying.length) + final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { + @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) } - final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal { - @inline def stepper: AnyStepper[Char] = new StepsBoxedCharArray(underlying, 0, underlying.length) + final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { + @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) } - final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: AnyStepper[Short] = new StepsBoxedShortArray(underlying, 0, underlying.length) + final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { + @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) } - final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal { - @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) + final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { + @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) } - final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) + final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) } - final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) + final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) + final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) + final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal { @@ -685,176 +733,191 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIterator(underlying) } - final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { - @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { + @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } - final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyVector[A](underlying, 0, underlying.length) + final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) } - final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = { + final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsAnyFlatHashTable(tbl, 0, tbl.length) } } - final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = { + final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsDoubleFlatHashTable(tbl, 0, tbl.length) } } - final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal { - @inline def stepper: IntStepper = { + final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsIntFlatHashTable(tbl, 0, tbl.length) } } - final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal { - @inline def stepper: LongStepper = { + final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsLongFlatHashTable(tbl, 0, tbl.length) } } - final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) extends AnyVal { - @inline def keyStepper: AnyStepper[K] = { + final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) + extends AnyVal with MakesAnyKeyStepper[K] { + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, HE](underlying) new StepsAnyHashTableKey(tbl, 0, tbl.length) } } - final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) extends AnyVal { - @inline def keyStepper: DoubleStepper = { + final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) + extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[Double, HE](underlying) new StepsDoubleHashTableKey(tbl, 0, tbl.length) } } - final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) extends AnyVal { - @inline def keyStepper: IntStepper = { + final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) + extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[Int, HE](underlying) new StepsIntHashTableKey(tbl, 0, tbl.length) } } - final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) extends AnyVal { - @inline def keyStepper: LongStepper = { + final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) + extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[Long, HE](underlying) new StepsLongHashTableKey(tbl, 0, tbl.length) } } - final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { - @inline def stepper: AnyStepper[(K,V)] = { + final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) + extends AnyVal with MakesAnyStepper[(K, V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTable(tbl, 0, tbl.length) } } - final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { - @inline def valueStepper: AnyStepper[V] = { + final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) + extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) extends AnyVal { - @inline def valueStepper: DoubleStepper = { + final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) + extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) extends AnyVal { - @inline def valueStepper: IntStepper = { + final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) + extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) extends AnyVal { - @inline def valueStepper: LongStepper = { + final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) + extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { - @inline def stepper: AnyStepper[(K,V)] = { + final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) + extends AnyVal with MakesAnyStepper[(K,V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTable(tbl, 0, tbl.length) } } - final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { - @inline def valueStepper: AnyStepper[V] = { + final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) + extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) extends AnyVal { - @inline def valueStepper: DoubleStepper = { + final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) + extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) extends AnyVal { - @inline def valueStepper: IntStepper = { + final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) + extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) extends AnyVal { - @inline def valueStepper: LongStepper = { + final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) + extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal { - @inline def stepper: AnyStepper[(K, V)] = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) - @inline def keyStepper: AnyStepper[K] = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) - @inline def valueStepper: AnyStepper[V] = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) + final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) + extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { + @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) } - final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal { - @inline def keyStepper: DoubleStepper = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) + final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) } - final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal { - @inline def valueStepper: DoubleStepper = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) + final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) } - final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal { - @inline def keyStepper: IntStepper = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) + final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) } - final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal { - @inline def valueStepper: IntStepper = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) + final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) } - final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal { - @inline def keyStepper: LongStepper = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) + final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) } - final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal { - @inline def valueStepper: LongStepper = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) + final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) } - final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyImmHashSet(underlying.iterator, underlying.size) + final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) } - final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal { - def stepper: IntStepper = { + final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { + def stepper: IntStepper with EfficientSubstep = { val bits: Array[Long] = underlying match { case m: collection.mutable.BitSet => runtime.CollectionInternals.getBitSetInternals(m) case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) @@ -868,7 +931,7 @@ package converterImpls { def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] } - private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { def characteristics() = NonNull def estimateSize = iN - i0 def hasNext = i0 < iN @@ -1060,55 +1123,55 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ import Stepper._ - implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleArray(underlying, 0, underlying.length) + implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) } - implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntArray(underlying, 0, underlying.length) + implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) } - implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongArray(underlying, 0, underlying.length) + implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) } - implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) + implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) } - implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntNumericRange(underlying, 0, underlying.length) + implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) } - implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongNumericRange(underlying, 0, underlying.length) - } - - implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntRange(underlying, 0, underlying.length) + implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) } - implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntVector(underlying, 0, underlying.length) + implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) + } + + implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) } - implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongVector(underlying, 0, underlying.length) + implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) } - implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) } - implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntImmHashSet(underlying.iterator, underlying.size) + implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) } - implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongImmHashSet(underlying.iterator, underlying.size) + implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) } - implicit class RichStringCanStep(val underlying: String) extends AnyVal { - @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) + implicit class RichStringCanStep(val underlying: String) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index d45a205..cf07193 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -4,6 +4,7 @@ import language.implicitConversions import java.util.stream._ import scala.compat.java8.collectionImpl._ +import scala.compat.java8.converterImpls._ trait PrimitiveStreamAccumulator[S, AA] { def streamAccumulate(stream: S): AA @@ -13,7 +14,7 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority3StreamConverters { +trait Priority6StreamConverters { implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { private def mkAcc() = { val acc = new Accumulator[A] @@ -27,7 +28,7 @@ trait Priority3StreamConverters { } } -trait Priority2StreamConverters extends Priority3StreamConverters { +trait Priority5StreamConverters extends Priority6StreamConverters { implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { if (t.isTraversableAgain && t.hasDefiniteSize) { @@ -43,8 +44,21 @@ trait Priority2StreamConverters extends Priority3StreamConverters { java.util.Arrays.stream(mkArr()) def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel + } +} + +trait Priority4StreamConverters extends Priority5StreamConverters { + implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { + def seqStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, false) + def parStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, true) } +} +trait Priority3StreamConverters extends Priority4StreamConverters { + +} + +trait Priority2StreamConverters extends Priority3StreamConverters { implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { private def mkAcc() = { val acc = new Accumulator[A] diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index af5c22a..0295d77 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -38,6 +38,12 @@ import java.util.Spliterator */ trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {} +/** An (optional) marker trait that indicates that a `Stepper` can call `substep` with + * at worst O(log N) time and space complexity, and that the division is likely to + * be reasonably even. + */ +trait EfficientSubstep {} + /** Provides functionality for Stepper while keeping track of a more precise type of the collection. */ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala index 87bb295..ab8f2e1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala @@ -35,7 +35,8 @@ abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val u */ abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) - with AnyStepper[A] + with AnyStepper[A] + with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -44,7 +45,8 @@ abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underly */ abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) - with DoubleStepper + with DoubleStepper + with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -53,7 +55,8 @@ abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_u */ abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) - with IntStepper + with IntStepper + with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -63,4 +66,5 @@ abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underly abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) with LongStepper + with EfficientSubstep {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index b9dfa55..6a55395 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -24,22 +24,26 @@ abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] + with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Ints */ abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Longs */ abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper + with EfficientSubstep {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala index a6f2110..d7a1fdb 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala @@ -19,22 +19,26 @@ abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] + with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) with DoubleStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) with IntStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) with LongStepper + with EfficientSubstep {} From 3f02f54749b4c03822198678ec056bfbe606a4da Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 24 Oct 2015 20:59:27 -0700 Subject: [PATCH 34/56] Modified stream converters to mostly defer to StepConverters. --- .../scala/compat/java8/StreamConverters.scala | 171 ++++++------------ .../compat/java8/collectionImpl/Stepper.scala | 3 + .../compat/java8/StreamConvertersTest.scala | 1 + 3 files changed, 56 insertions(+), 119 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index cf07193..d2e3997 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -15,22 +15,24 @@ trait PrimitiveStreamUnboxer[A, S] { } trait Priority6StreamConverters { - implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { + // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. + implicit class EnrichAnyScalaCollectionWithStream[A, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { private def mkAcc() = { val acc = new Accumulator[A] - t.foreach{ acc += _ } + ev(cc).foreach{ acc += _ } acc } def seqStream: Stream[A] = mkAcc().seqStream def parStream: Stream[A] = mkAcc().parStream - } + } } trait Priority5StreamConverters extends Priority6StreamConverters { - implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { + implicit class EnrichScalaCollectionWithStream[A <: AnyRef, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { + val t = ev(cc) if (t.isTraversableAgain && t.hasDefiniteSize) { val sz = t.size val a = new Array[A](sz) @@ -49,62 +51,62 @@ trait Priority5StreamConverters extends Priority6StreamConverters { trait Priority4StreamConverters extends Priority5StreamConverters { implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { - def seqStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, false) - def parStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, true) + def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) + def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichAnyKeySteppableWithStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeyStepper[K]) { + def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) + def parKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichAnyValueSteppableWithStream[V, CC](cc: CC)(implicit steppize: CC => MakesAnyValueStepper[V]) { + def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) + def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) } } trait Priority3StreamConverters extends Priority4StreamConverters { - -} - -trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { - private def mkAcc() = { - val acc = new Accumulator[A] - var i = 0 - while (i < a.length) { - acc += a(i) - i += 1 - } - acc - } - - def seqStream: Stream[A] = mkAcc().seqStream - - def parStream: Stream[A] = mkAcc().parStream + implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) { + def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) + def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) } -} - -trait Priority1StreamConverters extends Priority2StreamConverters { - implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { - def seqStream: Stream[A] = java.util.Arrays.stream(a) - def parStream: Stream[A] = seqStream.parallel + implicit class EnrichDoubleKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeyStepper) { + def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) + def parKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper.anticipateParallelism, true) } - - implicit class EnrichGenericIndexedSeqWithStream[A](c: collection.IndexedSeqLike[A, _]) { - private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyIndexedSeq[A](c, 0, c.length), parallel) - def seqStream: Stream[A] = someStream(false) - def parStream: Stream[A] = someStream(true) + implicit class EnrichDoubleValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleValueStepper) { + def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) + def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) } - - implicit class EnrichAnyVectorWithStream[A](c: Vector[A]) { - private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyVector[A](c, 0, c.length), parallel) - def seqStream: Stream[A] = someStream(false) - def parStream: Stream[A] = someStream(true) + implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) { + def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) + def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) } - - implicit class EnrichGenericFlatHashTableWithStream[A](fht: collection.mutable.FlatHashTable[A]) { - private def someStream(parallel: Boolean): Stream[A] = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.stream(new converterImpls.StepsAnyFlatHashTable[A](tbl, 0, tbl.length), parallel) - } - def seqStream: Stream[A] = someStream(false) - def parStream: Stream[A] = someStream(true) + implicit class EnrichIntKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntKeyStepper) { + def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) + def parKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichIntValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntValueStepper) { + def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) + def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) + } + implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) { + def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) + def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichLongKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongKeyStepper) { + def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) + def parKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper.anticipateParallelism, true) } + implicit class EnrichLongValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongValueStepper) { + def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) + def parValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper.anticipateParallelism, true) + } +} +trait Priority2StreamConverters extends Priority3StreamConverters { +} + +trait Priority1StreamConverters extends Priority2StreamConverters { implicit class RichStream[A](stream: Stream[A]) { def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) @@ -161,75 +163,6 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * ``` */ object StreamConverters extends Priority1StreamConverters { - implicit class EnrichDoubleIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Double, _]](c: CC) { - private def someStream(parallel: Boolean): DoubleStream = - StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeq[CC](c, 0, c.length), parallel) - def seqStream: DoubleStream = someStream(false) - def parStream: DoubleStream = someStream(true) - } - - implicit class EnrichIntIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Int, _]](c: CC) { - private def someStream(parallel: Boolean): IntStream = - StreamSupport.intStream(new converterImpls.StepsIntIndexedSeq[CC](c, 0, c.length), parallel) - def seqStream: IntStream = someStream(false) - def parStream: IntStream = someStream(true) - } - - implicit class EnrichLongIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Long, _]](c: CC) { - private def someStream(parallel: Boolean): LongStream = - StreamSupport.longStream(new converterImpls.StepsLongIndexedSeq[CC](c, 0, c.length), parallel) - def seqStream: LongStream = someStream(false) - def parStream: LongStream = someStream(true) - } - - implicit class EnrichDoubleVectorWithStream(c: Vector[Double]) { - private def someStream(parallel: Boolean): DoubleStream = - StreamSupport.doubleStream(new converterImpls.StepsDoubleVector(c, 0, c.length), parallel) - def seqStream: DoubleStream = someStream(false) - def parStream: DoubleStream = someStream(true) - } - - implicit class EnrichIntVectorWithStream(c: Vector[Int]) { - private def someStream(parallel: Boolean): IntStream = - StreamSupport.intStream(new converterImpls.StepsIntVector(c, 0, c.length), parallel) - def seqStream: IntStream = someStream(false) - def parStream: IntStream = someStream(true) - } - - implicit class EnrichLongVectorWithStream(c: Vector[Long]) { - private def someStream(parallel: Boolean): LongStream = - StreamSupport.longStream(new converterImpls.StepsLongVector(c, 0, c.length), parallel) - def seqStream: LongStream = someStream(false) - def parStream: LongStream = someStream(true) - } - - implicit class EnrichDoubleFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Double]) { - private def someStream(parallel: Boolean): DoubleStream = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.doubleStream(new converterImpls.StepsDoubleFlatHashTable(tbl, 0, tbl.length), parallel) - } - def seqStream: DoubleStream = someStream(false) - def parStream: DoubleStream = someStream(true) - } - - implicit class EnrichIntFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Int]) { - private def someStream(parallel: Boolean): IntStream = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.intStream(new converterImpls.StepsIntFlatHashTable(tbl, 0, tbl.length), parallel) - } - def seqStream: IntStream = someStream(false) - def parStream: IntStream = someStream(true) - } - - implicit class EnrichLongFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Long]) { - private def someStream(parallel: Boolean): LongStream = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.longStream(new converterImpls.StepsLongFlatHashTable(tbl, 0, tbl.length), parallel) - } - def seqStream: LongStream = someStream(false) - def parStream: LongStream = someStream(true) - } - implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 0295d77..ddacdd3 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -85,6 +85,9 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => /** Returns the precise underlying type of this `Stepper`. */ def typedPrecisely: CC + + /** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */ + def anticipateParallelism: this.type = this //// diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 9a5b7f9..5799712 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -6,6 +6,7 @@ import org.junit.Assert._ class StreamConvertersTest { import java.util.stream._ import StreamConverters._ + import StepConverters._ def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } From ace87d433aa41aa7d6e74540bb80451d99c5d64c Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 25 Oct 2015 20:56:25 -0700 Subject: [PATCH 35/56] Finished transition to only allowing parStream on Steppers that support it well. Not tested. --- .../scala/compat/java8/StepConverters.scala | 294 +++++++++++++----- .../scala/compat/java8/StreamConverters.scala | 71 +++-- .../compat/java8/StepConvertersTest.scala | 12 +- 3 files changed, 260 insertions(+), 117 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 7117628..9a93367 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,6 +8,54 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ + trait MakesAnySeqStepper[A] extends Any { + def stepper: AnyStepper[A] + } + + trait MakesAnyKeySeqStepper[A] extends Any { + def keyStepper: AnyStepper[A] + } + + trait MakesAnyValueSeqStepper[A] extends Any { + def valueStepper: AnyStepper[A] + } + + trait MakesDoubleSeqStepper extends Any { + def stepper: DoubleStepper + } + + trait MakesDoubleKeySeqStepper extends Any { + def keyStepper: DoubleStepper + } + + trait MakesDoubleValueSeqStepper extends Any { + def valueStepper: DoubleStepper + } + + trait MakesIntSeqStepper extends Any { + def stepper: IntStepper + } + + trait MakesIntKeySeqStepper extends Any { + def keyStepper: IntStepper + } + + trait MakesIntValueSeqStepper extends Any { + def valueStepper: IntStepper + } + + trait MakesLongSeqStepper extends Any { + def stepper: LongStepper + } + + trait MakesLongKeySeqStepper extends Any { + def keyStepper: LongStepper + } + + trait MakesLongValueSeqStepper extends Any { + def valueStepper: LongStepper + } + trait MakesAnyStepper[A] extends Any { def stepper: AnyStepper[A] with EfficientSubstep } @@ -701,35 +749,35 @@ package converterImpls { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal { + final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) } - final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal { + final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) } - final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal { + final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) } - final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal { + final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) } - final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal { + final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) } - final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal { + final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) } - final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal { + final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { @inline def stepper: IntStepper = new StepsIntIterator(underlying) } - final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal { + final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { @inline def stepper: LongStepper = new StepsLongIterator(underlying) } @@ -955,75 +1003,111 @@ package converterImpls { } } - final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal { + final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) } - final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal { + final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) } - final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal { + final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) } - final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal { + final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) } - final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal { + final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) } - final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal { + final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) } - final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal { + final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) } - final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def stepper: AnyStepper[A] = { - val acc = new Accumulator[A] - underlying.foreach(acc += _) - acc.stepper - } + final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) } - final class RichDoubleTraversableOnceCanStep(private val underlying: TraversableOnce[Double]) extends AnyVal { - def stepper: DoubleStepper = { - val acc = new DoubleAccumulator - underlying.foreach(acc += _) - acc.stepper - } + final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) } - final class RichIntTraversableOnceCanStep(private val underlying: TraversableOnce[Int]) extends AnyVal { - def stepper: IntStepper = { - val acc = new IntAccumulator - underlying.foreach(acc += _) - acc.stepper - } + final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) } - final class RichLongTraversableOnceCanStep(private val underlying: TraversableOnce[Long]) extends AnyVal { - def stepper: LongStepper = { - val acc = new LongAccumulator - underlying.foreach(acc += _) - acc.stepper - } + final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) + } + + final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) + } + + final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) + } + + final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) + } + + final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) + } + + final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) + } + + final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) + } + + final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) + } + + final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) + } + + final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) + } + + final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + } + + final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) + } + + final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) } + final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) + } + trait Priority7StepConverters { - implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) + implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) } trait Priority6StepConverters extends Priority7StepConverters { - implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) - implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) - implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) + implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) + implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) + implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } @@ -1117,61 +1201,109 @@ package converterImpls { implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) } -} -object StepConverters extends converterImpls.Priority2StepConverters { - import converterImpls._ - import Stepper._ + trait Priority1StepConverters extends Priority2StepConverters { + implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) + implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) + implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) + + implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) + implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) + implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) - implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) + implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) + implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) + implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) + + implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) + implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) + implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) + + implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } - implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) + final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + underlying.foreach(a += _) + a + } } - - implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) + + final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + underlying.foreach(da += _) + da + } } - - implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) + final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + underlying.foreach(da += _) + da + } } - - implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) + final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + underlying.foreach(da += _) + da + } } - - implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) - } - - implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) + final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + var i = 0 + while (i < underlying.length) { a += underlying(i); i += 1 } + a + } } - implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) + final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } } - - implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) + final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } } - - implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } } - implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) + trait Priority3AccumulatorConverters { + implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) } - implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) + trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { + implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) + implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) } - implicit class RichStringCanStep(val underlying: String) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) + trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { + implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) + implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) + implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) } } + +object StepConverters +extends converterImpls.Priority1StepConverters +with converterImpls.Priority1AccumulatorConverters +{} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index d2e3997..60d7114 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -14,42 +14,50 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority6StreamConverters { +trait Priority5StreamConverters { // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. - implicit class EnrichAnyScalaCollectionWithStream[A, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { - private def mkAcc() = { - val acc = new Accumulator[A] - ev(cc).foreach{ acc += _ } - acc - } - - def seqStream: Stream[A] = mkAcc().seqStream - - def parStream: Stream[A] = mkAcc().parStream + implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) { + def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeySeqStepper[K]) { + def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) + } + implicit class EnrichScalaCollectionWithValueSeqStream[V, CC](cc: CC)(implicit steppize: CC => MakesAnyValueSeqStepper[V]) { + def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) } } -trait Priority5StreamConverters extends Priority6StreamConverters { - implicit class EnrichScalaCollectionWithStream[A <: AnyRef, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { - private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { - val t = ev(cc) - if (t.isTraversableAgain && t.hasDefiniteSize) { - val sz = t.size - val a = new Array[A](sz) - t.copyToArray(a, 0, sz) - a - } - else t.toArray[A] - } - - def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = - java.util.Arrays.stream(mkArr()) - - def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel +trait Priority4StreamConverters extends Priority5StreamConverters { + implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) { + def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) { + def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) { + def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeySeqStepper) { + def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) } + implicit class EnrichScalaCollectionWithSeqIntKeyStream[CC](cc: CC)(implicit steppize: CC => MakesIntKeySeqStepper) { + def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) + } + implicit class EnrichScalaCollectionWithSeqLongKeyStream[CC](cc: CC)(implicit steppize: CC => MakesLongKeySeqStepper) { + def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) + } + implicit class EnrichScalaCollectionWithSeqDoubleValueStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleValueSeqStepper) { + def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) + } + implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesIntValueSeqStepper) { + def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) + } + implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesLongValueSeqStepper) { + def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) + } } -trait Priority4StreamConverters extends Priority5StreamConverters { +trait Priority3StreamConverters extends Priority4StreamConverters { implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) @@ -64,7 +72,7 @@ trait Priority4StreamConverters extends Priority5StreamConverters { } } -trait Priority3StreamConverters extends Priority4StreamConverters { +trait Priority2StreamConverters extends Priority3StreamConverters { implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) @@ -103,9 +111,6 @@ trait Priority3StreamConverters extends Priority4StreamConverters { } } -trait Priority2StreamConverters extends Priority3StreamConverters { -} - trait Priority1StreamConverters extends Priority2StreamConverters { implicit class RichStream[A](stream: Stream[A]) { def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index c227463..d0fb173 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -47,6 +47,12 @@ class StepConvertersTest { assert(isLin(x)) } + def Fine[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + assert(!isAcc(x)) + } + def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) @@ -81,9 +87,9 @@ class StepConvertersTest { Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.SortedSet[String]("salmon").stepper ) - IFFY( co.Traversable[String]("salmon").stepper ) - IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) - IFFY( co.Traversable[String]("salmon").view.stepper ) + IFFY( co.Traversable[String]("salmon").accumulate.stepper ) + IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).accumulate.stepper ) + IFFY( co.Traversable[String]("salmon").view.accumulate.stepper ) // Immutable section IFFY( ci.::("salmon", Nil).stepper ) From 72fb53dcf27cc663bcf1aa3baab303bee8faca6b Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 19:28:07 -0800 Subject: [PATCH 36/56] Fixed up tests after disallowing implicit Accumulator creation. --- .../compat/java8/collectionImpl/Stepper.scala | 9 + .../compat/java8/StepConvertersTest.scala | 294 +++++++++--------- .../compat/java8/StreamConvertersTest.scala | 8 +- 3 files changed, 160 insertions(+), 151 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index ddacdd3..730fef8 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -161,6 +161,7 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => } } + /** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false @@ -224,6 +225,8 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def trySplit() = substep.typedPrecisely final def typedPrecisely: AnyStepper[A] = this override def spliterator: Spliterator[A] = this + def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false) + def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true) } /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ @@ -239,6 +242,8 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD def trySplit() = substep.typedPrecisely final def typedPrecisely: DoubleStepper = this override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double + def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false) + def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, true) } /** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ @@ -254,6 +259,8 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit def trySplit() = substep.typedPrecisely final def typedPrecisely = this override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int + def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false) + def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, true) } /** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ @@ -269,6 +276,8 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong def trySplit() = substep.typedPrecisely final def typedPrecisely = this override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long + def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false) + def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, true) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index d0fb173..c3f1663 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -73,27 +73,27 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[String]("salmon").buffered.stepper ) good( co.IndexedSeq[String]("salmon").stepper ) - IFFY( co.Iterable[String]("salmon").stepper ) - IFFY( co.Iterable[String]("salmon").view.stepper ) + Okay( co.Iterable[String]("salmon").stepper ) + Okay( co.Iterable[String]("salmon").view.stepper ) Okay( co.Iterator[String]("salmon").stepper ) Okay( co.LinearSeq[String]("salmon").stepper ) - IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) + Okay( co.Map[String, String]("fish" -> "salmon").stepper ) Okay( co.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( co.Map[String, String]("fish" -> "salmon").valueStepper ) - IFFY( co.Seq[String]("salmon").stepper ) - IFFY( co.Seq[String]("salmon").view.stepper ) - IFFY( co.Set[String]("salmon").stepper ) - IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + Okay( co.Seq[String]("salmon").stepper ) + Okay( co.Seq[String]("salmon").view.stepper ) + Okay( co.Set[String]("salmon").stepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").stepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( co.SortedSet[String]("salmon").stepper ) + Okay( co.SortedSet[String]("salmon").stepper ) IFFY( co.Traversable[String]("salmon").accumulate.stepper ) IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).accumulate.stepper ) IFFY( co.Traversable[String]("salmon").view.accumulate.stepper ) // Immutable section - IFFY( ci.::("salmon", Nil).stepper ) - IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + Okay( ci.::("salmon", Nil).stepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) @@ -101,46 +101,46 @@ class StepConvertersTest { good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) - IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").stepper ) Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) - IFFY( ci.Iterable[String]("salmon").stepper ) + Okay( ci.Iterable[String]("salmon").stepper ) Okay( ci.LinearSeq[String]("salmon").stepper ) Okay( ci.List[String]("salmon").stepper ) - IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.ListSet[String]("salmon").stepper ) - IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( ci.ListSet[String]("salmon").stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").stepper ) Okay( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) - IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").stepper ) Okay( ci.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.Map[String, String]("fish" -> "salmon").valueStepper ) Okay( ci.Queue[String]("salmon").stepper ) - IFFY( ci.Seq[String]("salmon").stepper ) - IFFY( ci.Set[String]("salmon").stepper ) - IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.Seq[String]("salmon").stepper ) + Okay( ci.Set[String]("salmon").stepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.SortedSet[String]("salmon").stepper ) + Okay( ci.SortedSet[String]("salmon").stepper ) Okay( ci.Stack[String]("salmon").stepper ) Okay( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) - IFFY( ci.Traversable[String]("salmon").stepper ) - IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.Traversable[String]("salmon").accumulate.stepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.TreeSet[String]("salmon").stepper ) + Okay( ci.TreeSet[String]("salmon").stepper ) good( ci.Vector[String]("salmon").stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) - IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) - IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) + Okay( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) - IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) - IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) - IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) + Okay( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) @@ -148,43 +148,43 @@ class StepConvertersTest { good( (Array("salmon"): cm.ArrayOps[String]).stepper ) good( cm.ArraySeq[String]("salmon").stepper ) _eh_( cm.ArrayStack[String]("salmon").stepper ) - IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) good( cm.HashMap[String, String]("fish" -> "salmon").stepper ) good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) - IFFY( cm.Iterable[String]("salmon").stepper ) + Okay( cm.Iterable[String]("salmon").stepper ) Okay( cm.LinearSeq[String]("salmon").stepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( cm.LinkedHashSet[String]("salmon").stepper ) - IFFY( cm.ListBuffer[String]("salmon").stepper ) - IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.LinkedHashSet[String]("salmon").stepper ) + Okay( cm.ListBuffer[String]("salmon").stepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) - IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").stepper ) Okay( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) - IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").stepper ) Okay( cm.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.Map[String, String]("fish" -> "salmon").valueStepper ) Okay( cm.MutableList[String]("salmon").stepper ) - IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( cm.PriorityQueue[String]("salmon").stepper ) + Okay( cm.PriorityQueue[String]("salmon").stepper ) Okay( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) - IFFY( cm.Seq[String]("salmon").stepper ) - IFFY( cm.Set[String]("salmon").stepper ) - IFFY( cm.SortedSet[String]("salmon").stepper ) - IFFY( cm.Stack[String]("salmon").stepper ) - IFFY( cm.Traversable[String]("salmon").stepper ) - IFFY( cm.TreeSet[String]("salmon").stepper ) - IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) - IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.Seq[String]("salmon").stepper ) + Okay( cm.Set[String]("salmon").stepper ) + Okay( cm.SortedSet[String]("salmon").stepper ) + Okay( cm.Stack[String]("salmon").stepper ) + IFFY( cm.Traversable[String]("salmon").accumulate.stepper ) + Okay( cm.TreeSet[String]("salmon").stepper ) + Okay( cm.UnrolledBuffer[String]("salmon").stepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) good( (Array("salmon"): cm.WrappedArray[String]).stepper ) @@ -192,10 +192,10 @@ class StepConvertersTest { // Java 6 converters section // Concurrent section - IFFY( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) - IFFY( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).keyStepper ) Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).valueStepper ) } @@ -208,24 +208,24 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[Double](3.14159).buffered.stepper ) good( co.IndexedSeq[Double](3.14159).stepper ) - IFFY( co.Iterable[Double](3.14159).stepper ) - IFFY( co.Iterable[Double](3.14159).view.stepper ) + Okay( co.Iterable[Double](3.14159).stepper ) + Okay( co.Iterable[Double](3.14159).view.stepper ) Okay( co.Iterator[Double](3.14159).stepper ) Okay( co.LinearSeq[Double](3.14159).stepper ) Okay( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( co.Seq[Double](3.14159).stepper ) - IFFY( co.Seq[Double](3.14159).view.stepper ) - IFFY( co.Set[Double](3.14159).stepper ) + Okay( co.Seq[Double](3.14159).stepper ) + Okay( co.Seq[Double](3.14159).view.stepper ) + Okay( co.Set[Double](3.14159).stepper ) Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( co.SortedSet[Double](3.14159).stepper ) - IFFY( co.Traversable[Double](3.14159).stepper ) - IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) - IFFY( co.Traversable[Double](3.14159).view.stepper ) + Okay( co.SortedSet[Double](3.14159).stepper ) + IFFY( co.Traversable[Double](3.14159).accumulate.stepper ) + IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).accumulate.stepper ) + IFFY( co.Traversable[Double](3.14159).view.accumulate.stepper ) // Immutable section - IFFY( ci.::(3.14159, Nil).stepper ) + Okay( ci.::(3.14159, Nil).stepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) @@ -233,55 +233,55 @@ class StepConvertersTest { good( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) - IFFY( ci.Iterable[Double](3.14159).stepper ) + Okay( ci.Iterable[Double](3.14159).stepper ) Okay( ci.LinearSeq[Double](3.14159).stepper ) Okay( ci.List[Double](3.14159).stepper ) Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.ListSet[Double](3.14159).stepper ) + Okay( ci.ListSet[Double](3.14159).stepper ) Okay( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( ci.Queue[Double](3.14159).stepper ) - IFFY( ci.Seq[Double](3.14159).stepper ) - IFFY( ci.Set[Double](3.14159).stepper ) + Okay( ci.Seq[Double](3.14159).stepper ) + Okay( ci.Set[Double](3.14159).stepper ) Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.SortedSet[Double](3.14159).stepper ) + Okay( ci.SortedSet[Double](3.14159).stepper ) Okay( ci.Stack[Double](3.14159).stepper ) Okay( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) - IFFY( ci.Traversable[Double](3.14159).stepper ) + IFFY( ci.Traversable[Double](3.14159).accumulate.stepper ) Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.TreeSet[Double](3.14159).stepper ) + Okay( ci.TreeSet[Double](3.14159).stepper ) good( ci.Vector[Double](3.14159).stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) - IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) + Okay( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) - IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) - IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) + Okay( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) Okay( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) - IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) - IFFY( cm.Iterable[Double](3.14159).stepper ) + Okay( cm.Iterable[Double](3.14159).stepper ) Okay( cm.LinearSeq[Double](3.14159).stepper ) good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) - IFFY( cm.ListBuffer[Double](3.14159).stepper ) + Okay( cm.LinkedHashSet[Double](3.14159).stepper ) + Okay( cm.ListBuffer[Double](3.14159).stepper ) Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) @@ -290,16 +290,16 @@ class StepConvertersTest { Okay( cm.MutableList[Double](3.14159).stepper ) Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( cm.PriorityQueue[Double](3.14159).stepper ) + Okay( cm.PriorityQueue[Double](3.14159).stepper ) Okay( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) - IFFY( cm.Seq[Double](3.14159).stepper ) - IFFY( cm.Set[Double](3.14159).stepper ) - IFFY( cm.SortedSet[Double](3.14159).stepper ) - IFFY( cm.Stack[Double](3.14159).stepper ) - IFFY( cm.Traversable[Double](3.14159).stepper ) - IFFY( cm.TreeSet[Double](3.14159).stepper ) - IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) + Okay( cm.Seq[Double](3.14159).stepper ) + Okay( cm.Set[Double](3.14159).stepper ) + Okay( cm.SortedSet[Double](3.14159).stepper ) + Okay( cm.Stack[Double](3.14159).stepper ) + IFFY( cm.Traversable[Double](3.14159).accumulate.stepper ) + Okay( cm.TreeSet[Double](3.14159).stepper ) + Okay( cm.UnrolledBuffer[Double](3.14159).stepper ) Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) @@ -330,24 +330,24 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[Int](654321).buffered.stepper ) good( co.IndexedSeq[Int](654321).stepper ) - IFFY( co.Iterable[Int](654321).stepper ) - IFFY( co.Iterable[Int](654321).view.stepper ) + Okay( co.Iterable[Int](654321).stepper ) + Okay( co.Iterable[Int](654321).view.stepper ) Okay( co.Iterator[Int](654321).stepper ) Okay( co.LinearSeq[Int](654321).stepper ) Okay( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( co.Seq[Int](654321).stepper ) - IFFY( co.Seq[Int](654321).view.stepper ) - IFFY( co.Set[Int](654321).stepper ) + Okay( co.Seq[Int](654321).stepper ) + Okay( co.Seq[Int](654321).view.stepper ) + Okay( co.Set[Int](654321).stepper ) Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( co.SortedSet[Int](654321).stepper ) - IFFY( co.Traversable[Int](654321).stepper ) - IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) - IFFY( co.Traversable[Int](654321).view.stepper ) + Okay( co.SortedSet[Int](654321).stepper ) + IFFY( co.Traversable[Int](654321).accumulate.stepper ) + IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).accumulate.stepper ) + IFFY( co.Traversable[Int](654321).view.accumulate.stepper ) // Immutable section - IFFY( ci.::(654321, Nil).stepper ) + Okay( ci.::(654321, Nil).stepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) @@ -356,55 +356,55 @@ class StepConvertersTest { good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) - IFFY( ci.Iterable[Int](654321).stepper ) + Okay( ci.Iterable[Int](654321).stepper ) Okay( ci.LinearSeq[Int](654321).stepper ) Okay( ci.List[Int](654321).stepper ) Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.ListSet[Int](654321).stepper ) + Okay( ci.ListSet[Int](654321).stepper ) Okay( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) Okay( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( ci.Queue[Int](654321).stepper ) - IFFY( ci.Seq[Int](654321).stepper ) - IFFY( ci.Set[Int](654321).stepper ) + Okay( ci.Seq[Int](654321).stepper ) + Okay( ci.Set[Int](654321).stepper ) Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.SortedSet[Int](654321).stepper ) + Okay( ci.SortedSet[Int](654321).stepper ) Okay( ci.Stack[Int](654321).stepper ) Okay( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) - IFFY( ci.Traversable[Int](654321).stepper ) + IFFY( ci.Traversable[Int](654321).accumulate.stepper ) Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.TreeSet[Int](654321).stepper ) + Okay( ci.TreeSet[Int](654321).stepper ) good( ci.Vector[Int](654321).stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) - IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) + Okay( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) - IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) - IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) + Okay( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) Okay( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) good( (Array(654321): cm.ArrayOps[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) - IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) - IFFY( cm.Iterable[Int](654321).stepper ) + Okay( cm.Iterable[Int](654321).stepper ) Okay( cm.LinearSeq[Int](654321).stepper ) good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( cm.LinkedHashSet[Int](654321).stepper ) - IFFY( cm.ListBuffer[Int](654321).stepper ) + Okay( cm.LinkedHashSet[Int](654321).stepper ) + Okay( cm.ListBuffer[Int](654321).stepper ) Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) @@ -413,16 +413,16 @@ class StepConvertersTest { Okay( cm.MutableList[Int](654321).stepper ) Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( cm.PriorityQueue[Int](654321).stepper ) + Okay( cm.PriorityQueue[Int](654321).stepper ) Okay( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) - IFFY( cm.Seq[Int](654321).stepper ) - IFFY( cm.Set[Int](654321).stepper ) - IFFY( cm.SortedSet[Int](654321).stepper ) - IFFY( cm.Stack[Int](654321).stepper ) - IFFY( cm.Traversable[Int](654321).stepper ) - IFFY( cm.TreeSet[Int](654321).stepper ) - IFFY( cm.UnrolledBuffer[Int](654321).stepper ) + Okay( cm.Seq[Int](654321).stepper ) + Okay( cm.Set[Int](654321).stepper ) + Okay( cm.SortedSet[Int](654321).stepper ) + Okay( cm.Stack[Int](654321).stepper ) + IFFY( cm.Traversable[Int](654321).accumulate.stepper ) + Okay( cm.TreeSet[Int](654321).stepper ) + Okay( cm.UnrolledBuffer[Int](654321).stepper ) Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( (Array(654321): cm.WrappedArray[Int]).stepper ) @@ -452,24 +452,24 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[Long](0x123456789L).buffered.stepper ) good( co.IndexedSeq[Long](0x123456789L).stepper ) - IFFY( co.Iterable[Long](0x123456789L).stepper ) - IFFY( co.Iterable[Long](0x123456789L).view.stepper ) + Okay( co.Iterable[Long](0x123456789L).stepper ) + Okay( co.Iterable[Long](0x123456789L).view.stepper ) Okay( co.Iterator[Long](0x123456789L).stepper ) Okay( co.LinearSeq[Long](0x123456789L).stepper ) Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( co.Seq[Long](0x123456789L).stepper ) - IFFY( co.Seq[Long](0x123456789L).view.stepper ) - IFFY( co.Set[Long](0x123456789L).stepper ) + Okay( co.Seq[Long](0x123456789L).stepper ) + Okay( co.Seq[Long](0x123456789L).view.stepper ) + Okay( co.Set[Long](0x123456789L).stepper ) Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( co.SortedSet[Long](0x123456789L).stepper ) - IFFY( co.Traversable[Long](0x123456789L).stepper ) - IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) - IFFY( co.Traversable[Long](0x123456789L).view.stepper ) + Okay( co.SortedSet[Long](0x123456789L).stepper ) + IFFY( co.Traversable[Long](0x123456789L).accumulate.stepper ) + IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).accumulate.stepper ) + IFFY( co.Traversable[Long](0x123456789L).view.accumulate.stepper ) // Immutable section - IFFY( ci.::(0x123456789L, Nil).stepper ) + Okay( ci.::(0x123456789L, Nil).stepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) @@ -477,56 +477,56 @@ class StepConvertersTest { good( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) - IFFY( ci.Iterable[Long](0x123456789L).stepper ) + Okay( ci.Iterable[Long](0x123456789L).stepper ) Okay( ci.LinearSeq[Long](0x123456789L).stepper ) Okay( ci.List[Long](0x123456789L).stepper ) Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.ListSet[Long](0x123456789L).stepper ) + Okay( ci.ListSet[Long](0x123456789L).stepper ) Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( ci.Queue[Long](0x123456789L).stepper ) - IFFY( ci.Seq[Long](0x123456789L).stepper ) - IFFY( ci.Set[Long](0x123456789L).stepper ) + Okay( ci.Seq[Long](0x123456789L).stepper ) + Okay( ci.Set[Long](0x123456789L).stepper ) Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.SortedSet[Long](0x123456789L).stepper ) + Okay( ci.SortedSet[Long](0x123456789L).stepper ) Okay( ci.Stack[Long](0x123456789L).stepper ) Okay( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) - IFFY( ci.Traversable[Long](0x123456789L).stepper ) + IFFY( ci.Traversable[Long](0x123456789L).accumulate.stepper ) Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.TreeSet[Long](0x123456789L).stepper ) + Okay( ci.TreeSet[Long](0x123456789L).stepper ) good( ci.Vector[Long](0x123456789L).stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) - IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) + Okay( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) - IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) - IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) + Okay( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) Okay( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) - IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) - IFFY( cm.Iterable[Long](0x123456789L).stepper ) + Okay( cm.Iterable[Long](0x123456789L).stepper ) Okay( cm.LinearSeq[Long](0x123456789L).stepper ) good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) - IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) + Okay( cm.LinkedHashSet[Long](0x123456789L).stepper ) + Okay( cm.ListBuffer[Long](0x123456789L).stepper ) Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) @@ -536,16 +536,16 @@ class StepConvertersTest { Okay( cm.MutableList[Long](0x123456789L).stepper ) Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) + Okay( cm.PriorityQueue[Long](0x123456789L).stepper ) Okay( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) - IFFY( cm.Seq[Long](0x123456789L).stepper ) - IFFY( cm.Set[Long](0x123456789L).stepper ) - IFFY( cm.SortedSet[Long](0x123456789L).stepper ) - IFFY( cm.Stack[Long](0x123456789L).stepper ) - IFFY( cm.Traversable[Long](0x123456789L).stepper ) - IFFY( cm.TreeSet[Long](0x123456789L).stepper ) - IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) + Okay( cm.Seq[Long](0x123456789L).stepper ) + Okay( cm.Set[Long](0x123456789L).stepper ) + Okay( cm.SortedSet[Long](0x123456789L).stepper ) + Okay( cm.Stack[Long](0x123456789L).stepper ) + IFFY( cm.Traversable[Long](0x123456789L).accumulate.stepper ) + Okay( cm.TreeSet[Long](0x123456789L).stepper ) + Okay( cm.UnrolledBuffer[Long](0x123456789L).stepper ) Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 5799712..6a452ec 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -135,7 +135,7 @@ class StreamConvertersTest { val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) - assertEq(seqO, seqO.parStream.toScala[Seq]) + //assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) assertEq(seqO, abO.seqStream.toScala[Seq]) @@ -154,7 +154,7 @@ class StreamConvertersTest { val vecD = vectD(n) val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) - assertEq(seqD, seqD.parStream.toScala[Seq]) + //assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) assertEq(seqD, arrD.parStream.toScala[Seq]) assert(arrD.seqStream.isInstanceOf[DoubleStream]) @@ -183,7 +183,7 @@ class StreamConvertersTest { val vecI = vectI(n) val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) - assertEq(seqI, seqI.parStream.toScala[Seq]) + //assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) assertEq(seqI, arrI.parStream.toScala[Seq]) assert(arrI.seqStream.isInstanceOf[IntStream]) @@ -212,7 +212,7 @@ class StreamConvertersTest { val vecL = vectL(n) val hsL = hsetL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) - assertEq(seqL, seqL.parStream.toScala[Seq]) + //assertEq(seqL, seqL.stepper.parStream.toScala[Seq]) assertEq(seqL, arrL.seqStream.toScala[Seq]) assertEq(seqL, arrL.parStream.toScala[Seq]) assert(arrL.seqStream.isInstanceOf[LongStream]) From 675f2edc11c02388d5fecad53f6416f1bb77674a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 20:20:33 -0800 Subject: [PATCH 37/56] Factored out MakeXyzStepper traits into `MakesSteppers`. --- .../scala/compat/java8/StepConverters.scala | 96 ----------- .../java8/collectionImpl/MakesSteppers.scala | 150 ++++++++++++++++++ .../compat/java8/collectionImpl/Stepper.scala | 8 +- .../compat/java8/StreamConvertersTest.scala | 6 +- 4 files changed, 157 insertions(+), 103 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 9a93367..d88e34c 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,102 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - trait MakesAnySeqStepper[A] extends Any { - def stepper: AnyStepper[A] - } - - trait MakesAnyKeySeqStepper[A] extends Any { - def keyStepper: AnyStepper[A] - } - - trait MakesAnyValueSeqStepper[A] extends Any { - def valueStepper: AnyStepper[A] - } - - trait MakesDoubleSeqStepper extends Any { - def stepper: DoubleStepper - } - - trait MakesDoubleKeySeqStepper extends Any { - def keyStepper: DoubleStepper - } - - trait MakesDoubleValueSeqStepper extends Any { - def valueStepper: DoubleStepper - } - - trait MakesIntSeqStepper extends Any { - def stepper: IntStepper - } - - trait MakesIntKeySeqStepper extends Any { - def keyStepper: IntStepper - } - - trait MakesIntValueSeqStepper extends Any { - def valueStepper: IntStepper - } - - trait MakesLongSeqStepper extends Any { - def stepper: LongStepper - } - - trait MakesLongKeySeqStepper extends Any { - def keyStepper: LongStepper - } - - trait MakesLongValueSeqStepper extends Any { - def valueStepper: LongStepper - } - - trait MakesAnyStepper[A] extends Any { - def stepper: AnyStepper[A] with EfficientSubstep - } - - trait MakesAnyKeyStepper[A] extends Any { - def keyStepper: AnyStepper[A] with EfficientSubstep - } - - trait MakesAnyValueStepper[A] extends Any { - def valueStepper: AnyStepper[A] with EfficientSubstep - } - - trait MakesDoubleStepper extends Any { - def stepper: DoubleStepper with EfficientSubstep - } - - trait MakesDoubleKeyStepper extends Any { - def keyStepper: DoubleStepper with EfficientSubstep - } - - trait MakesDoubleValueStepper extends Any { - def valueStepper: DoubleStepper with EfficientSubstep - } - - trait MakesIntStepper extends Any { - def stepper: IntStepper with EfficientSubstep - } - - trait MakesIntKeyStepper extends Any { - def keyStepper: IntStepper with EfficientSubstep - } - - trait MakesIntValueStepper extends Any { - def valueStepper: IntStepper with EfficientSubstep - } - - trait MakesLongStepper extends Any { - def stepper: LongStepper with EfficientSubstep - } - - trait MakesLongKeyStepper extends Any { - def keyStepper: LongStepper with EfficientSubstep - } - - trait MakesLongValueStepper extends Any { - def valueStepper: LongStepper with EfficientSubstep - } - private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE diff --git a/src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala new file mode 100644 index 0000000..8a78541 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala @@ -0,0 +1,150 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +/** Classes or objects implementing this trait create generic steppers suitable for sequential use. */ +trait MakesAnySeqStepper[A] extends Any { + /** Generates a fresh stepper over `A`s suitable for sequential use */ + def stepper: AnyStepper[A] +} + +/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential use. */ +trait MakesAnyKeySeqStepper[A] extends Any { + /** Generates a fresh stepper over map keys of type `A` suitable for sequential use */ + def keyStepper: AnyStepper[A] +} + +/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential use. */ +trait MakesAnyValueSeqStepper[A] extends Any { + /** Generates a fresh stepper over map values of type `A` suitable for sequential use */ + def valueStepper: AnyStepper[A] +} + +/** Classes or objects implementing this trait create `Double` steppers suitable for sequential use. */ +trait MakesDoubleSeqStepper extends Any { + /** Generates a fresh stepper over `Double`s suitable for sequential use */ + def stepper: DoubleStepper +} + +/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential use. */ +trait MakesDoubleKeySeqStepper extends Any { + /** Generates a fresh stepper over map keys of type `Double` suitable for sequential use */ + def keyStepper: DoubleStepper +} + +/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential use. */ +trait MakesDoubleValueSeqStepper extends Any { + /** Generates a fresh stepper over map values of type `Double` suitable for sequential use */ + def valueStepper: DoubleStepper +} + +/** Classes or objects implementing this trait create `Int` steppers suitable for sequential use. */ +trait MakesIntSeqStepper extends Any { + /** Generates a fresh stepper over `Int`s suitable for sequential use */ + def stepper: IntStepper +} + +/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential use. */ +trait MakesIntKeySeqStepper extends Any { + /** Generates a fresh stepper over map keys of type `Int` suitable for sequential use */ + def keyStepper: IntStepper +} + +/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential use. */ +trait MakesIntValueSeqStepper extends Any { + /** Generates a fresh stepper over map values of type `Int` suitable for sequential use */ + def valueStepper: IntStepper +} + +/** Classes or objects implementing this trait create `Long` steppers suitable for sequential use. */ +trait MakesLongSeqStepper extends Any { + /** Generates a fresh stepper over `Long`s suitable for sequential use */ + def stepper: LongStepper +} + +/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential use. */ +trait MakesLongKeySeqStepper extends Any { + /** Generates a fresh stepper over map keys of type `Long` suitable for sequential use */ + def keyStepper: LongStepper +} + +/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential use. */ +trait MakesLongValueSeqStepper extends Any { + /** Generates a fresh stepper over map values of type `Long` suitable for sequential use */ + def valueStepper: LongStepper +} + +/** Classes or objects implementing this trait create generic steppers suitable for sequential or parallel use. */ +trait MakesAnyStepper[A] extends Any { + /** Generates a fresh stepper over `A`s that can be efficiently subdivided */ + def stepper: AnyStepper[A] with EfficientSubstep +} + +/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential or parallel use. */ +trait MakesAnyKeyStepper[A] extends Any { + /** Generates a fresh stepper over map keys of type `A` that can be efficiently subdivided */ + def keyStepper: AnyStepper[A] with EfficientSubstep +} + +/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential or parallel use. */ +trait MakesAnyValueStepper[A] extends Any { + /** Generates a fresh stepper over map values of type `A` that can be efficiently subdivided */ + def valueStepper: AnyStepper[A] with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Double` steppers suitable for sequential or parallel use. */ +trait MakesDoubleStepper extends Any { + /** Generates a fresh stepper over `Double`s that can be efficiently subdivided */ + def stepper: DoubleStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential or parallel use. */ +trait MakesDoubleKeyStepper extends Any { + /** Generates a fresh stepper over map keys of type `Double` that can be efficiently subdivided */ + def keyStepper: DoubleStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential or parallel use. */ +trait MakesDoubleValueStepper extends Any { + /** Generates a fresh stepper over map values of type `Double` that can be efficiently subdivided */ + def valueStepper: DoubleStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Int` steppers suitable for sequential or parallel use. */ +trait MakesIntStepper extends Any { + /** Generates a fresh stepper over `Int`s that can be efficiently subdivided */ + def stepper: IntStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential or parallel use. */ +trait MakesIntKeyStepper extends Any { + /** Generates a fresh stepper over map keys of type `Int` that can be efficiently subdivided */ + def keyStepper: IntStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential or parallel use. */ +trait MakesIntValueStepper extends Any { + /** Generates a fresh stepper over map values of type `Int` that can be efficiently subdivided */ + def valueStepper: IntStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Long` steppers suitable for sequential or parallel use. */ +trait MakesLongStepper extends Any { + /** Generates a fresh stepper over `Long`s that can be efficiently subdivided */ + def stepper: LongStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential or parallel use. */ +trait MakesLongKeyStepper extends Any { + /** Generates a fresh stepper over map keys of type `Long` that can be efficiently subdivided */ + def keyStepper: LongStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential or parallel use. */ +trait MakesLongValueStepper extends Any { + /** Generates a fresh stepper over map values of type `Long` that can be efficiently subdivided */ + def valueStepper: LongStepper with EfficientSubstep +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 730fef8..cc5a5bc 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -222,7 +222,7 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def nextStep = next def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely: AnyStepper[A] = this override def spliterator: Spliterator[A] = this def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false) @@ -239,7 +239,7 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely: DoubleStepper = this override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false) @@ -256,7 +256,7 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely = this override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false) @@ -273,7 +273,7 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely = this override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 6a452ec..c7806c7 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -135,7 +135,7 @@ class StreamConvertersTest { val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) - //assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well + assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) assertEq(seqO, abO.seqStream.toScala[Seq]) @@ -154,7 +154,7 @@ class StreamConvertersTest { val vecD = vectD(n) val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) - //assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) + assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) assertEq(seqD, arrD.parStream.toScala[Seq]) assert(arrD.seqStream.isInstanceOf[DoubleStream]) @@ -183,7 +183,7 @@ class StreamConvertersTest { val vecI = vectI(n) val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) - //assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) + assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) assertEq(seqI, arrI.parStream.toScala[Seq]) assert(arrI.seqStream.isInstanceOf[IntStream]) From 66756d1c4af351a8591c1889ed47afe6da0aee40 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 20:40:34 -0800 Subject: [PATCH 38/56] Split out steppers for Array, IndexedSeq, LinearSeq, Range, Vector --- .../scala/compat/java8/StepConverters.scala | 265 ------------------ .../java8/collectionImpl/StepsArray.scala | 74 +++++ .../collectionImpl/StepsIndexedSeq.scala | 32 +++ .../java8/collectionImpl/StepsLinearSeq.scala | 41 +++ .../java8/collectionImpl/StepsRange.scala | 32 +++ .../java8/collectionImpl/StepsVector.scala | 129 +++++++++ 6 files changed, 308 insertions(+), 265 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index d88e34c..0669aeb 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,120 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) - } - - private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) - } - - private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE - def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) - } - - private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) - } - - private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) - } - - private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) - } - - private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) - } - - private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) - } - - private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) - } - - private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) - } - - private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) - } - - private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) - } - - private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) - } - - private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) - } - - private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) - } - - private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) - extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) - } - - private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) - extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) - } - - private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) - extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) - } - private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { def semiclone() = new StepsAnyIterator(null) @@ -146,157 +32,6 @@ package converterImpls { def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next } - private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) - extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) - } - - private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) - } - - private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) - extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) - } - - private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) - } - - private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) - } - - private[java8] trait StepsVectorLike[A] { - protected def myVector: Vector[A] - protected var index: Int = 32 - protected var data: Array[AnyRef] = null - protected var index1: Int = 32 - protected var data1: Array[AnyRef] = null - protected final def advanceData(iX: Int) { - index1 += 1 - if (index >= 32) initTo(iX) - else { - data = data1(index1).asInstanceOf[Array[AnyRef]] - index = 0 - } - } - protected final def initTo(iX: Int) { - myVector.length match { - case x if x <= 0x20 => - index = iX - data = CollectionInternals.getDisplay0(myVector) - case x if x <= 0x400 => - index1 = iX >>> 5 - data1 = CollectionInternals.getDisplay1(myVector) - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - case x => - var N = 0 - var dataN: Array[AnyRef] = - if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } - else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } - else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } - else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } - while (N > 2) { - dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] - N -= 1 - } - index1 = (iX >>> 5) & 0x1F - data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - } - } - } - - private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) - with StepsVectorLike[A] { - protected def myVector = underlying - def next() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[A] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsAnyVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - - private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) - with StepsVectorLike[Double] { - protected def myVector = underlying - def nextDouble() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Double] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsDoubleVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - - private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) - with StepsVectorLike[Int] { - protected def myVector = underlying - def nextInt() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Int] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsIntVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - - private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) - with StepsVectorLike[Long] { - protected def myVector = underlying - def nextLong() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Long] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsLongVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala new file mode 100644 index 0000000..13c39ff --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala @@ -0,0 +1,74 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) +} + +private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) +} + +private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE + def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) +} + +private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) +} + +private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) +} + +private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) +} + +private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) +} + +private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) +} + +private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) +} + +private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) +} + +private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala new file mode 100644 index 0000000..271cfb6 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala @@ -0,0 +1,32 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) +} + +private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) +} + +private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) +} + +private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala new file mode 100644 index 0000000..947e490 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) +extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) +} + +private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) +extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) +} + +private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) +extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) +} + +private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) +extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala new file mode 100644 index 0000000..8272997 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala @@ -0,0 +1,32 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) +} + +private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) +extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) +} + +private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) +} + +private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala new file mode 100644 index 0000000..9803ab8 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala @@ -0,0 +1,129 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] trait StepsVectorLike[A] { + protected def myVector: Vector[A] + protected var index: Int = 32 + protected var data: Array[AnyRef] = null + protected var index1: Int = 32 + protected var data1: Array[AnyRef] = null + protected final def advanceData(iX: Int) { + index1 += 1 + if (index >= 32) initTo(iX) + else { + data = data1(index1).asInstanceOf[Array[AnyRef]] + index = 0 + } + } + protected final def initTo(iX: Int) { + myVector.length match { + case x if x <= 0x20 => + index = iX + data = CollectionInternals.getDisplay0(myVector) + case x if x <= 0x400 => + index1 = iX >>> 5 + data1 = CollectionInternals.getDisplay1(myVector) + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + case x => + var N = 0 + var dataN: Array[AnyRef] = + if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } + else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } + else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } + else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } + while (N > 2) { + dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] + N -= 1 + } + index1 = (iX >>> 5) & 0x1F + data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + } + } +} + +private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) +with StepsVectorLike[A] { + protected def myVector = underlying + def next() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[A] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsAnyVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + +private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) +with StepsVectorLike[Double] { + protected def myVector = underlying + def nextDouble() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Double] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsDoubleVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + +private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) +with StepsVectorLike[Int] { + protected def myVector = underlying + def nextInt() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Int] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsIntVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + +private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) +with StepsVectorLike[Long] { + protected def myVector = underlying + def nextLong() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Long] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsLongVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + + From 2674205b248f77de0571cafba6f2db7b4e320b46 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 20:56:06 -0800 Subject: [PATCH 39/56] Pulled out more steppers. This time: BitSet, FlatHashTable, HashTable, and immutable sets and maps (trie-based). --- .../scala/compat/java8/StepConverters.scala | 307 ------------------ .../java8/collectionImpl/StepsBitSet.scala | 47 +++ .../collectionImpl/StepsFlatHashTable.scala | 33 ++ .../java8/collectionImpl/StepsHashTable.scala | 137 ++++++++ .../collectionImpl/StepsImmHashMap.scala | 122 +++++++ .../collectionImpl/StepsImmHashSet.scala | 33 ++ 6 files changed, 372 insertions(+), 307 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 0669aeb..f9aadd2 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -32,313 +32,6 @@ package converterImpls { def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next } - private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) - } - - private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) - } - - private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) - } - - private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) - } - - private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) - extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) - } - - private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) - } - - private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) - } - - private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) - } - - private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } - def semiclone(half: Int) = - new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) - } - - private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) - } - - private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) - } - - private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) - } - - private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) - } - - private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } - def semiclone(half: Int) = - new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) - } - - private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) - } - - private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) - } - - private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) - } - - private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) - } - - private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) - def next(): (K, V) = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.iterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) - def next(): K = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) - def next(): V = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) - extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) - def nextDouble() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) - def nextDouble() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) - extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) - def nextInt() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) - extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) - def nextInt() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) - extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) - def nextLong() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) - extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) - def nextLong() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) - extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { - protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) - def next(): A = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) - extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) - def nextDouble() = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) - extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) - def nextInt() = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) - extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) - def nextLong() = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) - extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { - private var mask: Long = (-1L) << (i & 0x3F) - private var cache: Long = underlying(i >>> 6) - private var found: Boolean = false - def semiclone(half: Int) = { - val ans = new StepsIntBitSet(underlying, i, half) - i = half - mask = (-1L) << (i & 0x3F) - cache = underlying(i >>> 6) - found = false - ans - } - def hasNext(): Boolean = found || ((i < iN) && { - while ((mask & cache) == 0) { - i += java.lang.Long.numberOfLeadingZeros(~mask) - if (i < 0 || i >= iN) { i = iN; return false } - mask = -1L - cache = underlying(i >>> 6) - } - var m = mask << 1 - while ((mask & cache) == (m & cache)) { - mask = m - m = mask << 1 - i += 1 - } - if (i < 0 || i >= iN) { - i = iN - false - } - else { - found = true - true - } - }) - def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE - } final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala new file mode 100644 index 0000000..735dc04 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala @@ -0,0 +1,47 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) +extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { + private var mask: Long = (-1L) << (i & 0x3F) + private var cache: Long = underlying(i >>> 6) + private var found: Boolean = false + def semiclone(half: Int) = { + val ans = new StepsIntBitSet(underlying, i, half) + i = half + mask = (-1L) << (i & 0x3F) + cache = underlying(i >>> 6) + found = false + ans + } + def hasNext(): Boolean = found || ((i < iN) && { + while ((mask & cache) == 0) { + i += java.lang.Long.numberOfLeadingZeros(~mask) + if (i < 0 || i >= iN) { i = iN; return false } + mask = -1L + cache = underlying(i >>> 6) + } + var m = mask << 1 + while ((mask & cache) == (m & cache)) { + mask = m + m = mask << 1 + i += 1 + } + if (i < 0 || i >= iN) { + i = iN + false + } + else { + found = true + true + } + }) + def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala new file mode 100644 index 0000000..c634e37 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala @@ -0,0 +1,33 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) +} + +private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) +} + +private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) +} + +private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala new file mode 100644 index 0000000..d7ede16 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala @@ -0,0 +1,137 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +//////////////////////////// +// Steppers for keys (type of HashEntry doesn't matter) +//////////////////////////// + +private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) +extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) +} + +private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) +} + +private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) +} + +private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) +} + +//////////////////////////// +// Steppers for entries stored in DefaultEntry HashEntry +// (both for key-value pair and for values alone) +//////////////////////////// + +private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) +} + +private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) +} + +private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) +} + +private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) +} + +private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) +} + +//////////////////////////// +// Steppers for entries stored in LinkedEntry HashEntry +// (both for key-value pair and for values alone) +//////////////////////////// + +private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) +} + +private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) +} + +private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) +} + +private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) +} + +private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala new file mode 100644 index 0000000..6f28563 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala @@ -0,0 +1,122 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +////////////////////// +// Note that there are separate implementations for keys, values, and key-value pairs +///////////////////// + +private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) + def next(): (K, V) = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.iterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) + def next(): K = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) + def next(): V = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) +extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) +extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) +extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) +extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) +extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) +extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala new file mode 100644 index 0000000..a6edb7b --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala @@ -0,0 +1,33 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) +extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { + protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) + def next(): A = { val ans = underlying.next; i += 1; ans } +} + +private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) +extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) + def nextDouble() = { val ans = underlying.next; i += 1; ans } +} + +private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) +extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) + def nextInt() = { val ans = underlying.next; i += 1; ans } +} + +private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) +extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) + def nextLong() = { val ans = underlying.next; i += 1; ans } +} + From 4c5f0a1653d5e3193ff59db1819fd498420bcf8d Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 29 Nov 2015 13:41:07 -0800 Subject: [PATCH 40/56] Moved Iterator and String steppers to their own files. --- .../scala/compat/java8/StepConverters.scala | 49 ------------------- .../java8/collectionImpl/StepsIterator.scala | 32 ++++++++++++ .../java8/collectionImpl/StepsString.scala | 33 +++++++++++++ 3 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index f9aadd2..b6d1b8f 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,31 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) - extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { - def semiclone() = new StepsAnyIterator(null) - def next() = if (proxied ne null) proxied.nextStep else underlying.next - } - - private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) - extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { - def semiclone() = new StepsDoubleIterator(null) - def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next - } - - private[java8] class StepsIntIterator(_underlying: Iterator[Int]) - extends StepsIntLikeIterator[StepsIntIterator](_underlying) { - def semiclone() = new StepsIntIterator(null) - def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next - } - - private[java8] class StepsLongIterator(_underlying: Iterator[Long]) - extends StepsLongLikeIterator[StepsLongIterator](_underlying) { - def semiclone() = new StepsLongIterator(null) - def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next - } - - final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -311,30 +286,6 @@ package converterImpls { def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] } - private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { - def characteristics() = NonNull - def estimateSize = iN - i0 - def hasNext = i0 < iN - def nextInt() = { - if (hasNext()) { - val cp = underlying.codePointAt(i0) - i0 += java.lang.Character.charCount(cp) - cp - } - else throwNSEE - } - def substep() = { - if (iN-3 > i0) { - var half = (i0+iN) >>> 1 - if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 - val ans = new StepperStringCodePoint(underlying, i0, half) - i0 = half - ans - } - else null - } - } - final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala new file mode 100644 index 0000000..ade3055 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala @@ -0,0 +1,32 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) +extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { + def semiclone() = new StepsAnyIterator(null) + def next() = if (proxied ne null) proxied.nextStep else underlying.next +} + +private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) +extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { + def semiclone() = new StepsDoubleIterator(null) + def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next +} + +private[java8] class StepsIntIterator(_underlying: Iterator[Int]) +extends StepsIntLikeIterator[StepsIntIterator](_underlying) { + def semiclone() = new StepsIntIterator(null) + def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next +} + +private[java8] class StepsLongIterator(_underlying: Iterator[Long]) +extends StepsLongLikeIterator[StepsLongIterator](_underlying) { + def semiclone() = new StepsLongIterator(null) + def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala new file mode 100644 index 0000000..b8b37d2 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala @@ -0,0 +1,33 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { + def characteristics() = NonNull + def estimateSize = iN - i0 + def hasNext = i0 < iN + def nextInt() = { + if (hasNext()) { + val cp = underlying.codePointAt(i0) + i0 += java.lang.Character.charCount(cp) + cp + } + else throwNSEE + } + def substep() = { + if (iN-3 > i0) { + var half = (i0+iN) >>> 1 + if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 + val ans = new StepperStringCodePoint(underlying, i0, half) + i0 = half + ans + } + else null + } +} + From 02d56d568725183f51770c14c264cadb8d51d709 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 29 Nov 2015 14:26:56 -0800 Subject: [PATCH 41/56] Moved all value classes out of StepConverters. --- .../scala/compat/java8/StepConverters.scala | 437 ------------------ .../java8/collectionImpl/Accumulates.scala | 74 +++ .../java8/collectionImpl/StepsArray.scala | 52 +++ .../java8/collectionImpl/StepsBitSet.scala | 23 + .../collectionImpl/StepsFlatHashTable.scala | 35 ++ .../java8/collectionImpl/StepsHashTable.scala | 134 +++++- .../collectionImpl/StepsImmHashMap.scala | 40 +- .../collectionImpl/StepsImmHashSet.scala | 23 + .../collectionImpl/StepsIndexedSeq.scala | 24 + .../java8/collectionImpl/StepsIterable.scala | 27 ++ .../java8/collectionImpl/StepsIterator.scala | 25 + .../java8/collectionImpl/StepsLinearSeq.scala | 23 + .../java8/collectionImpl/StepsMap.scala | 41 ++ .../java8/collectionImpl/StepsRange.scala | 24 + .../java8/collectionImpl/StepsString.scala | 11 + .../java8/collectionImpl/StepsVector.scala | 22 + 16 files changed, 570 insertions(+), 445 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index b6d1b8f..13ba8d0 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,381 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) - } - - final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) - } - - final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { - @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) - } - - final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { - @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) - } - - final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { - @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) - } - - final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { - @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) - } - - final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { - @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) - } - - final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { - @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) - } - - final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) - } - - final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) - } - - final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) - } - - final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) - } - - final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { - @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) - } - - final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { - @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) - } - - final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { - @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) - } - - final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { - @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) - } - - final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { - @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) - } - - final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { - @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) - } - - final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { - @inline def stepper: IntStepper = new StepsIntIterator(underlying) - } - - final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { - @inline def stepper: LongStepper = new StepsLongIterator(underlying) - } - - final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { - @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) - } - - final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) - } - - final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsAnyFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsDoubleFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsIntFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsLongFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) - extends AnyVal with MakesAnyKeyStepper[K] { - @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, HE](underlying) - new StepsAnyHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) - extends AnyVal with MakesDoubleKeyStepper { - @inline def keyStepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[Double, HE](underlying) - new StepsDoubleHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) - extends AnyVal with MakesIntKeyStepper { - @inline def keyStepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[Int, HE](underlying) - new StepsIntHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) - extends AnyVal with MakesLongKeyStepper { - @inline def keyStepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[Long, HE](underlying) - new StepsLongHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) - extends AnyVal with MakesAnyStepper[(K, V)] { - @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTable(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) - extends AnyVal with MakesAnyValueStepper[V] { - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) - extends AnyVal with MakesDoubleValueStepper { - @inline def valueStepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) - new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) - extends AnyVal with MakesIntValueStepper { - @inline def valueStepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) - new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) - extends AnyVal with MakesLongValueStepper { - @inline def valueStepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) - new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) - extends AnyVal with MakesAnyStepper[(K,V)] { - @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTable(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) - extends AnyVal with MakesAnyValueStepper[V] { - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) - extends AnyVal with MakesDoubleValueStepper { - @inline def valueStepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) - new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) - extends AnyVal with MakesIntValueStepper { - @inline def valueStepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) - new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) - extends AnyVal with MakesLongValueStepper { - @inline def valueStepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) - new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) - extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { - @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) - @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) - } - - final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { - @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) - } - - final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { - @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) - } - - final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { - @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) - } - - final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { - @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) - } - - final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { - @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) - } - - final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { - @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) - } - - final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) - } - - final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { - def stepper: IntStepper with EfficientSubstep = { - val bits: Array[Long] = underlying match { - case m: collection.mutable.BitSet => runtime.CollectionInternals.getBitSetInternals(m) - case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) - case x => x.toBitMask - } - new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) - } - } - private[java8] object RichBitSetCanStep { - private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") - def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] - } - - final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { - def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) - def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) - } - - final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { - def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) - } - - final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { - def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) - } - - final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { - def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) - } - - final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { - def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) - } - - final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { - def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) - } - - final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { - def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) - } - - final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { - @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) - } - - final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { - @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) - } - - final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { - @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) - } - - final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { - @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) - } - - final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) - } - - final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) - } - - final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) - } - - final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) - } - - final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) - } - - final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) - } - - final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) - } - - final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) - } - - final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) - } - - final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) - } - - final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) - } - - final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) - } - - final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) - } - trait Priority7StepConverters { implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) } @@ -505,68 +130,6 @@ package converterImpls { implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } - final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def accumulate: Accumulator[A] = { - val a = new Accumulator[A] - underlying.foreach(a += _) - a - } - } - - final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { - def accumulate: DoubleAccumulator = { - val da = new DoubleAccumulator - underlying.foreach(da += _) - da - } - } - final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { - def accumulate: IntAccumulator = { - val da = new IntAccumulator - underlying.foreach(da += _) - da - } - } - final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { - def accumulate: LongAccumulator = { - val da = new LongAccumulator - underlying.foreach(da += _) - da - } - } - final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { - def accumulate: Accumulator[A] = { - val a = new Accumulator[A] - var i = 0 - while (i < underlying.length) { a += underlying(i); i += 1 } - a - } - } - - final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { - def accumulate: DoubleAccumulator = { - val da = new DoubleAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } - } - final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { - def accumulate: IntAccumulator = { - val da = new IntAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } - } - final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { - def accumulate: LongAccumulator = { - val da = new LongAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } - } trait Priority3AccumulatorConverters { implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala new file mode 100644 index 0000000..ae4e6fe --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala @@ -0,0 +1,74 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + underlying.foreach(a += _) + a + } +} + +final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + underlying.foreach(da += _) + da + } +} + +final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + underlying.foreach(da += _) + da + } +} + +final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + underlying.foreach(da += _) + da + } +} + +final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + var i = 0 + while (i < underlying.length) { a += underlying(i); i += 1 } + a + } +} + +final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } +} + +final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } +} + +final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala index 13c39ff..b9177d0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -72,3 +76,51 @@ extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) +} + +final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) +} + +final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { + @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) +} + +final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { + @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) +} + +final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { + @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) +} + +final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { + @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) +} + +final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { + @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) +} + +final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { + @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) +} + +final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) +} + +final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) +} + +final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala index 735dc04..c3fac1c 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +//////////////////////////// +// Stepper implementation // +//////////////////////////// + private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { private var mask: Long = (-1L) << (i & 0x3F) @@ -45,3 +49,22 @@ extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE } +///////////////////////// +// Value class adapter // +///////////////////////// + +final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { + def stepper: IntStepper with EfficientSubstep = { + val bits: Array[Long] = underlying match { + case m: collection.mutable.BitSet => CollectionInternals.getBitSetInternals(m) + case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) + case x => x.toBitMask + } + new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) + } +} +private[java8] object RichBitSetCanStep { + private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") + def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala index c634e37..144a4df 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } @@ -31,3 +35,34 @@ extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsAnyFlatHashTable(tbl, 0, tbl.length) + } +} + +final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsDoubleFlatHashTable(tbl, 0, tbl.length) + } +} + +final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsIntFlatHashTable(tbl, 0, tbl.length) + } +} + +final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsLongFlatHashTable(tbl, 0, tbl.length) + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala index d7ede16..def363e 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala @@ -7,9 +7,11 @@ import scala.compat.java8.runtime._ import Stepper._ -//////////////////////////// +///////////////////////////// +// Stepper implementations // +///////////////////////////// + // Steppers for keys (type of HashEntry doesn't matter) -//////////////////////////// private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { @@ -35,10 +37,8 @@ extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[ def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) } -//////////////////////////// // Steppers for entries stored in DefaultEntry HashEntry // (both for key-value pair and for values alone) -//////////////////////////// private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { @@ -85,10 +85,8 @@ extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asIns new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) } -//////////////////////////// // Steppers for entries stored in LinkedEntry HashEntry // (both for key-value pair and for values alone) -//////////////////////////// private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { @@ -135,3 +133,127 @@ extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInst new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +// Steppers for keys (type of HashEntry doesn't matter) + +final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) +extends AnyVal with MakesAnyKeyStepper[K] { + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, HE](underlying) + new StepsAnyHashTableKey(tbl, 0, tbl.length) + } +} + +final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) +extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[Double, HE](underlying) + new StepsDoubleHashTableKey(tbl, 0, tbl.length) + } +} + +final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) +extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[Int, HE](underlying) + new StepsIntHashTableKey(tbl, 0, tbl.length) + } +} + +final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) +extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[Long, HE](underlying) + new StepsLongHashTableKey(tbl, 0, tbl.length) + } +} + +// Steppers for entries stored in DefaultEntry HashEntry +// (both for key-value pair and for values alone) + +final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) +extends AnyVal with MakesAnyStepper[(K, V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTable(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) +extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) +extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) + new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) +extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) + new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) +extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) + new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +// Steppers for entries stored in LinkedEntry HashEntry +// (both for key-value pair and for values alone) + +final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) +extends AnyVal with MakesAnyStepper[(K,V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTable(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) +extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) +extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) + new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) +extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) + new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) +extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) + new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala index 6f28563..65b69dd 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala @@ -7,9 +7,11 @@ import scala.compat.java8.runtime._ import Stepper._ -////////////////////// // Note that there are separate implementations for keys, values, and key-value pairs -///////////////////// + +///////////////////////////// +// Stepper implementations // +///////////////////////////// private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { @@ -119,4 +121,38 @@ extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlyin else throwNSEE } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) +extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { + @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) +} + +final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) +} + +final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) +} + +final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) +} + +final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) +} + +final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) +} +final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala index a6edb7b..0f9c2e0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) @@ -31,3 +35,22 @@ extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { def nextLong() = { val ans = underlying.next; i += 1; ans } } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) +} + +final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) +} + +final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) +} + +final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala index 271cfb6..65c2232 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -30,3 +34,23 @@ extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) +} + +final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) +} + +final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) +} + +final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala new file mode 100644 index 0000000..70a6bca --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala @@ -0,0 +1,27 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +// Iterables just defer to iterator unless they can pattern match something better. +// TODO: implement pattern matching! + +final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) +} + +final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) +} + +final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) +} + +final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala index ade3055..eb951d6 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { def semiclone() = new StepsAnyIterator(null) @@ -30,3 +34,24 @@ extends StepsLongLikeIterator[StepsLongIterator](_underlying) { def semiclone() = new StepsLongIterator(null) def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) +} + +final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) +} + +final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntIterator(underlying) +} + +final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongIterator(underlying) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala index 947e490..e809424 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty @@ -39,3 +43,22 @@ extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) +} + +final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) +} + +final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) +} + +final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala new file mode 100644 index 0000000..fcaaa67 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +// Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching +// TODO: implement pattern matching + +final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { + // No generic stepper because RichIterableCanStep will get that anyway, and we don't pattern match here + def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) + def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) +} + +final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { + def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) +} + +final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { + def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) +} + +final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { + def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) +} + +final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { + def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) +} + +final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { + def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) +} + +final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { + def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala index 8272997..1eb1282 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -30,3 +34,23 @@ extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) +} + +final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { + @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) +} + +final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) +} + +final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala index b8b37d2..d3bccc0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +//////////////////////////// +// Stepper implementation // +//////////////////////////// + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { def characteristics() = NonNull def estimateSize = iN - i0 @@ -31,3 +35,10 @@ private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var } } +///////////////////////// +// Value class adapter // +///////////////////////// + +final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala index 9803ab8..12923c9 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] trait StepsVectorLike[A] { protected def myVector: Vector[A] protected var index: Int = 32 @@ -126,4 +130,22 @@ with StepsVectorLike[Long] { } } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) +} + +final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) +} + +final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) +} +final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) +} From c96039d32820cd5bbed68a4e98800dbbabbd3d63 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 29 Nov 2015 14:37:11 -0800 Subject: [PATCH 42/56] Made StreamConverters responsible for Steps and Accumulators also. Split out Accumulators from StepConverters so StepConverters could just be hierarchy of traits for implicit conversion. --- .../scala/compat/java8/StepConverters.scala | 268 ++++++++---------- .../scala/compat/java8/StreamConverters.scala | 6 +- .../AccumulatorConverters.scala | 20 ++ .../compat/java8/StepConvertersTest.scala | 2 +- .../compat/java8/StreamConvertersTest.scala | 1 - 5 files changed, 148 insertions(+), 149 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 13ba8d0..85b42f0 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -1,155 +1,131 @@ -package scala.compat.java8 +package scala.compat.java8.converterImpls import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ -package converterImpls { - import Stepper._ - - trait Priority7StepConverters { - implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) - } - - trait Priority6StepConverters extends Priority7StepConverters { - implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) - implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) - implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) - implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) - } - - trait Priority5StepConverters extends Priority6StepConverters { - implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) - implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) - implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) - implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) - implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) - implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) - } - - trait Priority4StepConverters extends Priority5StepConverters { - implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) - implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = - new RichHashTableKeyCanStep[K, HE](underlying) - implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = - new RichDefaultHashTableCanStep[K, V](underlying) - implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = - new RichDefaultHashTableValueCanStep[K, V](underlying) - implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = - new RichLinkedHashTableCanStep[K, V](underlying) - implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = - new RichLinkedHashTableValueCanStep[K, V](underlying) - } - - trait Priority3StepConverters extends Priority4StepConverters { - implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = - new RichIndexedSeqCanStep[A](underlying) - implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) - implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = - new RichDoubleLinearSeqCanStep[CC](underlying) - implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = - new RichIntLinearSeqCanStep[CC](underlying) - implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = - new RichLongLinearSeqCanStep[CC](underlying) - implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) - implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = - new RichHashTableDoubleKeyCanStep[HE](underlying) - implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = - new RichHashTableIntKeyCanStep[HE](underlying) - implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = - new RichHashTableLongKeyCanStep[HE](underlying) - implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = - new RichDefaultHashTableDoubleValueCanStep[K](underlying) - implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = - new RichDefaultHashTableIntValueCanStep[K](underlying) - implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = - new RichDefaultHashTableLongValueCanStep[K](underlying) - implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = - new RichLinkedHashTableDoubleValueCanStep[K](underlying) - implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = - new RichLinkedHashTableIntValueCanStep[K](underlying) - implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = - new RichLinkedHashTableLongValueCanStep[K](underlying) - - implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) - implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) - } +import Stepper._ + +trait Priority7StepConverters { + implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) +} + +trait Priority6StepConverters extends Priority7StepConverters { + implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) + implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) + implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) + implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) +} + +trait Priority5StepConverters extends Priority6StepConverters { + implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) + implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) + implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) + implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) + implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) + implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) +} + +trait Priority4StepConverters extends Priority5StepConverters { + implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) + implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = + new RichHashTableKeyCanStep[K, HE](underlying) + implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableCanStep[K, V](underlying) + implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableValueCanStep[K, V](underlying) + implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableCanStep[K, V](underlying) + implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableValueCanStep[K, V](underlying) +} + +trait Priority3StepConverters extends Priority4StepConverters { + implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) + implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = + new RichIndexedSeqCanStep[A](underlying) + implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) + implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = + new RichDoubleLinearSeqCanStep[CC](underlying) + implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = + new RichIntLinearSeqCanStep[CC](underlying) + implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = + new RichLongLinearSeqCanStep[CC](underlying) + implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) + implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = + new RichHashTableDoubleKeyCanStep[HE](underlying) + implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = + new RichHashTableIntKeyCanStep[HE](underlying) + implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = + new RichHashTableLongKeyCanStep[HE](underlying) + implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = + new RichDefaultHashTableDoubleValueCanStep[K](underlying) + implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = + new RichDefaultHashTableIntValueCanStep[K](underlying) + implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = + new RichDefaultHashTableLongValueCanStep[K](underlying) + implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = + new RichLinkedHashTableDoubleValueCanStep[K](underlying) + implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = + new RichLinkedHashTableIntValueCanStep[K](underlying) + implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = + new RichLinkedHashTableLongValueCanStep[K](underlying) + + implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) + implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) +} + +trait Priority2StepConverters extends Priority3StepConverters { + implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) + implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) + implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) + implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) + implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) + implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) + implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = + new RichDoubleIndexedSeqCanStep[CC](underlying) + implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = + new RichIntIndexedSeqCanStep[CC](underlying) + implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = + new RichLongIndexedSeqCanStep[CC](underlying) + implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) + implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) + implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) + implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) + implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) + implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) + implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) + implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) + + implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) + implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) + implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) + implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) + implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) + implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) + + implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) +} + +trait Priority1StepConverters extends Priority2StepConverters { + implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) + implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) + implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) - trait Priority2StepConverters extends Priority3StepConverters { - implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) - implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) - implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) - implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) - implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) - implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) - implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) - implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = - new RichDoubleIndexedSeqCanStep[CC](underlying) - implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = - new RichIntIndexedSeqCanStep[CC](underlying) - implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = - new RichLongIndexedSeqCanStep[CC](underlying) - implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) - implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) - implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) - implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) - implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) - implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) - implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) - implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) - - implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) - implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) - implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) - implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) - implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) - implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) - - implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) - } - - trait Priority1StepConverters extends Priority2StepConverters { - implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) - implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) - implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) - - implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) - implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) - implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) - - implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) - implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) - implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) - - implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) - implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) - implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) - - implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) - } - - - trait Priority3AccumulatorConverters { - implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) - } - - trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { - implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) - implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) - implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) - implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) - } - - trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { - implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) - implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) - implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) - } + implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) + implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) + implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) + + implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) + implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) + implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) + + implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) + implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) + implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) + + implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } -object StepConverters -extends converterImpls.Priority1StepConverters -with converterImpls.Priority1AccumulatorConverters -{} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 60d7114..a6ae6d1 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -167,7 +167,11 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] * ``` */ -object StreamConverters extends Priority1StreamConverters { +object StreamConverters +extends Priority1StreamConverters +with converterImpls.Priority1StepConverters +with converterImpls.Priority1AccumulatorConverters +{ implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala new file mode 100644 index 0000000..1f44f97 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala @@ -0,0 +1,20 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +trait Priority3AccumulatorConverters { + implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) +} + +trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { + implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) + implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) +} + +trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { + implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) + implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) + implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) +} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index c3f1663..ac18a7c 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -6,7 +6,7 @@ import org.junit.Assert._ class StepConvertersTest { import java.util._ import collectionImpl._ - import StepConverters._ + import StreamConverters._ // Includes StepConverters! import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index c7806c7..b1ad2f5 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -6,7 +6,6 @@ import org.junit.Assert._ class StreamConvertersTest { import java.util.stream._ import StreamConverters._ - import StepConverters._ def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } From 043672b032911f959ab8f80306f37a18c9c12c2a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 30 Nov 2015 19:41:22 -0800 Subject: [PATCH 43/56] Java class full of static methods that give streams from collections. --- README.md | 49 +- .../scala/compat/java8/ScalaStreaming.java | 904 ++++++++++++++++++ .../scala/compat/java8/StreamConverters.scala | 60 +- .../java8/collectionImpl/Accumulates.scala | 4 + .../java8/collectionImpl/Accumulator.scala | 7 + .../AccumulatorConverters.scala | 15 + .../collectionImpl/DoubleAccumulator.scala | 7 + .../java8/collectionImpl/IntAccumulator.scala | 7 + .../collectionImpl/LongAccumulator.scala | 7 + .../compat/java8/collectionImpl/Stepper.scala | 16 +- 10 files changed, 1068 insertions(+), 8 deletions(-) create mode 100644 src/main/java/scala/compat/java8/ScalaStreaming.java diff --git a/README.md b/README.md index b3f11ba..b757697 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,49 @@ class Test { ``` -## Future work - - Converters for `java.util.stream` - - [`Spliterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html)s for Scala collections +## Converters from Scala collections to Java 8 Streams + +Scala collections gain `seqStream` and `parStream` as extension methods that produce a Java 8 Stream +running sequentially or in parallel, respectively. These are automatically specialized to a primitive +type if possible. For instance, `List(1,2).seqStream` produces an `IntStream`. Maps additionally have +`seqKeyStream`, `seqValueStream`, `parKeyStream`, and `parValueStream` methods. + +Scala collections also gain `accumulate` and `stepper` methods that produce utility collections that +can be useful when working with Java 8 Streams. `accumulate` produces an `Accumulator` or its primitive +counterpart (`DoubleAccumulator`, etc.), which is a low-level collection designed for efficient collection +and dispatching of results to and from Streams. Unlike most collections, it can contain more than +`Int.MaxValue` elements. `stepper` produces a `Stepper` which is a fusion of `Spliterator` and `Iterator`. +`Stepper`s underlie the Scala collections' instances of Java 8 Streams. + +Java 8 Streams gain `toScala[Coll]` and `accumulate` methods, to make it easy to produce Scala collections +or Accumulators, respectively, from Java 8 Streams. For instance, `myStream.to[Vector]` will collect the +contents of a Stream into a `scala.collection.immutable.Vector`. Note that standard sequential builders +are used for collections, so this is best done to gather the results of an expensive computation. + +Finally, there is a Java class, `ScalaStreamer`, that has a series of `from` methods that can be used to +obtain Java 8 Streams from Scala collections from within Java. + +#### Scala Usage Example + +```scala +import scala.compat.java8.StreamConverters._ + +object Test { + val m = collection.immutable.HashMap("fish" -> 2, "bird" -> 4) + val s = m.parValueStream.sum // 6, potientially computed in parallel + val t = m.seqKeyStream.toScala[List] // List("fish", "bird") + val a = t.accumulate // Accumulator[(String, Int)] + + val n = a.splitter.fold(0)(_ + _._1.length) + + a.parStream.count // 8 + 2 = 10 + + val b = java.util.Arrays.stream(Array(2L, 3L, 4L)). + accumulate // LongAccumulator +} +``` + +#### Java Usage Example + +```java +// TODO -- write converter and create example +``` diff --git a/src/main/java/scala/compat/java8/ScalaStreaming.java b/src/main/java/scala/compat/java8/ScalaStreaming.java new file mode 100644 index 0000000..b32ae32 --- /dev/null +++ b/src/main/java/scala/compat/java8/ScalaStreaming.java @@ -0,0 +1,904 @@ +package scala.compat.java8; + +import scala.compat.java8.converterImpls.*; +import java.util.stream.*; +import scala.compat.java8.runtime.CollectionInternals; + +public class ScalaStreaming { + ///////////////////// + // Generic Streams // + ///////////////////// + + /** + * Generates a Stream that traverses an IndexedSeq. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.IndexedSeq coll) { + return StreamSupport.stream(new StepsAnyIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.stream(new StepsAnyImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.stream(new StepsAnyImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.immutable.HashMap. + * The key-value pairs are presented as instances of scala.Tuple2. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > from(scala.collection.immutable.HashMap coll) { + return StreamSupport.stream(new StepsAnyImmHashMap(coll, 0, coll.size()), false); + } + + /** + * Generates a Stream that traverses a scala.collection.immutable.HashSet. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.immutable.HashSet coll) { + return StreamSupport.stream(new StepsAnyImmHashSet(coll.iterator(), coll.size()), false); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.mutable.HashMap. + * The key-value pairs are presented as instances of scala.Tuple2. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > from(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry< K, scala.collection.mutable.DefaultEntry >[] tbl = + CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyDefaultHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses a scala.collection.mutable.HashSet. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses a scala.collection.immutable.Vector. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.immutable.Vector coll) { + return StreamSupport.stream(new StepsAnyVector(coll, 0, coll.length()), false); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromKeys(scala.collection.Map coll) { + return StreamSupport.stream(new StepsAnyIterator(coll.keysIterator()), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromValues(scala.collection.Map coll) { + return StreamSupport.stream(new StepsAnyIterator(coll.valuesIterator()), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulated method instead, but + * note that this creates a new collection containing the Map's key-value pairs. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > from(scala.collection.Map coll) { + return StreamSupport.stream(new StepsAnyIterator< scala.Tuple2 >(coll.iterator()), false); + } + + /** + * Generates a Stream that traverses a scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.Iterator coll) { + return StreamSupport.stream(new StepsAnyIterator(coll), false); + } + + /** + * Generates a Stream that traverses a scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable + * + * @param coll The scala.collection.Iterable to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.Iterable coll) { + return StreamSupport.stream(new StepsAnyIterator(coll.iterator()), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll); + return StreamSupport.stream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.keysIterator()); + return StreamSupport.stream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.valuesIterator()); + return StreamSupport.stream(acc.spliterator(), false); + } + + //////////////////// + // Double Streams // + //////////////////// + + /** + * Generates a DoubleStream that traverses an IndexedSeq of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.IndexedSeq coll) { + return StreamSupport.doubleStream(new StepsDoubleIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a DoubleStream that traverses double-valued keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.doubleStream(new StepsDoubleImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a DoubleStream that traverses double-valued values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.doubleStream(new StepsDoubleImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a DoubleStream that traverses a scala.collection.immutable.HashSet of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.immutable.HashSet coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.doubleStream(new StepsDoubleImmHashSet(iter, coll.size()), false); + } + + /** + * Generates a DoubleStream that traverses double-valued keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.doubleStream(new StepsDoubleHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a DoubleStream that traverses double-valued values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.doubleStream(new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a DoubleStream that traverses a scala.collection.mutable.HashSet of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.doubleStream(new StepsDoubleFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a DoubleStream that traverses a scala.collection.immutable.Vector of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.immutable.Vector coll) { + scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; + return StreamSupport.doubleStream(new StepsDoubleVector(erased, 0, coll.length()), false); + } + + /** + * Generates a DoubleStream that traverses the double-valued keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromKeys(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); + return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + } + + /** + * Generates a DoubleStream that traverses the double-valued values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromValues(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); + return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + } + + /** + * Generates a DoubleStream that traverses a double-valued scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.Iterator coll) { + return StreamSupport.doubleStream(new StepsDoubleIterator((scala.collection.Iterator)coll), false); + } + + /** + * Generates a DoubleStream that traverses a double-valued scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable. + * + * @param coll The scala.collection.Iterable to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.Iterable coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.DoubleAccumulator acc = + scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.TraversableOnce)coll); + return StreamSupport.doubleStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.DoubleAccumulator acc = + scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.keysIterator()); + return StreamSupport.doubleStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.DoubleAccumulator acc = + scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); + return StreamSupport.doubleStream(acc.spliterator(), false); + } + + ///////////////// + // Int Streams // + ///////////////// + + /** + * Generates a IntStream that traverses a BitSet. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The BitSet to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.BitSet coll) { + // Let the value class figure out the casting! + scala.compat.java8.converterImpls.RichBitSetCanStep rbscs = + new scala.compat.java8.converterImpls.RichBitSetCanStep(coll); + return StreamSupport.intStream(rbscs.stepper(), false); + } + + /** + * Generates a IntStream that traverses a Range. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Range to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.immutable.Range coll) { + return StreamSupport.intStream(new scala.compat.java8.converterImpls.StepsIntRange(coll, 0, coll.length()), false); + } + + /** + * Generates a IntStream that traverses an IndexedSeq of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.IndexedSeq coll) { + return StreamSupport.intStream(new StepsIntIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a IntStream that traverses int-valued keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.intStream(new StepsIntImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a IntStream that traverses int-valued values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.intStream(new StepsIntImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a IntStream that traverses a scala.collection.immutable.HashSet of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.immutable.HashSet coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.intStream(new StepsIntImmHashSet(iter, coll.size()), false); + } + + /** + * Generates a IntStream that traverses int-valued keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.intStream(new StepsIntHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a IntStream that traverses int-valued values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.intStream(new StepsIntDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a IntStream that traverses a scala.collection.mutable.HashSet of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.intStream(new StepsIntFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a IntStream that traverses a scala.collection.immutable.Vector of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.immutable.Vector coll) { + scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; + return StreamSupport.intStream(new StepsIntVector(erased, 0, coll.length()), false); + } + + /** + * Generates a IntStream that traverses the int-valued keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromKeys(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); + return StreamSupport.intStream(new StepsIntIterator(iter), false); + } + + /** + * Generates a IntStream that traverses the int-valued values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromValues(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); + return StreamSupport.intStream(new StepsIntIterator(iter), false); + } + + /** + * Generates a IntStream that traverses a int-valued scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.Iterator coll) { + return StreamSupport.intStream(new StepsIntIterator((scala.collection.Iterator)coll), false); + } + + /** + * Generates a IntStream that traverses a int-valued scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable. + * + * @param coll The scala.collection.Iterable to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.Iterable coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.intStream(new StepsIntIterator(iter), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.IntAccumulator acc = + scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.TraversableOnce)coll); + return StreamSupport.intStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.IntAccumulator acc = + scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.keysIterator()); + return StreamSupport.intStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.IntAccumulator acc = + scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); + return StreamSupport.intStream(acc.spliterator(), false); + } + + ////////////////// + // Long Streams // + ////////////////// + + /** + * Generates a LongStream that traverses an IndexedSeq of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.IndexedSeq coll) { + return StreamSupport.longStream(new StepsLongIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a LongStream that traverses long-valued keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.longStream(new StepsLongImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a LongStream that traverses long-valued values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.longStream(new StepsLongImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a LongStream that traverses a scala.collection.immutable.HashSet of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.immutable.HashSet coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.longStream(new StepsLongImmHashSet(iter, coll.size()), false); + } + + /** + * Generates a LongStream that traverses long-valued keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.longStream(new StepsLongHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a LongStream that traverses long-valued values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.longStream(new StepsLongDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a LongStream that traverses a scala.collection.mutable.HashSet of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.longStream(new StepsLongFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a LongStream that traverses a scala.collection.immutable.Vector of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.immutable.Vector coll) { + scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; + return StreamSupport.longStream(new StepsLongVector(erased, 0, coll.length()), false); + } + + /** + * Generates a LongStream that traverses the long-valued keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromKeys(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); + return StreamSupport.longStream(new StepsLongIterator(iter), false); + } + + /** + * Generates a LongStream that traverses the long-valued values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromValues(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); + return StreamSupport.longStream(new StepsLongIterator(iter), false); + } + + /** + * Generates a LongStream that traverses a long-valued scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.Iterator coll) { + return StreamSupport.longStream(new StepsLongIterator((scala.collection.Iterator)coll), false); + } + + /** + * Generates a LongStream that traverses a long-valued scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable. + * + * @param coll The scala.collection.Iterable to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.Iterable coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.longStream(new StepsLongIterator(iter), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.LongAccumulator acc = + scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.TraversableOnce)coll); + return StreamSupport.longStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.LongAccumulator acc = + scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.keysIterator()); + return StreamSupport.longStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.LongAccumulator acc = + scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); + return StreamSupport.longStream(acc.spliterator(), false); + } +} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index a6ae6d1..af24359 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -137,6 +137,10 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * * Scala collections gain extension methods `seqStream` and * `parStream` that allow them to be used as the source of a `Stream`. + * Some collections either intrinsically cannot be paralellized, or + * could be but an efficient implementation is missing. It this case, + * only `seqStream` is provided. If a collection cannot be stepped over + * at all (e.g. `Traversable`), then it gains neither method. * * `Array` also gains `seqStream` and `parStream` methods, and calling those * on `Array[Double]`, `Array[Int]`, or `Array[Long]` will produce the @@ -152,10 +156,32 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * have custom accumulators with improved performance. * * Accumulators have `toArray`, `toList`, `iterator`, and `to[_]` methods - * to convert to standard Scala collections. + * to convert to standard Scala collections. Note that if you wish to + * create an array from a `Stream`, going through an `Accumulator` is + * not the most efficient option: just create the `Array` directly. * - * Example: - * ``` + * Internally, Scala collections implement a hybrid of `Iterator` and + * `java.util.Spliterator` to implement `Stream` compatibility; these + * are called `Stepper`s. In particular, they can test for the presence + * of a next element using `hasStep`, can retrieve the next value with + * `nextStep`, or can optionally retrieve and operate on a value if present + * with `tryStep`, which works like `tryAdvance` in `java.util.Spliterator`. + * + * Every Scala collection that can be stepped + * through has a `stepper` method implicitly provided. In addition, + * maps have `keyStepper` and `valueStepper` methods. A limited number + * of collections operations are defined on `Stepper`s, including conversion + * to Scala collections with `to` or accumulation via `accumulate`. + * `Stepper`s also implement `seqStream` and `parStream` to generate `Stream`s. + * These are provided regardless of whether a `Stepper` can efficiently + * subdivide itself for parallel processing (though one can check for the + * presence of the `EfficientSubstep` trait to know that parallel execution will + * not be limited by long sequential searching steps, and one can call + * `anticipateParallelism` to warn a `Stepper` that it will be used in a parallel + * context and thus may wish to make different tradeoffs). + * + * Examples: + * {{{ * import scala.compat.java8.StreamConverers._ * * val s = Vector(1,2,3,4).parStream // Stream[Int] @@ -165,7 +191,9 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * * val t = Array(2.0, 3.0, 4.0).parStream // DoubleStream * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] - * ``` + * + * val x = List(1L, 2L, 3L, 4L).stepper.parStream.sum // 10, potentially computed in parallel + * }}} */ object StreamConverters extends Priority1StreamConverters @@ -273,4 +301,28 @@ with converterImpls.Priority1AccumulatorConverters } } } + + implicit val accumulateDoubleStepper = new AccumulatesFromStepper[Double, DoubleAccumulator] { + def apply(stepper: Stepper[Double]) = { + val a = new DoubleAccumulator + while (stepper.hasStep) a += stepper.nextStep + a + } + } + + implicit val accumulateIntStepper = new AccumulatesFromStepper[Int, IntAccumulator] { + def apply(stepper: Stepper[Int]) = { + val a = new IntAccumulator + while (stepper.hasStep) a += stepper.nextStep + a + } + } + + implicit val accumulateLongStepper = new AccumulatesFromStepper[Long, LongAccumulator] { + def apply(stepper: Stepper[Long]) = { + val a = new LongAccumulator + while (stepper.hasStep) a += stepper.nextStep + a + } + } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala index ae4e6fe..ed7105d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala @@ -5,6 +5,10 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ +trait AccumulatesFromStepper[@specialized(Double, Int, Long) A, Acc <: AccumulatorLike[A, Acc]] { + def apply(stepper: Stepper[A]): Acc +} + final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { def accumulate: Accumulator[A] = { val a = new Accumulator[A] diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala index b28790c..e67ca79 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -214,6 +214,13 @@ object Accumulator { /** A `BiConsumer` that merges `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]) { a1 drain a2 } } + + /** Builds an `Accumulator` from any `TraversableOnce` */ + def from[A](source: TraversableOnce[A]) = { + val a = new Accumulator[A] + source.foreach(a += _) + a + } } private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) extends AnyStepper[A] { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala index 1f44f97..7e95a69 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala @@ -2,6 +2,8 @@ package scala.compat.java8.converterImpls import language.implicitConversions +import scala.compat.java8.collectionImpl._ + trait Priority3AccumulatorConverters { implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) } @@ -17,4 +19,17 @@ trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) + + implicit def accumulateAnyStepper[A]: AccumulatesFromStepper[A, Accumulator[A]] = + PrivateAccumulatorConverters.genericAccumulateAnyStepper.asInstanceOf[AccumulatesFromStepper[A, Accumulator[A]]] +} + +private[java8] object PrivateAccumulatorConverters { + val genericAccumulateAnyStepper: AccumulatesFromStepper[Any, Accumulator[Any]] = new AccumulatesFromStepper[Any, Accumulator[Any]] { + def apply(stepper: Stepper[Any]) = { + val a = new Accumulator[Any] + while (stepper.hasStep) a += stepper.nextStep + a + } + } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index 9703fe9..b99ba7d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -211,6 +211,13 @@ object DoubleAccumulator { /** A `BiConsumer` that merges `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator) { a1 drain a2 } } + + /** Builds a `DoubleAccumulator` from any `Double`-valued `TraversableOnce` */ + def from[A](source: TraversableOnce[Double]) = { + val a = new DoubleAccumulator + source.foreach(a += _) + a + } } private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator) extends DoubleStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala index 69a13d1..253119e 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -218,6 +218,13 @@ object IntAccumulator { /** A `BiConsumer` that merges `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator) { a1 drain a2 } } + + /** Builds an `IntAccumulator` from any `Int`-valued `TraversableOnce` */ + def from[A](source: TraversableOnce[Int]) = { + val a = new IntAccumulator + source.foreach(a += _) + a + } } private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) extends IntStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala index 8cf770c..270d400 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -212,6 +212,13 @@ object LongAccumulator { /** A `BiConsumer` that merges `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator) { a1 drain a2 } } + + /** Builds a `LongAccumulator` from any `Long`-valued `TraversableOnce` */ + def from[A](source: TraversableOnce[Long]) = { + val a = new LongAccumulator + source.foreach(a += _) + a + } } private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) extends LongStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index cc5a5bc..8963462 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -36,7 +36,14 @@ import java.util.Spliterator * println(s.hasStep) // Prints `false` * }}} */ -trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {} +trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] { + /** Drains the contents of this stepper into an `Accumulator` or specialized variant thereof as appropriate. + * This is a terminal operation. + * + * Note: accumulation will occur sequentially. To accumulate in parallel, use a `Stream` (i.e. `.parStream.accumulate`). + */ + def accumulate[Acc <: AccumulatorLike[A, Acc]](implicit accer: scala.compat.java8.converterImpls.AccumulatesFromStepper[A, Acc]) = accer(this) +} /** An (optional) marker trait that indicates that a `Stepper` can call `substep` with * at worst O(log N) time and space complexity, and that the division is likely to @@ -159,6 +166,13 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => def hasNext = self.hasStep def next = self.nextStep } + + /** Returns a Scala collection of the type requested. */ + def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { + val b = cbf() + while (hasStep) b += nextStep + b.result() + } } From 86370b046bdbfc86a8f6dccd121e9e1e90ded372 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 1 Dec 2015 18:29:38 -0800 Subject: [PATCH 44/56] Reorganized namespaces for Stream compatibility. Basically, everything to do with conversion is in conversionImpl, while actual collection classes are in collectionImpl. Most everything in here should be private[java8], but it probably isn't yet. --- .../java/scala/compat/java8/ScalaStreaming.java | 9 +++++---- .../scala/compat/java8/StreamConverters.scala | 6 +++--- .../compat/java8/collectionImpl/Stepper.scala | 2 +- .../Accumulates.scala | 2 +- .../AccumulatorConverters.scala | 2 +- .../MakesSteppers.scala | 2 +- .../{ => converterImpl}/StepConverters.scala | 2 +- .../StepsArray.scala | 2 +- .../StepsBitSet.scala | 2 +- .../StepsFlatHashTable.scala | 2 +- .../StepsHashTable.scala | 2 +- .../StepsImmHashMap.scala | 2 +- .../StepsImmHashSet.scala | 2 +- .../StepsIndexedSeq.scala | 2 +- .../StepsIterable.scala | 2 +- .../StepsIterator.scala | 2 +- .../StepsLikeGapped.scala | 13 +++++++------ .../StepsLikeImmHashMap.scala | 14 ++++++++------ .../StepsLikeIndexed.scala | 14 ++++++++------ .../StepsLikeIterator.scala | 14 ++++++++------ .../StepsLikeSliced.scala | 14 ++++++++------ .../StepsLikeTrieIterator.scala | 17 +++++++++-------- .../StepsLinearSeq.scala | 2 +- .../StepsMap.scala | 2 +- .../StepsRange.scala | 2 +- .../StepsString.scala | 2 +- .../StepsVector.scala | 2 +- .../StepsWithTail.scala | 13 +++++++------ .../scala/compat/java8/StepConvertersTest.scala | 1 + 29 files changed, 83 insertions(+), 70 deletions(-) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/Accumulates.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/AccumulatorConverters.scala (97%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/MakesSteppers.scala (99%) rename src/main/scala/scala/compat/java8/{ => converterImpl}/StepConverters.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsArray.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsBitSet.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsFlatHashTable.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsHashTable.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsImmHashMap.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsImmHashSet.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsIndexedSeq.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsIterable.scala (96%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsIterator.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeGapped.scala (74%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeImmHashMap.scala (66%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeIndexed.scala (65%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeIterator.scala (81%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeSliced.scala (67%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeTrieIterator.scala (61%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLinearSeq.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsMap.scala (97%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsRange.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsString.scala (96%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsVector.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsWithTail.scala (79%) diff --git a/src/main/java/scala/compat/java8/ScalaStreaming.java b/src/main/java/scala/compat/java8/ScalaStreaming.java index b32ae32..9367361 100644 --- a/src/main/java/scala/compat/java8/ScalaStreaming.java +++ b/src/main/java/scala/compat/java8/ScalaStreaming.java @@ -1,6 +1,7 @@ package scala.compat.java8; -import scala.compat.java8.converterImpls.*; +import scala.compat.java8.converterImpl.*; +import scala.compat.java8.collectionImpl.*; import java.util.stream.*; import scala.compat.java8.runtime.CollectionInternals; @@ -471,8 +472,8 @@ public static DoubleStream doubleFromAccumulatedValues(scala.collection.Map: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { protected var currentEntry: AnyRef = null def semiclone(half: Int): Semi def characteristics(): Int = Ordered @@ -33,7 +34,7 @@ abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val u /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` * and interpreting the contents as the elements of a collection. */ -abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] with EfficientSubstep @@ -43,7 +44,7 @@ abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underly * and interpreting the contents as the elements of a collection of `Double`s. Subclasses * are responsible for unboxing the `AnyRef` inside `nextDouble`. */ -abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) with DoubleStepper with EfficientSubstep @@ -53,7 +54,7 @@ abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_u * and interpreting the contents as the elements of a collection of `Int`s. Subclasses * are responsible for unboxing the `AnyRef` inside `nextInt`. */ -abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) with IntStepper with EfficientSubstep @@ -63,7 +64,7 @@ abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underly * and interpreting the contents as the elements of a collection of `Long`s. Subclasses * are responsible for unboxing the `AnyRef` inside `nextLong`. */ -abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) with LongStepper with EfficientSubstep diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala similarity index 66% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala index 169991c..6f4d0c9 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala @@ -1,13 +1,15 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over an immutable HashMap by slicing it into pieces. * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the * collection needs some sort of modification before transmission to the subclass. */ -trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] +private[java8] trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { protected var theIterator: Iterator[A] = null protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int): Semi @@ -32,22 +34,22 @@ extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { } } -abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsLikeSliced[A, collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, A, AnyStepper[A], SIHM] {} -abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsDoubleLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, Double, DoubleStepper, SIHM] {} -abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsIntLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, Int, IntStepper, SIHM] {} -abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsLongLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, Long, LongStepper, SIHM] {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala similarity index 65% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index 6a55395..175cf0d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -1,10 +1,12 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over an indexable collection */ -abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { def semiclone(half: Int): Semi def characteristics(): Int = Ordered + Sized + SubSized def estimateSize(): Long = iN - i0 @@ -21,28 +23,28 @@ abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var } /** Abstracts the operation of stepping over a generic indexable collection */ -abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) +private[java8] abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ -abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Ints */ -abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Longs */ -abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper with EfficientSubstep diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala similarity index 81% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala index 972b989..116e921 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala @@ -1,10 +1,12 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Common functionality for Steppers that step through an Iterator, caching the results as needed when a split is requested. */ -abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { +private[java8] abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { final protected var nextChunkSize = 16 final protected var proxied: SP = null def semiclone(): Semi // Must initialize with null iterator! @@ -14,7 +16,7 @@ abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP } /** Abstracts the operation of stepping over an iterator (that needs to be cached when splitting) */ -abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) +private[java8] abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) extends AbstractStepsLikeIterator[A, AnyStepper[A], SLI](_underlying) with AnyStepper[A] { @@ -37,7 +39,7 @@ abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] wit } /** Abstracts the operation of stepping over an iterator of Doubles (needs caching when split) */ -abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) +private[java8] abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) extends AbstractStepsLikeIterator[Double, DoubleStepper, SLI](_underlying) with DoubleStepper { @@ -60,7 +62,7 @@ abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SL } /** Abstracts the operation of stepping over an iterator of Ints (needs caching when split) */ -abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) +private[java8] abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) extends AbstractStepsLikeIterator[Int, IntStepper, SLI](_underlying) with IntStepper { @@ -83,7 +85,7 @@ abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] wit } /** Abstracts the operation of stepping over an iterator of Longs (needs caching when split) */ -abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) +private[java8] abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) extends AbstractStepsLikeIterator[Long, LongStepper, SLI](_underlying) with LongStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala similarity index 67% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala index d7a1fdb..4ec9b74 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -1,13 +1,15 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over a collection that can be sliced into pieces. * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the * collection needs some sort of modification before transmission to the subclass. */ -abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { protected var i0: Int = i def semiclone(halfHint: Int): Semi // Must really do all the work for both this and cloned collection! def characteristics(): Int = Ordered @@ -16,28 +18,28 @@ abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected } /** Abstracts the operation of stepping over a generic collection that can be efficiently sliced or otherwise subdivided */ -abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ -abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) with DoubleStepper with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ -abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) with IntStepper with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ -abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) with LongStepper with EfficientSubstep diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala similarity index 61% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala index 631ed11..6565dd8 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala @@ -1,20 +1,21 @@ -package scala.compat.java8 -package collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over a TrieIterator by asking itself to * slice itself into pieces. Note that `i` must be kept up to date in subclasses. */ -trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] +private[java8] trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { protected def demiclone(it: Iterator[A], N: Int): Semi override def characteristics() = Immutable def hasNext(): Boolean = underlying.hasNext def semiclone(halfHint: Int): Semi = if (!underlying.hasNext || i > iN-2) null - else runtime.CollectionInternals.trieIteratorSplit(underlying) match { + else scala.compat.java8.runtime.CollectionInternals.trieIteratorSplit(underlying) match { case null => null case ((pre: Iterator[A], pno), post: Iterator[A]) => val pn = (pno: Any) match { case i: Int => i; case _ => throw new Exception("Unexpected type") } @@ -27,22 +28,22 @@ extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { } } -abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) +private[java8] abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) extends StepsLikeSliced[A, Iterator[A], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[A, AnyStepper[A], STI] {} -abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) +private[java8] abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) extends StepsDoubleLikeSliced[Iterator[Double], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[Double, DoubleStepper, STI] {} -abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) +private[java8] abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) extends StepsIntLikeSliced[Iterator[Int], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[Int, IntStepper, STI] {} -abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) +private[java8] abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) extends StepsLongLikeSliced[Iterator[Long], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[Long, LongStepper, STI] {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala similarity index 98% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index e809424..d310560 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala similarity index 97% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index fcaaa67..e5c072b 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala similarity index 98% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index 1eb1282..bde77dc 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala similarity index 96% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index d3bccc0..a281068 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala similarity index 99% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index 12923c9..e3188f0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala similarity index 79% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala index 464880b..0fcc12b 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala @@ -1,6 +1,7 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over a collection with a fast tail operation. @@ -10,7 +11,7 @@ import Stepper._ * * Subclasses MUST decrement `maxN` when consuming elements, or this will not work! */ -abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { +private[java8] abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { private var nextChunkSize: Int = 0 protected def myIsEmpty(cc: CC): Boolean protected def myTailOf(cc: CC): CC @@ -62,25 +63,25 @@ abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final } /** Abstracts the operation of stepping over a generic indexable collection */ -abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, AnyStepper[A], STA](_underlying, _maxN) with AnyStepper[A] {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ -abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, DoubleStepper, STD](_underlying, _maxN) with DoubleStepper {} /** Abstracts the operation of stepping over an indexable collection of Ints */ -abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, IntStepper, STI](_underlying, _maxN) with IntStepper {} /** Abstracts the operation of stepping over an indexable collection of Longs */ -abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, LongStepper, STL](_underlying, _maxN) with LongStepper {} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index ac18a7c..2f09927 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -6,6 +6,7 @@ import org.junit.Assert._ class StepConvertersTest { import java.util._ import collectionImpl._ + import converterImpl._ import StreamConverters._ // Includes StepConverters! import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } From e77ca8724986895acaa594114ac2458db5ccfa45 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 5 Dec 2015 16:41:50 -0800 Subject: [PATCH 45/56] Adding benchmarking: made generators for collections. Also retrofitted stream converters so you can use them generically. --- benchmark/build.sbt | 10 +++ benchmark/project/plugins.sbt | 1 + .../main/scala/bench/CollectionSource.scala | 68 +++++++++++++++++++ .../scala/compat/java8/StreamConverters.scala | 33 ++++++--- .../java8/converterImpl/MakesSteppers.scala | 10 +++ 5 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 benchmark/build.sbt create mode 100644 benchmark/project/plugins.sbt create mode 100644 benchmark/src/main/scala/bench/CollectionSource.scala diff --git a/benchmark/build.sbt b/benchmark/build.sbt new file mode 100644 index 0000000..5365275 --- /dev/null +++ b/benchmark/build.sbt @@ -0,0 +1,10 @@ +enablePlugins(JmhPlugin) + +lazy val root = (project in file(".")).settings( + name := "java8-compat-bench", + scalaVersion := "2.11.7", + crossScalaVersions := List("2.11.7" /* TODO, "2.12.0-M3"*/), + organization := "org.scala-lang.modules", + version := "0.6.0-SNAPSHOT", + unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.6.0-SNAPSHOT.jar") +) diff --git a/benchmark/project/plugins.sbt b/benchmark/project/plugins.sbt new file mode 100644 index 0000000..d85fed8 --- /dev/null +++ b/benchmark/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.4") diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala new file mode 100644 index 0000000..4c01c7d --- /dev/null +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -0,0 +1,68 @@ +package bench + +import java.util.stream._ + +import scala.collection.generic.CanBuildFrom +import scala.compat.java8.StreamConverters._ +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.converterImpl._ + +package object generate { + private def myInty(n: Int) = 0 until n + private def myStringy(n: Int) = myInty(n).map(i => (i*i).toString) + + object Coll { + def i[CC[_]](n: Int)(implicit cbf: CanBuildFrom[Nothing, Int, CC[Int]]): CC[Int] = { + val b = cbf(); + myInty(n).foreach(b += _) + b.result() + } + def s[CC[_]](n: Int)(implicit cbf: CanBuildFrom[Nothing, String, CC[String]]): CC[String] = { + val b = cbf(); + myStringy(n).foreach(b += _) + b.result() + } + } + + object Pstep { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntStepper): IntStepper = + steppize(cc).stepper + def s[CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[String]): AnyStepper[String] = + steppize(cc).stepper + } + + object Sstep { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper): IntStepper = + steppize(cc).stepper + def s[CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[String]): AnyStepper[String] = + steppize(cc).stepper + } + + object PsStream { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntStepper): IntStream = + steppize(cc).stepper.parStream + def s[CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[String]): Stream[String] = + steppize(cc).stepper.parStream + } + + object SsStream { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper): IntStream = + steppize(cc).stepper.seqStream + def s[CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[String]): Stream[String] = + steppize(cc).stepper.seqStream + } + + object Sstream { + def i[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[java.lang.Integer, IntStream]) = + streamize(cc).seqStream + def s[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[String, Stream[String]]) = + streamize(cc).seqStream + } + + object Pstream { + def i[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[java.lang.Integer, IntStream]) = + streamize(cc).parStream + def s[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[String, Stream[String]]) = + streamize(cc).parStream + } +} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 9efc805..3999761 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -16,7 +16,8 @@ trait PrimitiveStreamUnboxer[A, S] { trait Priority5StreamConverters { // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. - implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) { + implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) + extends MakesSequentialStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) } implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeySeqStepper[K]) { @@ -28,13 +29,16 @@ trait Priority5StreamConverters { } trait Priority4StreamConverters extends Priority5StreamConverters { - implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) { + implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) + extends MakesSequentialStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) { + implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) + extends MakesSequentialStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) { + implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) + extends MakesSequentialStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) } implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeySeqStepper) { @@ -58,7 +62,8 @@ trait Priority4StreamConverters extends Priority5StreamConverters { } trait Priority3StreamConverters extends Priority4StreamConverters { - implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { + implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) + extends MakesSequentialStream[A, Stream[A]] with MakesParallelStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) } @@ -73,7 +78,8 @@ trait Priority3StreamConverters extends Priority4StreamConverters { } trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) { + implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) + extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) } @@ -85,7 +91,8 @@ trait Priority2StreamConverters extends Priority3StreamConverters { def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) { + implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) + extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) } @@ -97,7 +104,8 @@ trait Priority2StreamConverters extends Priority3StreamConverters { def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) { + implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) + extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) } @@ -200,17 +208,20 @@ extends Priority1StreamConverters with converterImpl.Priority1StepConverters with converterImpl.Priority1AccumulatorConverters { - implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) + extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel } - implicit class EnrichIntArrayWithStream(a: Array[Int]) { + implicit class EnrichIntArrayWithStream(a: Array[Int]) + extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { def seqStream: IntStream = java.util.Arrays.stream(a) def parStream: IntStream = seqStream.parallel } - implicit class EnrichLongArrayWithStream(a: Array[Long]) { + implicit class EnrichLongArrayWithStream(a: Array[Long]) + extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { def seqStream: LongStream = java.util.Arrays.stream(a) def parStream: LongStream = seqStream.parallel } diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index ed315a8..ed7607d 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -5,6 +5,16 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ +/** Classes or objects implementing this trait create streams suitable for sequential use */ +trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { + def seqStream: SS +} + +/** Classes or objects implementing this trait create streams suitable for parallel use */ +trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { + def parStream: SS +} + /** Classes or objects implementing this trait create generic steppers suitable for sequential use. */ trait MakesAnySeqStepper[A] extends Any { /** Generates a fresh stepper over `A`s suitable for sequential use */ From 970278cc9a837043898b8a10dd6f2a1a1d1f3745 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 7 Dec 2015 16:49:31 -0800 Subject: [PATCH 46/56] Create a bunch of classes for benchmarking. Code is quite general, since compiler can be tricked into expanding everything the way it needs to be. --- .../main/scala/bench/CollectionSource.scala | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 4c01c7d..9f63422 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -65,4 +65,106 @@ package object generate { def s[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[String, Stream[String]]) = streamize(cc).parStream } + + trait GenThingsOf[CC[_]] { + def title: String + def sizes: Array[Int] + } + + trait IntThingsOf[CC[_]] extends GenThingsOf[CC] { + implicit def myCBFi: CanBuildFrom[Nothing, Int, CC[Int]] + // Base collection + val cI = sizes.map(n => Coll.i[CC](n)) + // Iterator + def iI(j: Int)(implicit x: CC[Int] => Iterator[Int]) = x(cI(j)) + // Steppers (second letter--s = sequential, p = parallel) + def tsI(j: Int)(implicit x: CC[Int] => MakesIntSeqStepper) = Sstep i cI(j) + def tpI(j: Int)(implicit x: CC[Int] => MakesIntStepper) = Pstep i cI(j) + // Streams + def ssI(j: Int)(implicit x: CC[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = Sstream i cI(j) + def spI(j: Int)(implicit x: CC[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = Pstream i cI(j) + // Streams via steppers + def zsI(j: Int)(implicit x: CC[Int] => MakesIntSeqStepper) = SsStream i cI(j) + def zpI(j: Int)(implicit x: CC[Int] => MakesIntStepper) = PsStream i cI(j) + } + + trait StringThingsOf[CC[_]] extends GenThingsOf[CC] { + implicit def myCBFs: CanBuildFrom[Nothing, String, CC[String]] + // Base collection + val cS = sizes.map(n => Coll.s[CC](n)) + // Iterator + def iS(j: Int)(implicit x: CC[String] => Iterator[String]) = x(cS(j)) + // Steppers (second letter--s = sequential, p = parallel) + def tsS(j: Int)(implicit x: CC[String] => MakesAnySeqStepper[String]) = Sstep s cS(j) + def tpS(j: Int)(implicit x: CC[String] => MakesAnyStepper[String]) = Pstep s cS(j) + // Streams + def ssS(j: Int)(implicit x: CC[String] => MakesSequentialStream[String, Stream[String]]) = Sstream s cS(j) + def spS(j: Int)(implicit x: CC[String] => MakesParallelStream[String, Stream[String]]) = Pstream s cS(j) + // Streams via steppers + def zsS(j: Int)(implicit x: CC[String] => MakesAnySeqStepper[String]) = SsStream s cS(j) + def zpS(j: Int)(implicit x: CC[String] => MakesAnyStepper[String]) = PsStream s cS(j) + } + + trait ThingsOf[CC[_]] extends IntThingsOf[CC] with StringThingsOf[CC] {} + + abstract class AbstractThings[CC[_]](val title: String)( + implicit + outerCBFi: CanBuildFrom[Nothing, Int, CC[Int]], + outerCBFs: CanBuildFrom[Nothing, String, CC[String]] + ) + extends ThingsOf[CC] { + implicit def myCBFi = outerCBFi + implicit def myCBFs = outerCBFs + } + + class ArrThings(val sizes: Array[Int]) extends AbstractThings[Array]("Array") {} + + class IshThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.HashSet]("immutable.HashSet") {} + + class LstThings(val sizes: Array[Int]) extends AbstractThings[List]("List") {} + + class IlsThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.ListSet]("immutable.ListSet") {} + + class QueThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.Queue]("immutable.Queue") {} + + class StmThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.Stream]("immutable.Stream") {} + + class TrsThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.TreeSet]("immutable.TreeSet") {} + + class VecThings(val sizes: Array[Int]) extends AbstractThings[Vector]("Vector") {} + + class ArbThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArrayBuffer]("mutable.ArrayBuffer") {} + + class ArsThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArraySeq]("mutable.ArraySeq") {} + + class AstThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArrayStack]("mutable.ArrayStack") {} + + class MhsThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.HashSet]("mutable.HashSet") {} + + class LhsThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.LinkedHashSet]("mutable.LinkedHashSet") {} + + class PrqThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.PriorityQueue]("mutable.PriorityQueue") {} + + class MuqThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.Queue]("mutable.Queue") {} + + class WraThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.WrappedArray]("mutable.WrappedArray") {} + + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 50000, 200000, 1000000)) { + lazy val arr = new ArrThings(sizes) + lazy val ish = new IshThings(sizes) + lazy val lst = new LstThings(sizes) + lazy val ils = new IlsThings(sizes) + lazy val que = new QueThings(sizes) + lazy val stm = new StmThings(sizes) + lazy val trs = new TrsThings(sizes) + lazy val vec = new VecThings(sizes) + lazy val arb = new ArbThings(sizes) + lazy val ars = new ArsThings(sizes) + lazy val ast = new AstThings(sizes) + lazy val mhs = new MhsThings(sizes) + lazy val lhs = new LhsThings(sizes) + lazy val prq = new PrqThings(sizes) + lazy val muq = new MuqThings(sizes) + lazy val wra = new WraThings(sizes) + } } From 82ec9a518f825b4d3e314898ef751b50e990fc4f Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 19 Dec 2015 20:56:46 -0800 Subject: [PATCH 47/56] Finished Java collection stream typeclasses. Writing code generator for tests. --- benchmark/src/main/scala/bench/CodeGen.scala | 27 +++++ .../main/scala/bench/CollectionSource.scala | 103 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 benchmark/src/main/scala/bench/CodeGen.scala diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala new file mode 100644 index 0000000..90bbaa4 --- /dev/null +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -0,0 +1,27 @@ +package bench.codegen + +import scala.util._ +import scala.util.control.NonFatal + +object Generator { + val names = "arr ish lst ils que stm trs vec arb ars ast mhs lhs prq muq wra jix jln".split(' ') + def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { + try { + val pw = new java.io.PrintWriter(f) + val wr: String => Unit = s => pw.println(s) + try { pr(wr); Right(()) } + catch { case NonFatal(t) => Left(t) } + finally { pw.close() } + } + catch { case NonFatal(t) => Left(t) } + } + def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { + if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) + writeTo(target){ pr => + Seq("test").foreach(pr) + } match { + case Left(t) => println("Did not successfully write file: " + target.getPath); throw t + case _ => + } + } +} diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 9f63422..5ddf263 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -117,6 +117,103 @@ package object generate { implicit def myCBFs = outerCBFs } + // Java collection CBFs + + implicit val javaUtilArrayListIntCanBuildFrom = new CanBuildFrom[Nothing, Int, java.util.ArrayList[Int]] { + def apply(from: Nothing): collection.mutable.Builder[Int, java.util.ArrayList[Int]] = apply() + def apply(): collection.mutable.Builder[Int, java.util.ArrayList[Int]] = new collection.mutable.Builder[Int, java.util.ArrayList[Int]] { + private var myAL = new java.util.ArrayList[Int] + def clear() = { myAL = new java.util.ArrayList[Int]; () } + def result() = { val ans = myAL; clear(); ans } + def +=(x: Int) = { myAL add x; this } + } + } + implicit val javaUtilArrayListStringCanBuildFrom = new CanBuildFrom[Nothing, String, java.util.ArrayList[String]] { + def apply(from: Nothing): collection.mutable.Builder[String, java.util.ArrayList[String]] = apply() + def apply(): collection.mutable.Builder[String, java.util.ArrayList[String]] = new collection.mutable.Builder[String, java.util.ArrayList[String]] { + private var myAL = new java.util.ArrayList[String] + def clear() = { myAL = new java.util.ArrayList[String]; () } + def result() = { val ans = myAL; clear(); ans } + def +=(x: String) = { myAL add x; this } + } + } + implicit val javaUtilLinkedListIntCanBuildFrom = new CanBuildFrom[Nothing, Int, java.util.LinkedList[Int]] { + def apply(from: Nothing): collection.mutable.Builder[Int, java.util.LinkedList[Int]] = apply() + def apply(): collection.mutable.Builder[Int, java.util.LinkedList[Int]] = new collection.mutable.Builder[Int, java.util.LinkedList[Int]] { + private var myLL = new java.util.LinkedList[Int] + def clear() = { myLL = new java.util.LinkedList[Int]; () } + def result() = { val ans = myLL; clear(); ans } + def +=(x: Int) = { myLL add x; this } + } + } + implicit val javaUtilLinkedListStringCanBuildFrom = new CanBuildFrom[Nothing, String, java.util.LinkedList[String]] { + def apply(from: Nothing): collection.mutable.Builder[String, java.util.LinkedList[String]] = apply() + def apply(): collection.mutable.Builder[String, java.util.LinkedList[String]] = new collection.mutable.Builder[String, java.util.LinkedList[String]] { + private var myLL = new java.util.LinkedList[String] + def clear() = { myLL = new java.util.LinkedList[String]; () } + def result() = { val ans = myLL; clear(); ans } + def +=(x: String) = { myLL add x; this } + } + } + + // Streams from ArrayList (Java) + + implicit val getsParStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = ali => { + new MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = ali. + asInstanceOf[java.util.ArrayList[java.lang.Integer]]. + parallelStream.parallel. + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsSeqStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = ali => { + new MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = ali. + asInstanceOf[java.util.ArrayList[java.lang.Integer]]. + stream(). + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsParStreamFromArrayListString: (java.util.ArrayList[String] => MakesParallelStream[String, Stream[String]]) = als => { + new MakesParallelStream[String, Stream[String]] { + def parStream: Stream[String] = als.parallelStream.parallel + } + } + implicit val getsSeqStreamFromArrayListString: (java.util.ArrayList[String] => MakesSequentialStream[String, Stream[String]]) = als => { + new MakesSequentialStream[String, Stream[String]] { + def seqStream: Stream[String] = als.stream + } + } + + // Streams from LinkedList (Java) + + implicit val getsParStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = ali => { + new MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = ali. + asInstanceOf[java.util.LinkedList[java.lang.Integer]]. + parallelStream.parallel. + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsSeqStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = ali => { + new MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = ali. + asInstanceOf[java.util.LinkedList[java.lang.Integer]]. + stream(). + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsParStreamFromLinkedListString: (java.util.LinkedList[String] => MakesParallelStream[String, Stream[String]]) = als => { + new MakesParallelStream[String, Stream[String]] { + def parStream: Stream[String] = als.parallelStream.parallel + } + } + implicit val getsSeqStreamFromLinkedListString: (java.util.LinkedList[String] => MakesSequentialStream[String, Stream[String]]) = als => { + new MakesSequentialStream[String, Stream[String]] { + def seqStream: Stream[String] = als.stream + } + } + class ArrThings(val sizes: Array[Int]) extends AbstractThings[Array]("Array") {} class IshThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.HashSet]("immutable.HashSet") {} @@ -149,6 +246,10 @@ package object generate { class WraThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.WrappedArray]("mutable.WrappedArray") {} + class JixThings(val sizes: Array[Int]) extends AbstractThings[java.util.ArrayList]("java.util.ArrayList") {} + + class JlnThings(val sizes: Array[Int]) extends AbstractThings[java.util.LinkedList]("java.util.LinkedList") {} + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 50000, 200000, 1000000)) { lazy val arr = new ArrThings(sizes) lazy val ish = new IshThings(sizes) @@ -166,5 +267,7 @@ package object generate { lazy val prq = new PrqThings(sizes) lazy val muq = new MuqThings(sizes) lazy val wra = new WraThings(sizes) + lazy val jix = new JixThings(sizes) + lazy val jln = new JlnThings(sizes) } } From 021490bce129cf5f521a6f2929b4607ec109e501 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 21 Dec 2015 20:38:25 -0800 Subject: [PATCH 48/56] Got a little more of the code gen framework written. --- benchmark/src/main/scala/bench/CodeGen.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 90bbaa4..a4d2dfb 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -5,6 +5,7 @@ import scala.util.control.NonFatal object Generator { val names = "arr ish lst ils que stm trs vec arb ars ast mhs lhs prq muq wra jix jln".split(' ') + def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { val pw = new java.io.PrintWriter(f) @@ -15,10 +16,21 @@ object Generator { } catch { case NonFatal(t) => Left(t) } } + + def sayArrayI(oa: Option[Array[Int]]) = oa match { case Some(a) => a.mkString("Array(", ",", ")"); case _ => "" } + def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => - Seq("test").foreach(pr) + pr("""package bench.test""") + pr("""""") + pr("""object Agreement {""") + pr(""" def run() {""") + pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") + pr(""" def check[A](a1: A, a2: A, msg: String) = if (a1 != a2) wrong += msg""") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr(""" }""") + pr("""}""") } match { case Left(t) => println("Did not successfully write file: " + target.getPath); throw t case _ => From 733a0353371b83c310a070f4e13f2d920bfe79f8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Thu, 31 Dec 2015 17:46:36 -0800 Subject: [PATCH 49/56] Starting to fill in code generators. Have basic correctness test several. --- benchmark/src/main/scala/bench/CodeGen.scala | 30 +++++++++++++++++-- .../main/scala/bench/CollectionSource.scala | 14 ++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index a4d2dfb..94ecefe 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -4,7 +4,9 @@ import scala.util._ import scala.util.control.NonFatal object Generator { - val names = "arr ish lst ils que stm trs vec arb ars ast mhs lhs prq muq wra jix jln".split(' ') + val annotated = "arr ish lst* ils* que* stm* trs* vec arb ars ast* mhs lhs* prq* muq* wra jix jln".split(' ') + val names = annotated.map(_.takeWhile(_.isLetter)) + val nojnames = names.filterNot(_ startsWith "j") def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -20,15 +22,39 @@ object Generator { def sayArrayI(oa: Option[Array[Int]]) = oa match { case Some(a) => a.mkString("Array(", ",", ")"); case _ => "" } def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { + val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => pr("""package bench.test""") pr("""""") + pr("""import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr("""import scala.compat.java8.StreamConverters._""") + pr("""""") pr("""object Agreement {""") pr(""" def run() {""") pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") - pr(""" def check[A](a1: A, a2: A, msg: String) = if (a1 != a2) wrong += msg""") + pr(""" def check[A](a1: A, a2: => A, msg: String) {""") + pr(""" var t = System.nanoTime""") + pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans})) wrong += msg""") + pr(""" if (t > 2000000000) wrong += "Slow " + msg""") + pr(""" }""") pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr(""" for (i <- 0 until x.N) {""") + pr(""" val si = OnInt.sum(x.arr.cI(i))""") + nojnames.tail.foreach{ n => + pr( s" check(si, OnInt.sum(x.$n.cI(i)), ${q}cI sum $n ${q}+i.toString)") + } + nojnames.foreach{ n => + pr( s" check(si, OnInt.sum(x.$n.iI(i)), ${q}iI sum $n ${q}+i.toString)") + } + annotated.foreach{ m => + val n = m.takeWhile(_.isLetter) + val c = if (m contains "*") "ssI" else "spI" + pr( s" check(si, OnInt.sum(x.$n.$c(i)), ${q}$c sum $n ${q}+i.toString)") + } + pr( s" }") + pr(""" wrong.foreach(println)""") + pr(""" if (wrong.nonEmpty) sys.exit(1) """) pr(""" }""") pr("""}""") } match { diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 5ddf263..db8e4e4 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -214,6 +214,17 @@ package object generate { } } + object EnableIterators { + implicit val iterableIntToIterator: (Iterable[Int] => Iterator[Int]) = _.iterator + implicit val iterableStringToIterator: (Iterable[String] => Iterator[String]) = _.iterator + implicit val arrayIntToIterator: (Array[Int] => Iterator[Int]) = (a: Array[Int]) => new Iterator[Int] { + private[this] var i = 0 + def hasNext = i < a.length + def next = if (hasNext) { var ans = a(i); i += 1; ans } else throw new NoSuchElementException(i.toString) + } + implicit val arrayStringToIterator: (Array[String] => Iterator[String]) = _.iterator + } + class ArrThings(val sizes: Array[Int]) extends AbstractThings[Array]("Array") {} class IshThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.HashSet]("immutable.HashSet") {} @@ -250,7 +261,8 @@ package object generate { class JlnThings(val sizes: Array[Int]) extends AbstractThings[java.util.LinkedList]("java.util.LinkedList") {} - class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 50000, 200000, 1000000)) { + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 20000, 50000, 200000)) { + def N = sizes.length lazy val arr = new ArrThings(sizes) lazy val ish = new IshThings(sizes) lazy val lst = new LstThings(sizes) From 75a625df34cd8b15dace807c358ebc3f866d0537 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 1 Jan 2016 19:54:18 -0800 Subject: [PATCH 50/56] Generator for correctness almost complete. Still some differences between algorithms for different methods, so results aren't actually identical yet. (May need to intercept sets differently also.) --- benchmark/src/main/scala/bench/CodeGen.scala | 52 +++++++++++++------ .../main/scala/bench/CollectionSource.scala | 2 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 94ecefe..43623e3 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -1,12 +1,17 @@ package bench.codegen import scala.util._ -import scala.util.control.NonFatal +import control.NonFatal object Generator { val annotated = "arr ish lst* ils* que* stm* trs* vec arb ars ast* mhs lhs* prq* muq* wra jix jln".split(' ') + val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc")) + def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { case Array(x) => (x, None); case Array(x,y) => (x, Some(y)) }) + val names = annotated.map(_.takeWhile(_.isLetter)) - val nojnames = names.filterNot(_ startsWith "j") + val nojname = names.filterNot(_ startsWith "j").toSet + val parname = annotated.filter(_.forall(_.isLetter)).toSet + val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -35,24 +40,39 @@ object Generator { pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") pr(""" def check[A](a1: A, a2: => A, msg: String) {""") pr(""" var t = System.nanoTime""") - pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans})) wrong += msg""") + pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") + pr(""" wrong += msg""") pr(""" if (t > 2000000000) wrong += "Slow " + msg""") pr(""" }""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + allops.foreach{ case (o, t, fs) => + names.foreach{ n => + pr( s" { // Scope for operations $o collection $n") pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) - pr(""" for (i <- 0 until x.N) {""") - pr(""" val si = OnInt.sum(x.arr.cI(i))""") - nojnames.tail.foreach{ n => - pr( s" check(si, OnInt.sum(x.$n.cI(i)), ${q}cI sum $n ${q}+i.toString)") - } - nojnames.foreach{ n => - pr( s" check(si, OnInt.sum(x.$n.iI(i)), ${q}iI sum $n ${q}+i.toString)") - } - annotated.foreach{ m => - val n = m.takeWhile(_.isLetter) - val c = if (m contains "*") "ssI" else "spI" - pr( s" check(si, OnInt.sum(x.$n.$c(i)), ${q}$c sum $n ${q}+i.toString)") - } + parsefs(fs).foreach{ case (f, pf) => + pr(""" for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + } + if (sqnname(n)) { + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + } + } + if (parname(n)) { + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + } + } pr( s" }") + } + pr( s" } // End scope for operations $o collection $n") + } + } pr(""" wrong.foreach(println)""") pr(""" if (wrong.nonEmpty) sys.exit(1) """) pr(""" }""") diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index db8e4e4..689aa42 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -261,7 +261,7 @@ package object generate { class JlnThings(val sizes: Array[Int]) extends AbstractThings[java.util.LinkedList]("java.util.LinkedList") {} - class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 20000, 50000, 200000)) { + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151/*, 20000, 50000, 200000*/)) { def N = sizes.length lazy val arr = new ArrThings(sizes) lazy val ish = new IshThings(sizes) From 29b5ad11a5e061af5b669c9f897d36ef6d02224e Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 2 Jan 2016 13:31:28 -0800 Subject: [PATCH 51/56] All tests for agreement of results pass. That prerequisite for sane benchmarking is therefore met. --- benchmark/src/main/scala/bench/CodeGen.scala | 96 +++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 43623e3..fe46a2f 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -4,14 +4,24 @@ import scala.util._ import control.NonFatal object Generator { - val annotated = "arr ish lst* ils* que* stm* trs* vec arb ars ast* mhs lhs* prq* muq* wra jix jln".split(' ') - val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc")) - def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { case Array(x) => (x, None); case Array(x,y) => (x, Some(y)) }) + // Trailing * means that a collection is not expected to work efficiently in parallel + // Trailing ! means that a collection is not expected to maintain original order + val annotated = "arr ish! lst* ils*! que* stm* trs*! vec arb ars ast* mhs! lhs*! prq*! muq* wra jix jln".split(' ') + + // Parallel version if any appears after / + // Trailing ! means that collection must maintain original order (i.e. don't use if collection is marked !) + val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc!"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc!")) + + def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { + case Array(x) => (x.takeWhile(_.isLetter), None, x contains "!") + case Array(x,y) => (x.takeWhile(_.isLetter), Some(y.takeWhile(_.isLetter)), (x+y) contains "!") + }) val names = annotated.map(_.takeWhile(_.isLetter)) val nojname = names.filterNot(_ startsWith "j").toSet - val parname = annotated.filter(_.forall(_.isLetter)).toSet + val parname = annotated.filterNot(_ contains "*").map(_.takeWhile(_.isLetter)).toSet val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet + val ordname = annotated.filterNot(_ contains "!").map(_.takeWhile(_.isLetter)).toSet def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -30,53 +40,53 @@ object Generator { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => - pr("""package bench.test""") - pr("""""") - pr("""import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") - pr("""import scala.compat.java8.StreamConverters._""") - pr("""""") - pr("""object Agreement {""") - pr(""" def run() {""") - pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") - pr(""" def check[A](a1: A, a2: => A, msg: String) {""") - pr(""" var t = System.nanoTime""") - pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") - pr(""" wrong += msg""") - pr(""" if (t > 2000000000) wrong += "Slow " + msg""") - pr(""" }""") - pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """""") + pr( """object Agreement {""") + pr( """ def run() {""") + pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""") + pr( """ def check[A](a1: A, a2: => A, msg: String) {""") + pr( """ var t = System.nanoTime""") + pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") + pr( """ wrong += msg""") + pr( """ if (t > 2000000000) wrong += "Slow " + msg""") + pr( """ }""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) - parsefs(fs).foreach{ case (f, pf) => - pr(""" for (i <- 0 until m) {""") - pr( s" val z = $o.$f(x.arr.c$t(i))") - if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") - } - if (sqnname(n)) { - pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") - if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" { // Scope for operations $o collection $n") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + parsefs(fs).foreach{ case (f, pf, ord) => + if (ordname(n) || !ord) { + pr( """ for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") } - } - if (parname(n)) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") - if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + if (sqnname(n)) { + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + } + if (parname(n) && pf.isDefined) { + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") } + pr( s" }") } - pr( s" }") } - pr( s" } // End scope for operations $o collection $n") + pr( s" } // End scope for operations $o collection $n") } } - pr(""" wrong.foreach(println)""") - pr(""" if (wrong.nonEmpty) sys.exit(1) """) - pr(""" }""") - pr("""}""") + pr( """ wrong.foreach(println)""") + pr( """ if (wrong.nonEmpty) sys.exit(1) """) + pr( """ }""") + pr( """}""") } match { case Left(t) => println("Did not successfully write file: " + target.getPath); throw t case _ => From 00977b83ef2a0837dc3e7417aa48ecff7448d673 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 2 Jan 2016 14:15:50 -0800 Subject: [PATCH 52/56] Added overlooked Operations file! Also wrote a first pass of a Thyme benchmark generator. --- benchmark/src/main/scala/bench/CodeGen.scala | 129 +++++++++++++----- .../src/main/scala/bench/Operations.scala | 117 ++++++++++++++++ 2 files changed, 215 insertions(+), 31 deletions(-) create mode 100644 benchmark/src/main/scala/bench/Operations.scala diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index fe46a2f..c0e6e1b 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -40,53 +40,120 @@ object Generator { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => - pr( """package bench.test""") - pr( """""") - pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") - pr( """import scala.compat.java8.StreamConverters._""") - pr( """""") - pr( """object Agreement {""") - pr( """ def run() {""") - pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""") - pr( """ def check[A](a1: A, a2: => A, msg: String) {""") - pr( """ var t = System.nanoTime""") - pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") - pr( """ wrong += msg""") - pr( """ if (t > 2000000000) wrong += "Slow " + msg""") - pr( """ }""") - pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """""") + pr( """object Agreement {""") + pr( """ def run() {""") + pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""") + pr( """ def check[A](a1: A, a2: => A, msg: String) {""") + pr( """ var t = System.nanoTime""") + pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") + pr( """ wrong += msg""") + pr( """ if (t > 2000000000) wrong += "Slow " + msg""") + pr( """ }""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr( s" { // Scope for operations $o collection $n") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) parsefs(fs).foreach{ case (f, pf, ord) => if (ordname(n) || !ord) { - pr( """ for (i <- 0 until m) {""") - pr( s" val z = $o.$f(x.arr.c$t(i))") + pr( """ for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") } if (sqnname(n)) { - pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") } if (parname(n) && pf.isDefined) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") } - pr( s" }") + pr( s" }") } } - pr( s" } // End scope for operations $o collection $n") + pr( s" } // End scope for operations $o collection $n") } } - pr( """ wrong.foreach(println)""") - pr( """ if (wrong.nonEmpty) sys.exit(1) """) - pr( """ }""") - pr( """}""") + pr( """ wrong.foreach(println)""") + pr( """ if (wrong.nonEmpty) sys.exit(1) """) + pr( """ }""") + pr( """}""") + } match { + case Left(t) => println("Did not successfully write file: " + target.getPath); throw t + case _ => + } + } + + def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]]) { + val q = "\"" + if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) + writeTo(target){ pr => + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """import ichi.bench.Thyme""") + pr( """""") + pr( """object Agreement {""") + pr( """ def run() {""") + pr( """ val th = Thyme.warmed()""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + pr( """ def timings[A](x: bench.generate.Things, op: Int => A, name: String) {""") + pr( """ val ts = new collection.mutable.ArrayBuffer[(Double, Double, Double)]""") + pr( """ for (i <- 0 until m) {""") + pr( """ val b = Thyme.Benched.empty""") + pr( """ val a = th.bench(op(i))(b)""") + pr( """ if (a == null) ts += ((Double.NaN, Double.NaN, Double.NaN))""") + pr( """ else ts += ((b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6)""") + pr( """ }""") + pr( """ val sb = new StringBuilder""") + pr( """ sb ++= name + $q: $q""") + pr( """ if (sb.length < 36) sb ++= $q $q * (36 - sb.length)""") + pr( """ ts.foreach{ case (c, lo, hi) =>""") + pr( """ sb ++= $q $q""") + pr( """ sb ++= ${q}12.4f${q}.format(c)""") + pr( """ sb ++= ${q}12.4f${q}.format(lo)""") + pr( """ sb ++= ${q}12.4f${q}.format(hi)""") + pr( """ }""") + pr( """ println(sb.result)""") + pr( """ }""") + allops.foreach{ case (o, t, fs) => + names.foreach{ n => + pr( s" { // Scope for operations $o collection $n") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + parsefs(fs).foreach{ case (f, pf, ord) => + if (ordname(n) || !ord) { + if (nojname(n)) { + pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + } + if (sqnname(n)) { + pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + } + if (parname(n) && pf.isDefined) { + pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + } + pr( s" }") + } + } + pr( s" } // End scope for operations $o collection $n") + } + } + pr( """ }""") + pr( """}""") } match { case Left(t) => println("Did not successfully write file: " + target.getPath); throw t case _ => diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala new file mode 100644 index 0000000..38c3f4c --- /dev/null +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -0,0 +1,117 @@ +package bench.operate + +import java.util.stream._ +import java.util.{function => jf} +import scala.compat.java8.StreamConverters._ +import scala.compat.java8.converterImpl._ +import scala.compat.java8.collectionImpl._ + +object CloseEnough { + import scala.math._ + def apply[A](a: A, b: => A): Boolean = a match { + case da: Double => b match { + case db: Double => (da.isNaN && db.isNaN) || abs(da - db) <= max(1, max(abs(da), abs(db)))*1e-6 + case x => a == x + } + case _ => a == b + } +} + +object OnInt { + def expensive(i: Int) = { var v = i.toDouble; var j = 0; while (j < 10) { v = math.exp(math.sin(v)); j += 1 }; v+j } + + def sum(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { s += a(i); i += 1 }; s } + def sum(t: Traversable[Int]): Int = t.sum + def sum(i: Iterator[Int]): Int = i.sum + def sum(s: IntStepper): Int = s.fold(0)(_ + _) + def sum(s: IntStream): Int = s.sum + def psum(i: Iterable[Int]): Int = i.par.sum + def psum(s: IntStream): Int = s.parallel.sum + + def trig(a: Array[Int]): Double = { var i = 0; var s = 0.0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } + def trig(t: Traversable[Int]): Double = t.map(expensive).sum + def trig(i: Iterator[Int]): Double = i.map(expensive).sum + def trig(s: IntStepper): Double = s.fold(0.0)((x,i) => x + expensive(i)) + def trig(s: IntStream): Double = s.mapToDouble(new jf.IntToDoubleFunction{ def applyAsDouble(i: Int) = expensive(i) }).sum + def ptrig(i: Iterable[Int]): Double = i.par.map(expensive).sum + def ptrig(s: IntStream): Double = trig(s.parallel) + + def fmc(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { if (i%7 == 1) s += (i/7)*i; i += 1 }; s } + def fmc(t: Traversable[Int]): Int = t.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def fmc(i: Iterator[Int]): Int = i.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def fmc(s: IntStream): Int = s. + filter(new jf.IntPredicate { def test(x: Int) = (x%7) == 1 }). + map(new jf.IntUnaryOperator{ def applyAsInt(x: Int) = (x/7)*x }). + sum + def pfmc(i: Iterable[Int]): Int = i.par.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def pfmc(s: IntStream): Int = fmc(s.parallel) + + def mdtc(a: Array[Int]): Int = { var i = 1; while(i < a.length) { if ((a(i) << 1) >= 42) return i-1; i += 1 }; i - 1 } + def mdtc(t: Traversable[Int]): Int = t.map(_ << 1).drop(1).takeWhile(_ < 42).size + def mdtc(i: Iterator[Int]): Int = i.map(_ << 1).drop(1).takeWhile(_ < 42).size + def mdtc(s: IntStream): Int = { + val temp = s.map(new jf.IntUnaryOperator { def applyAsInt(x: Int) = x << 1 }).skip(1) + val acc = new IntAccumulator + temp.allMatch(new jf.IntPredicate{ def test(x: Int) = if (x < 42) { acc += x; true } else false }) + acc.size.toInt + } +} + +object OnString { + def expensive(s: String) = { val h = scala.util.hashing.MurmurHash3.stringHash(s); OnInt.expensive(h) } + + def nbr(a: Array[String]): Int = { var s,i = 0; while (i < a.length) { if (a(i).charAt(a(i).length-1) < '5') s += 1; i += 1 }; s } + def nbr(t: Traversable[String]): Int = t.count(s => s.charAt(s.length-1) < '5') + def nbr(i: Iterator[String]): Int = i.count(s => s.charAt(s.length-1) < '5') + def nbr(p: Stepper[String]): Int = p.fold(0)((i,s) => if (s.charAt(s.length-1) < '5') i+1 else i) + def nbr(q: Stream[String]): Int = q.filter(new jf.Predicate[String] { def test(s: String) = s.charAt(s.length-1) < '5' }).count.toInt + def pnbr(i: Iterable[String]): Int = i.par.count(s => s.charAt(s.length-1) < '5') + def pnbr(q: Stream[String]): Int = nbr(q.parallel) + + def htrg(a: Array[String]): Double = { var s = 0.0; var i = 0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } + def htrg(t: Traversable[String]): Double = t.map(expensive).sum + def htrg(i: Iterator[String]): Double = i.map(expensive).sum + def htrg(p: Stepper[String]): Double = p.fold(0.0)((x,s) => x + expensive(s)) + def htrg(q: Stream[String]): Double = q.mapToDouble(new jf.ToDoubleFunction[String]{ def applyAsDouble(s: String) = expensive(s) }).sum + def phtrg(i: Iterable[String]): Double = i.par.map(expensive).sum + def phtrg(q: Stream[String]): Double = htrg(q.parallel) + + def fmc(a: Array[String]): Int = { + var s, i = 0 + while (i < a.length) { + val x = a(i) + if (x.charAt(x.length-1) == '1' && (x.length > 2 || (x.charAt(0) != '-' && x.length > 1))) s += 1 + i += 1 + } + s + } + def fmc(t: Traversable[String]): Int = + t.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def fmc(i: Iterator[String]): Int = + i.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def fmc(q: Stream[String]): Int = + q.filter(new jf.Predicate[String]{ def test(x: String) = x.charAt(x.length-1) == '1' }). + map[String](new jf.Function[String, String]{ def apply(x: String) = if (x.charAt(0) == '-') x.substring(1) else x }). + filter(new jf.Predicate[String]{ def test(x: String) = x.length > 1 }). + count.toInt + def pfmc(i: Iterable[String]): Int = + i.par.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def pfmc(q: Stream[String]): Int = fmc(q.parallel) + + def mdtc(a: Array[String]): Int = { + var i = 1 + while (i < a.length) { + if (a(i).reverse.length >= 3) return i-1 + i += 1 + } + i-1 + } + def mdtc(t: Traversable[String]): Int = t.map(_.reverse).drop(1).takeWhile(_.length < 3).size + def mdtc(i: Iterator[String]): Int = i.map(_.reverse).drop(1).takeWhile(_.length < 3).size + def mdtc(q: Stream[String]): Int = { + val temp = q.map[String](new jf.UnaryOperator[String] { def apply(x: String) = x.reverse }).skip(1) + val acc = new Accumulator[String] + temp.allMatch(new jf.Predicate[String]{ def test(x: String) = if (x.length < 3) { acc += x; true } else false }) + acc.size.toInt + } +} From 8ab04680a29f6fa25a2dcdc4305c078917fe4982 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 2 Jan 2016 18:13:49 -0800 Subject: [PATCH 53/56] JMH benchmarks working, and take less time than forever. --- benchmark/src/main/scala/bench/CodeGen.scala | 111 ++++++++++++++----- 1 file changed, 82 insertions(+), 29 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index c0e6e1b..7563a88 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -22,6 +22,7 @@ object Generator { val parname = annotated.filterNot(_ contains "*").map(_.takeWhile(_.isLetter)).toSet val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet val ordname = annotated.filterNot(_ contains "!").map(_.takeWhile(_.isLetter)).toSet + val jmhsizes = Array(10, 10000) // JMH takes FOREVER, so we're lucky to get two sizes. def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -57,29 +58,30 @@ object Generator { pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr( s" { // Scope for operations $o collection $n") + pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) parsefs(fs).foreach{ case (f, pf, ord) => if (ordname(n) || !ord) { - pr( """ for (i <- 0 until m) {""") - pr( s" val z = $o.$f(x.arr.c$t(i))") + pr( """ for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") } if (sqnname(n)) { - pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") } if (parname(n) && pf.isDefined) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") } - pr( s" }") + pr( s" }") } } + pr( s" x = null // Allow GC" ) pr( s" } // End scope for operations $o collection $n") } } @@ -93,7 +95,7 @@ object Generator { } } - def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]]) { + def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]] = None) { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => @@ -103,52 +105,56 @@ object Generator { pr( """import scala.compat.java8.StreamConverters._""") pr( """import ichi.bench.Thyme""") pr( """""") - pr( """object Agreement {""") + pr( """object ThymeBench {""") pr( """ def run() {""") pr( """ val th = Thyme.warmed()""") pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) pr( """ def timings[A](x: bench.generate.Things, op: Int => A, name: String) {""") pr( """ val ts = new collection.mutable.ArrayBuffer[(Double, Double, Double)]""") + pr( """ val discard = th.clock(op(m-1))(_ => ()) // Init collections""") pr( """ for (i <- 0 until m) {""") + pr( """ println(name + i)""") pr( """ val b = Thyme.Benched.empty""") pr( """ val a = th.bench(op(i))(b)""") pr( """ if (a == null) ts += ((Double.NaN, Double.NaN, Double.NaN))""") - pr( """ else ts += ((b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6)""") + pr( """ else ts += ((""") + pr( """ b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6""") + pr( """ ))""") pr( """ }""") pr( """ val sb = new StringBuilder""") - pr( """ sb ++= name + $q: $q""") - pr( """ if (sb.length < 36) sb ++= $q $q * (36 - sb.length)""") + pr( """ sb ++= name + ":" """) + pr( """ if (sb.length < 16) sb ++= " " * (16 - sb.length)""") pr( """ ts.foreach{ case (c, lo, hi) =>""") - pr( """ sb ++= $q $q""") - pr( """ sb ++= ${q}12.4f${q}.format(c)""") - pr( """ sb ++= ${q}12.4f${q}.format(lo)""") - pr( """ sb ++= ${q}12.4f${q}.format(hi)""") + pr( """ sb ++= " " """) + pr( """ sb ++= " %11.4f".format(c)""") + pr( """ sb ++= " %11.4f".format(lo)""") + pr( """ sb ++= " %11.4f".format(hi)""") pr( """ }""") pr( """ println(sb.result)""") pr( """ }""") allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr( s" { // Scope for operations $o collection $n") + pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) parsefs(fs).foreach{ case (f, pf, ord) => if (ordname(n) || !ord) { if (nojname(n)) { - pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n${q})"); + pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n${q})") } if (sqnname(n)) { - pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n${q})") if (nojname(n)) - pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n${q})") } if (parname(n) && pf.isDefined) { - pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n${q})") if (nojname(n)) - pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n${q})") } - pr( s" }") } } + pr( s" x = null // Allow GC" ) pr( s" } // End scope for operations $o collection $n") } } @@ -159,4 +165,51 @@ object Generator { case _ => } } + + def jmhBench(target: java.io.File = new java.io.File("JmhBench.scala"), sizes: Option[Array[Int]] = Some(jmhsizes)) { + val q = "\"" + if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) + writeTo(target){ pr => + pr( """// This file auto-generated by bench.codegen.Generator.jmhBench. Do not modify directly.""") + pr( """""") + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """import org.openjdk.jmh.annotations._""") + pr( """""") + pr( """@State(Scope.Benchmark)""") + pr( """class JmhBench {""") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})") + val m = sizes.map(_.length).getOrElse(new bench.generate.Things().N) + allops.foreach{ case (o, t, fs) => + names.foreach{ n => + parsefs(fs).foreach{ case (f, pf, ord) => + for (i <- 0 until m) { + if (ordname(n) || !ord) { + if (nojname(n)) { + pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))"); + pr( s" @Benchmark def bench_i${t}_${f}_${n}_$i() = $o.$f(x.$n.i$t($i))") + } + if (sqnname(n)) { + pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))") + //if (nojname(n)) + // pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))") + } + if (parname(n) && pf.isDefined) { + pr( s" @Benchmark def bench_sp${t}_${f}_${n}_$i() = $o.$f(x.$n.sp$t($i))") + //if (nojname(n)) + // pr( s" @Benchmark def bench_zp${t}_${f}_${n}_$i() = $o.$f(x.$n.zp$t($i))") + } + } + } + } + } + } + pr( """}""") + } match { + case Left(t) => println("Did not successfully write file: " + target.getPath); throw t + case _ => + } + } } From bea1d3936cccdf3c145c7ce565ae018f1381526e Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 8 Jan 2016 12:36:39 -0800 Subject: [PATCH 54/56] Added docs and benchmark results. --- README.md | 56 + benchmark/README.md | 33 + benchmark/project/plugins.sbt | 2 +- benchmark/results/jmhbench.graphs.ascii | 2537 +++++++++++++++++ benchmark/results/jmhbench.log | 1054 +++++++ benchmark/src/main/scala/bench/CodeGen.scala | 59 +- .../src/main/scala/bench/Operations.scala | 29 +- .../src/main/scala/bench/ParseJmhLog.scala | 146 + .../java8/converterImpl/MakesSteppers.scala | 2 +- 9 files changed, 3883 insertions(+), 35 deletions(-) create mode 100644 benchmark/README.md create mode 100644 benchmark/results/jmhbench.graphs.ascii create mode 100644 benchmark/results/jmhbench.log create mode 100644 benchmark/src/main/scala/bench/ParseJmhLog.scala diff --git a/README.md b/README.md index b757697..6f7b472 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,31 @@ are used for collections, so this is best done to gather the results of an expen Finally, there is a Java class, `ScalaStreamer`, that has a series of `from` methods that can be used to obtain Java 8 Streams from Scala collections from within Java. +#### Performance Considerations + +For sequential operations, Scala's `iterator` almost always equals or exceeds the performance of a Java 8 stream. Thus, +one should favor `iterator` (and its richer set of operations) over `seqStream` for general use. However, long +chains of processing of primitive types can sometimes benefit from the manually specialized methods in `DoubleStream`, +`IntStream`, and `LongStream`. + +Note that although `iterator` typically has superior performance in a sequential context, the advantage is modest +(usually less than 50% higher throughput for `iterator`). + +For parallel operations, `parStream` and even `seqStream.parallel` meets or exceeds the performance of Scala parallel +collections methods (invoked with `.par`). Especially for small collections, the difference can be substantial. In +some cases, when a Scala (parallel) collection is the ultimate result, Scala parallel collections can have an advantage +as the collection can (in some cases) be built in parallel. + +Because the wrappers are invoked based on the static type of the collection, there are also cases where parallelization +is inefficient when interfacing with Java 8 Streams (e.g. when a collection is typed as `Seq[String]` so might have linear +access like `List`, but actually is a `WrappedArray[String]` that can be efficiently parallelized) but can be efficient +with Scala parallel collections. The `parStream` method is only available when the static type is known to be compatible +with rapid parallel operation; `seqStream` can be parallelized by using `.parallel`, but may or may not be efficient. + +If the operations available on Java 8 Streams are sufficient, the collection type is known statically with enough precision +to enable parStream, and an `Accumulator` or non-collection type is an acceptable result, Java 8 Streams will essentially +always outperform the Scala parallel collections. + #### Scala Usage Example ```scala @@ -158,6 +183,37 @@ object Test { } ``` +#### Using Java 8 Streams with Scala Function Converters + +Scala can emit Java SAMs for lambda expressions that are arguments to methods that take a Java SAM rather than +a Scala Function. However, it can be convenient to restrict the SAM interface to interactions with Java code +(including Java 8 Streams) rather than having it propagate throughout Scala code. + +Using Java 8 Stream converters together with function converters allows one to accomplish this with only a modest +amount of fuss. + +Example: + +```scala +import scala.compat.java8.FunctionConverters._ +import scala.compat.java8.StreamConverters._ + +def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = + xs.parStream. // Creates java.util.stream.Stream[String] + map[String](f.asJava).sorted. // Maps A to String and sorts (in parallel) + toArray.mkString(sep) // Back to an Array to use Scala's mkString +``` + +Note that explicit creation of a new lambda will tend to lead to improved type inference and at least equal +performance: + +```scala +def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = + xs.parStream. + map[String](a => f(a)).sorted. // Explicit lambda creates a SAM wrapper for f + toArray.mkString(sep) +``` + #### Java Usage Example ```java diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 0000000..eb68ef9 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,33 @@ +# Benchmark suite for Java 8 Streams compatibility layer + +This project is intended to support semi-manual benchmarking of the Java 8 streams compatibility layer in Scala collections. + +Because the benchmarking is **very computationally expensive** it should be done occasionally, not automatically. + +## Code generation step + +1. Run `sbt console` + +2. If the `JmhBench.scala` file already exists, delete it. + +3. Enter `bench.codegen.Generate.jmhBench()` to generate the `JmhBench.scala` file. + +## Benchmarking step + +1. Make sure your terminal has plenty of lines of scrollback. (A couple thousand should do.) + +2. Run `sbt` + +3. Enter `jmh:run -i 5 -wi 3 -f5`. Wait overnight. + +4. Clip off the last set of lines from the terminal window starting before the line that contains `[info] # Run complete. Total time:` and including that line until the end. + +5. Save that in the file `results/jmhbench.log` + +## Comparison step + +1. Run `sbt console` + +2. Enter `bench.examine.SpeedReports()` + +3. Look at the ASCII art results showing speed comparisons. diff --git a/benchmark/project/plugins.sbt b/benchmark/project/plugins.sbt index d85fed8..c5220d0 100644 --- a/benchmark/project/plugins.sbt +++ b/benchmark/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.4") +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.5") diff --git a/benchmark/results/jmhbench.graphs.ascii b/benchmark/results/jmhbench.graphs.ascii new file mode 100644 index 0000000..b6f4c9d --- /dev/null +++ b/benchmark/results/jmhbench.graphs.ascii @@ -0,0 +1,2537 @@ +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + Int, base collection ##= 0.112 +- 9.4 % + Int, iterator on coll #### 0.160 +- 14.7 % + Int, serial stream ###- 0.129 +- 9.6 % + +filter/map/sum trio +10 elements +Array + Int, base collection ######################### 1.000 +- 0.2 % + Int, iterator on coll ###= 0.150 +- 10.1 % + Int, serial stream #####= 0.223 +- 6.0 % + +filter/map/sum trio +10 elements +collection.mutable.ArraySeq + Int, base collection #= 0.068 +- 12.4 % + Int, iterator on coll ##### 0.197 +- 11.1 % + Int, serial stream ### 0.122 +- 8.4 % + +filter/map/sum trio +10 elements +collection.mutable.ArrayStack + Int, base collection ## 0.081 +- 5.1 % + Int, iterator on coll ####- 0.171 +- 1.4 % + Int, serial stream ##= 0.113 +- 7.8 % + +filter/map/sum trio +10 elements +collection.immutable.ListSet + Int, base collection # 0.037 +- 15.6 % + Int, iterator on coll ####= 0.185 +- 15.0 % + Int, serial stream ##- 0.091 +- 6.1 % + +filter/map/sum trio +10 elements +collection.immutable.HashSet + Int, base collection #= 0.069 +- 13.0 % + Int, iterator on coll ###- 0.132 +- 14.3 % + Int, serial stream ##= 0.111 +- 10.1 % + +filter/map/sum trio +10 elements +java.util.ArrayList + Int, serial stream ###= 0.144 +- 7.1 % + +filter/map/sum trio +10 elements +java.util.LinkedList + Int, serial stream ###= 0.141 +- 3.2 % + +filter/map/sum trio +10 elements +collection.mutable.LinkedHashSet + Int, base collection ## 0.081 +- 17.3 % + Int, iterator on coll ####= 0.189 +- 0.6 % + Int, serial stream ### 0.114 +- 0.8 % + +filter/map/sum trio +10 elements +collection.immutable.List + Int, base collection ##- 0.099 +- 6.1 % + Int, iterator on coll #### 0.165 +- 20.9 % + Int, serial stream ##= 0.104 +- 11.6 % + +filter/map/sum trio +10 elements +collection.mutable.HashSet + Int, base collection #- 0.060 +- 1.1 % + Int, iterator on coll ##= 0.106 +- 1.2 % + Int, serial stream ##= 0.101 +- 6.6 % + +filter/map/sum trio +10 elements +collection.mutable.Queue + Int, base collection # 0.035 +- 13.4 % + Int, iterator on coll ##= 0.106 +- 0.8 % + Int, serial stream # 0.046 +- 7.3 % + +filter/map/sum trio +10 elements +collection.mutable.PriorityQueue + Int, base collection ##- 0.092 +- 3.6 % + Int, iterator on coll ####- 0.174 +- 12.0 % + Int, serial stream ### 0.118 +- 7.8 % + +filter/map/sum trio +10 elements +collection.immutable.Queue + Int, base collection #= 0.069 +- 1.7 % + Int, iterator on coll ### 0.124 +- 21.0 % + Int, serial stream ##= 0.102 +- 3.2 % + +filter/map/sum trio +10 elements +collection.immutable.Stream + Int, base collection ## 0.075 +- 5.5 % + Int, iterator on coll #- 0.056 +- 4.7 % + Int, serial stream ##= 0.102 +- 15.3 % + +filter/map/sum trio +10 elements +collection.immutable.TreeSet + Int, base collection #= 0.069 +- 3.9 % + Int, iterator on coll ### 0.125 +- 3.5 % + Int, serial stream ##= 0.108 +- 1.4 % + +filter/map/sum trio +10 elements +collection.immutable.Vector + Int, base collection ##- 0.093 +- 2.9 % + Int, iterator on coll #### 0.164 +- 1.2 % + Int, serial stream ###- 0.127 +- 2.7 % + +filter/map/sum trio +10 elements +collection.mutable.WrappedArray + Int, base collection ##- 0.095 +- 2.1 % + Int, iterator on coll ###- 0.128 +- 0.6 % + Int, serial stream ###- 0.129 +- 4.9 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + Int, base collection #####= 0.225 +- 0.7 % + Int, iterator on coll ######- 0.258 +- 0.4 % + Int, serial stream ##= 0.101 +- 7.9 % + +filter/map/sum trio +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.1 % + Int, iterator on coll #### 0.165 +- 2.9 % + Int, serial stream ####################= 0.833 +- 1.8 % + +filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + Int, base collection ####= 0.181 +- 3.2 % + Int, iterator on coll ######- 0.258 +- 0.7 % + Int, serial stream ##- 0.098 +- 8.6 % + +filter/map/sum trio +10000 elements +collection.mutable.ArrayStack + Int, base collection ####= 0.187 +- 1.3 % + Int, iterator on coll ######= 0.273 +- 0.5 % + Int, serial stream ##= 0.109 +- 5.0 % + +filter/map/sum trio +10000 elements +collection.immutable.ListSet + Int, base collection 0.005 +- 5.2 % + Int, iterator on coll #####- 0.214 +- 1.3 % + Int, serial stream ##- 0.099 +- 3.6 % + +filter/map/sum trio +10000 elements +collection.immutable.HashSet + Int, base collection # 0.037 +- 9.0 % + Int, iterator on coll ##= 0.107 +- 0.6 % + Int, serial stream ##- 0.092 +- 0.9 % + +filter/map/sum trio +10000 elements +java.util.ArrayList + Int, serial stream ######- 0.256 +- 5.5 % + +filter/map/sum trio +10000 elements +java.util.LinkedList + Int, serial stream ####### 0.280 +- 3.4 % + +filter/map/sum trio +10000 elements +collection.mutable.LinkedHashSet + Int, base collection ## 0.082 +- 4.3 % + Int, iterator on coll ######= 0.261 +- 2.9 % + Int, serial stream ##= 0.112 +- 6.3 % + +filter/map/sum trio +10000 elements +collection.immutable.List + Int, base collection ###- 0.135 +- 1.8 % + Int, iterator on coll #####- 0.215 +- 1.6 % + Int, serial stream #= 0.060 +- 1.6 % + +filter/map/sum trio +10000 elements +collection.mutable.HashSet + Int, base collection # 0.046 +- 2.7 % + Int, iterator on coll ##= 0.111 +- 1.6 % + Int, serial stream ##= 0.109 +- 2.1 % + +filter/map/sum trio +10000 elements +collection.mutable.Queue + Int, base collection #- 0.059 +- 1.1 % + Int, iterator on coll ##### 0.204 +- 1.2 % + Int, serial stream #- 0.051 +- 2.4 % + +filter/map/sum trio +10000 elements +collection.mutable.PriorityQueue + Int, base collection ##= 0.103 +- 9.3 % + Int, iterator on coll ######- 0.248 +- 0.6 % + Int, serial stream ##- 0.088 +- 4.4 % + +filter/map/sum trio +10000 elements +collection.immutable.Queue + Int, base collection ## 0.079 +- 0.7 % + Int, iterator on coll #####- 0.211 +- 2.5 % + Int, serial stream ##= 0.113 +- 1.6 % + +filter/map/sum trio +10000 elements +collection.immutable.Stream + Int, base collection ##- 0.087 +- 2.4 % + Int, iterator on coll #- 0.050 +- 6.6 % + Int, serial stream ##- 0.089 +- 31.9 % + +filter/map/sum trio +10000 elements +collection.immutable.TreeSet + Int, base collection = 0.023 +- 2.5 % + Int, iterator on coll ###= 0.146 +- 1.6 % + Int, serial stream ## 0.083 +- 2.6 % + +filter/map/sum trio +10000 elements +collection.immutable.Vector + Int, base collection #### 0.159 +- 5.3 % + Int, iterator on coll ##### 0.206 +- 0.9 % + Int, serial stream ##= 0.104 +- 18.7 % + +filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + Int, base collection ### 0.125 +- 1.9 % + Int, iterator on coll #### 0.157 +- 3.4 % + Int, serial stream ##- 0.091 +- 8.9 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + String, base collection #### 0.153 +- 0.6 % + String, iterator on coll #########= 0.381 +- 1.0 % + String, serial stream ###- 0.138 +- 10.2 % + +filter/map/sum trio +10 elements +Array + String, base collection ######################### 1.000 +- 0.1 % + String, iterator on coll #########= 0.389 +- 1.0 % + String, serial stream ###= 0.142 +- 8.6 % + +filter/map/sum trio +10 elements +collection.mutable.ArraySeq + String, base collection ##- 0.094 +- 4.2 % + String, iterator on coll #########= 0.382 +- 0.4 % + String, serial stream ###- 0.136 +- 10.0 % + +filter/map/sum trio +10 elements +collection.mutable.ArrayStack + String, base collection ### 0.124 +- 1.3 % + String, iterator on coll ###########= 0.473 +- 1.2 % + String, serial stream ### 0.125 +- 10.5 % + +filter/map/sum trio +10 elements +collection.immutable.ListSet + String, base collection #- 0.054 +- 4.9 % + String, iterator on coll ######= 0.265 +- 1.2 % + String, serial stream ##= 0.102 +- 3.1 % + +filter/map/sum trio +10 elements +collection.immutable.HashSet + String, base collection ##- 0.093 +- 3.1 % + String, iterator on coll ##### 0.205 +- 2.7 % + String, serial stream ##- 0.097 +- 2.9 % + +filter/map/sum trio +10 elements +java.util.ArrayList + String, serial stream #### 0.159 +- 6.3 % + +filter/map/sum trio +10 elements +java.util.LinkedList + String, serial stream ###= 0.150 +- 4.1 % + +filter/map/sum trio +10 elements +collection.mutable.LinkedHashSet + String, base collection ###- 0.134 +- 1.4 % + String, iterator on coll ##########- 0.419 +- 0.7 % + String, serial stream ### 0.125 +- 10.9 % + +filter/map/sum trio +10 elements +collection.immutable.List + String, base collection ###- 0.138 +- 3.0 % + String, iterator on coll ########## 0.401 +- 1.1 % + String, serial stream ##= 0.105 +- 17.2 % + +filter/map/sum trio +10 elements +collection.mutable.HashSet + String, base collection ##= 0.102 +- 2.1 % + String, iterator on coll ######- 0.252 +- 0.6 % + String, serial stream ##- 0.091 +- 20.6 % + +filter/map/sum trio +10 elements +collection.mutable.Queue + String, base collection # 0.035 +- 1.9 % + String, iterator on coll ####- 0.178 +- 1.6 % + String, serial stream #- 0.058 +- 5.1 % + +filter/map/sum trio +10 elements +collection.mutable.PriorityQueue + String, base collection ### 0.117 +- 1.0 % + String, iterator on coll ########## 0.398 +- 2.4 % + String, serial stream ### 0.120 +- 10.1 % + +filter/map/sum trio +10 elements +collection.immutable.Queue + String, base collection ##= 0.102 +- 4.6 % + String, iterator on coll ######### 0.357 +- 1.5 % + String, serial stream ##- 0.097 +- 11.5 % + +filter/map/sum trio +10 elements +collection.immutable.Stream + String, base collection ##= 0.101 +- 7.1 % + String, iterator on coll #= 0.073 +- 5.8 % + String, serial stream ##= 0.110 +- 12.1 % + +filter/map/sum trio +10 elements +collection.immutable.TreeSet + String, base collection ##- 0.097 +- 1.6 % + String, iterator on coll ##### 0.194 +- 5.2 % + String, serial stream ##= 0.102 +- 7.8 % + +filter/map/sum trio +10 elements +collection.immutable.Vector + String, base collection ### 0.126 +- 0.8 % + String, iterator on coll #######- 0.299 +- 7.3 % + String, serial stream ### 0.123 +- 12.2 % + +filter/map/sum trio +10 elements +collection.mutable.WrappedArray + String, base collection ### 0.123 +- 1.1 % + String, iterator on coll ##########- 0.409 +- 0.4 % + String, serial stream ###- 0.135 +- 9.9 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + String, base collection ########- 0.328 +- 1.2 % + String, iterator on coll ############# 0.518 +- 0.6 % + String, serial stream ##########= 0.427 +- 1.0 % + +filter/map/sum trio +10000 elements +Array + String, base collection ######################### 1.000 +- 0.8 % + String, iterator on coll #############= 0.548 +- 0.9 % + String, serial stream ########### 0.442 +- 13.1 % + +filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + String, base collection #######- 0.292 +- 5.3 % + String, iterator on coll ############# 0.523 +- 0.6 % + String, serial stream ########= 0.342 +- 17.6 % + +filter/map/sum trio +10000 elements +collection.mutable.ArrayStack + String, base collection ######## 0.325 +- 1.8 % + String, iterator on coll ############### 0.600 +- 0.8 % + String, serial stream ########- 0.338 +- 15.3 % + +filter/map/sum trio +10000 elements +collection.immutable.ListSet + String, base collection 0.003 +- 8.8 % + String, iterator on coll ############# 0.516 +- 1.7 % + String, serial stream #######= 0.306 +- 12.0 % + +filter/map/sum trio +10000 elements +collection.immutable.HashSet + String, base collection #- 0.054 +- 1.3 % + String, iterator on coll ### 0.118 +- 0.8 % + String, serial stream ##= 0.103 +- 0.5 % + +filter/map/sum trio +10000 elements +java.util.ArrayList + String, serial stream ############ 0.478 +- 8.2 % + +filter/map/sum trio +10000 elements +java.util.LinkedList + String, serial stream ############- 0.496 +- 8.7 % + +filter/map/sum trio +10000 elements +collection.mutable.LinkedHashSet + String, base collection ##- 0.091 +- 0.5 % + String, iterator on coll #############= 0.545 +- 1.1 % + String, serial stream #########= 0.392 +- 10.3 % + +filter/map/sum trio +10000 elements +collection.immutable.List + String, base collection ####- 0.175 +- 3.4 % + String, iterator on coll ############= 0.511 +- 2.1 % + String, serial stream #######= 0.301 +- 0.7 % + +filter/map/sum trio +10000 elements +collection.mutable.HashSet + String, base collection #- 0.047 +- 0.6 % + String, iterator on coll ##= 0.108 +- 0.5 % + String, serial stream ### 0.117 +- 0.3 % + +filter/map/sum trio +10000 elements +collection.mutable.Queue + String, base collection # 0.046 +- 0.7 % + String, iterator on coll ###########= 0.461 +- 1.3 % + String, serial stream ##- 0.097 +- 1.7 % + +filter/map/sum trio +10000 elements +collection.mutable.PriorityQueue + String, base collection ### 0.115 +- 10.9 % + String, iterator on coll #########- 0.376 +- 2.2 % + String, serial stream ###### 0.245 +- 1.0 % + +filter/map/sum trio +10000 elements +collection.immutable.Queue + String, base collection ###- 0.135 +- 2.0 % + String, iterator on coll ############# 0.516 +- 0.9 % + String, serial stream #####= 0.220 +- 2.2 % + +filter/map/sum trio +10000 elements +collection.immutable.Stream + String, base collection ### 0.120 +- 2.5 % + String, iterator on coll ## 0.086 +- 6.3 % + String, serial stream ###### 0.235 +- 5.3 % + +filter/map/sum trio +10000 elements +collection.immutable.TreeSet + String, base collection = 0.024 +- 0.9 % + String, iterator on coll ###= 0.146 +- 3.4 % + String, serial stream ###= 0.148 +- 0.6 % + +filter/map/sum trio +10000 elements +collection.immutable.Vector + String, base collection #####- 0.207 +- 2.9 % + String, iterator on coll #########= 0.382 +- 1.8 % + String, serial stream ######### 0.353 +- 24.5 % + +filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + String, base collection ########- 0.334 +- 2.4 % + String, iterator on coll #############= 0.542 +- 0.9 % + String, serial stream #########- 0.376 +- 18.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trig on hashCode +10 elements +collection.mutable.ArrayBuffer + String, base collection ########################= 0.982 +- 0.1 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ########################= 0.989 +- 0.3 % + String Stepper (can par) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10 elements +Array + String, base collection ######################### 1.000 +- 0.1 % + String, iterator on coll ########################= 0.991 +- 0.2 % + String, serial stream ########################= 0.990 +- 0.3 % + String Stepper (can par) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.ArraySeq + String, base collection #################= 0.704 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ########################= 0.989 +- 0.3 % + String Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.ArrayStack + String, base collection #################= 0.701 +- 0.2 % + String, iterator on coll ########################= 0.988 +- 0.3 % + String, serial stream ########################= 0.988 +- 0.2 % + String Stepper (seq only) ######################### 0.994 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.ListSet + String, base collection #######################- 0.935 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ########################= 0.985 +- 0.9 % + String Stepper (seq only) ########################= 0.992 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.HashSet + String, base collection #################- 0.689 +- 0.2 % + String, iterator on coll ########################= 0.989 +- 0.2 % + String, serial stream ########################= 0.991 +- 0.2 % + String Stepper (can par) ########################= 0.992 +- 0.2 % + +slow trig on hashCode +10 elements +java.util.ArrayList + String, serial stream ######################### 0.995 +- 0.3 % + +slow trig on hashCode +10 elements +java.util.LinkedList + String, serial stream ######################### 0.997 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.LinkedHashSet + String, base collection ######################## 0.960 +- 0.4 % + String, iterator on coll ########################= 0.987 +- 0.3 % + String, serial stream ########################= 0.992 +- 0.2 % + String Stepper (seq only) ########################= 0.993 +- 0.4 % + +slow trig on hashCode +10 elements +collection.immutable.List + String, base collection ########################= 0.985 +- 0.2 % + String, iterator on coll ######################### 0.993 +- 0.2 % + String, serial stream ########################= 0.993 +- 0.2 % + String Stepper (seq only) ######################### 0.994 +- 0.3 % + +slow trig on hashCode +10 elements +collection.mutable.HashSet + String, base collection ######################## 0.960 +- 0.3 % + String, iterator on coll ########################= 0.984 +- 0.2 % + String, serial stream ########################= 0.989 +- 0.2 % + String Stepper (can par) ########################= 0.992 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.Queue + String, base collection #######################- 0.927 +- 0.4 % + String, iterator on coll ######################### 0.994 +- 0.3 % + String, serial stream ########################- 0.972 +- 0.3 % + String Stepper (seq only) ########################- 0.973 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.PriorityQueue + String, base collection ########################= 0.983 +- 0.2 % + String, iterator on coll ######################### 0.993 +- 0.3 % + String, serial stream ########################= 0.989 +- 0.4 % + String Stepper (seq only) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.Queue + String, base collection ######################## 0.966 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ########################= 0.986 +- 0.5 % + String Stepper (seq only) ######################### 0.993 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.Stream + String, base collection ######################## 0.956 +- 0.2 % + String, iterator on coll ########################- 0.975 +- 0.2 % + String, serial stream ########################= 0.987 +- 0.5 % + String Stepper (seq only) ######################### 0.994 +- 0.6 % + +slow trig on hashCode +10 elements +collection.immutable.TreeSet + String, base collection ################# 0.682 +- 0.2 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ########################= 0.991 +- 0.2 % + String Stepper (seq only) ########################= 0.993 +- 0.3 % + +slow trig on hashCode +10 elements +collection.immutable.Vector + String, base collection ########################= 0.982 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ########################= 0.988 +- 0.3 % + String Stepper (can par) ########################= 0.991 +- 0.5 % + +slow trig on hashCode +10 elements +collection.mutable.WrappedArray + String, base collection ########################= 0.983 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ########################= 0.988 +- 0.4 % + String Stepper (can par) ######################### 0.995 +- 0.2 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trig on hashCode +10000 elements +collection.mutable.ArrayBuffer + String, base collection ########################= 0.989 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.2 % + String Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10000 elements +Array + String, base collection ######################### 1.000 +- 0.1 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ######################### 0.996 +- 0.1 % + String Stepper (can par) ######################### 0.996 +- 0.3 % + +slow trig on hashCode +10000 elements +collection.mutable.ArraySeq + String, base collection ##################### 0.839 +- 11.2 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ######################### 0.994 +- 0.2 % + String Stepper (can par) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.ArrayStack + String, base collection #################= 0.713 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ######################### 0.994 +- 0.2 % + String Stepper (seq only) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.immutable.ListSet + String, base collection ######################= 0.913 +- 0.3 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ########################= 0.991 +- 0.2 % + String Stepper (seq only) ########################= 0.986 +- 1.0 % + +slow trig on hashCode +10000 elements +collection.immutable.HashSet + String, base collection ###############= 0.627 +- 0.4 % + String, iterator on coll ########################= 0.982 +- 0.2 % + String, serial stream ########################- 0.970 +- 0.1 % + String Stepper (can par) ########################= 0.981 +- 0.5 % + +slow trig on hashCode +10000 elements +java.util.ArrayList + String, serial stream ######################### 0.996 +- 0.1 % + +slow trig on hashCode +10000 elements +java.util.LinkedList + String, serial stream ######################### 0.996 +- 0.1 % + +slow trig on hashCode +10000 elements +collection.mutable.LinkedHashSet + String, base collection #######################= 0.941 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.1 % + String Stepper (seq only) ######################### 0.994 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.immutable.List + String, base collection ########################= 0.987 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ######################### 0.996 +- 0.1 % + String Stepper (seq only) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.HashSet + String, base collection ####################### 0.916 +- 0.4 % + String, iterator on coll ########################- 0.977 +- 0.4 % + String, serial stream ########################- 0.979 +- 0.1 % + String Stepper (can par) ########################= 0.983 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.mutable.Queue + String, base collection ######################## 0.957 +- 0.3 % + String, iterator on coll ########################= 0.992 +- 0.3 % + String, serial stream ########################- 0.977 +- 0.2 % + String Stepper (seq only) ########################- 0.971 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.PriorityQueue + String, base collection #################= 0.711 +- 0.3 % + String, iterator on coll ########################= 0.988 +- 0.4 % + String, serial stream ########################= 0.989 +- 0.1 % + String Stepper (seq only) ########################= 0.990 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.immutable.Queue + String, base collection ########################- 0.972 +- 0.3 % + String, iterator on coll ########################= 0.993 +- 0.3 % + String, serial stream ########################= 0.987 +- 0.7 % + String Stepper (seq only) ########################= 0.990 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.immutable.Stream + String, base collection ######################## 0.954 +- 0.2 % + String, iterator on coll ########################- 0.975 +- 0.3 % + String, serial stream ########################= 0.992 +- 0.1 % + String Stepper (seq only) ########################= 0.993 +- 0.3 % + +slow trig on hashCode +10000 elements +collection.immutable.TreeSet + String, base collection ################ 0.635 +- 0.4 % + String, iterator on coll ########################= 0.983 +- 0.3 % + String, serial stream ########################= 0.981 +- 0.2 % + String Stepper (seq only) ########################= 0.983 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.immutable.Vector + String, base collection ########################= 0.984 +- 0.2 % + String, iterator on coll ########################= 0.991 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.1 % + String Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.WrappedArray + String, base collection ########################= 0.986 +- 0.2 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.1 % + String Stepper (can par) ######################### 0.996 +- 0.2 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10 elements +collection.mutable.ArrayBuffer + Int, base collection # 0.043 +- 0.7 % + Int, iterator on coll ###### 0.237 +- 14.9 % + Int, serial stream #= 0.067 +- 3.1 % + +map/filter/take trio +10 elements +Array + Int, base collection ######################### 1.000 +- 0.9 % + Int, iterator on coll ######- 0.257 +- 25.2 % + Int, serial stream ## 0.076 +- 2.2 % + +map/filter/take trio +10 elements +collection.mutable.ArraySeq + Int, base collection = 0.031 +- 1.2 % + Int, iterator on coll #####- 0.213 +- 20.9 % + Int, serial stream #= 0.065 +- 7.1 % + +map/filter/take trio +10 elements +collection.mutable.ArrayStack + Int, base collection = 0.023 +- 1.6 % + Int, iterator on coll ######- 0.259 +- 15.7 % + Int, serial stream #= 0.066 +- 1.0 % + +map/filter/take trio +10 elements +java.util.ArrayList + Int, serial stream #- 0.051 +- 1.8 % + +map/filter/take trio +10 elements +java.util.LinkedList + Int, serial stream #- 0.052 +- 4.6 % + +map/filter/take trio +10 elements +collection.immutable.List + Int, base collection #= 0.063 +- 2.1 % + Int, iterator on coll ######= 0.267 +- 2.3 % + Int, serial stream #- 0.059 +- 1.9 % + +map/filter/take trio +10 elements +collection.mutable.Queue + Int, base collection - 0.013 +- 4.4 % + Int, iterator on coll ###- 0.130 +- 3.8 % + Int, serial stream = 0.027 +- 2.4 % + +map/filter/take trio +10 elements +collection.immutable.Queue + Int, base collection = 0.022 +- 0.8 % + Int, iterator on coll #####= 0.222 +- 13.2 % + Int, serial stream #- 0.050 +- 2.0 % + +map/filter/take trio +10 elements +collection.immutable.Stream + Int, base collection - 0.013 +- 3.4 % + Int, iterator on coll # 0.039 +- 5.1 % + Int, serial stream #- 0.058 +- 2.7 % + +map/filter/take trio +10 elements +collection.immutable.Vector + Int, base collection #- 0.058 +- 1.1 % + Int, iterator on coll ######- 0.254 +- 2.1 % + Int, serial stream #= 0.066 +- 2.4 % + +map/filter/take trio +10 elements +collection.mutable.WrappedArray + Int, base collection # 0.045 +- 0.6 % + Int, iterator on coll #####- 0.209 +- 14.9 % + Int, serial stream #= 0.063 +- 1.3 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10000 elements +collection.mutable.ArrayBuffer + Int, base collection 0.000 +- 3.5 % + Int, iterator on coll #= 0.067 +- 13.3 % + Int, serial stream #- 0.056 +- 1.9 % + +map/filter/take trio +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.7 % + Int, iterator on coll ## 0.084 +- 10.5 % + Int, serial stream #= 0.063 +- 1.0 % + +map/filter/take trio +10000 elements +collection.mutable.ArraySeq + Int, base collection 0.000 +- 2.3 % + Int, iterator on coll #= 0.062 +- 0.4 % + Int, serial stream #- 0.056 +- 1.1 % + +map/filter/take trio +10000 elements +collection.mutable.ArrayStack + Int, base collection 0.000 +- 8.5 % + Int, iterator on coll ## 0.080 +- 17.5 % + Int, serial stream #- 0.053 +- 2.6 % + +map/filter/take trio +10000 elements +java.util.ArrayList + Int, serial stream # 0.042 +- 4.4 % + +map/filter/take trio +10000 elements +java.util.LinkedList + Int, serial stream # 0.041 +- 5.9 % + +map/filter/take trio +10000 elements +collection.immutable.List + Int, base collection 0.000 +- 1.0 % + Int, iterator on coll #= 0.072 +- 0.8 % + Int, serial stream #- 0.055 +- 10.6 % + +map/filter/take trio +10000 elements +collection.mutable.Queue + Int, base collection 0.000 +- 3.2 % + Int, iterator on coll #- 0.053 +- 28.4 % + Int, serial stream - 0.018 +- 1.7 % + +map/filter/take trio +10000 elements +collection.immutable.Queue + Int, base collection 0.000 +- 1.4 % + Int, iterator on coll ## 0.076 +- 10.0 % + Int, serial stream # 0.037 +- 1.2 % + +map/filter/take trio +10000 elements +collection.immutable.Stream + Int, base collection - 0.009 +- 6.4 % + Int, iterator on coll = 0.026 +- 4.1 % + Int, serial stream #- 0.056 +- 0.8 % + +map/filter/take trio +10000 elements +collection.immutable.Vector + Int, base collection 0.000 +- 2.0 % + Int, iterator on coll ## 0.082 +- 15.8 % + Int, serial stream #- 0.055 +- 3.9 % + +map/filter/take trio +10000 elements +collection.mutable.WrappedArray + Int, base collection 0.000 +- 8.8 % + Int, iterator on coll #- 0.053 +- 1.3 % + Int, serial stream #- 0.049 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10 elements +collection.mutable.ArrayBuffer + String, base collection ############ 0.485 +- 0.8 % + String, iterator on coll #############- 0.531 +- 1.1 % + String, serial stream ############= 0.502 +- 3.1 % + +map/filter/take trio +10 elements +Array + String, base collection ######################### 1.000 +- 0.6 % + String, iterator on coll #############- 0.527 +- 1.7 % + String, serial stream ############# 0.516 +- 1.0 % + +map/filter/take trio +10 elements +collection.mutable.ArraySeq + String, base collection ##########- 0.414 +- 0.9 % + String, iterator on coll ############= 0.509 +- 3.8 % + String, serial stream #############= 0.545 +- 12.0 % + +map/filter/take trio +10 elements +collection.mutable.ArrayStack + String, base collection ########- 0.335 +- 1.8 % + String, iterator on coll #############= 0.551 +- 10.2 % + String, serial stream #############- 0.531 +- 10.7 % + +map/filter/take trio +10 elements +java.util.ArrayList + String, serial stream ############ 0.477 +- 2.2 % + +map/filter/take trio +10 elements +java.util.LinkedList + String, serial stream ############- 0.487 +- 5.2 % + +map/filter/take trio +10 elements +collection.immutable.List + String, base collection #############= 0.547 +- 5.1 % + String, iterator on coll ##############= 0.589 +- 1.4 % + String, serial stream #############- 0.528 +- 13.5 % + +map/filter/take trio +10 elements +collection.mutable.Queue + String, base collection ###### 0.235 +- 3.4 % + String, iterator on coll #############- 0.531 +- 1.2 % + String, serial stream #########= 0.389 +- 9.1 % + +map/filter/take trio +10 elements +collection.immutable.Queue + String, base collection ########- 0.336 +- 1.1 % + String, iterator on coll ##############= 0.589 +- 1.3 % + String, serial stream ###########- 0.458 +- 2.1 % + +map/filter/take trio +10 elements +collection.immutable.Stream + String, base collection ######- 0.250 +- 2.5 % + String, iterator on coll ##########- 0.415 +- 2.0 % + String, serial stream #############= 0.546 +- 12.1 % + +map/filter/take trio +10 elements +collection.immutable.Vector + String, base collection ############= 0.512 +- 6.6 % + String, iterator on coll ############# 0.525 +- 1.2 % + String, serial stream ############- 0.496 +- 1.0 % + +map/filter/take trio +10 elements +collection.mutable.WrappedArray + String, base collection ###########= 0.472 +- 4.5 % + String, iterator on coll #############- 0.527 +- 2.6 % + String, serial stream ############- 0.500 +- 1.0 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10000 elements +collection.mutable.ArrayBuffer + String, base collection 0.000 +- 9.2 % + String, iterator on coll ############## 0.555 +- 1.4 % + String, serial stream #############- 0.530 +- 1.4 % + +map/filter/take trio +10000 elements +Array + String, base collection ######################### 1.000 +- 8.4 % + String, iterator on coll #############= 0.542 +- 1.1 % + String, serial stream #############= 0.549 +- 3.1 % + +map/filter/take trio +10000 elements +collection.mutable.ArraySeq + String, base collection 0.000 +- 6.2 % + String, iterator on coll #############= 0.550 +- 2.2 % + String, serial stream ##############- 0.571 +- 12.9 % + +map/filter/take trio +10000 elements +collection.mutable.ArrayStack + String, base collection 0.000 +- 6.9 % + String, iterator on coll ###############= 0.624 +- 7.3 % + String, serial stream ############# 0.516 +- 1.8 % + +map/filter/take trio +10000 elements +java.util.ArrayList + String, serial stream ############# 0.522 +- 4.9 % + +map/filter/take trio +10000 elements +java.util.LinkedList + String, serial stream ############= 0.511 +- 1.6 % + +map/filter/take trio +10000 elements +collection.immutable.List + String, base collection 0.001 +- 9.9 % + String, iterator on coll ############### 0.600 +- 2.1 % + String, serial stream ############## 0.554 +- 5.2 % + +map/filter/take trio +10000 elements +collection.mutable.Queue + String, base collection 0.000 +- 7.9 % + String, iterator on coll ############## 0.562 +- 1.2 % + String, serial stream ########## 0.396 +- 9.2 % + +map/filter/take trio +10000 elements +collection.immutable.Queue + String, base collection 0.000 +- 3.8 % + String, iterator on coll ##############= 0.590 +- 2.3 % + String, serial stream #############= 0.546 +- 13.1 % + +map/filter/take trio +10000 elements +collection.immutable.Stream + String, base collection ######= 0.273 +- 2.0 % + String, iterator on coll ###########- 0.458 +- 3.7 % + String, serial stream ############### 0.606 +- 11.6 % + +map/filter/take trio +10000 elements +collection.immutable.Vector + String, base collection 0.001 +- 8.4 % + String, iterator on coll ############# 0.521 +- 1.4 % + String, serial stream #############= 0.540 +- 4.6 % + +map/filter/take trio +10000 elements +collection.mutable.WrappedArray + String, base collection 0.001 +- 1.7 % + String, iterator on coll #############= 0.544 +- 2.2 % + String, serial stream #############= 0.543 +- 3.3 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast sum of lengths +10 elements +collection.mutable.ArrayBuffer + String, base collection ########- 0.332 +- 0.8 % + String, iterator on coll ######## 0.316 +- 2.1 % + String, serial stream ######## 0.318 +- 1.3 % + String Stepper (can par) ##############= 0.582 +- 0.4 % + +fast sum of lengths +10 elements +Array + String, base collection ######################### 1.000 +- 0.4 % + String, iterator on coll #######- 0.287 +- 15.1 % + String, serial stream ######## 0.325 +- 1.5 % + String Stepper (can par) ################# 0.686 +- 0.4 % + +fast sum of lengths +10 elements +collection.mutable.ArraySeq + String, base collection ##################- 0.731 +- 1.2 % + String, iterator on coll ######## 0.319 +- 0.5 % + String, serial stream ######## 0.319 +- 0.6 % + String Stepper (can par) ##############= 0.582 +- 0.3 % + +fast sum of lengths +10 elements +collection.mutable.ArrayStack + String, base collection ##################- 0.729 +- 1.5 % + String, iterator on coll ########= 0.344 +- 1.0 % + String, serial stream ####### 0.282 +- 3.0 % + String Stepper (seq only) ############# 0.519 +- 9.1 % + +fast sum of lengths +10 elements +collection.immutable.ListSet + String, base collection #####- 0.219 +- 0.4 % + String, iterator on coll ####### 0.285 +- 0.9 % + String, serial stream ####- 0.179 +- 5.8 % + String Stepper (seq only) ########## 0.394 +- 1.2 % + +fast sum of lengths +10 elements +collection.immutable.HashSet + String, base collection ######= 0.266 +- 11.3 % + String, iterator on coll ####### 0.277 +- 11.4 % + String, serial stream #### 0.161 +- 1.3 % + String Stepper (can par) #####= 0.221 +- 3.2 % + +fast sum of lengths +10 elements +java.util.ArrayList + String, serial stream ########- 0.337 +- 0.4 % + +fast sum of lengths +10 elements +java.util.LinkedList + String, serial stream ######## 0.314 +- 1.6 % + +fast sum of lengths +10 elements +collection.mutable.LinkedHashSet + String, base collection ################= 0.668 +- 1.1 % + String, iterator on coll #########- 0.370 +- 0.9 % + String, serial stream #######- 0.292 +- 0.8 % + String Stepper (seq only) ############- 0.495 +- 0.9 % + +fast sum of lengths +10 elements +collection.immutable.List + String, base collection ###############- 0.613 +- 1.3 % + String, iterator on coll ########= 0.343 +- 0.4 % + String, serial stream #####- 0.214 +- 2.0 % + String Stepper (seq only) ########- 0.339 +- 2.4 % + +fast sum of lengths +10 elements +collection.mutable.HashSet + String, base collection ###########- 0.458 +- 4.6 % + String, iterator on coll ######- 0.248 +- 0.7 % + String, serial stream ##### 0.199 +- 0.9 % + String Stepper (can par) ##########= 0.432 +- 1.4 % + +fast sum of lengths +10 elements +collection.mutable.Queue + String, base collection ## 0.086 +- 0.8 % + String, iterator on coll ###### 0.245 +- 0.4 % + String, serial stream #= 0.069 +- 1.0 % + String Stepper (seq only) ## 0.084 +- 1.8 % + +fast sum of lengths +10 elements +collection.mutable.PriorityQueue + String, base collection ######## 0.314 +- 0.3 % + String, iterator on coll ######## 0.322 +- 0.5 % + String, serial stream ####### 0.285 +- 1.3 % + String Stepper (seq only) ############= 0.505 +- 0.8 % + +fast sum of lengths +10 elements +collection.immutable.Queue + String, base collection #####= 0.232 +- 0.4 % + String, iterator on coll ########- 0.330 +- 0.7 % + String, serial stream #### 0.166 +- 0.9 % + String Stepper (seq only) #####= 0.231 +- 1.1 % + +fast sum of lengths +10 elements +collection.immutable.Stream + String, base collection ###############= 0.629 +- 0.7 % + String, iterator on coll ## 0.087 +- 4.7 % + String, serial stream #####- 0.219 +- 1.6 % + String Stepper (seq only) ########- 0.331 +- 1.0 % + +fast sum of lengths +10 elements +collection.immutable.TreeSet + String, base collection ########- 0.338 +- 0.4 % + String, iterator on coll #####= 0.224 +- 0.7 % + String, serial stream ####- 0.173 +- 1.6 % + String Stepper (seq only) ######- 0.255 +- 3.4 % + +fast sum of lengths +10 elements +collection.immutable.Vector + String, base collection ####### 0.276 +- 0.5 % + String, iterator on coll #######= 0.307 +- 0.5 % + String, serial stream ###### 0.236 +- 1.2 % + String Stepper (can par) ##########- 0.418 +- 0.6 % + +fast sum of lengths +10 elements +collection.mutable.WrappedArray + String, base collection ########= 0.344 +- 0.3 % + String, iterator on coll ########- 0.329 +- 0.3 % + String, serial stream ######## 0.317 +- 0.5 % + String Stepper (can par) ##############= 0.583 +- 1.4 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast sum of lengths +10000 elements +collection.mutable.ArrayBuffer + String, base collection ########= 0.340 +- 0.9 % + String, iterator on coll ########- 0.334 +- 0.3 % + String, serial stream #################- 0.690 +- 33.6 % + String Stepper (can par) ############# 0.526 +- 2.1 % + +fast sum of lengths +10000 elements +Array + String, base collection ######################### 1.000 +- 0.6 % + String, iterator on coll ########- 0.328 +- 0.9 % + String, serial stream ################## 0.726 +- 27.9 % + String Stepper (can par) ################ 0.640 +- 4.6 % + +fast sum of lengths +10000 elements +collection.mutable.ArraySeq + String, base collection ####################= 0.830 +- 0.7 % + String, iterator on coll ########- 0.332 +- 0.4 % + String, serial stream ###################- 0.774 +- 24.4 % + String Stepper (can par) ############# 0.523 +- 1.9 % + +fast sum of lengths +10000 elements +collection.mutable.ArrayStack + String, base collection ################- 0.654 +- 6.7 % + String, iterator on coll ######### 0.362 +- 0.3 % + String, serial stream ################= 0.666 +- 25.4 % + String Stepper (seq only) ############# 0.515 +- 9.1 % + +fast sum of lengths +10000 elements +collection.immutable.ListSet + String, base collection #########- 0.379 +- 30.0 % + String, iterator on coll ######## 0.325 +- 16.5 % + String, serial stream ########### 0.436 +- 39.9 % + String Stepper (seq only) #########- 0.372 +- 6.0 % + +fast sum of lengths +10000 elements +collection.immutable.HashSet + String, base collection ### 0.125 +- 3.1 % + String, iterator on coll ### 0.123 +- 1.0 % + String, serial stream ### 0.118 +- 0.5 % + String Stepper (can par) ###- 0.135 +- 0.6 % + +fast sum of lengths +10000 elements +java.util.ArrayList + String, serial stream ####################= 0.821 +- 10.1 % + +fast sum of lengths +10000 elements +java.util.LinkedList + String, serial stream ################### 0.755 +- 3.9 % + +fast sum of lengths +10000 elements +collection.mutable.LinkedHashSet + String, base collection #################- 0.691 +- 2.3 % + String, iterator on coll ##########- 0.412 +- 11.4 % + String, serial stream #############= 0.551 +- 30.5 % + String Stepper (seq only) ########## 0.402 +- 3.8 % + +fast sum of lengths +10000 elements +collection.immutable.List + String, base collection #################= 0.713 +- 1.4 % + String, iterator on coll #########- 0.372 +- 11.2 % + String, serial stream ###########- 0.459 +- 0.6 % + String Stepper (seq only) #######= 0.304 +- 1.5 % + +fast sum of lengths +10000 elements +collection.mutable.HashSet + String, base collection ###- 0.127 +- 0.2 % + String, iterator on coll ##= 0.113 +- 0.3 % + String, serial stream ## 0.086 +- 0.4 % + String Stepper (can par) ###- 0.133 +- 0.9 % + +fast sum of lengths +10000 elements +collection.mutable.Queue + String, base collection #= 0.072 +- 1.4 % + String, iterator on coll #########- 0.367 +- 26.7 % + String, serial stream ### 0.115 +- 1.7 % + String Stepper (seq only) ## 0.080 +- 1.2 % + +fast sum of lengths +10000 elements +collection.mutable.PriorityQueue + String, base collection ########- 0.338 +- 30.0 % + String, iterator on coll ######## 0.319 +- 30.9 % + String, serial stream #### 0.166 +- 16.9 % + String Stepper (seq only) ###### 0.243 +- 5.6 % + +fast sum of lengths +10000 elements +collection.immutable.Queue + String, base collection #########= 0.381 +- 32.4 % + String, iterator on coll ########## 0.399 +- 11.0 % + String, serial stream ######- 0.254 +- 2.7 % + String Stepper (seq only) #####= 0.220 +- 0.8 % + +fast sum of lengths +10000 elements +collection.immutable.Stream + String, base collection #######- 0.287 +- 4.8 % + String, iterator on coll ##- 0.095 +- 7.2 % + String, serial stream #####= 0.220 +- 8.0 % + String Stepper (seq only) ######- 0.258 +- 1.7 % + +fast sum of lengths +10000 elements +collection.immutable.TreeSet + String, base collection ####= 0.180 +- 0.7 % + String, iterator on coll ##### 0.194 +- 8.2 % + String, serial stream ##= 0.110 +- 0.9 % + String Stepper (seq only) ####= 0.190 +- 2.3 % + +fast sum of lengths +10000 elements +collection.immutable.Vector + String, base collection ##########- 0.412 +- 15.0 % + String, iterator on coll ######### 0.355 +- 22.0 % + String, serial stream ###########= 0.460 +- 16.9 % + String Stepper (can par) ###########- 0.452 +- 3.0 % + +fast sum of lengths +10000 elements +collection.mutable.WrappedArray + String, base collection ########= 0.353 +- 0.3 % + String, iterator on coll ########- 0.340 +- 0.8 % + String, serial stream ################# 0.683 +- 32.7 % + String Stepper (can par) #############- 0.533 +- 2.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + Int, par collection ########################- 0.968 +- 3.4 % + Int, parallel stream ##############################~~# 4.299 +- 2.7 % + +parallel filter/map/sum trio +10 elements +Array + Int, par collection ######################### 1.000 +- 2.1 % + Int, parallel stream ##############################~~# 4.361 +- 1.2 % + +parallel filter/map/sum trio +10 elements +collection.mutable.ArraySeq + Int, par collection #########################- 1.014 +- 1.2 % + Int, parallel stream ##############################~~# 4.362 +- 2.0 % + +parallel filter/map/sum trio +10 elements +collection.immutable.HashSet + Int, par collection ####################= 0.830 +- 2.2 % + Int, parallel stream ##############################~~# 3.569 +- 1.5 % + +parallel filter/map/sum trio +10 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 4.389 +- 1.1 % + +parallel filter/map/sum trio +10 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 4.299 +- 2.4 % + +parallel filter/map/sum trio +10 elements +collection.mutable.HashSet + Int, par collection ########################### 1.079 +- 1.1 % + Int, parallel stream ##############################~~# 5.277 +- 2.3 % + +parallel filter/map/sum trio +10 elements +collection.immutable.Vector + Int, par collection #####################- 0.847 +- 1.7 % + Int, parallel stream ##############################~~# 4.289 +- 1.2 % + +parallel filter/map/sum trio +10 elements +collection.mutable.WrappedArray + Int, par collection ######################### 1.003 +- 1.4 % + Int, parallel stream ##############################~~# 4.399 +- 0.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + Int, par collection ##############################~~# 1.469 +- 1.3 % + Int, parallel stream ##############################~~# 6.310 +- 10.2 % + +parallel filter/map/sum trio +10000 elements +Array + Int, par collection ######################### 1.000 +- 1.0 % + Int, parallel stream ##############################~~# 11.043 +- 1.0 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + Int, par collection ##############################~~# 1.469 +- 1.5 % + Int, parallel stream ##############################~~# 6.301 +- 4.2 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.HashSet + Int, par collection ################= 0.664 +- 0.8 % + Int, parallel stream ##############################~~# 3.468 +- 1.0 % + +parallel filter/map/sum trio +10000 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 9.264 +- 3.0 % + +parallel filter/map/sum trio +10000 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 4.247 +- 10.6 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.HashSet + Int, par collection ################## 0.727 +- 1.2 % + Int, parallel stream ##############################~~# 3.579 +- 7.4 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.Vector + Int, par collection ##############################- 1.216 +- 2.2 % + Int, parallel stream ##############################~~# 5.987 +- 3.6 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + Int, par collection ########################### 1.074 +- 1.1 % + Int, parallel stream ##############################~~# 5.150 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + String, par collection #########################- 1.014 +- 0.8 % + String, parallel stream ##############################~~# 4.219 +- 3.2 % + +parallel filter/map/sum trio +10 elements +Array + String, par collection ######################### 1.000 +- 2.8 % + String, parallel stream ##############################~~# 4.299 +- 1.1 % + +parallel filter/map/sum trio +10 elements +collection.mutable.ArraySeq + String, par collection ######################### 1.002 +- 1.6 % + String, parallel stream ##############################~~# 4.326 +- 1.5 % + +parallel filter/map/sum trio +10 elements +collection.immutable.HashSet + String, par collection #####################= 0.861 +- 1.1 % + String, parallel stream ##############################~~# 3.656 +- 1.1 % + +parallel filter/map/sum trio +10 elements +java.util.ArrayList + String, parallel stream ##############################~~# 4.173 +- 3.2 % + +parallel filter/map/sum trio +10 elements +java.util.LinkedList + String, parallel stream ##############################~~# 4.073 +- 3.0 % + +parallel filter/map/sum trio +10 elements +collection.mutable.HashSet + String, par collection ######################## 0.964 +- 1.3 % + String, parallel stream ##############################~~# 4.613 +- 1.2 % + +parallel filter/map/sum trio +10 elements +collection.immutable.Vector + String, par collection #####################- 0.857 +- 1.2 % + String, parallel stream ##############################~~# 4.221 +- 1.6 % + +parallel filter/map/sum trio +10 elements +collection.mutable.WrappedArray + String, par collection ########################= 0.982 +- 2.7 % + String, parallel stream ##############################~~# 4.370 +- 1.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + String, par collection ######################### 0.994 +- 1.4 % + String, parallel stream ##############################~~# 5.317 +- 7.5 % + +parallel filter/map/sum trio +10000 elements +Array + String, par collection ######################### 1.000 +- 1.3 % + String, parallel stream ##############################~~# 6.147 +- 1.0 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + String, par collection ######################### 1.004 +- 1.5 % + String, parallel stream ##############################~~# 5.464 +- 5.9 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.HashSet + String, par collection ########### 0.434 +- 2.2 % + String, parallel stream ##############################~~# 2.221 +- 6.4 % + +parallel filter/map/sum trio +10000 elements +java.util.ArrayList + String, parallel stream ##############################~~# 6.477 +- 0.4 % + +parallel filter/map/sum trio +10000 elements +java.util.LinkedList + String, parallel stream ##############################~~# 2.252 +- 10.3 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.HashSet + String, par collection ###########= 0.470 +- 0.9 % + String, parallel stream ##############################~~# 2.477 +- 8.0 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.Vector + String, par collection ###################= 0.786 +- 0.7 % + String, parallel stream ##############################~~# 5.795 +- 1.1 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + String, par collection ########################= 0.985 +- 1.7 % + String, parallel stream ##############################~~# 5.575 +- 5.4 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trig on hashCode +10 elements +collection.mutable.ArrayBuffer + String, par collection ######################### 0.999 +- 1.3 % + String, parallel stream ##############################~~# 3.106 +- 0.7 % + +slow parallel trig on hashCode +10 elements +Array + String, par collection ######################### 1.000 +- 1.1 % + String, parallel stream ##############################~~# 3.144 +- 0.8 % + +slow parallel trig on hashCode +10 elements +collection.mutable.ArraySeq + String, par collection #########################- 1.016 +- 1.1 % + String, parallel stream ##############################~~# 3.117 +- 1.0 % + +slow parallel trig on hashCode +10 elements +collection.immutable.HashSet + String, par collection ################ 0.638 +- 1.3 % + String, parallel stream ##############################~~# 2.879 +- 0.6 % + +slow parallel trig on hashCode +10 elements +java.util.ArrayList + String, parallel stream ##############################~~# 3.144 +- 0.7 % + +slow parallel trig on hashCode +10 elements +java.util.LinkedList + String, parallel stream ##############################~~# 3.126 +- 1.0 % + +slow parallel trig on hashCode +10 elements +collection.mutable.HashSet + String, par collection #######################- 0.937 +- 1.0 % + String, parallel stream ##############################~~# 2.938 +- 0.5 % + +slow parallel trig on hashCode +10 elements +collection.immutable.Vector + String, par collection ##################= 0.741 +- 1.5 % + String, parallel stream ##############################~~# 3.139 +- 1.0 % + +slow parallel trig on hashCode +10 elements +collection.mutable.WrappedArray + String, par collection ######################### 1.000 +- 1.0 % + String, parallel stream ##############################~~# 3.104 +- 1.1 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trig on hashCode +10000 elements +collection.mutable.ArrayBuffer + String, par collection ########################- 0.978 +- 2.1 % + String, parallel stream ##############################- 1.209 +- 0.9 % + +slow parallel trig on hashCode +10000 elements +Array + String, par collection ######################### 1.000 +- 0.9 % + String, parallel stream ##############################- 1.211 +- 0.9 % + +slow parallel trig on hashCode +10000 elements +collection.mutable.ArraySeq + String, par collection ########################- 0.975 +- 2.2 % + String, parallel stream ##############################- 1.215 +- 0.7 % + +slow parallel trig on hashCode +10000 elements +collection.immutable.HashSet + String, par collection ####################- 0.809 +- 1.9 % + String, parallel stream ############################- 1.129 +- 0.5 % + +slow parallel trig on hashCode +10000 elements +java.util.ArrayList + String, parallel stream ############################## 1.200 +- 2.0 % + +slow parallel trig on hashCode +10000 elements +java.util.LinkedList + String, parallel stream ############################ 1.121 +- 0.6 % + +slow parallel trig on hashCode +10000 elements +collection.mutable.HashSet + String, par collection ##################- 0.734 +- 1.8 % + String, parallel stream #############################- 1.176 +- 0.4 % + +slow parallel trig on hashCode +10000 elements +collection.immutable.Vector + String, par collection #################- 0.698 +- 1.3 % + String, parallel stream ##############################- 1.216 +- 0.6 % + +slow parallel trig on hashCode +10000 elements +collection.mutable.WrappedArray + String, par collection ########################- 0.969 +- 2.4 % + String, parallel stream ##############################- 1.213 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel sum of lengths +10 elements +collection.mutable.ArrayBuffer + String, par collection ########################## 1.036 +- 6.6 % + String, parallel stream ##############################~~# 1.759 +- 1.2 % + +fast parallel sum of lengths +10 elements +Array + String, par collection ######################### 1.000 +- 6.4 % + String, parallel stream ##############################~~# 1.740 +- 1.8 % + +fast parallel sum of lengths +10 elements +collection.mutable.ArraySeq + String, par collection ###########################- 1.099 +- 12.3 % + String, parallel stream ##############################~~# 1.748 +- 2.1 % + +fast parallel sum of lengths +10 elements +collection.immutable.HashSet + String, par collection #########################- 1.019 +- 2.9 % + String, parallel stream ##############################~~# 1.470 +- 1.1 % + +fast parallel sum of lengths +10 elements +java.util.ArrayList + String, parallel stream ##############################~~# 1.729 +- 1.0 % + +fast parallel sum of lengths +10 elements +java.util.LinkedList + String, parallel stream ##############################~~# 1.690 +- 1.4 % + +fast parallel sum of lengths +10 elements +collection.mutable.HashSet + String, par collection ###########################- 1.092 +- 3.1 % + String, parallel stream ##############################~~# 1.902 +- 3.4 % + +fast parallel sum of lengths +10 elements +collection.immutable.Vector + String, par collection ######################= 0.908 +- 3.1 % + String, parallel stream ##############################~~# 1.761 +- 1.4 % + +fast parallel sum of lengths +10 elements +collection.mutable.WrappedArray + String, par collection #########################= 1.032 +- 10.0 % + String, parallel stream ##############################~~# 1.751 +- 1.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel sum of lengths +10000 elements +collection.mutable.ArrayBuffer + String, par collection ######################### 1.002 +- 1.0 % + String, parallel stream ############################ 1.122 +- 0.9 % + +fast parallel sum of lengths +10000 elements +Array + String, par collection ######################### 1.000 +- 0.9 % + String, parallel stream ################################ 1.284 +- 1.7 % + +fast parallel sum of lengths +10000 elements +collection.mutable.ArraySeq + String, par collection ########################= 0.992 +- 1.6 % + String, parallel stream ################################- 1.287 +- 6.4 % + +fast parallel sum of lengths +10000 elements +collection.immutable.HashSet + String, par collection ##########- 0.408 +- 0.9 % + String, parallel stream ################- 0.648 +- 0.6 % + +fast parallel sum of lengths +10000 elements +java.util.ArrayList + String, parallel stream ##############################~~# 1.432 +- 13.1 % + +fast parallel sum of lengths +10000 elements +java.util.LinkedList + String, parallel stream #############= 0.550 +- 12.9 % + +fast parallel sum of lengths +10000 elements +collection.mutable.HashSet + String, par collection ##########- 0.411 +- 0.8 % + String, parallel stream ##############= 0.583 +- 0.6 % + +fast parallel sum of lengths +10000 elements +collection.immutable.Vector + String, par collection ################### 0.759 +- 1.2 % + String, parallel stream ##############################= 1.221 +- 0.8 % + +fast parallel sum of lengths +10000 elements +collection.mutable.WrappedArray + String, par collection ######################### 0.999 +- 1.0 % + String, parallel stream ################################- 1.294 +- 7.0 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel summation +10 elements +collection.mutable.ArrayBuffer + Int, par collection ######################- 0.890 +- 6.7 % + Int, parallel stream ##############################~~# 1.483 +- 1.2 % + +fast parallel summation +10 elements +Array + Int, par collection ######################### 1.000 +- 6.0 % + Int, parallel stream ##############################~~# 1.467 +- 1.2 % + +fast parallel summation +10 elements +collection.mutable.ArraySeq + Int, par collection ######################= 0.904 +- 6.7 % + Int, parallel stream ##############################~~# 1.471 +- 1.4 % + +fast parallel summation +10 elements +collection.immutable.HashSet + Int, par collection ##################- 0.737 +- 5.1 % + Int, parallel stream ###############################- 1.257 +- 1.4 % + +fast parallel summation +10 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 1.497 +- 1.0 % + +fast parallel summation +10 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 1.463 +- 1.4 % + +fast parallel summation +10 elements +collection.mutable.HashSet + Int, par collection ##########################- 1.060 +- 1.0 % + Int, parallel stream ##############################~~# 1.800 +- 1.4 % + +fast parallel summation +10 elements +collection.immutable.Vector + Int, par collection ####################= 0.829 +- 0.7 % + Int, parallel stream ##############################~~# 1.459 +- 2.1 % + +fast parallel summation +10 elements +collection.mutable.WrappedArray + Int, par collection #########################- 1.008 +- 7.5 % + Int, parallel stream ##############################~~# 1.489 +- 0.8 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel summation +10000 elements +collection.mutable.ArrayBuffer + Int, par collection ##############################~~# 2.489 +- 0.8 % + Int, parallel stream ##############################~~# 3.404 +- 1.4 % + +fast parallel summation +10000 elements +Array + Int, par collection ######################### 1.000 +- 9.6 % + Int, parallel stream ##############################~~# 6.862 +- 4.9 % + +fast parallel summation +10000 elements +collection.mutable.ArraySeq + Int, par collection ##############################~~# 2.482 +- 0.8 % + Int, parallel stream ##############################~~# 3.686 +- 0.8 % + +fast parallel summation +10000 elements +collection.immutable.HashSet + Int, par collection ################################- 1.300 +- 1.0 % + Int, parallel stream ##############################~~# 1.898 +- 0.5 % + +fast parallel summation +10000 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 5.781 +- 16.3 % + +fast parallel summation +10000 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 2.435 +- 8.6 % + +fast parallel summation +10000 elements +collection.mutable.HashSet + Int, par collection ###############################- 1.259 +- 0.9 % + Int, parallel stream ##############################~~# 1.749 +- 0.4 % + +fast parallel summation +10000 elements +collection.immutable.Vector + Int, par collection ##############################~~# 1.993 +- 1.1 % + Int, parallel stream ##############################~~# 3.596 +- 0.9 % + +fast parallel summation +10000 elements +collection.mutable.WrappedArray + Int, par collection ###############################= 1.272 +- 4.8 % + Int, parallel stream ##############################~~# 2.706 +- 0.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trigonometry +10 elements +collection.mutable.ArrayBuffer + Int, par collection ######################### 0.999 +- 1.6 % + Int, parallel stream ##############################~~# 3.251 +- 0.9 % + +slow parallel trigonometry +10 elements +Array + Int, par collection ######################### 1.000 +- 1.0 % + Int, parallel stream ##############################~~# 3.257 +- 0.6 % + +slow parallel trigonometry +10 elements +collection.mutable.ArraySeq + Int, par collection #########################- 1.009 +- 1.4 % + Int, parallel stream ##############################~~# 3.252 +- 0.9 % + +slow parallel trigonometry +10 elements +collection.immutable.HashSet + Int, par collection ###############- 0.610 +- 1.2 % + Int, parallel stream ##############################~~# 2.825 +- 0.9 % + +slow parallel trigonometry +10 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 3.210 +- 1.3 % + +slow parallel trigonometry +10 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 3.196 +- 0.4 % + +slow parallel trigonometry +10 elements +collection.mutable.HashSet + Int, par collection ########################- 0.969 +- 2.4 % + Int, parallel stream ##############################~~# 3.086 +- 0.4 % + +slow parallel trigonometry +10 elements +collection.immutable.Vector + Int, par collection ################## 0.721 +- 2.2 % + Int, parallel stream ##############################~~# 3.180 +- 0.9 % + +slow parallel trigonometry +10 elements +collection.mutable.WrappedArray + Int, par collection ######################### 1.000 +- 1.1 % + Int, parallel stream ##############################~~# 3.259 +- 1.1 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trigonometry +10000 elements +collection.mutable.ArrayBuffer + Int, par collection ###########################- 1.096 +- 0.7 % + Int, parallel stream ##############################~~# 1.369 +- 0.5 % + +slow parallel trigonometry +10000 elements +Array + Int, par collection ######################### 1.000 +- 2.1 % + Int, parallel stream ##############################~~# 1.385 +- 0.7 % + +slow parallel trigonometry +10000 elements +collection.mutable.ArraySeq + Int, par collection ########################### 1.078 +- 2.1 % + Int, parallel stream ##############################~~# 1.347 +- 2.6 % + +slow parallel trigonometry +10000 elements +collection.immutable.HashSet + Int, par collection #####################- 0.854 +- 2.2 % + Int, parallel stream ################################- 1.290 +- 0.7 % + +slow parallel trigonometry +10000 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 1.381 +- 0.9 % + +slow parallel trigonometry +10000 elements +java.util.LinkedList + Int, parallel stream ###############################= 1.273 +- 0.6 % + +slow parallel trigonometry +10000 elements +collection.mutable.HashSet + Int, par collection ##################- 0.731 +- 3.7 % + Int, parallel stream ##############################~~# 1.338 +- 0.5 % + +slow parallel trigonometry +10000 elements +collection.immutable.Vector + Int, par collection #################- 0.699 +- 1.7 % + Int, parallel stream ##############################~~# 1.358 +- 1.2 % + +slow parallel trigonometry +10000 elements +collection.mutable.WrappedArray + Int, par collection #########################- 1.018 +- 2.1 % + Int, parallel stream ##############################~~# 1.356 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast summation +10 elements +collection.mutable.ArrayBuffer + Int, base collection #### 0.162 +- 4.7 % + Int, iterator on coll ### 0.121 +- 1.4 % + Int, serial stream ## 0.086 +- 2.3 % + Int Stepper (can par) ###### 0.236 +- 1.3 % + +fast summation +10 elements +Array + Int, base collection ######################### 1.000 +- 0.2 % + Int, iterator on coll ##- 0.097 +- 2.3 % + Int, serial stream #####- 0.217 +- 1.0 % + Int Stepper (can par) #####################- 0.855 +- 0.3 % + +fast summation +10 elements +collection.mutable.ArraySeq + Int, base collection ####- 0.167 +- 0.3 % + Int, iterator on coll ###- 0.140 +- 2.3 % + Int, serial stream ## 0.084 +- 4.9 % + Int Stepper (can par) #############= 0.552 +- 0.4 % + +fast summation +10 elements +collection.mutable.ArrayStack + Int, base collection ####- 0.169 +- 4.1 % + Int, iterator on coll #### 0.157 +- 2.3 % + Int, serial stream ## 0.074 +- 4.7 % + Int Stepper (seq only) ######- 0.258 +- 1.3 % + +fast summation +10 elements +collection.immutable.ListSet + Int, base collection ##= 0.107 +- 0.9 % + Int, iterator on coll #### 0.163 +- 1.3 % + Int, serial stream ###= 0.140 +- 2.2 % + Int Stepper (seq only) ##= 0.111 +- 18.1 % + +fast summation +10 elements +collection.immutable.HashSet + Int, base collection ###= 0.148 +- 3.7 % + Int, iterator on coll ## 0.086 +- 0.8 % + Int, serial stream ### 0.120 +- 1.1 % + Int Stepper (can par) ### 0.119 +- 4.0 % + +fast summation +10 elements +java.util.ArrayList + Int, serial stream #####= 0.232 +- 0.6 % + +fast summation +10 elements +java.util.LinkedList + Int, serial stream #####- 0.214 +- 0.5 % + +fast summation +10 elements +collection.mutable.LinkedHashSet + Int, base collection #### 0.159 +- 5.0 % + Int, iterator on coll #### 0.157 +- 2.3 % + Int, serial stream ## 0.080 +- 2.9 % + Int Stepper (seq only) ####- 0.168 +- 0.5 % + +fast summation +10 elements +collection.immutable.List + Int, base collection ######= 0.263 +- 0.2 % + Int, iterator on coll #### 0.155 +- 1.4 % + Int, serial stream ### 0.121 +- 2.4 % + Int Stepper (seq only) ### 0.117 +- 2.1 % + +fast summation +10 elements +collection.mutable.HashSet + Int, base collection ##= 0.109 +- 2.1 % + Int, iterator on coll #= 0.070 +- 0.3 % + Int, serial stream ##- 0.093 +- 0.8 % + Int Stepper (can par) #######= 0.308 +- 0.5 % + +fast summation +10 elements +collection.mutable.Queue + Int, base collection # 0.041 +- 0.8 % + Int, iterator on coll ##- 0.088 +- 0.3 % + Int, serial stream # 0.034 +- 7.5 % + Int Stepper (seq only) #- 0.055 +- 0.8 % + +fast summation +10 elements +collection.mutable.PriorityQueue + Int, base collection ##= 0.104 +- 2.7 % + Int, iterator on coll ###- 0.133 +- 2.1 % + Int, serial stream #= 0.073 +- 2.1 % + Int Stepper (seq only) ###- 0.136 +- 0.4 % + +fast summation +10 elements +collection.immutable.Queue + Int, base collection ##= 0.108 +- 0.7 % + Int, iterator on coll ###= 0.146 +- 0.8 % + Int, serial stream ## 0.081 +- 18.1 % + Int Stepper (seq only) #- 0.058 +- 1.4 % + +fast summation +10 elements +collection.immutable.Stream + Int, base collection ######= 0.261 +- 0.2 % + Int, iterator on coll # 0.035 +- 5.4 % + Int, serial stream ### 0.116 +- 1.7 % + Int Stepper (seq only) ##= 0.113 +- 0.3 % + +fast summation +10 elements +collection.immutable.TreeSet + Int, base collection #### 0.166 +- 0.6 % + Int, iterator on coll ## 0.081 +- 0.6 % + Int, serial stream ##= 0.102 +- 1.5 % + Int Stepper (seq only) ##- 0.097 +- 0.3 % + +fast summation +10 elements +collection.immutable.Vector + Int, base collection ##= 0.104 +- 0.5 % + Int, iterator on coll ###- 0.130 +- 2.2 % + Int, serial stream ## 0.078 +- 2.1 % + Int Stepper (can par) ######### 0.359 +- 0.8 % + +fast summation +10 elements +collection.mutable.WrappedArray + Int, base collection ###= 0.141 +- 0.3 % + Int, iterator on coll ##- 0.096 +- 5.1 % + Int, serial stream ## 0.079 +- 0.4 % + Int Stepper (can par) ####= 0.186 +- 1.5 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast summation +10000 elements +collection.mutable.ArrayBuffer + Int, base collection # 0.043 +- 2.8 % + Int, iterator on coll # 0.038 +- 8.6 % + Int, serial stream = 0.027 +- 14.9 % + Int Stepper (can par) ## 0.083 +- 0.5 % + +fast summation +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.1 % + Int, iterator on coll = 0.027 +- 5.5 % + Int, serial stream ###- 0.128 +- 0.3 % + Int Stepper (can par) ######################### 1.000 +- 0.1 % + +fast summation +10000 elements +collection.mutable.ArraySeq + Int, base collection # 0.044 +- 4.0 % + Int, iterator on coll # 0.042 +- 2.9 % + Int, serial stream = 0.026 +- 15.1 % + Int Stepper (can par) #######= 0.309 +- 1.5 % + +fast summation +10000 elements +collection.mutable.ArrayStack + Int, base collection # 0.043 +- 15.3 % + Int, iterator on coll # 0.044 +- 1.8 % + Int, serial stream = 0.026 +- 11.4 % + Int Stepper (seq only) ##- 0.089 +- 0.6 % + +fast summation +10000 elements +collection.immutable.ListSet + Int, base collection #- 0.058 +- 1.8 % + Int, iterator on coll #- 0.059 +- 2.7 % + Int, serial stream = 0.022 +- 2.4 % + Int Stepper (seq only) #- 0.048 +- 35.9 % + +fast summation +10000 elements +collection.immutable.HashSet + Int, base collection = 0.028 +- 1.6 % + Int, iterator on coll = 0.023 +- 1.2 % + Int, serial stream - 0.014 +- 0.9 % + Int Stepper (can par) - 0.016 +- 1.2 % + +fast summation +10000 elements +java.util.ArrayList + Int, serial stream ######- 0.252 +- 11.9 % + +fast summation +10000 elements +java.util.LinkedList + Int, serial stream ##= 0.103 +- 7.4 % + +fast summation +10000 elements +collection.mutable.LinkedHashSet + Int, base collection # 0.044 +- 12.3 % + Int, iterator on coll #- 0.047 +- 2.8 % + Int, serial stream = 0.026 +- 14.3 % + Int Stepper (seq only) #- 0.049 +- 9.0 % + +fast summation +10000 elements +collection.immutable.List + Int, base collection #- 0.053 +- 9.6 % + Int, iterator on coll #- 0.055 +- 3.4 % + Int, serial stream # 0.040 +- 1.0 % + Int Stepper (seq only) #- 0.048 +- 34.9 % + +fast summation +10000 elements +collection.mutable.HashSet + Int, base collection = 0.021 +- 8.1 % + Int, iterator on coll = 0.023 +- 5.8 % + Int, serial stream - 0.011 +- 0.8 % + Int Stepper (can par) #= 0.067 +- 14.8 % + +fast summation +10000 elements +collection.mutable.Queue + Int, base collection - 0.009 +- 1.0 % + Int, iterator on coll = 0.028 +- 4.4 % + Int, serial stream - 0.012 +- 1.3 % + Int Stepper (seq only) - 0.016 +- 1.0 % + +fast summation +10000 elements +collection.mutable.PriorityQueue + Int, base collection # 0.034 +- 29.3 % + Int, iterator on coll # 0.043 +- 1.3 % + Int, serial stream = 0.024 +- 8.8 % + Int Stepper (seq only) # 0.036 +- 0.3 % + +fast summation +10000 elements +collection.immutable.Queue + Int, base collection #- 0.056 +- 3.3 % + Int, iterator on coll #- 0.055 +- 2.0 % + Int, serial stream = 0.026 +- 1.2 % + Int Stepper (seq only) - 0.017 +- 1.1 % + +fast summation +10000 elements +collection.immutable.Stream + Int, base collection # 0.042 +- 11.4 % + Int, iterator on coll - 0.010 +- 8.4 % + Int, serial stream = 0.022 +- 2.1 % + Int Stepper (seq only) = 0.031 +- 3.1 % + +fast summation +10000 elements +collection.immutable.TreeSet + Int, base collection #- 0.048 +- 1.4 % + Int, iterator on coll = 0.032 +- 3.8 % + Int, serial stream - 0.019 +- 2.7 % + Int Stepper (seq only) = 0.030 +- 2.5 % + +fast summation +10000 elements +collection.immutable.Vector + Int, base collection # 0.039 +- 12.1 % + Int, iterator on coll # 0.041 +- 3.3 % + Int, serial stream = 0.027 +- 14.5 % + Int Stepper (can par) ###- 0.131 +- 0.8 % + +fast summation +10000 elements +collection.mutable.WrappedArray + Int, base collection # 0.035 +- 2.0 % + Int, iterator on coll = 0.028 +- 2.5 % + Int, serial stream = 0.025 +- 17.6 % + Int Stepper (can par) #- 0.050 +- 7.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trigonometry +10 elements +collection.mutable.ArrayBuffer + Int, base collection ########################- 0.980 +- 0.2 % + Int, iterator on coll ########################= 0.980 +- 0.2 % + Int, serial stream ########################= 0.982 +- 0.2 % + Int Stepper (can par) ######################### 0.997 +- 0.1 % + +slow trigonometry +10 elements +Array + Int, base collection ######################### 1.000 +- 0.1 % + Int, iterator on coll ########################= 0.981 +- 0.2 % + Int, serial stream ########################= 0.989 +- 0.1 % + Int Stepper (can par) ######################### 1.000 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.ArraySeq + Int, base collection ################ 0.645 +- 0.1 % + Int, iterator on coll ########################= 0.980 +- 0.2 % + Int, serial stream ########################= 0.984 +- 0.1 % + Int Stepper (can par) ######################### 0.998 +- 0.2 % + +slow trigonometry +10 elements +collection.mutable.ArrayStack + Int, base collection ################ 0.642 +- 0.2 % + Int, iterator on coll ########################= 0.981 +- 0.5 % + Int, serial stream ########################= 0.983 +- 0.2 % + Int Stepper (seq only) ######################### 0.994 +- 0.2 % + +slow trigonometry +10 elements +collection.immutable.ListSet + Int, base collection ######################= 0.910 +- 0.3 % + Int, iterator on coll ########################- 0.978 +- 0.3 % + Int, serial stream ########################= 0.980 +- 0.2 % + Int Stepper (seq only) ########################= 0.991 +- 0.2 % + +slow trigonometry +10 elements +collection.immutable.HashSet + Int, base collection ###############= 0.628 +- 0.2 % + Int, iterator on coll ########################- 0.978 +- 0.4 % + Int, serial stream ########################- 0.977 +- 0.2 % + Int Stepper (can par) ########################= 0.989 +- 0.2 % + +slow trigonometry +10 elements +java.util.ArrayList + Int, serial stream ########################= 0.985 +- 0.2 % + +slow trigonometry +10 elements +java.util.LinkedList + Int, serial stream ########################= 0.988 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.LinkedHashSet + Int, base collection #######################= 0.950 +- 0.3 % + Int, iterator on coll ########################= 0.981 +- 0.2 % + Int, serial stream ########################= 0.984 +- 0.2 % + Int Stepper (seq only) ######################### 0.995 +- 0.3 % + +slow trigonometry +10 elements +collection.immutable.List + Int, base collection ########################- 0.974 +- 0.3 % + Int, iterator on coll ########################- 0.977 +- 0.2 % + Int, serial stream ########################- 0.978 +- 0.3 % + Int Stepper (seq only) ########################= 0.990 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.HashSet + Int, base collection #######################= 0.944 +- 0.2 % + Int, iterator on coll ########################= 0.981 +- 0.2 % + Int, serial stream ########################- 0.979 +- 0.6 % + Int Stepper (can par) ########################= 0.993 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.Queue + Int, base collection ######################= 0.909 +- 0.3 % + Int, iterator on coll ########################- 0.977 +- 0.1 % + Int, serial stream ######################## 0.962 +- 0.2 % + Int Stepper (seq only) ########################- 0.976 +- 0.2 % + +slow trigonometry +10 elements +collection.mutable.PriorityQueue + Int, base collection ########################- 0.970 +- 0.3 % + Int, iterator on coll ########################- 0.976 +- 0.2 % + Int, serial stream ########################- 0.978 +- 0.3 % + Int Stepper (seq only) ########################= 0.990 +- 0.1 % + +slow trigonometry +10 elements +collection.immutable.Queue + Int, base collection ######################## 0.956 +- 0.2 % + Int, iterator on coll ########################- 0.976 +- 0.3 % + Int, serial stream ########################- 0.978 +- 0.6 % + Int Stepper (seq only) ########################- 0.977 +- 0.2 % + +slow trigonometry +10 elements +collection.immutable.Stream + Int, base collection #######################= 0.941 +- 0.3 % + Int, iterator on coll ######################## 0.960 +- 0.3 % + Int, serial stream ########################- 0.978 +- 0.2 % + Int Stepper (seq only) ########################= 0.991 +- 0.1 % + +slow trigonometry +10 elements +collection.immutable.TreeSet + Int, base collection ###############= 0.624 +- 0.2 % + Int, iterator on coll ########################- 0.972 +- 0.2 % + Int, serial stream ########################- 0.978 +- 0.2 % + Int Stepper (seq only) ########################= 0.987 +- 0.1 % + +slow trigonometry +10 elements +collection.immutable.Vector + Int, base collection ########################- 0.975 +- 0.2 % + Int, iterator on coll ########################= 0.981 +- 0.1 % + Int, serial stream ########################= 0.984 +- 0.1 % + Int Stepper (can par) ######################### 0.997 +- 0.2 % + +slow trigonometry +10 elements +collection.mutable.WrappedArray + Int, base collection ########################- 0.974 +- 0.2 % + Int, iterator on coll ########################- 0.980 +- 0.2 % + Int, serial stream ########################= 0.985 +- 0.2 % + Int Stepper (can par) ######################### 0.996 +- 0.1 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trigonometry +10000 elements +collection.mutable.ArrayBuffer + Int, base collection ########################= 0.985 +- 0.2 % + Int, iterator on coll ########################= 0.986 +- 0.8 % + Int, serial stream ########################= 0.988 +- 0.2 % + Int Stepper (can par) ######################### 0.996 +- 0.1 % + +slow trigonometry +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.2 % + Int, iterator on coll ########################= 0.987 +- 0.2 % + Int, serial stream ########################= 0.990 +- 0.1 % + Int Stepper (can par) ######################### 1.000 +- 0.1 % + +slow trigonometry +10000 elements +collection.mutable.ArraySeq + Int, base collection ################## 0.725 +- 13.6 % + Int, iterator on coll ########################= 0.988 +- 0.2 % + Int, serial stream ########################= 0.987 +- 0.3 % + Int Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.ArrayStack + Int, base collection ################- 0.651 +- 0.2 % + Int, iterator on coll ########################= 0.986 +- 0.5 % + Int, serial stream ########################= 0.988 +- 0.2 % + Int Stepper (seq only) ######################### 0.995 +- 0.1 % + +slow trigonometry +10000 elements +collection.immutable.ListSet + Int, base collection ######################- 0.888 +- 0.4 % + Int, iterator on coll ########################= 0.988 +- 0.2 % + Int, serial stream ########################= 0.986 +- 0.2 % + Int Stepper (seq only) ########################= 0.992 +- 0.2 % + +slow trigonometry +10000 elements +collection.immutable.HashSet + Int, base collection ##############- 0.569 +- 0.4 % + Int, iterator on coll ########################- 0.977 +- 0.4 % + Int, serial stream ########################- 0.969 +- 0.7 % + Int Stepper (can par) ########################- 0.969 +- 0.1 % + +slow trigonometry +10000 elements +java.util.ArrayList + Int, serial stream ########################= 0.989 +- 0.1 % + +slow trigonometry +10000 elements +java.util.LinkedList + Int, serial stream ########################= 0.989 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.LinkedHashSet + Int, base collection ####################### 0.922 +- 0.3 % + Int, iterator on coll ########################= 0.991 +- 0.2 % + Int, serial stream ########################= 0.986 +- 0.2 % + Int Stepper (seq only) ######################### 0.996 +- 0.1 % + +slow trigonometry +10000 elements +collection.immutable.List + Int, base collection ########################= 0.982 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.2 % + Int, serial stream ########################= 0.987 +- 0.2 % + Int Stepper (seq only) ######################### 0.995 +- 0.1 % + +slow trigonometry +10000 elements +collection.mutable.HashSet + Int, base collection ######################= 0.904 +- 0.3 % + Int, iterator on coll ########################- 0.979 +- 0.3 % + Int, serial stream ########################- 0.977 +- 0.3 % + Int Stepper (can par) ########################= 0.982 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.Queue + Int, base collection #######################= 0.945 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.2 % + Int, serial stream ######################## 0.960 +- 0.7 % + Int Stepper (seq only) ######################## 0.959 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.PriorityQueue + Int, base collection ################- 0.650 +- 0.2 % + Int, iterator on coll ########################= 0.984 +- 0.4 % + Int, serial stream ########################= 0.982 +- 0.3 % + Int Stepper (seq only) ########################= 0.983 +- 0.2 % + +slow trigonometry +10000 elements +collection.immutable.Queue + Int, base collection ######################## 0.966 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.3 % + Int, serial stream ########################- 0.975 +- 1.1 % + Int Stepper (seq only) ########################= 0.982 +- 0.3 % + +slow trigonometry +10000 elements +collection.immutable.Stream + Int, base collection #######################= 0.941 +- 0.3 % + Int, iterator on coll ######################## 0.962 +- 0.4 % + Int, serial stream ########################= 0.982 +- 0.3 % + Int Stepper (seq only) ########################= 0.988 +- 0.3 % + +slow trigonometry +10000 elements +collection.immutable.TreeSet + Int, base collection ##############- 0.571 +- 0.4 % + Int, iterator on coll ########################- 0.978 +- 0.3 % + Int, serial stream ########################- 0.973 +- 0.3 % + Int Stepper (seq only) ########################- 0.972 +- 0.6 % + +slow trigonometry +10000 elements +collection.immutable.Vector + Int, base collection ########################= 0.982 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.2 % + Int, serial stream ########################= 0.988 +- 0.1 % + Int Stepper (can par) ######################### 0.996 +- 0.1 % + +slow trigonometry +10000 elements +collection.mutable.WrappedArray + Int, base collection ########################= 0.982 +- 0.2 % + Int, iterator on coll ########################= 0.989 +- 0.1 % + Int, serial stream ########################= 0.988 +- 0.1 % + Int Stepper (can par) ########################= 0.992 +- 0.2 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/benchmark/results/jmhbench.log b/benchmark/results/jmhbench.log new file mode 100644 index 0000000..63568d1 --- /dev/null +++ b/benchmark/results/jmhbench.log @@ -0,0 +1,1054 @@ +[info] +[info] # Run complete. Total time: 11:52:29 +[info] +[info] Benchmark Mode Cnt Score Error Units +[info] JmhBench.bench_cI_fmc_arb_0 thrpt 25 8035423.336 ± 755409.322 ops/s +[info] JmhBench.bench_cI_fmc_arb_1 thrpt 25 20747.799 ± 136.417 ops/s +[info] JmhBench.bench_cI_fmc_arr_0 thrpt 25 71925991.876 ± 147120.839 ops/s +[info] JmhBench.bench_cI_fmc_arr_1 thrpt 25 92378.767 ± 100.507 ops/s +[info] JmhBench.bench_cI_fmc_ars_0 thrpt 25 4887009.610 ± 607583.010 ops/s +[info] JmhBench.bench_cI_fmc_ars_1 thrpt 25 16764.023 ± 542.731 ops/s +[info] JmhBench.bench_cI_fmc_ast_0 thrpt 25 5855354.579 ± 297609.045 ops/s +[info] JmhBench.bench_cI_fmc_ast_1 thrpt 25 17296.740 ± 230.641 ops/s +[info] JmhBench.bench_cI_fmc_ils_0 thrpt 25 2652720.262 ± 414787.126 ops/s +[info] JmhBench.bench_cI_fmc_ils_1 thrpt 25 487.348 ± 25.292 ops/s +[info] JmhBench.bench_cI_fmc_ish_0 thrpt 25 4987836.424 ± 646222.972 ops/s +[info] JmhBench.bench_cI_fmc_ish_1 thrpt 25 3382.659 ± 305.098 ops/s +[info] JmhBench.bench_cI_fmc_lhs_0 thrpt 25 5835320.671 ± 1009998.646 ops/s +[info] JmhBench.bench_cI_fmc_lhs_1 thrpt 25 7535.361 ± 327.683 ops/s +[info] JmhBench.bench_cI_fmc_lst_0 thrpt 25 7099167.181 ± 429761.270 ops/s +[info] JmhBench.bench_cI_fmc_lst_1 thrpt 25 12440.006 ± 224.875 ops/s +[info] JmhBench.bench_cI_fmc_mhs_0 thrpt 25 4291393.195 ± 47473.930 ops/s +[info] JmhBench.bench_cI_fmc_mhs_1 thrpt 25 4203.392 ± 112.937 ops/s +[info] JmhBench.bench_cI_fmc_muq_0 thrpt 25 2496111.379 ± 333932.718 ops/s +[info] JmhBench.bench_cI_fmc_muq_1 thrpt 25 5458.980 ± 58.848 ops/s +[info] JmhBench.bench_cI_fmc_prq_0 thrpt 25 6648768.148 ± 240161.420 ops/s +[info] JmhBench.bench_cI_fmc_prq_1 thrpt 25 9518.984 ± 882.821 ops/s +[info] JmhBench.bench_cI_fmc_que_0 thrpt 25 4993970.353 ± 84787.715 ops/s +[info] JmhBench.bench_cI_fmc_que_1 thrpt 25 7301.230 ± 48.307 ops/s +[info] JmhBench.bench_cI_fmc_stm_0 thrpt 25 5372437.328 ± 295448.912 ops/s +[info] JmhBench.bench_cI_fmc_stm_1 thrpt 25 8047.781 ± 190.906 ops/s +[info] JmhBench.bench_cI_fmc_trs_0 thrpt 25 4988067.719 ± 194129.387 ops/s +[info] JmhBench.bench_cI_fmc_trs_1 thrpt 25 2085.913 ± 52.524 ops/s +[info] JmhBench.bench_cI_fmc_vec_0 thrpt 25 6669754.581 ± 192303.049 ops/s +[info] JmhBench.bench_cI_fmc_vec_1 thrpt 25 14678.526 ± 774.640 ops/s +[info] JmhBench.bench_cI_fmc_wra_0 thrpt 25 6826577.628 ± 145826.670 ops/s +[info] JmhBench.bench_cI_fmc_wra_1 thrpt 25 11525.280 ± 217.619 ops/s +[info] JmhBench.bench_cI_mdtc_arb_0 thrpt 25 4443593.338 ± 31059.496 ops/s +[info] JmhBench.bench_cI_mdtc_arb_1 thrpt 25 11797.585 ± 410.228 ops/s +[info] JmhBench.bench_cI_mdtc_arr_0 thrpt 25 103444873.867 ± 944076.540 ops/s +[info] JmhBench.bench_cI_mdtc_arr_1 thrpt 25 75842976.523 ± 549782.886 ops/s +[info] JmhBench.bench_cI_mdtc_ars_0 thrpt 25 3207470.098 ± 38695.027 ops/s +[info] JmhBench.bench_cI_mdtc_ars_1 thrpt 25 8556.621 ± 195.807 ops/s +[info] JmhBench.bench_cI_mdtc_ast_0 thrpt 25 2355394.121 ± 38473.884 ops/s +[info] JmhBench.bench_cI_mdtc_ast_1 thrpt 25 8607.394 ± 728.653 ops/s +[info] JmhBench.bench_cI_mdtc_lst_0 thrpt 25 6468557.411 ± 137487.766 ops/s +[info] JmhBench.bench_cI_mdtc_lst_1 thrpt 25 13991.072 ± 136.574 ops/s +[info] JmhBench.bench_cI_mdtc_muq_0 thrpt 25 1345227.001 ± 58882.319 ops/s +[info] JmhBench.bench_cI_mdtc_muq_1 thrpt 25 2502.709 ± 79.914 ops/s +[info] JmhBench.bench_cI_mdtc_que_0 thrpt 25 2301715.037 ± 18642.229 ops/s +[info] JmhBench.bench_cI_mdtc_que_1 thrpt 25 4201.094 ± 57.552 ops/s +[info] JmhBench.bench_cI_mdtc_stm_0 thrpt 25 1351471.957 ± 46355.839 ops/s +[info] JmhBench.bench_cI_mdtc_stm_1 thrpt 25 664904.819 ± 42603.168 ops/s +[info] JmhBench.bench_cI_mdtc_vec_0 thrpt 25 5978680.943 ± 65546.254 ops/s +[info] JmhBench.bench_cI_mdtc_vec_1 thrpt 25 15557.817 ± 309.459 ops/s +[info] JmhBench.bench_cI_mdtc_wra_0 thrpt 25 4673494.151 ± 27640.256 ops/s +[info] JmhBench.bench_cI_mdtc_wra_1 thrpt 25 9370.962 ± 826.045 ops/s +[info] JmhBench.bench_cI_sum_arb_0 thrpt 25 18335880.324 ± 860611.155 ops/s +[info] JmhBench.bench_cI_sum_arb_1 thrpt 25 18799.347 ± 521.962 ops/s +[info] JmhBench.bench_cI_sum_arr_0 thrpt 25 113429397.689 ± 246632.083 ops/s +[info] JmhBench.bench_cI_sum_arr_1 thrpt 25 433573.009 ± 405.219 ops/s +[info] JmhBench.bench_cI_sum_ars_0 thrpt 25 18914632.257 ± 65515.415 ops/s +[info] JmhBench.bench_cI_sum_ars_1 thrpt 25 18879.126 ± 757.161 ops/s +[info] JmhBench.bench_cI_sum_ast_0 thrpt 25 19140457.190 ± 777303.561 ops/s +[info] JmhBench.bench_cI_sum_ast_1 thrpt 25 18800.310 ± 2869.443 ops/s +[info] JmhBench.bench_cI_sum_ils_0 thrpt 25 12156588.727 ± 114845.877 ops/s +[info] JmhBench.bench_cI_sum_ils_1 thrpt 25 25213.376 ± 444.053 ops/s +[info] JmhBench.bench_cI_sum_ish_0 thrpt 25 16761123.678 ± 614314.543 ops/s +[info] JmhBench.bench_cI_sum_ish_1 thrpt 25 12198.185 ± 194.961 ops/s +[info] JmhBench.bench_cI_sum_lhs_0 thrpt 25 18039130.300 ± 906017.637 ops/s +[info] JmhBench.bench_cI_sum_lhs_1 thrpt 25 18922.333 ± 2320.040 ops/s +[info] JmhBench.bench_cI_sum_lst_0 thrpt 25 29817559.612 ± 58412.021 ops/s +[info] JmhBench.bench_cI_sum_lst_1 thrpt 25 22834.330 ± 2183.263 ops/s +[info] JmhBench.bench_cI_sum_mhs_0 thrpt 25 12329436.432 ± 253623.619 ops/s +[info] JmhBench.bench_cI_sum_mhs_1 thrpt 25 8952.772 ± 723.365 ops/s +[info] JmhBench.bench_cI_sum_muq_0 thrpt 25 4613996.286 ± 35553.633 ops/s +[info] JmhBench.bench_cI_sum_muq_1 thrpt 25 3965.004 ± 40.291 ops/s +[info] JmhBench.bench_cI_sum_prq_0 thrpt 25 11768606.036 ± 322246.512 ops/s +[info] JmhBench.bench_cI_sum_prq_1 thrpt 25 14595.293 ± 4283.029 ops/s +[info] JmhBench.bench_cI_sum_que_0 thrpt 25 12216359.219 ± 84893.062 ops/s +[info] JmhBench.bench_cI_sum_que_1 thrpt 25 24107.095 ± 790.558 ops/s +[info] JmhBench.bench_cI_sum_stm_0 thrpt 25 29645049.582 ± 59278.612 ops/s +[info] JmhBench.bench_cI_sum_stm_1 thrpt 25 18080.340 ± 2059.034 ops/s +[info] JmhBench.bench_cI_sum_trs_0 thrpt 25 18874037.032 ± 120977.755 ops/s +[info] JmhBench.bench_cI_sum_trs_1 thrpt 25 20810.794 ± 288.713 ops/s +[info] JmhBench.bench_cI_sum_vec_0 thrpt 25 11742774.808 ± 63268.375 ops/s +[info] JmhBench.bench_cI_sum_vec_1 thrpt 25 16853.876 ± 2040.181 ops/s +[info] JmhBench.bench_cI_sum_wra_0 thrpt 25 16037638.914 ± 48094.558 ops/s +[info] JmhBench.bench_cI_sum_wra_1 thrpt 25 15035.828 ± 298.395 ops/s +[info] JmhBench.bench_cI_trig_arb_0 thrpt 25 127384.023 ± 230.345 ops/s +[info] JmhBench.bench_cI_trig_arb_1 thrpt 25 127.523 ± 0.207 ops/s +[info] JmhBench.bench_cI_trig_arr_0 thrpt 25 129984.043 ± 152.548 ops/s +[info] JmhBench.bench_cI_trig_arr_1 thrpt 25 129.418 ± 0.233 ops/s +[info] JmhBench.bench_cI_trig_ars_0 thrpt 25 83843.573 ± 112.771 ops/s +[info] JmhBench.bench_cI_trig_ars_1 thrpt 25 93.856 ± 12.751 ops/s +[info] JmhBench.bench_cI_trig_ast_0 thrpt 25 83514.043 ± 144.645 ops/s +[info] JmhBench.bench_cI_trig_ast_1 thrpt 25 84.199 ± 0.141 ops/s +[info] JmhBench.bench_cI_trig_ils_0 thrpt 25 118241.682 ± 333.038 ops/s +[info] JmhBench.bench_cI_trig_ils_1 thrpt 25 114.961 ± 0.485 ops/s +[info] JmhBench.bench_cI_trig_ish_0 thrpt 25 81627.106 ± 148.992 ops/s +[info] JmhBench.bench_cI_trig_ish_1 thrpt 25 73.677 ± 0.328 ops/s +[info] JmhBench.bench_cI_trig_lhs_0 thrpt 25 123484.374 ± 418.215 ops/s +[info] JmhBench.bench_cI_trig_lhs_1 thrpt 25 119.347 ± 0.338 ops/s +[info] JmhBench.bench_cI_trig_lst_0 thrpt 25 126621.643 ± 359.486 ops/s +[info] JmhBench.bench_cI_trig_lst_1 thrpt 25 127.104 ± 0.287 ops/s +[info] JmhBench.bench_cI_trig_mhs_0 thrpt 25 122733.756 ± 238.867 ops/s +[info] JmhBench.bench_cI_trig_mhs_1 thrpt 25 117.038 ± 0.317 ops/s +[info] JmhBench.bench_cI_trig_muq_0 thrpt 25 118220.195 ± 404.616 ops/s +[info] JmhBench.bench_cI_trig_muq_1 thrpt 25 122.307 ± 0.246 ops/s +[info] JmhBench.bench_cI_trig_prq_0 thrpt 25 126111.667 ± 361.165 ops/s +[info] JmhBench.bench_cI_trig_prq_1 thrpt 25 84.151 ± 0.161 ops/s +[info] JmhBench.bench_cI_trig_que_0 thrpt 25 124229.823 ± 295.406 ops/s +[info] JmhBench.bench_cI_trig_que_1 thrpt 25 124.972 ± 0.303 ops/s +[info] JmhBench.bench_cI_trig_stm_0 thrpt 25 122279.057 ± 426.484 ops/s +[info] JmhBench.bench_cI_trig_stm_1 thrpt 25 121.842 ± 0.404 ops/s +[info] JmhBench.bench_cI_trig_trs_0 thrpt 25 81105.244 ± 128.368 ops/s +[info] JmhBench.bench_cI_trig_trs_1 thrpt 25 73.845 ± 0.314 ops/s +[info] JmhBench.bench_cI_trig_vec_0 thrpt 25 126718.115 ± 223.274 ops/s +[info] JmhBench.bench_cI_trig_vec_1 thrpt 25 127.101 ± 0.219 ops/s +[info] JmhBench.bench_cI_trig_wra_0 thrpt 25 126664.936 ± 216.923 ops/s +[info] JmhBench.bench_cI_trig_wra_1 thrpt 25 127.123 ± 0.273 ops/s +[info] JmhBench.bench_cS_fmc_arb_0 thrpt 25 8309821.046 ± 49072.647 ops/s +[info] JmhBench.bench_cS_fmc_arb_1 thrpt 25 17422.556 ± 212.521 ops/s +[info] JmhBench.bench_cS_fmc_arr_0 thrpt 25 54179418.146 ± 74335.302 ops/s +[info] JmhBench.bench_cS_fmc_arr_1 thrpt 25 53181.927 ± 446.294 ops/s +[info] JmhBench.bench_cS_fmc_ars_0 thrpt 25 5103543.646 ± 215901.936 ops/s +[info] JmhBench.bench_cS_fmc_ars_1 thrpt 25 15554.519 ± 823.745 ops/s +[info] JmhBench.bench_cS_fmc_ast_0 thrpt 25 6700667.336 ± 85523.401 ops/s +[info] JmhBench.bench_cS_fmc_ast_1 thrpt 25 17258.969 ± 314.253 ops/s +[info] JmhBench.bench_cS_fmc_ils_0 thrpt 25 2941128.962 ± 142969.982 ops/s +[info] JmhBench.bench_cS_fmc_ils_1 thrpt 25 135.655 ± 11.876 ops/s +[info] JmhBench.bench_cS_fmc_ish_0 thrpt 25 5044613.272 ± 157906.830 ops/s +[info] JmhBench.bench_cS_fmc_ish_1 thrpt 25 2872.376 ± 36.541 ops/s +[info] JmhBench.bench_cS_fmc_lhs_0 thrpt 25 7265749.135 ± 101616.705 ops/s +[info] JmhBench.bench_cS_fmc_lhs_1 thrpt 25 4845.430 ± 26.025 ops/s +[info] JmhBench.bench_cS_fmc_lst_0 thrpt 25 7501407.130 ± 224844.340 ops/s +[info] JmhBench.bench_cS_fmc_lst_1 thrpt 25 9301.948 ± 312.874 ops/s +[info] JmhBench.bench_cS_fmc_mhs_0 thrpt 25 5517297.556 ± 113251.344 ops/s +[info] JmhBench.bench_cS_fmc_mhs_1 thrpt 25 2515.193 ± 13.965 ops/s +[info] JmhBench.bench_cS_fmc_muq_0 thrpt 25 1899649.245 ± 35990.877 ops/s +[info] JmhBench.bench_cS_fmc_muq_1 thrpt 25 2421.534 ± 17.772 ops/s +[info] JmhBench.bench_cS_fmc_prq_0 thrpt 25 6326339.430 ± 63789.733 ops/s +[info] JmhBench.bench_cS_fmc_prq_1 thrpt 25 6136.747 ± 671.604 ops/s +[info] JmhBench.bench_cS_fmc_que_0 thrpt 25 5503013.635 ± 251275.430 ops/s +[info] JmhBench.bench_cS_fmc_que_1 thrpt 25 7203.193 ± 147.509 ops/s +[info] JmhBench.bench_cS_fmc_stm_0 thrpt 25 5472585.642 ± 388387.172 ops/s +[info] JmhBench.bench_cS_fmc_stm_1 thrpt 25 6386.356 ± 157.946 ops/s +[info] JmhBench.bench_cS_fmc_trs_0 thrpt 25 5265384.984 ± 84795.494 ops/s +[info] JmhBench.bench_cS_fmc_trs_1 thrpt 25 1272.612 ± 11.984 ops/s +[info] JmhBench.bench_cS_fmc_vec_0 thrpt 25 6851462.782 ± 52096.647 ops/s +[info] JmhBench.bench_cS_fmc_vec_1 thrpt 25 10994.253 ± 317.945 ops/s +[info] JmhBench.bench_cS_fmc_wra_0 thrpt 25 6661645.674 ± 74676.590 ops/s +[info] JmhBench.bench_cS_fmc_wra_1 thrpt 25 17783.760 ± 433.679 ops/s +[info] JmhBench.bench_cS_htrg_arb_0 thrpt 25 98786.541 ± 135.038 ops/s +[info] JmhBench.bench_cS_htrg_arb_1 thrpt 25 98.001 ± 0.163 ops/s +[info] JmhBench.bench_cS_htrg_arr_0 thrpt 25 100566.283 ± 111.351 ops/s +[info] JmhBench.bench_cS_htrg_arr_1 thrpt 25 99.116 ± 0.146 ops/s +[info] JmhBench.bench_cS_htrg_ars_0 thrpt 25 70824.755 ± 159.884 ops/s +[info] JmhBench.bench_cS_htrg_ars_1 thrpt 25 83.161 ± 9.309 ops/s +[info] JmhBench.bench_cS_htrg_ast_0 thrpt 25 70497.771 ± 137.953 ops/s +[info] JmhBench.bench_cS_htrg_ast_1 thrpt 25 70.669 ± 0.111 ops/s +[info] JmhBench.bench_cS_htrg_ils_0 thrpt 25 93979.601 ± 143.990 ops/s +[info] JmhBench.bench_cS_htrg_ils_1 thrpt 25 90.501 ± 0.227 ops/s +[info] JmhBench.bench_cS_htrg_ish_0 thrpt 25 69330.554 ± 108.192 ops/s +[info] JmhBench.bench_cS_htrg_ish_1 thrpt 25 62.102 ± 0.265 ops/s +[info] JmhBench.bench_cS_htrg_lhs_0 thrpt 25 96535.109 ± 339.936 ops/s +[info] JmhBench.bench_cS_htrg_lhs_1 thrpt 25 93.221 ± 0.205 ops/s +[info] JmhBench.bench_cS_htrg_lst_0 thrpt 25 99009.318 ± 190.428 ops/s +[info] JmhBench.bench_cS_htrg_lst_1 thrpt 25 97.804 ± 0.203 ops/s +[info] JmhBench.bench_cS_htrg_mhs_0 thrpt 25 96569.398 ± 329.995 ops/s +[info] JmhBench.bench_cS_htrg_mhs_1 thrpt 25 90.747 ± 0.333 ops/s +[info] JmhBench.bench_cS_htrg_muq_0 thrpt 25 93247.558 ± 334.412 ops/s +[info] JmhBench.bench_cS_htrg_muq_1 thrpt 25 94.833 ± 0.283 ops/s +[info] JmhBench.bench_cS_htrg_prq_0 thrpt 25 98817.647 ± 226.278 ops/s +[info] JmhBench.bench_cS_htrg_prq_1 thrpt 25 70.441 ± 0.178 ops/s +[info] JmhBench.bench_cS_htrg_que_0 thrpt 25 97188.745 ± 169.364 ops/s +[info] JmhBench.bench_cS_htrg_que_1 thrpt 25 96.327 ± 0.291 ops/s +[info] JmhBench.bench_cS_htrg_stm_0 thrpt 25 96162.631 ± 162.971 ops/s +[info] JmhBench.bench_cS_htrg_stm_1 thrpt 25 94.593 ± 0.183 ops/s +[info] JmhBench.bench_cS_htrg_trs_0 thrpt 25 68623.297 ± 153.165 ops/s +[info] JmhBench.bench_cS_htrg_trs_1 thrpt 25 62.935 ± 0.265 ops/s +[info] JmhBench.bench_cS_htrg_vec_0 thrpt 25 98793.504 ± 237.187 ops/s +[info] JmhBench.bench_cS_htrg_vec_1 thrpt 25 97.576 ± 0.231 ops/s +[info] JmhBench.bench_cS_htrg_wra_0 thrpt 25 98854.153 ± 239.193 ops/s +[info] JmhBench.bench_cS_htrg_wra_1 thrpt 25 97.760 ± 0.233 ops/s +[info] JmhBench.bench_cS_mdtc_arb_0 thrpt 25 1918033.395 ± 16232.747 ops/s +[info] JmhBench.bench_cS_mdtc_arb_1 thrpt 25 1617.014 ± 148.727 ops/s +[info] JmhBench.bench_cS_mdtc_arr_0 thrpt 25 3952629.619 ± 25689.408 ops/s +[info] JmhBench.bench_cS_mdtc_arr_1 thrpt 25 3402684.776 ± 284371.307 ops/s +[info] JmhBench.bench_cS_mdtc_ars_0 thrpt 25 1638242.587 ± 14473.305 ops/s +[info] JmhBench.bench_cS_mdtc_ars_1 thrpt 25 1674.373 ± 103.550 ops/s +[info] JmhBench.bench_cS_mdtc_ast_0 thrpt 25 1325591.166 ± 23723.433 ops/s +[info] JmhBench.bench_cS_mdtc_ast_1 thrpt 25 1675.501 ± 116.342 ops/s +[info] JmhBench.bench_cS_mdtc_lst_0 thrpt 25 2161734.107 ± 109210.632 ops/s +[info] JmhBench.bench_cS_mdtc_lst_1 thrpt 25 1763.655 ± 175.337 ops/s +[info] JmhBench.bench_cS_mdtc_muq_0 thrpt 25 929318.339 ± 31646.687 ops/s +[info] JmhBench.bench_cS_mdtc_muq_1 thrpt 25 1139.156 ± 90.269 ops/s +[info] JmhBench.bench_cS_mdtc_que_0 thrpt 25 1327489.572 ± 14055.324 ops/s +[info] JmhBench.bench_cS_mdtc_que_1 thrpt 25 1394.055 ± 52.289 ops/s +[info] JmhBench.bench_cS_mdtc_stm_0 thrpt 25 989690.937 ± 25041.440 ops/s +[info] JmhBench.bench_cS_mdtc_stm_1 thrpt 25 928921.110 ± 18259.866 ops/s +[info] JmhBench.bench_cS_mdtc_vec_0 thrpt 25 2021845.500 ± 133044.349 ops/s +[info] JmhBench.bench_cS_mdtc_vec_1 thrpt 25 1752.712 ± 147.928 ops/s +[info] JmhBench.bench_cS_mdtc_wra_0 thrpt 25 1864950.656 ± 83548.897 ops/s +[info] JmhBench.bench_cS_mdtc_wra_1 thrpt 25 1933.967 ± 33.820 ops/s +[info] JmhBench.bench_cS_nbr_arb_0 thrpt 25 15835328.428 ± 122519.272 ops/s +[info] JmhBench.bench_cS_nbr_arb_1 thrpt 25 16840.766 ± 148.609 ops/s +[info] JmhBench.bench_cS_nbr_arr_0 thrpt 25 47695446.412 ± 182044.808 ops/s +[info] JmhBench.bench_cS_nbr_arr_1 thrpt 25 49504.973 ± 304.514 ops/s +[info] JmhBench.bench_cS_nbr_ars_0 thrpt 25 34856004.018 ± 401233.203 ops/s +[info] JmhBench.bench_cS_nbr_ars_1 thrpt 25 41092.593 ± 281.731 ops/s +[info] JmhBench.bench_cS_nbr_ast_0 thrpt 25 34757354.930 ± 535394.356 ops/s +[info] JmhBench.bench_cS_nbr_ast_1 thrpt 25 32360.450 ± 2172.594 ops/s +[info] JmhBench.bench_cS_nbr_ils_0 thrpt 25 10446844.257 ± 42499.180 ops/s +[info] JmhBench.bench_cS_nbr_ils_1 thrpt 25 18753.206 ± 5631.309 ops/s +[info] JmhBench.bench_cS_nbr_ish_0 thrpt 25 12678676.031 ± 1433593.642 ops/s +[info] JmhBench.bench_cS_nbr_ish_1 thrpt 25 6185.141 ± 193.784 ops/s +[info] JmhBench.bench_cS_nbr_lhs_0 thrpt 25 31868157.935 ± 355816.238 ops/s +[info] JmhBench.bench_cS_nbr_lhs_1 thrpt 25 34227.377 ± 800.219 ops/s +[info] JmhBench.bench_cS_nbr_lst_0 thrpt 25 29253945.968 ± 374855.998 ops/s +[info] JmhBench.bench_cS_nbr_lst_1 thrpt 25 35282.813 ± 492.016 ops/s +[info] JmhBench.bench_cS_nbr_mhs_0 thrpt 25 21835577.282 ± 1003688.165 ops/s +[info] JmhBench.bench_cS_nbr_mhs_1 thrpt 25 6272.351 ± 12.551 ops/s +[info] JmhBench.bench_cS_nbr_muq_0 thrpt 25 4114620.171 ± 31542.905 ops/s +[info] JmhBench.bench_cS_nbr_muq_1 thrpt 25 3541.869 ± 48.004 ops/s +[info] JmhBench.bench_cS_nbr_prq_0 thrpt 25 14977117.576 ± 48707.583 ops/s +[info] JmhBench.bench_cS_nbr_prq_1 thrpt 25 16714.493 ± 5012.246 ops/s +[info] JmhBench.bench_cS_nbr_que_0 thrpt 25 11073586.828 ± 41004.373 ops/s +[info] JmhBench.bench_cS_nbr_que_1 thrpt 25 18873.971 ± 6113.197 ops/s +[info] JmhBench.bench_cS_nbr_stm_0 thrpt 25 30003437.166 ± 204518.569 ops/s +[info] JmhBench.bench_cS_nbr_stm_1 thrpt 25 14211.397 ± 688.546 ops/s +[info] JmhBench.bench_cS_nbr_trs_0 thrpt 25 16120209.876 ± 69947.418 ops/s +[info] JmhBench.bench_cS_nbr_trs_1 thrpt 25 8927.765 ± 60.115 ops/s +[info] JmhBench.bench_cS_nbr_vec_0 thrpt 25 13156985.945 ± 62188.986 ops/s +[info] JmhBench.bench_cS_nbr_vec_1 thrpt 25 20392.272 ± 3067.769 ops/s +[info] JmhBench.bench_cS_nbr_wra_0 thrpt 25 16390141.475 ± 56090.429 ops/s +[info] JmhBench.bench_cS_nbr_wra_1 thrpt 25 17489.550 ± 47.421 ops/s +[info] JmhBench.bench_cpI_pfmc_arb_0 thrpt 25 27474.789 ± 928.921 ops/s +[info] JmhBench.bench_cpI_pfmc_arb_1 thrpt 25 7441.663 ± 93.625 ops/s +[info] JmhBench.bench_cpI_pfmc_arr_0 thrpt 25 28387.894 ± 596.492 ops/s +[info] JmhBench.bench_cpI_pfmc_arr_1 thrpt 25 5064.334 ± 50.797 ops/s +[info] JmhBench.bench_cpI_pfmc_ars_0 thrpt 25 28798.766 ± 335.791 ops/s +[info] JmhBench.bench_cpI_pfmc_ars_1 thrpt 25 7437.116 ± 108.032 ops/s +[info] JmhBench.bench_cpI_pfmc_ish_0 thrpt 25 23565.704 ± 517.381 ops/s +[info] JmhBench.bench_cpI_pfmc_ish_1 thrpt 25 3360.815 ± 27.573 ops/s +[info] JmhBench.bench_cpI_pfmc_mhs_0 thrpt 25 30631.073 ± 337.113 ops/s +[info] JmhBench.bench_cpI_pfmc_mhs_1 thrpt 25 3679.460 ± 44.876 ops/s +[info] JmhBench.bench_cpI_pfmc_vec_0 thrpt 25 24037.121 ± 400.303 ops/s +[info] JmhBench.bench_cpI_pfmc_vec_1 thrpt 25 6158.006 ± 137.476 ops/s +[info] JmhBench.bench_cpI_pfmc_wra_0 thrpt 25 28461.197 ± 406.506 ops/s +[info] JmhBench.bench_cpI_pfmc_wra_1 thrpt 25 5437.056 ± 62.127 ops/s +[info] JmhBench.bench_cpI_psum_arb_0 thrpt 25 72361.424 ± 4874.360 ops/s +[info] JmhBench.bench_cpI_psum_arb_1 thrpt 25 24580.891 ± 188.592 ops/s +[info] JmhBench.bench_cpI_psum_arr_0 thrpt 25 81295.376 ± 4901.317 ops/s +[info] JmhBench.bench_cpI_psum_arr_1 thrpt 25 9877.067 ± 949.170 ops/s +[info] JmhBench.bench_cpI_psum_ars_0 thrpt 25 73484.665 ± 4937.921 ops/s +[info] JmhBench.bench_cpI_psum_ars_1 thrpt 25 24514.076 ± 192.678 ops/s +[info] JmhBench.bench_cpI_psum_ish_0 thrpt 25 59907.362 ± 3036.537 ops/s +[info] JmhBench.bench_cpI_psum_ish_1 thrpt 25 12840.071 ± 125.814 ops/s +[info] JmhBench.bench_cpI_psum_mhs_0 thrpt 25 86150.260 ± 888.758 ops/s +[info] JmhBench.bench_cpI_psum_mhs_1 thrpt 25 12432.879 ± 107.465 ops/s +[info] JmhBench.bench_cpI_psum_vec_0 thrpt 25 67410.471 ± 503.168 ops/s +[info] JmhBench.bench_cpI_psum_vec_1 thrpt 25 19689.700 ± 224.288 ops/s +[info] JmhBench.bench_cpI_psum_wra_0 thrpt 25 81936.702 ± 6116.035 ops/s +[info] JmhBench.bench_cpI_psum_wra_1 thrpt 25 12562.928 ± 602.681 ops/s +[info] JmhBench.bench_cpI_ptrig_arb_0 thrpt 25 27500.407 ± 451.591 ops/s +[info] JmhBench.bench_cpI_ptrig_arb_1 thrpt 25 636.484 ± 4.737 ops/s +[info] JmhBench.bench_cpI_ptrig_arr_0 thrpt 25 27522.840 ± 278.360 ops/s +[info] JmhBench.bench_cpI_ptrig_arr_1 thrpt 25 580.587 ± 12.258 ops/s +[info] JmhBench.bench_cpI_ptrig_ars_0 thrpt 25 27760.222 ± 383.837 ops/s +[info] JmhBench.bench_cpI_ptrig_ars_1 thrpt 25 626.056 ± 13.349 ops/s +[info] JmhBench.bench_cpI_ptrig_ish_0 thrpt 25 16795.172 ± 199.894 ops/s +[info] JmhBench.bench_cpI_ptrig_ish_1 thrpt 25 495.891 ± 11.044 ops/s +[info] JmhBench.bench_cpI_ptrig_mhs_0 thrpt 25 26673.936 ± 630.916 ops/s +[info] JmhBench.bench_cpI_ptrig_mhs_1 thrpt 25 424.598 ± 15.818 ops/s +[info] JmhBench.bench_cpI_ptrig_vec_0 thrpt 25 19853.009 ± 430.607 ops/s +[info] JmhBench.bench_cpI_ptrig_vec_1 thrpt 25 406.065 ± 6.945 ops/s +[info] JmhBench.bench_cpI_ptrig_wra_0 thrpt 25 27526.423 ± 304.224 ops/s +[info] JmhBench.bench_cpI_ptrig_wra_1 thrpt 25 590.973 ± 12.122 ops/s +[info] JmhBench.bench_cpS_pfmc_arb_0 thrpt 25 28842.541 ± 242.274 ops/s +[info] JmhBench.bench_cpS_pfmc_arb_1 thrpt 25 7437.332 ± 102.398 ops/s +[info] JmhBench.bench_cpS_pfmc_arr_0 thrpt 25 28444.328 ± 788.916 ops/s +[info] JmhBench.bench_cpS_pfmc_arr_1 thrpt 25 7480.643 ± 100.594 ops/s +[info] JmhBench.bench_cpS_pfmc_ars_0 thrpt 25 28489.525 ± 464.335 ops/s +[info] JmhBench.bench_cpS_pfmc_ars_1 thrpt 25 7509.309 ± 111.292 ops/s +[info] JmhBench.bench_cpS_pfmc_ish_0 thrpt 25 24479.975 ± 278.588 ops/s +[info] JmhBench.bench_cpS_pfmc_ish_1 thrpt 25 3249.879 ± 72.414 ops/s +[info] JmhBench.bench_cpS_pfmc_mhs_0 thrpt 25 27431.881 ± 346.329 ops/s +[info] JmhBench.bench_cpS_pfmc_mhs_1 thrpt 25 3515.211 ± 32.526 ops/s +[info] JmhBench.bench_cpS_pfmc_vec_0 thrpt 25 24390.048 ± 299.352 ops/s +[info] JmhBench.bench_cpS_pfmc_vec_1 thrpt 25 5880.720 ± 40.165 ops/s +[info] JmhBench.bench_cpS_pfmc_wra_0 thrpt 25 27932.560 ± 745.187 ops/s +[info] JmhBench.bench_cpS_pfmc_wra_1 thrpt 25 7371.214 ± 122.236 ops/s +[info] JmhBench.bench_cpS_phtrg_arb_0 thrpt 25 26302.214 ± 350.122 ops/s +[info] JmhBench.bench_cpS_phtrg_arb_1 thrpt 25 461.723 ± 9.907 ops/s +[info] JmhBench.bench_cpS_phtrg_arr_0 thrpt 25 26334.485 ± 294.864 ops/s +[info] JmhBench.bench_cpS_phtrg_arr_1 thrpt 25 471.983 ± 4.097 ops/s +[info] JmhBench.bench_cpS_phtrg_ars_0 thrpt 25 26745.117 ± 302.547 ops/s +[info] JmhBench.bench_cpS_phtrg_ars_1 thrpt 25 460.382 ± 10.151 ops/s +[info] JmhBench.bench_cpS_phtrg_ish_0 thrpt 25 16794.377 ± 217.144 ops/s +[info] JmhBench.bench_cpS_phtrg_ish_1 thrpt 25 381.766 ± 7.441 ops/s +[info] JmhBench.bench_cpS_phtrg_mhs_0 thrpt 25 24664.868 ± 234.874 ops/s +[info] JmhBench.bench_cpS_phtrg_mhs_1 thrpt 25 346.646 ± 6.224 ops/s +[info] JmhBench.bench_cpS_phtrg_vec_0 thrpt 25 19515.505 ± 291.700 ops/s +[info] JmhBench.bench_cpS_phtrg_vec_1 thrpt 25 329.508 ± 4.446 ops/s +[info] JmhBench.bench_cpS_phtrg_wra_0 thrpt 25 26324.009 ± 260.212 ops/s +[info] JmhBench.bench_cpS_phtrg_wra_1 thrpt 25 457.488 ± 11.205 ops/s +[info] JmhBench.bench_cpS_pnbr_arb_0 thrpt 25 73769.996 ± 4888.976 ops/s +[info] JmhBench.bench_cpS_pnbr_arb_1 thrpt 25 26655.950 ± 267.853 ops/s +[info] JmhBench.bench_cpS_pnbr_arr_0 thrpt 25 71213.033 ± 4539.260 ops/s +[info] JmhBench.bench_cpS_pnbr_arr_1 thrpt 25 26608.171 ± 238.450 ops/s +[info] JmhBench.bench_cpS_pnbr_ars_0 thrpt 25 78247.370 ± 9646.793 ops/s +[info] JmhBench.bench_cpS_pnbr_ars_1 thrpt 25 26383.234 ± 418.183 ops/s +[info] JmhBench.bench_cpS_pnbr_ish_0 thrpt 25 72540.054 ± 2073.362 ops/s +[info] JmhBench.bench_cpS_pnbr_ish_1 thrpt 25 10859.745 ± 100.505 ops/s +[info] JmhBench.bench_cpS_pnbr_mhs_0 thrpt 25 77753.110 ± 2422.987 ops/s +[info] JmhBench.bench_cpS_pnbr_mhs_1 thrpt 25 10940.002 ± 87.312 ops/s +[info] JmhBench.bench_cpS_pnbr_vec_0 thrpt 25 64658.143 ± 2006.249 ops/s +[info] JmhBench.bench_cpS_pnbr_vec_1 thrpt 25 20204.269 ± 242.223 ops/s +[info] JmhBench.bench_cpS_pnbr_wra_0 thrpt 25 73522.170 ± 7333.002 ops/s +[info] JmhBench.bench_cpS_pnbr_wra_1 thrpt 25 26573.617 ± 275.909 ops/s +[info] JmhBench.bench_iI_fmc_arb_0 thrpt 25 11534951.751 ± 1691165.189 ops/s +[info] JmhBench.bench_iI_fmc_arb_1 thrpt 25 23810.169 ± 96.643 ops/s +[info] JmhBench.bench_iI_fmc_arr_0 thrpt 25 10757732.243 ± 1081713.666 ops/s +[info] JmhBench.bench_iI_fmc_arr_1 thrpt 25 15286.908 ± 436.672 ops/s +[info] JmhBench.bench_iI_fmc_ars_0 thrpt 25 14166687.269 ± 1566994.869 ops/s +[info] JmhBench.bench_iI_fmc_ars_1 thrpt 25 23799.914 ± 175.777 ops/s +[info] JmhBench.bench_iI_fmc_ast_0 thrpt 25 12292010.377 ± 176433.123 ops/s +[info] JmhBench.bench_iI_fmc_ast_1 thrpt 25 25241.034 ± 120.206 ops/s +[info] JmhBench.bench_iI_fmc_ils_0 thrpt 25 13282888.820 ± 1987503.472 ops/s +[info] JmhBench.bench_iI_fmc_ils_1 thrpt 25 19804.166 ± 254.272 ops/s +[info] JmhBench.bench_iI_fmc_ish_0 thrpt 25 9527444.984 ± 1365718.073 ops/s +[info] JmhBench.bench_iI_fmc_ish_1 thrpt 25 9854.394 ± 63.613 ops/s +[info] JmhBench.bench_iI_fmc_lhs_0 thrpt 25 13602398.626 ± 83211.972 ops/s +[info] JmhBench.bench_iI_fmc_lhs_1 thrpt 25 24091.137 ± 702.120 ops/s +[info] JmhBench.bench_iI_fmc_lst_0 thrpt 25 11879620.676 ± 2484773.765 ops/s +[info] JmhBench.bench_iI_fmc_lst_1 thrpt 25 19869.918 ± 309.872 ops/s +[info] JmhBench.bench_iI_fmc_mhs_0 thrpt 25 7592696.142 ± 89270.023 ops/s +[info] JmhBench.bench_iI_fmc_mhs_1 thrpt 25 10258.397 ± 167.902 ops/s +[info] JmhBench.bench_iI_fmc_muq_0 thrpt 25 7592332.150 ± 62151.207 ops/s +[info] JmhBench.bench_iI_fmc_muq_1 thrpt 25 18870.776 ± 230.705 ops/s +[info] JmhBench.bench_iI_fmc_prq_0 thrpt 25 12541183.516 ± 1500910.168 ops/s +[info] JmhBench.bench_iI_fmc_prq_1 thrpt 25 22868.330 ± 128.832 ops/s +[info] JmhBench.bench_iI_fmc_que_0 thrpt 25 8906589.116 ± 1870066.573 ops/s +[info] JmhBench.bench_iI_fmc_que_1 thrpt 25 19476.309 ± 495.972 ops/s +[info] JmhBench.bench_iI_fmc_stm_0 thrpt 25 4046667.237 ± 192062.337 ops/s +[info] JmhBench.bench_iI_fmc_stm_1 thrpt 25 4574.786 ± 302.886 ops/s +[info] JmhBench.bench_iI_fmc_trs_0 thrpt 25 8992324.317 ± 318613.523 ops/s +[info] JmhBench.bench_iI_fmc_trs_1 thrpt 25 13485.785 ± 211.286 ops/s +[info] JmhBench.bench_iI_fmc_vec_0 thrpt 25 11822416.084 ± 142156.960 ops/s +[info] JmhBench.bench_iI_fmc_vec_1 thrpt 25 19049.985 ± 180.215 ops/s +[info] JmhBench.bench_iI_fmc_wra_0 thrpt 25 9234532.837 ± 56329.639 ops/s +[info] JmhBench.bench_iI_fmc_wra_1 thrpt 25 14532.597 ± 495.601 ops/s +[info] JmhBench.bench_iI_mdtc_arb_0 thrpt 25 24564626.307 ± 3669838.680 ops/s +[info] JmhBench.bench_iI_mdtc_arb_1 thrpt 25 5108174.772 ± 678000.865 ops/s +[info] JmhBench.bench_iI_mdtc_arr_0 thrpt 25 26535121.610 ± 6675643.142 ops/s +[info] JmhBench.bench_iI_mdtc_arr_1 thrpt 25 6362301.204 ± 667303.594 ops/s +[info] JmhBench.bench_iI_mdtc_ars_0 thrpt 25 22085306.151 ± 4620817.939 ops/s +[info] JmhBench.bench_iI_mdtc_ars_1 thrpt 25 4685615.766 ± 17669.801 ops/s +[info] JmhBench.bench_iI_mdtc_ast_0 thrpt 25 26824525.002 ± 4209095.277 ops/s +[info] JmhBench.bench_iI_mdtc_ast_1 thrpt 25 6032697.890 ± 1056453.803 ops/s +[info] JmhBench.bench_iI_mdtc_lst_0 thrpt 25 27610068.280 ± 622136.640 ops/s +[info] JmhBench.bench_iI_mdtc_lst_1 thrpt 25 5461025.518 ± 41410.786 ops/s +[info] JmhBench.bench_iI_mdtc_muq_0 thrpt 25 13497138.952 ± 511813.331 ops/s +[info] JmhBench.bench_iI_mdtc_muq_1 thrpt 25 4042199.341 ± 1148290.848 ops/s +[info] JmhBench.bench_iI_mdtc_que_0 thrpt 25 22956764.241 ± 3036473.817 ops/s +[info] JmhBench.bench_iI_mdtc_que_1 thrpt 25 5744120.080 ± 575906.527 ops/s +[info] JmhBench.bench_iI_mdtc_stm_0 thrpt 25 3983205.096 ± 203586.052 ops/s +[info] JmhBench.bench_iI_mdtc_stm_1 thrpt 25 1952832.766 ± 80784.271 ops/s +[info] JmhBench.bench_iI_mdtc_vec_0 thrpt 25 26238397.353 ± 559877.283 ops/s +[info] JmhBench.bench_iI_mdtc_vec_1 thrpt 25 6202379.758 ± 981088.096 ops/s +[info] JmhBench.bench_iI_mdtc_wra_0 thrpt 25 21628417.878 ± 3218213.725 ops/s +[info] JmhBench.bench_iI_mdtc_wra_1 thrpt 25 3989870.457 ± 53216.895 ops/s +[info] JmhBench.bench_iI_sum_arb_0 thrpt 25 13677150.793 ± 196430.726 ops/s +[info] JmhBench.bench_iI_sum_arb_1 thrpt 25 16594.802 ± 1428.913 ops/s +[info] JmhBench.bench_iI_sum_arr_0 thrpt 25 11018038.688 ± 253894.491 ops/s +[info] JmhBench.bench_iI_sum_arr_1 thrpt 25 11801.147 ± 650.632 ops/s +[info] JmhBench.bench_iI_sum_ars_0 thrpt 25 15848085.664 ± 367685.730 ops/s +[info] JmhBench.bench_iI_sum_ars_1 thrpt 25 18191.993 ± 519.274 ops/s +[info] JmhBench.bench_iI_sum_ast_0 thrpt 25 17845530.592 ± 404346.784 ops/s +[info] JmhBench.bench_iI_sum_ast_1 thrpt 25 19225.305 ± 353.326 ops/s +[info] JmhBench.bench_iI_sum_ils_0 thrpt 25 18507893.432 ± 244915.056 ops/s +[info] JmhBench.bench_iI_sum_ils_1 thrpt 25 25558.552 ± 679.197 ops/s +[info] JmhBench.bench_iI_sum_ish_0 thrpt 25 9720641.170 ± 76384.111 ops/s +[info] JmhBench.bench_iI_sum_ish_1 thrpt 25 9909.417 ± 115.705 ops/s +[info] JmhBench.bench_iI_sum_lhs_0 thrpt 25 17819380.379 ± 415435.915 ops/s +[info] JmhBench.bench_iI_sum_lhs_1 thrpt 25 20293.239 ± 574.528 ops/s +[info] JmhBench.bench_iI_sum_lst_0 thrpt 25 17618830.518 ± 247702.793 ops/s +[info] JmhBench.bench_iI_sum_lst_1 thrpt 25 23871.318 ± 821.518 ops/s +[info] JmhBench.bench_iI_sum_mhs_0 thrpt 25 7920199.338 ± 25073.016 ops/s +[info] JmhBench.bench_iI_sum_mhs_1 thrpt 25 9793.600 ± 565.252 ops/s +[info] JmhBench.bench_iI_sum_muq_0 thrpt 25 9990945.720 ± 31626.968 ops/s +[info] JmhBench.bench_iI_sum_muq_1 thrpt 25 12188.211 ± 537.108 ops/s +[info] JmhBench.bench_iI_sum_prq_0 thrpt 25 15093045.013 ± 316551.848 ops/s +[info] JmhBench.bench_iI_sum_prq_1 thrpt 25 18429.280 ± 240.042 ops/s +[info] JmhBench.bench_iI_sum_que_0 thrpt 25 16518172.761 ± 133367.414 ops/s +[info] JmhBench.bench_iI_sum_que_1 thrpt 25 23915.095 ± 480.386 ops/s +[info] JmhBench.bench_iI_sum_stm_0 thrpt 25 3960336.238 ± 213043.035 ops/s +[info] JmhBench.bench_iI_sum_stm_1 thrpt 25 4173.550 ± 349.392 ops/s +[info] JmhBench.bench_iI_sum_trs_0 thrpt 25 9199624.201 ± 56259.658 ops/s +[info] JmhBench.bench_iI_sum_trs_1 thrpt 25 13869.328 ± 530.911 ops/s +[info] JmhBench.bench_iI_sum_vec_0 thrpt 25 14795372.228 ± 324576.889 ops/s +[info] JmhBench.bench_iI_sum_vec_1 thrpt 25 17685.259 ± 588.780 ops/s +[info] JmhBench.bench_iI_sum_wra_0 thrpt 25 10885962.925 ± 557809.799 ops/s +[info] JmhBench.bench_iI_sum_wra_1 thrpt 25 12222.309 ± 300.230 ops/s +[info] JmhBench.bench_iI_trig_arb_0 thrpt 25 127425.280 ± 191.414 ops/s +[info] JmhBench.bench_iI_trig_arb_1 thrpt 25 127.634 ± 0.991 ops/s +[info] JmhBench.bench_iI_trig_arr_0 thrpt 25 127512.032 ± 274.842 ops/s +[info] JmhBench.bench_iI_trig_arr_1 thrpt 25 127.698 ± 0.193 ops/s +[info] JmhBench.bench_iI_trig_ars_0 thrpt 25 127436.172 ± 238.600 ops/s +[info] JmhBench.bench_iI_trig_ars_1 thrpt 25 127.869 ± 0.295 ops/s +[info] JmhBench.bench_iI_trig_ast_0 thrpt 25 127494.683 ± 602.866 ops/s +[info] JmhBench.bench_iI_trig_ast_1 thrpt 25 127.612 ± 0.632 ops/s +[info] JmhBench.bench_iI_trig_ils_0 thrpt 25 127113.022 ± 332.672 ops/s +[info] JmhBench.bench_iI_trig_ils_1 thrpt 25 127.901 ± 0.286 ops/s +[info] JmhBench.bench_iI_trig_ish_0 thrpt 25 127092.736 ± 457.161 ops/s +[info] JmhBench.bench_iI_trig_ish_1 thrpt 25 126.436 ± 0.534 ops/s +[info] JmhBench.bench_iI_trig_lhs_0 thrpt 25 127514.664 ± 231.652 ops/s +[info] JmhBench.bench_iI_trig_lhs_1 thrpt 25 128.273 ± 0.254 ops/s +[info] JmhBench.bench_iI_trig_lst_0 thrpt 25 127022.490 ± 248.515 ops/s +[info] JmhBench.bench_iI_trig_lst_1 thrpt 25 128.115 ± 0.293 ops/s +[info] JmhBench.bench_iI_trig_mhs_0 thrpt 25 127550.698 ± 198.539 ops/s +[info] JmhBench.bench_iI_trig_mhs_1 thrpt 25 126.677 ± 0.344 ops/s +[info] JmhBench.bench_iI_trig_muq_0 thrpt 25 126992.882 ± 183.521 ops/s +[info] JmhBench.bench_iI_trig_muq_1 thrpt 25 128.114 ± 0.314 ops/s +[info] JmhBench.bench_iI_trig_prq_0 thrpt 25 126839.329 ± 193.157 ops/s +[info] JmhBench.bench_iI_trig_prq_1 thrpt 25 127.293 ± 0.463 ops/s +[info] JmhBench.bench_iI_trig_que_0 thrpt 25 126802.756 ± 375.210 ops/s +[info] JmhBench.bench_iI_trig_que_1 thrpt 25 128.106 ± 0.397 ops/s +[info] JmhBench.bench_iI_trig_stm_0 thrpt 25 124764.329 ± 430.653 ops/s +[info] JmhBench.bench_iI_trig_stm_1 thrpt 25 124.498 ± 0.485 ops/s +[info] JmhBench.bench_iI_trig_trs_0 thrpt 25 126340.545 ± 237.574 ops/s +[info] JmhBench.bench_iI_trig_trs_1 thrpt 25 126.564 ± 0.356 ops/s +[info] JmhBench.bench_iI_trig_vec_0 thrpt 25 127474.814 ± 164.684 ops/s +[info] JmhBench.bench_iI_trig_vec_1 thrpt 25 128.064 ± 0.313 ops/s +[info] JmhBench.bench_iI_trig_wra_0 thrpt 25 127331.453 ± 261.737 ops/s +[info] JmhBench.bench_iI_trig_wra_1 thrpt 25 128.023 ± 0.172 ops/s +[info] JmhBench.bench_iS_fmc_arb_0 thrpt 25 20660242.351 ± 209369.661 ops/s +[info] JmhBench.bench_iS_fmc_arb_1 thrpt 25 27552.048 ± 172.476 ops/s +[info] JmhBench.bench_iS_fmc_arr_0 thrpt 25 21065476.479 ± 205039.828 ops/s +[info] JmhBench.bench_iS_fmc_arr_1 thrpt 25 29128.579 ± 250.629 ops/s +[info] JmhBench.bench_iS_fmc_ars_0 thrpt 25 20695026.482 ± 88802.378 ops/s +[info] JmhBench.bench_iS_fmc_ars_1 thrpt 25 27806.607 ± 178.834 ops/s +[info] JmhBench.bench_iS_fmc_ast_0 thrpt 25 25600313.157 ± 317157.005 ops/s +[info] JmhBench.bench_iS_fmc_ast_1 thrpt 25 31883.764 ± 250.718 ops/s +[info] JmhBench.bench_iS_fmc_ils_0 thrpt 25 14362194.610 ± 173685.590 ops/s +[info] JmhBench.bench_iS_fmc_ils_1 thrpt 25 27422.246 ± 475.305 ops/s +[info] JmhBench.bench_iS_fmc_ish_0 thrpt 25 11106914.870 ± 304024.165 ops/s +[info] JmhBench.bench_iS_fmc_ish_1 thrpt 25 6266.457 ± 50.467 ops/s +[info] JmhBench.bench_iS_fmc_lhs_0 thrpt 25 22715287.169 ± 149617.853 ops/s +[info] JmhBench.bench_iS_fmc_lhs_1 thrpt 25 28972.273 ± 328.804 ops/s +[info] JmhBench.bench_iS_fmc_lst_0 thrpt 25 21752765.860 ± 238227.475 ops/s +[info] JmhBench.bench_iS_fmc_lst_1 thrpt 25 27163.131 ± 560.292 ops/s +[info] JmhBench.bench_iS_fmc_mhs_0 thrpt 25 13668175.591 ± 75209.492 ops/s +[info] JmhBench.bench_iS_fmc_mhs_1 thrpt 25 5765.118 ± 29.925 ops/s +[info] JmhBench.bench_iS_fmc_muq_0 thrpt 25 9638550.537 ± 157743.693 ops/s +[info] JmhBench.bench_iS_fmc_muq_1 thrpt 25 24535.554 ± 319.728 ops/s +[info] JmhBench.bench_iS_fmc_prq_0 thrpt 25 21586397.825 ± 513866.266 ops/s +[info] JmhBench.bench_iS_fmc_prq_1 thrpt 25 20012.133 ± 438.172 ops/s +[info] JmhBench.bench_iS_fmc_que_0 thrpt 25 19349313.994 ± 291925.270 ops/s +[info] JmhBench.bench_iS_fmc_que_1 thrpt 25 27455.560 ± 249.001 ops/s +[info] JmhBench.bench_iS_fmc_stm_0 thrpt 25 3967962.807 ± 230987.833 ops/s +[info] JmhBench.bench_iS_fmc_stm_1 thrpt 25 4584.761 ± 288.495 ops/s +[info] JmhBench.bench_iS_fmc_trs_0 thrpt 25 10500586.619 ± 543350.914 ops/s +[info] JmhBench.bench_iS_fmc_trs_1 thrpt 25 7758.939 ± 260.818 ops/s +[info] JmhBench.bench_iS_fmc_vec_0 thrpt 25 16202222.266 ± 1185179.036 ops/s +[info] JmhBench.bench_iS_fmc_vec_1 thrpt 25 20328.860 ± 357.803 ops/s +[info] JmhBench.bench_iS_fmc_wra_0 thrpt 25 22170885.258 ± 82756.344 ops/s +[info] JmhBench.bench_iS_fmc_wra_1 thrpt 25 28812.002 ± 257.772 ops/s +[info] JmhBench.bench_iS_htrg_arb_0 thrpt 25 99861.730 ± 209.117 ops/s +[info] JmhBench.bench_iS_htrg_arb_1 thrpt 25 98.417 ± 0.171 ops/s +[info] JmhBench.bench_iS_htrg_arr_0 thrpt 25 99625.567 ± 163.801 ops/s +[info] JmhBench.bench_iS_htrg_arr_1 thrpt 25 98.296 ± 0.210 ops/s +[info] JmhBench.bench_iS_htrg_ars_0 thrpt 25 99879.643 ± 156.190 ops/s +[info] JmhBench.bench_iS_htrg_ars_1 thrpt 25 98.363 ± 0.183 ops/s +[info] JmhBench.bench_iS_htrg_ast_0 thrpt 25 99380.973 ± 336.195 ops/s +[info] JmhBench.bench_iS_htrg_ast_1 thrpt 25 98.387 ± 0.198 ops/s +[info] JmhBench.bench_iS_htrg_ils_0 thrpt 25 99964.680 ± 174.309 ops/s +[info] JmhBench.bench_iS_htrg_ils_1 thrpt 25 98.294 ± 0.227 ops/s +[info] JmhBench.bench_iS_htrg_ish_0 thrpt 25 99433.408 ± 247.431 ops/s +[info] JmhBench.bench_iS_htrg_ish_1 thrpt 25 97.311 ± 0.150 ops/s +[info] JmhBench.bench_iS_htrg_lhs_0 thrpt 25 99265.630 ± 291.685 ops/s +[info] JmhBench.bench_iS_htrg_lhs_1 thrpt 25 98.447 ± 0.194 ops/s +[info] JmhBench.bench_iS_htrg_lst_0 thrpt 25 99902.619 ± 186.008 ops/s +[info] JmhBench.bench_iS_htrg_lst_1 thrpt 25 98.498 ± 0.209 ops/s +[info] JmhBench.bench_iS_htrg_mhs_0 thrpt 25 99003.158 ± 187.515 ops/s +[info] JmhBench.bench_iS_htrg_mhs_1 thrpt 25 96.822 ± 0.413 ops/s +[info] JmhBench.bench_iS_htrg_muq_0 thrpt 25 100012.595 ± 276.322 ops/s +[info] JmhBench.bench_iS_htrg_muq_1 thrpt 25 98.282 ± 0.258 ops/s +[info] JmhBench.bench_iS_htrg_prq_0 thrpt 25 99909.274 ± 269.579 ops/s +[info] JmhBench.bench_iS_htrg_prq_1 thrpt 25 97.929 ± 0.434 ops/s +[info] JmhBench.bench_iS_htrg_que_0 thrpt 25 99927.315 ± 151.573 ops/s +[info] JmhBench.bench_iS_htrg_que_1 thrpt 25 98.434 ± 0.299 ops/s +[info] JmhBench.bench_iS_htrg_stm_0 thrpt 25 98035.244 ± 198.742 ops/s +[info] JmhBench.bench_iS_htrg_stm_1 thrpt 25 96.635 ± 0.265 ops/s +[info] JmhBench.bench_iS_htrg_trs_0 thrpt 25 99717.022 ± 174.509 ops/s +[info] JmhBench.bench_iS_htrg_trs_1 thrpt 25 97.415 ± 0.245 ops/s +[info] JmhBench.bench_iS_htrg_vec_0 thrpt 25 99966.597 ± 221.390 ops/s +[info] JmhBench.bench_iS_htrg_vec_1 thrpt 25 98.199 ± 0.172 ops/s +[info] JmhBench.bench_iS_htrg_wra_0 thrpt 25 99874.236 ± 179.219 ops/s +[info] JmhBench.bench_iS_htrg_wra_1 thrpt 25 98.288 ± 0.196 ops/s +[info] JmhBench.bench_iS_mdtc_arb_0 thrpt 25 2097899.982 ± 23027.980 ops/s +[info] JmhBench.bench_iS_mdtc_arb_1 thrpt 25 1887060.512 ± 26123.879 ops/s +[info] JmhBench.bench_iS_mdtc_arr_0 thrpt 25 2082275.844 ± 34790.548 ops/s +[info] JmhBench.bench_iS_mdtc_arr_1 thrpt 25 1845126.936 ± 20293.322 ops/s +[info] JmhBench.bench_iS_mdtc_ars_0 thrpt 25 2009995.771 ± 76910.203 ops/s +[info] JmhBench.bench_iS_mdtc_ars_1 thrpt 25 1870000.666 ± 40742.596 ops/s +[info] JmhBench.bench_iS_mdtc_ast_0 thrpt 25 2178819.994 ± 221518.015 ops/s +[info] JmhBench.bench_iS_mdtc_ast_1 thrpt 25 2123261.170 ± 154628.266 ops/s +[info] JmhBench.bench_iS_mdtc_lst_0 thrpt 25 2328914.058 ± 32074.037 ops/s +[info] JmhBench.bench_iS_mdtc_lst_1 thrpt 25 2041954.017 ± 42234.460 ops/s +[info] JmhBench.bench_iS_mdtc_muq_0 thrpt 25 2100724.686 ± 25639.833 ops/s +[info] JmhBench.bench_iS_mdtc_muq_1 thrpt 25 1911625.218 ± 23276.435 ops/s +[info] JmhBench.bench_iS_mdtc_que_0 thrpt 25 2329239.766 ± 30110.120 ops/s +[info] JmhBench.bench_iS_mdtc_que_1 thrpt 25 2006283.293 ± 45267.124 ops/s +[info] JmhBench.bench_iS_mdtc_stm_0 thrpt 25 1639832.628 ± 33564.535 ops/s +[info] JmhBench.bench_iS_mdtc_stm_1 thrpt 25 1559980.428 ± 58314.308 ops/s +[info] JmhBench.bench_iS_mdtc_vec_0 thrpt 25 2075815.450 ± 25831.246 ops/s +[info] JmhBench.bench_iS_mdtc_vec_1 thrpt 25 1774053.986 ± 24836.414 ops/s +[info] JmhBench.bench_iS_mdtc_wra_0 thrpt 25 2082465.430 ± 54266.074 ops/s +[info] JmhBench.bench_iS_mdtc_wra_1 thrpt 25 1852111.865 ± 40534.660 ops/s +[info] JmhBench.bench_iS_nbr_arb_0 thrpt 25 15093643.409 ± 312819.522 ops/s +[info] JmhBench.bench_iS_nbr_arb_1 thrpt 25 16536.134 ± 44.776 ops/s +[info] JmhBench.bench_iS_nbr_arr_0 thrpt 25 13681116.218 ± 2069446.439 ops/s +[info] JmhBench.bench_iS_nbr_arr_1 thrpt 25 16216.197 ± 153.748 ops/s +[info] JmhBench.bench_iS_nbr_ars_0 thrpt 25 15231820.552 ± 71198.860 ops/s +[info] JmhBench.bench_iS_nbr_ars_1 thrpt 25 16431.260 ± 58.286 ops/s +[info] JmhBench.bench_iS_nbr_ast_0 thrpt 25 16422832.425 ± 160552.096 ops/s +[info] JmhBench.bench_iS_nbr_ast_1 thrpt 25 17926.164 ± 56.371 ops/s +[info] JmhBench.bench_iS_nbr_ils_0 thrpt 25 13584445.254 ± 117216.650 ops/s +[info] JmhBench.bench_iS_nbr_ils_1 thrpt 25 16068.090 ± 2653.041 ops/s +[info] JmhBench.bench_iS_nbr_ish_0 thrpt 25 13215826.280 ± 1505586.375 ops/s +[info] JmhBench.bench_iS_nbr_ish_1 thrpt 25 6105.864 ± 59.147 ops/s +[info] JmhBench.bench_iS_nbr_lhs_0 thrpt 25 17670261.677 ± 161144.754 ops/s +[info] JmhBench.bench_iS_nbr_lhs_1 thrpt 25 20389.690 ± 2324.186 ops/s +[info] JmhBench.bench_iS_nbr_lst_0 thrpt 25 16357641.101 ± 60754.533 ops/s +[info] JmhBench.bench_iS_nbr_lst_1 thrpt 25 18433.714 ± 2057.837 ops/s +[info] JmhBench.bench_iS_nbr_mhs_0 thrpt 25 11812511.313 ± 88367.679 ops/s +[info] JmhBench.bench_iS_nbr_mhs_1 thrpt 25 5600.543 ± 17.450 ops/s +[info] JmhBench.bench_iS_nbr_muq_0 thrpt 25 11691763.921 ± 46245.840 ops/s +[info] JmhBench.bench_iS_nbr_muq_1 thrpt 25 18182.019 ± 4847.548 ops/s +[info] JmhBench.bench_iS_nbr_prq_0 thrpt 25 15349594.898 ± 76157.252 ops/s +[info] JmhBench.bench_iS_nbr_prq_1 thrpt 25 15811.057 ± 4892.669 ops/s +[info] JmhBench.bench_iS_nbr_que_0 thrpt 25 15718603.188 ± 111532.970 ops/s +[info] JmhBench.bench_iS_nbr_que_1 thrpt 25 19776.658 ± 2178.055 ops/s +[info] JmhBench.bench_iS_nbr_stm_0 thrpt 25 4132893.909 ± 194559.967 ops/s +[info] JmhBench.bench_iS_nbr_stm_1 thrpt 25 4726.500 ± 338.295 ops/s +[info] JmhBench.bench_iS_nbr_trs_0 thrpt 25 10698968.841 ± 70991.716 ops/s +[info] JmhBench.bench_iS_nbr_trs_1 thrpt 25 9598.236 ± 785.458 ops/s +[info] JmhBench.bench_iS_nbr_vec_0 thrpt 25 14664874.142 ± 77772.684 ops/s +[info] JmhBench.bench_iS_nbr_vec_1 thrpt 25 17564.678 ± 3868.762 ops/s +[info] JmhBench.bench_iS_nbr_wra_0 thrpt 25 15708895.657 ± 50767.513 ops/s +[info] JmhBench.bench_iS_nbr_wra_1 thrpt 25 16808.537 ± 132.263 ops/s +[info] JmhBench.bench_spI_pfmc_arb_0 thrpt 25 122026.458 ± 3338.778 ops/s +[info] JmhBench.bench_spI_pfmc_arb_1 thrpt 25 31955.438 ± 3265.388 ops/s +[info] JmhBench.bench_spI_pfmc_arr_0 thrpt 25 123793.942 ± 1465.776 ops/s +[info] JmhBench.bench_spI_pfmc_arr_1 thrpt 25 55926.755 ± 582.057 ops/s +[info] JmhBench.bench_spI_pfmc_ars_0 thrpt 25 123838.933 ± 2528.316 ops/s +[info] JmhBench.bench_spI_pfmc_ars_1 thrpt 25 31911.979 ± 1354.094 ops/s +[info] JmhBench.bench_spI_pfmc_ish_0 thrpt 25 101313.969 ± 1541.856 ops/s +[info] JmhBench.bench_spI_pfmc_ish_1 thrpt 25 17564.133 ± 179.150 ops/s +[info] JmhBench.bench_spI_pfmc_jix_0 thrpt 25 124602.760 ± 1339.185 ops/s +[info] JmhBench.bench_spI_pfmc_jix_1 thrpt 25 46913.983 ± 1399.403 ops/s +[info] JmhBench.bench_spI_pfmc_jln_0 thrpt 25 122034.673 ± 2914.257 ops/s +[info] JmhBench.bench_spI_pfmc_jln_1 thrpt 25 21508.984 ± 2283.637 ops/s +[info] JmhBench.bench_spI_pfmc_mhs_0 thrpt 25 149803.545 ± 3416.269 ops/s +[info] JmhBench.bench_spI_pfmc_mhs_1 thrpt 25 18125.518 ± 1343.974 ops/s +[info] JmhBench.bench_spI_pfmc_vec_0 thrpt 25 121742.883 ± 1495.545 ops/s +[info] JmhBench.bench_spI_pfmc_vec_1 thrpt 25 30318.891 ± 1097.725 ops/s +[info] JmhBench.bench_spI_pfmc_wra_0 thrpt 25 124890.583 ± 706.846 ops/s +[info] JmhBench.bench_spI_pfmc_wra_1 thrpt 25 26081.649 ± 187.747 ops/s +[info] JmhBench.bench_spI_psum_arb_0 thrpt 25 120576.423 ± 1468.003 ops/s +[info] JmhBench.bench_spI_psum_arb_1 thrpt 25 33624.042 ± 476.147 ops/s +[info] JmhBench.bench_spI_psum_arr_0 thrpt 25 119288.186 ± 1423.925 ops/s +[info] JmhBench.bench_spI_psum_arr_1 thrpt 25 67775.549 ± 3304.787 ops/s +[info] JmhBench.bench_spI_psum_ars_0 thrpt 25 119588.690 ± 1729.515 ops/s +[info] JmhBench.bench_spI_psum_ars_1 thrpt 25 36403.156 ± 302.723 ops/s +[info] JmhBench.bench_spI_psum_ish_0 thrpt 25 102179.787 ± 1467.909 ops/s +[info] JmhBench.bench_spI_psum_ish_1 thrpt 25 18745.407 ± 97.495 ops/s +[info] JmhBench.bench_spI_psum_jix_0 thrpt 25 121718.375 ± 1209.540 ops/s +[info] JmhBench.bench_spI_psum_jix_1 thrpt 25 57101.512 ± 9299.544 ops/s +[info] JmhBench.bench_spI_psum_jln_0 thrpt 25 118907.263 ± 1689.327 ops/s +[info] JmhBench.bench_spI_psum_jln_1 thrpt 25 24048.469 ± 2075.903 ops/s +[info] JmhBench.bench_spI_psum_mhs_0 thrpt 25 146367.207 ± 2070.261 ops/s +[info] JmhBench.bench_spI_psum_mhs_1 thrpt 25 17278.757 ± 65.427 ops/s +[info] JmhBench.bench_spI_psum_vec_0 thrpt 25 118634.736 ± 2482.411 ops/s +[info] JmhBench.bench_spI_psum_vec_1 thrpt 25 35514.411 ± 316.920 ops/s +[info] JmhBench.bench_spI_psum_wra_0 thrpt 25 121026.432 ± 976.185 ops/s +[info] JmhBench.bench_spI_psum_wra_1 thrpt 25 26725.301 ± 163.464 ops/s +[info] JmhBench.bench_spI_ptrig_arb_0 thrpt 25 89470.600 ± 767.024 ops/s +[info] JmhBench.bench_spI_ptrig_arb_1 thrpt 25 794.995 ± 3.720 ops/s +[info] JmhBench.bench_spI_ptrig_arr_0 thrpt 25 89645.535 ± 571.222 ops/s +[info] JmhBench.bench_spI_ptrig_arr_1 thrpt 25 804.330 ± 5.509 ops/s +[info] JmhBench.bench_spI_ptrig_ars_0 thrpt 25 89499.574 ± 825.471 ops/s +[info] JmhBench.bench_spI_ptrig_ars_1 thrpt 25 782.195 ± 20.628 ops/s +[info] JmhBench.bench_spI_ptrig_ish_0 thrpt 25 77761.399 ± 661.445 ops/s +[info] JmhBench.bench_spI_ptrig_ish_1 thrpt 25 749.151 ± 5.523 ops/s +[info] JmhBench.bench_spI_ptrig_jix_0 thrpt 25 88337.024 ± 1120.008 ops/s +[info] JmhBench.bench_spI_ptrig_jix_1 thrpt 25 801.746 ± 7.369 ops/s +[info] JmhBench.bench_spI_ptrig_jln_0 thrpt 25 87959.641 ± 364.156 ops/s +[info] JmhBench.bench_spI_ptrig_jln_1 thrpt 25 739.279 ± 4.313 ops/s +[info] JmhBench.bench_spI_ptrig_mhs_0 thrpt 25 84923.215 ± 359.009 ops/s +[info] JmhBench.bench_spI_ptrig_mhs_1 thrpt 25 776.755 ± 4.260 ops/s +[info] JmhBench.bench_spI_ptrig_vec_0 thrpt 25 87511.031 ± 774.512 ops/s +[info] JmhBench.bench_spI_ptrig_vec_1 thrpt 25 788.650 ± 9.614 ops/s +[info] JmhBench.bench_spI_ptrig_wra_0 thrpt 25 89686.421 ± 971.655 ops/s +[info] JmhBench.bench_spI_ptrig_wra_1 thrpt 25 787.302 ± 5.752 ops/s +[info] JmhBench.bench_spS_pfmc_arb_0 thrpt 25 120005.523 ± 3795.221 ops/s +[info] JmhBench.bench_spS_pfmc_arb_1 thrpt 25 39776.834 ± 2984.305 ops/s +[info] JmhBench.bench_spS_pfmc_arr_0 thrpt 25 122280.558 ± 1336.325 ops/s +[info] JmhBench.bench_spS_pfmc_arr_1 thrpt 25 45979.842 ± 477.262 ops/s +[info] JmhBench.bench_spS_pfmc_ars_0 thrpt 25 123052.552 ± 1867.415 ops/s +[info] JmhBench.bench_spS_pfmc_ars_1 thrpt 25 40875.035 ± 2405.416 ops/s +[info] JmhBench.bench_spS_pfmc_ish_0 thrpt 25 103990.927 ± 1116.911 ops/s +[info] JmhBench.bench_spS_pfmc_ish_1 thrpt 25 16612.000 ± 1061.350 ops/s +[info] JmhBench.bench_spS_pfmc_jix_0 thrpt 25 118688.056 ± 3835.042 ops/s +[info] JmhBench.bench_spS_pfmc_jix_1 thrpt 25 48450.737 ± 209.135 ops/s +[info] JmhBench.bench_spS_pfmc_jln_0 thrpt 25 115844.257 ± 3520.553 ops/s +[info] JmhBench.bench_spS_pfmc_jln_1 thrpt 25 16845.440 ± 1730.417 ops/s +[info] JmhBench.bench_spS_pfmc_mhs_0 thrpt 25 131205.292 ± 1626.360 ops/s +[info] JmhBench.bench_spS_pfmc_mhs_1 thrpt 25 18525.922 ± 1488.423 ops/s +[info] JmhBench.bench_spS_pfmc_vec_0 thrpt 25 120071.251 ± 1925.718 ops/s +[info] JmhBench.bench_spS_pfmc_vec_1 thrpt 25 43352.191 ± 472.814 ops/s +[info] JmhBench.bench_spS_pfmc_wra_0 thrpt 25 124290.660 ± 2022.406 ops/s +[info] JmhBench.bench_spS_pfmc_wra_1 thrpt 25 41701.119 ± 2265.434 ops/s +[info] JmhBench.bench_spS_phtrg_arb_0 thrpt 25 81797.538 ± 548.798 ops/s +[info] JmhBench.bench_spS_phtrg_arb_1 thrpt 25 570.817 ± 5.242 ops/s +[info] JmhBench.bench_spS_phtrg_arr_0 thrpt 25 82795.075 ± 685.318 ops/s +[info] JmhBench.bench_spS_phtrg_arr_1 thrpt 25 571.434 ± 4.941 ops/s +[info] JmhBench.bench_spS_phtrg_ars_0 thrpt 25 82077.986 ± 824.614 ops/s +[info] JmhBench.bench_spS_phtrg_ars_1 thrpt 25 573.351 ± 3.988 ops/s +[info] JmhBench.bench_spS_phtrg_ish_0 thrpt 25 75813.040 ± 434.354 ops/s +[info] JmhBench.bench_spS_phtrg_ish_1 thrpt 25 532.699 ± 2.842 ops/s +[info] JmhBench.bench_spS_phtrg_jix_0 thrpt 25 82789.954 ± 556.422 ops/s +[info] JmhBench.bench_spS_phtrg_jix_1 thrpt 25 566.457 ± 11.434 ops/s +[info] JmhBench.bench_spS_phtrg_jln_0 thrpt 25 82330.442 ± 848.242 ops/s +[info] JmhBench.bench_spS_phtrg_jln_1 thrpt 25 529.041 ± 2.995 ops/s +[info] JmhBench.bench_spS_phtrg_mhs_0 thrpt 25 77381.806 ± 381.747 ops/s +[info] JmhBench.bench_spS_phtrg_mhs_1 thrpt 25 555.069 ± 2.452 ops/s +[info] JmhBench.bench_spS_phtrg_vec_0 thrpt 25 82664.902 ± 862.091 ops/s +[info] JmhBench.bench_spS_phtrg_vec_1 thrpt 25 573.708 ± 3.414 ops/s +[info] JmhBench.bench_spS_phtrg_wra_0 thrpt 25 81739.577 ± 929.248 ops/s +[info] JmhBench.bench_spS_phtrg_wra_1 thrpt 25 572.521 ± 4.090 ops/s +[info] JmhBench.bench_spS_pnbr_arb_0 thrpt 25 125276.095 ± 1514.002 ops/s +[info] JmhBench.bench_spS_pnbr_arb_1 thrpt 25 29841.668 ± 254.424 ops/s +[info] JmhBench.bench_spS_pnbr_arr_0 thrpt 25 123884.469 ± 2242.992 ops/s +[info] JmhBench.bench_spS_pnbr_arr_1 thrpt 25 34171.150 ± 571.312 ops/s +[info] JmhBench.bench_spS_pnbr_ars_0 thrpt 25 124496.684 ± 2599.330 ops/s +[info] JmhBench.bench_spS_pnbr_ars_1 thrpt 25 34250.875 ± 2183.277 ops/s +[info] JmhBench.bench_spS_pnbr_ish_0 thrpt 25 104652.916 ± 1160.961 ops/s +[info] JmhBench.bench_spS_pnbr_ish_1 thrpt 25 17229.432 ± 109.380 ops/s +[info] JmhBench.bench_spS_pnbr_jix_0 thrpt 25 123150.422 ± 1242.209 ops/s +[info] JmhBench.bench_spS_pnbr_jix_1 thrpt 25 38114.715 ± 4984.153 ops/s +[info] JmhBench.bench_spS_pnbr_jln_0 thrpt 25 120365.993 ± 1728.280 ops/s +[info] JmhBench.bench_spS_pnbr_jln_1 thrpt 25 14622.187 ± 1880.274 ops/s +[info] JmhBench.bench_spS_pnbr_mhs_0 thrpt 25 135428.927 ± 4568.452 ops/s +[info] JmhBench.bench_spS_pnbr_mhs_1 thrpt 25 15520.900 ± 88.414 ops/s +[info] JmhBench.bench_spS_pnbr_vec_0 thrpt 25 125389.867 ± 1739.809 ops/s +[info] JmhBench.bench_spS_pnbr_vec_1 thrpt 25 32482.390 ± 250.674 ops/s +[info] JmhBench.bench_spS_pnbr_wra_0 thrpt 25 124679.925 ± 2175.996 ops/s +[info] JmhBench.bench_spS_pnbr_wra_1 thrpt 25 34420.077 ± 2410.935 ops/s +[info] JmhBench.bench_ssI_fmc_arb_0 thrpt 25 9250153.823 ± 888445.531 ops/s +[info] JmhBench.bench_ssI_fmc_arb_1 thrpt 25 9355.086 ± 742.574 ops/s +[info] JmhBench.bench_ssI_fmc_arr_0 thrpt 25 16052416.844 ± 961240.618 ops/s +[info] JmhBench.bench_ssI_fmc_arr_1 thrpt 25 76936.655 ± 1407.831 ops/s +[info] JmhBench.bench_ssI_fmc_ars_0 thrpt 25 8782587.762 ± 742059.840 ops/s +[info] JmhBench.bench_ssI_fmc_ars_1 thrpt 25 9050.227 ± 780.554 ops/s +[info] JmhBench.bench_ssI_fmc_ast_0 thrpt 25 8141416.177 ± 637829.950 ops/s +[info] JmhBench.bench_ssI_fmc_ast_1 thrpt 25 10100.534 ± 503.490 ops/s +[info] JmhBench.bench_ssI_fmc_ils_0 thrpt 25 6515951.736 ± 398883.162 ops/s +[info] JmhBench.bench_ssI_fmc_ils_1 thrpt 25 9154.419 ± 328.846 ops/s +[info] JmhBench.bench_ssI_fmc_ish_0 thrpt 25 7957383.510 ± 807469.463 ops/s +[info] JmhBench.bench_ssI_fmc_ish_1 thrpt 25 8534.034 ± 76.508 ops/s +[info] JmhBench.bench_ssI_fmc_jix_0 thrpt 25 10325320.390 ± 737830.832 ops/s +[info] JmhBench.bench_ssI_fmc_jix_1 thrpt 25 23670.508 ± 1300.536 ops/s +[info] JmhBench.bench_ssI_fmc_jln_0 thrpt 25 10147871.532 ± 321143.743 ops/s +[info] JmhBench.bench_ssI_fmc_jln_1 thrpt 25 25868.179 ± 890.519 ops/s +[info] JmhBench.bench_ssI_fmc_lhs_0 thrpt 25 8167530.225 ± 68842.632 ops/s +[info] JmhBench.bench_ssI_fmc_lhs_1 thrpt 25 10305.165 ± 649.741 ops/s +[info] JmhBench.bench_ssI_fmc_lst_0 thrpt 25 7450089.752 ± 860591.681 ops/s +[info] JmhBench.bench_ssI_fmc_lst_1 thrpt 25 5580.838 ± 89.269 ops/s +[info] JmhBench.bench_ssI_fmc_mhs_0 thrpt 25 7298703.199 ± 478617.272 ops/s +[info] JmhBench.bench_ssI_fmc_mhs_1 thrpt 25 10089.122 ± 207.164 ops/s +[info] JmhBench.bench_ssI_fmc_muq_0 thrpt 25 3306530.823 ± 240247.734 ops/s +[info] JmhBench.bench_ssI_fmc_muq_1 thrpt 25 4707.455 ± 112.368 ops/s +[info] JmhBench.bench_ssI_fmc_prq_0 thrpt 25 8466869.742 ± 656493.257 ops/s +[info] JmhBench.bench_ssI_fmc_prq_1 thrpt 25 8092.785 ± 356.931 ops/s +[info] JmhBench.bench_ssI_fmc_que_0 thrpt 25 7342169.186 ± 237418.673 ops/s +[info] JmhBench.bench_ssI_fmc_que_1 thrpt 25 10399.761 ± 166.829 ops/s +[info] JmhBench.bench_ssI_fmc_stm_0 thrpt 25 7367724.075 ± 1129148.866 ops/s +[info] JmhBench.bench_ssI_fmc_stm_1 thrpt 25 8236.488 ± 2628.423 ops/s +[info] JmhBench.bench_ssI_fmc_trs_0 thrpt 25 7780121.129 ± 108678.562 ops/s +[info] JmhBench.bench_ssI_fmc_trs_1 thrpt 25 7679.958 ± 200.984 ops/s +[info] JmhBench.bench_ssI_fmc_vec_0 thrpt 25 9118653.340 ± 247215.668 ops/s +[info] JmhBench.bench_ssI_fmc_vec_1 thrpt 25 9589.100 ± 1791.009 ops/s +[info] JmhBench.bench_ssI_fmc_wra_0 thrpt 25 9262801.298 ± 456880.630 ops/s +[info] JmhBench.bench_ssI_fmc_wra_1 thrpt 25 8448.089 ± 751.665 ops/s +[info] JmhBench.bench_ssI_mdtc_arb_0 thrpt 25 6947123.970 ± 215862.500 ops/s +[info] JmhBench.bench_ssI_mdtc_arb_1 thrpt 25 4216205.596 ± 81236.212 ops/s +[info] JmhBench.bench_ssI_mdtc_arr_0 thrpt 25 7877041.387 ± 175458.225 ops/s +[info] JmhBench.bench_ssI_mdtc_arr_1 thrpt 25 4754725.775 ± 49021.630 ops/s +[info] JmhBench.bench_ssI_mdtc_ars_0 thrpt 25 6745190.439 ± 476861.322 ops/s +[info] JmhBench.bench_ssI_mdtc_ars_1 thrpt 25 4262939.806 ± 47183.691 ops/s +[info] JmhBench.bench_ssI_mdtc_ast_0 thrpt 25 6854949.067 ± 68537.150 ops/s +[info] JmhBench.bench_ssI_mdtc_ast_1 thrpt 25 4025499.567 ± 104981.719 ops/s +[info] JmhBench.bench_ssI_mdtc_jix_0 thrpt 25 5227027.825 ± 94030.854 ops/s +[info] JmhBench.bench_ssI_mdtc_jix_1 thrpt 25 3156089.920 ± 140112.857 ops/s +[info] JmhBench.bench_ssI_mdtc_jln_0 thrpt 25 5380258.918 ± 245567.821 ops/s +[info] JmhBench.bench_ssI_mdtc_jln_1 thrpt 25 3130643.665 ± 184628.801 ops/s +[info] JmhBench.bench_ssI_mdtc_lst_0 thrpt 25 6075277.338 ± 117938.332 ops/s +[info] JmhBench.bench_ssI_mdtc_lst_1 thrpt 25 4140145.442 ± 438069.320 ops/s +[info] JmhBench.bench_ssI_mdtc_muq_0 thrpt 25 2785261.264 ± 65612.901 ops/s +[info] JmhBench.bench_ssI_mdtc_muq_1 thrpt 25 1364771.167 ± 23748.839 ops/s +[info] JmhBench.bench_ssI_mdtc_que_0 thrpt 25 5122120.176 ± 104187.267 ops/s +[info] JmhBench.bench_ssI_mdtc_que_1 thrpt 25 2820520.670 ± 33621.491 ops/s +[info] JmhBench.bench_ssI_mdtc_stm_0 thrpt 25 6030630.852 ± 162783.134 ops/s +[info] JmhBench.bench_ssI_mdtc_stm_1 thrpt 25 4232143.930 ± 34806.929 ops/s +[info] JmhBench.bench_ssI_mdtc_vec_0 thrpt 25 6841092.491 ± 167568.603 ops/s +[info] JmhBench.bench_ssI_mdtc_vec_1 thrpt 25 4182368.069 ± 164073.205 ops/s +[info] JmhBench.bench_ssI_mdtc_wra_0 thrpt 25 6514842.858 ± 82706.838 ops/s +[info] JmhBench.bench_ssI_mdtc_wra_1 thrpt 25 3742865.389 ± 25362.161 ops/s +[info] JmhBench.bench_ssI_sum_arb_0 thrpt 25 9715905.252 ± 226945.687 ops/s +[info] JmhBench.bench_ssI_sum_arb_1 thrpt 25 11672.133 ± 1735.140 ops/s +[info] JmhBench.bench_ssI_sum_arr_0 thrpt 25 24618518.546 ± 257756.997 ops/s +[info] JmhBench.bench_ssI_sum_arr_1 thrpt 25 55474.149 ± 161.288 ops/s +[info] JmhBench.bench_ssI_sum_ars_0 thrpt 25 9485950.081 ± 462558.656 ops/s +[info] JmhBench.bench_ssI_sum_ars_1 thrpt 25 11299.644 ± 1711.369 ops/s +[info] JmhBench.bench_ssI_sum_ast_0 thrpt 25 8429742.725 ± 392860.041 ops/s +[info] JmhBench.bench_ssI_sum_ast_1 thrpt 25 11110.412 ± 1268.393 ops/s +[info] JmhBench.bench_ssI_sum_ils_0 thrpt 25 15909722.568 ± 349441.040 ops/s +[info] JmhBench.bench_ssI_sum_ils_1 thrpt 25 9678.768 ± 235.065 ops/s +[info] JmhBench.bench_ssI_sum_ish_0 thrpt 25 13619341.652 ± 147547.281 ops/s +[info] JmhBench.bench_ssI_sum_ish_1 thrpt 25 6212.693 ± 56.017 ops/s +[info] JmhBench.bench_ssI_sum_jix_0 thrpt 25 26310816.947 ± 153269.402 ops/s +[info] JmhBench.bench_ssI_sum_jix_1 thrpt 25 109104.485 ± 12951.334 ops/s +[info] JmhBench.bench_ssI_sum_jln_0 thrpt 25 24230659.032 ± 130893.341 ops/s +[info] JmhBench.bench_ssI_sum_jln_1 thrpt 25 44752.456 ± 3333.934 ops/s +[info] JmhBench.bench_ssI_sum_lhs_0 thrpt 25 9055689.390 ± 262812.071 ops/s +[info] JmhBench.bench_ssI_sum_lhs_1 thrpt 25 11230.558 ± 1611.547 ops/s +[info] JmhBench.bench_ssI_sum_lst_0 thrpt 25 13729453.044 ± 327014.089 ops/s +[info] JmhBench.bench_ssI_sum_lst_1 thrpt 25 17518.869 ± 183.762 ops/s +[info] JmhBench.bench_ssI_sum_mhs_0 thrpt 25 10573254.637 ± 79889.822 ops/s +[info] JmhBench.bench_ssI_sum_mhs_1 thrpt 25 4901.874 ± 36.980 ops/s +[info] JmhBench.bench_ssI_sum_muq_0 thrpt 25 3809588.908 ± 286246.301 ops/s +[info] JmhBench.bench_ssI_sum_muq_1 thrpt 25 5193.727 ± 65.227 ops/s +[info] JmhBench.bench_ssI_sum_prq_0 thrpt 25 8280044.390 ± 169984.161 ops/s +[info] JmhBench.bench_ssI_sum_prq_1 thrpt 25 10344.875 ± 908.924 ops/s +[info] JmhBench.bench_ssI_sum_que_0 thrpt 25 9207756.772 ± 1668707.276 ops/s +[info] JmhBench.bench_ssI_sum_que_1 thrpt 25 11101.518 ± 132.127 ops/s +[info] JmhBench.bench_ssI_sum_stm_0 thrpt 25 13160208.480 ± 222285.592 ops/s +[info] JmhBench.bench_ssI_sum_stm_1 thrpt 25 9703.721 ± 199.536 ops/s +[info] JmhBench.bench_ssI_sum_trs_0 thrpt 25 11550300.294 ± 168610.279 ops/s +[info] JmhBench.bench_ssI_sum_trs_1 thrpt 25 8148.181 ± 221.631 ops/s +[info] JmhBench.bench_ssI_sum_vec_0 thrpt 25 8807366.131 ± 181526.563 ops/s +[info] JmhBench.bench_ssI_sum_vec_1 thrpt 25 11708.860 ± 1701.693 ops/s +[info] JmhBench.bench_ssI_sum_wra_0 thrpt 25 8933774.049 ± 32608.515 ops/s +[info] JmhBench.bench_ssI_sum_wra_1 thrpt 25 10768.478 ± 1900.586 ops/s +[info] JmhBench.bench_ssI_trig_arb_0 thrpt 25 127701.752 ± 300.487 ops/s +[info] JmhBench.bench_ssI_trig_arb_1 thrpt 25 127.874 ± 0.244 ops/s +[info] JmhBench.bench_ssI_trig_arr_0 thrpt 25 128529.229 ± 147.708 ops/s +[info] JmhBench.bench_ssI_trig_arr_1 thrpt 25 128.141 ± 0.184 ops/s +[info] JmhBench.bench_ssI_trig_ars_0 thrpt 25 127889.038 ± 160.223 ops/s +[info] JmhBench.bench_ssI_trig_ars_1 thrpt 25 127.690 ± 0.348 ops/s +[info] JmhBench.bench_ssI_trig_ast_0 thrpt 25 127744.419 ± 223.829 ops/s +[info] JmhBench.bench_ssI_trig_ast_1 thrpt 25 127.805 ± 0.212 ops/s +[info] JmhBench.bench_ssI_trig_ils_0 thrpt 25 127427.062 ± 250.370 ops/s +[info] JmhBench.bench_ssI_trig_ils_1 thrpt 25 127.624 ± 0.198 ops/s +[info] JmhBench.bench_ssI_trig_ish_0 thrpt 25 126980.180 ± 201.098 ops/s +[info] JmhBench.bench_ssI_trig_ish_1 thrpt 25 125.386 ± 0.839 ops/s +[info] JmhBench.bench_ssI_trig_jix_0 thrpt 25 128047.658 ± 232.857 ops/s +[info] JmhBench.bench_ssI_trig_jix_1 thrpt 25 127.976 ± 0.179 ops/s +[info] JmhBench.bench_ssI_trig_jln_0 thrpt 25 128373.708 ± 156.722 ops/s +[info] JmhBench.bench_ssI_trig_jln_1 thrpt 25 127.963 ± 0.215 ops/s +[info] JmhBench.bench_ssI_trig_lhs_0 thrpt 25 127860.927 ± 268.862 ops/s +[info] JmhBench.bench_ssI_trig_lhs_1 thrpt 25 127.581 ± 0.288 ops/s +[info] JmhBench.bench_ssI_trig_lst_0 thrpt 25 127175.254 ± 376.425 ops/s +[info] JmhBench.bench_ssI_trig_lst_1 thrpt 25 127.725 ± 0.237 ops/s +[info] JmhBench.bench_ssI_trig_mhs_0 thrpt 25 127309.073 ± 796.229 ops/s +[info] JmhBench.bench_ssI_trig_mhs_1 thrpt 25 126.488 ± 0.355 ops/s +[info] JmhBench.bench_ssI_trig_muq_0 thrpt 25 125063.545 ± 299.759 ops/s +[info] JmhBench.bench_ssI_trig_muq_1 thrpt 25 124.286 ± 0.881 ops/s +[info] JmhBench.bench_ssI_trig_prq_0 thrpt 25 127111.698 ± 354.458 ops/s +[info] JmhBench.bench_ssI_trig_prq_1 thrpt 25 127.102 ± 0.424 ops/s +[info] JmhBench.bench_ssI_trig_que_0 thrpt 25 127059.599 ± 786.206 ops/s +[info] JmhBench.bench_ssI_trig_que_1 thrpt 25 126.141 ± 1.355 ops/s +[info] JmhBench.bench_ssI_trig_stm_0 thrpt 25 127112.678 ± 241.836 ops/s +[info] JmhBench.bench_ssI_trig_stm_1 thrpt 25 127.085 ± 0.441 ops/s +[info] JmhBench.bench_ssI_trig_trs_0 thrpt 25 127168.343 ± 253.254 ops/s +[info] JmhBench.bench_ssI_trig_trs_1 thrpt 25 125.868 ± 0.414 ops/s +[info] JmhBench.bench_ssI_trig_vec_0 thrpt 25 127900.540 ± 166.834 ops/s +[info] JmhBench.bench_ssI_trig_vec_1 thrpt 25 127.803 ± 0.190 ops/s +[info] JmhBench.bench_ssI_trig_wra_0 thrpt 25 128020.166 ± 213.353 ops/s +[info] JmhBench.bench_ssI_trig_wra_1 thrpt 25 127.817 ± 0.152 ops/s +[info] JmhBench.bench_ssS_fmc_arb_0 thrpt 25 7463503.099 ± 761023.850 ops/s +[info] JmhBench.bench_ssS_fmc_arb_1 thrpt 25 22735.029 ± 216.868 ops/s +[info] JmhBench.bench_ssS_fmc_arr_0 thrpt 25 7692217.391 ± 662399.601 ops/s +[info] JmhBench.bench_ssS_fmc_arr_1 thrpt 25 23523.761 ± 3082.429 ops/s +[info] JmhBench.bench_ssS_fmc_ars_0 thrpt 25 7359939.104 ± 733550.142 ops/s +[info] JmhBench.bench_ssS_fmc_ars_1 thrpt 25 18184.014 ± 3207.106 ops/s +[info] JmhBench.bench_ssS_fmc_ast_0 thrpt 25 6777545.559 ± 711554.629 ops/s +[info] JmhBench.bench_ssS_fmc_ast_1 thrpt 25 17990.091 ± 2754.649 ops/s +[info] JmhBench.bench_ssS_fmc_ils_0 thrpt 25 5536641.969 ± 173682.607 ops/s +[info] JmhBench.bench_ssS_fmc_ils_1 thrpt 25 16297.925 ± 1948.984 ops/s +[info] JmhBench.bench_ssS_fmc_ish_0 thrpt 25 5276557.648 ± 151673.651 ops/s +[info] JmhBench.bench_ssS_fmc_ish_1 thrpt 25 5487.043 ± 26.346 ops/s +[info] JmhBench.bench_ssS_fmc_jix_0 thrpt 25 8622948.878 ± 545772.382 ops/s +[info] JmhBench.bench_ssS_fmc_jix_1 thrpt 25 25400.994 ± 2093.185 ops/s +[info] JmhBench.bench_ssS_fmc_jln_0 thrpt 25 8110492.748 ± 334080.983 ops/s +[info] JmhBench.bench_ssS_fmc_jln_1 thrpt 25 26365.259 ± 2299.475 ops/s +[info] JmhBench.bench_ssS_fmc_lhs_0 thrpt 25 6786461.725 ± 739728.565 ops/s +[info] JmhBench.bench_ssS_fmc_lhs_1 thrpt 25 20871.320 ± 2145.218 ops/s +[info] JmhBench.bench_ssS_fmc_lst_0 thrpt 25 5694810.309 ± 980249.336 ops/s +[info] JmhBench.bench_ssS_fmc_lst_1 thrpt 25 16006.665 ± 115.192 ops/s +[info] JmhBench.bench_ssS_fmc_mhs_0 thrpt 25 4918958.662 ± 1011742.955 ops/s +[info] JmhBench.bench_ssS_fmc_mhs_1 thrpt 25 6243.466 ± 16.259 ops/s +[info] JmhBench.bench_ssS_fmc_muq_0 thrpt 25 3143846.099 ± 161160.702 ops/s +[info] JmhBench.bench_ssS_fmc_muq_1 thrpt 25 5153.514 ± 88.295 ops/s +[info] JmhBench.bench_ssS_fmc_prq_0 thrpt 25 6494916.233 ± 659140.032 ops/s +[info] JmhBench.bench_ssS_fmc_prq_1 thrpt 25 13046.181 ± 129.301 ops/s +[info] JmhBench.bench_ssS_fmc_que_0 thrpt 25 5233751.510 ± 600136.627 ops/s +[info] JmhBench.bench_ssS_fmc_que_1 thrpt 25 11701.632 ± 255.248 ops/s +[info] JmhBench.bench_ssS_fmc_stm_0 thrpt 25 5954886.043 ± 721275.435 ops/s +[info] JmhBench.bench_ssS_fmc_stm_1 thrpt 25 12476.953 ± 657.314 ops/s +[info] JmhBench.bench_ssS_fmc_trs_0 thrpt 25 5512418.318 ± 431220.677 ops/s +[info] JmhBench.bench_ssS_fmc_trs_1 thrpt 25 7876.367 ± 49.840 ops/s +[info] JmhBench.bench_ssS_fmc_vec_0 thrpt 25 6647652.124 ± 808794.052 ops/s +[info] JmhBench.bench_ssS_fmc_vec_1 thrpt 25 18797.521 ± 4612.928 ops/s +[info] JmhBench.bench_ssS_fmc_wra_0 thrpt 25 7312179.994 ± 727113.651 ops/s +[info] JmhBench.bench_ssS_fmc_wra_1 thrpt 25 19996.576 ± 3747.471 ops/s +[info] JmhBench.bench_ssS_htrg_arb_0 thrpt 25 99446.779 ± 280.765 ops/s +[info] JmhBench.bench_ssS_htrg_arb_1 thrpt 25 98.641 ± 0.151 ops/s +[info] JmhBench.bench_ssS_htrg_arr_0 thrpt 25 99590.833 ± 277.204 ops/s +[info] JmhBench.bench_ssS_htrg_arr_1 thrpt 25 98.728 ± 0.115 ops/s +[info] JmhBench.bench_ssS_htrg_ars_0 thrpt 25 99488.987 ± 325.960 ops/s +[info] JmhBench.bench_ssS_htrg_ars_1 thrpt 25 98.556 ± 0.157 ops/s +[info] JmhBench.bench_ssS_htrg_ast_0 thrpt 25 99404.624 ± 239.178 ops/s +[info] JmhBench.bench_ssS_htrg_ast_1 thrpt 25 98.474 ± 0.236 ops/s +[info] JmhBench.bench_ssS_htrg_ils_0 thrpt 25 99089.876 ± 928.141 ops/s +[info] JmhBench.bench_ssS_htrg_ils_1 thrpt 25 98.270 ± 0.161 ops/s +[info] JmhBench.bench_ssS_htrg_ish_0 thrpt 25 99700.720 ± 151.216 ops/s +[info] JmhBench.bench_ssS_htrg_ish_1 thrpt 25 96.097 ± 0.123 ops/s +[info] JmhBench.bench_ssS_htrg_jix_0 thrpt 25 100076.554 ± 253.018 ops/s +[info] JmhBench.bench_ssS_htrg_jix_1 thrpt 25 98.762 ± 0.134 ops/s +[info] JmhBench.bench_ssS_htrg_jln_0 thrpt 25 100312.125 ± 185.924 ops/s +[info] JmhBench.bench_ssS_htrg_jln_1 thrpt 25 98.734 ± 0.126 ops/s +[info] JmhBench.bench_ssS_htrg_lhs_0 thrpt 25 99754.119 ± 217.214 ops/s +[info] JmhBench.bench_ssS_htrg_lhs_1 thrpt 25 98.602 ± 0.120 ops/s +[info] JmhBench.bench_ssS_htrg_lst_0 thrpt 25 99829.970 ± 238.825 ops/s +[info] JmhBench.bench_ssS_htrg_lst_1 thrpt 25 98.721 ± 0.082 ops/s +[info] JmhBench.bench_ssS_htrg_mhs_0 thrpt 25 99476.088 ± 201.311 ops/s +[info] JmhBench.bench_ssS_htrg_mhs_1 thrpt 25 97.000 ± 0.127 ops/s +[info] JmhBench.bench_ssS_htrg_muq_0 thrpt 25 97745.699 ± 289.134 ops/s +[info] JmhBench.bench_ssS_htrg_muq_1 thrpt 25 96.814 ± 0.216 ops/s +[info] JmhBench.bench_ssS_htrg_prq_0 thrpt 25 99471.700 ± 420.144 ops/s +[info] JmhBench.bench_ssS_htrg_prq_1 thrpt 25 97.984 ± 0.144 ops/s +[info] JmhBench.bench_ssS_htrg_que_0 thrpt 25 99167.531 ± 519.919 ops/s +[info] JmhBench.bench_ssS_htrg_que_1 thrpt 25 97.867 ± 0.734 ops/s +[info] JmhBench.bench_ssS_htrg_stm_0 thrpt 25 99286.997 ± 493.065 ops/s +[info] JmhBench.bench_ssS_htrg_stm_1 thrpt 25 98.307 ± 0.123 ops/s +[info] JmhBench.bench_ssS_htrg_trs_0 thrpt 25 99632.863 ± 167.388 ops/s +[info] JmhBench.bench_ssS_htrg_trs_1 thrpt 25 97.235 ± 0.186 ops/s +[info] JmhBench.bench_ssS_htrg_vec_0 thrpt 25 99346.287 ± 342.790 ops/s +[info] JmhBench.bench_ssS_htrg_vec_1 thrpt 25 98.639 ± 0.134 ops/s +[info] JmhBench.bench_ssS_htrg_wra_0 thrpt 25 99393.808 ± 435.384 ops/s +[info] JmhBench.bench_ssS_htrg_wra_1 thrpt 25 98.650 ± 0.113 ops/s +[info] JmhBench.bench_ssS_mdtc_arb_0 thrpt 25 1984988.001 ± 60815.590 ops/s +[info] JmhBench.bench_ssS_mdtc_arb_1 thrpt 25 1804763.676 ± 24880.414 ops/s +[info] JmhBench.bench_ssS_mdtc_arr_0 thrpt 25 2039192.164 ± 20642.902 ops/s +[info] JmhBench.bench_ssS_mdtc_arr_1 thrpt 25 1869149.671 ± 57778.551 ops/s +[info] JmhBench.bench_ssS_mdtc_ars_0 thrpt 25 2152810.620 ± 257467.311 ops/s +[info] JmhBench.bench_ssS_mdtc_ars_1 thrpt 25 1943524.599 ± 249992.603 ops/s +[info] JmhBench.bench_ssS_mdtc_ast_0 thrpt 25 2098672.703 ± 224737.345 ops/s +[info] JmhBench.bench_ssS_mdtc_ast_1 thrpt 25 1756317.464 ± 32268.509 ops/s +[info] JmhBench.bench_ssS_mdtc_jix_0 thrpt 25 1886876.043 ± 40790.835 ops/s +[info] JmhBench.bench_ssS_mdtc_jix_1 thrpt 25 1776842.938 ± 87607.424 ops/s +[info] JmhBench.bench_ssS_mdtc_jln_0 thrpt 25 1924389.622 ± 100113.823 ops/s +[info] JmhBench.bench_ssS_mdtc_jln_1 thrpt 25 1739231.139 ± 27705.929 ops/s +[info] JmhBench.bench_ssS_mdtc_lst_0 thrpt 25 2088812.599 ± 282022.358 ops/s +[info] JmhBench.bench_ssS_mdtc_lst_1 thrpt 25 1885221.781 ± 98783.686 ops/s +[info] JmhBench.bench_ssS_mdtc_muq_0 thrpt 25 1535772.126 ± 139156.482 ops/s +[info] JmhBench.bench_ssS_mdtc_muq_1 thrpt 25 1348730.978 ± 123859.731 ops/s +[info] JmhBench.bench_ssS_mdtc_que_0 thrpt 25 1808813.567 ± 38380.283 ops/s +[info] JmhBench.bench_ssS_mdtc_que_1 thrpt 25 1859406.391 ± 243374.664 ops/s +[info] JmhBench.bench_ssS_mdtc_stm_0 thrpt 25 2159647.943 ± 261644.254 ops/s +[info] JmhBench.bench_ssS_mdtc_stm_1 thrpt 25 2060597.468 ± 239102.768 ops/s +[info] JmhBench.bench_ssS_mdtc_vec_0 thrpt 25 1960074.223 ± 19074.784 ops/s +[info] JmhBench.bench_ssS_mdtc_vec_1 thrpt 25 1838536.051 ± 83700.683 ops/s +[info] JmhBench.bench_ssS_mdtc_wra_0 thrpt 25 1974542.200 ± 19477.153 ops/s +[info] JmhBench.bench_ssS_mdtc_wra_1 thrpt 25 1846644.168 ± 61236.016 ops/s +[info] JmhBench.bench_ssS_nbr_arb_0 thrpt 25 15162942.609 ± 190397.163 ops/s +[info] JmhBench.bench_ssS_nbr_arb_1 thrpt 25 34172.246 ± 11486.810 ops/s +[info] JmhBench.bench_ssS_nbr_arr_0 thrpt 25 15507888.940 ± 238185.693 ops/s +[info] JmhBench.bench_ssS_nbr_arr_1 thrpt 25 35941.101 ± 10040.604 ops/s +[info] JmhBench.bench_ssS_nbr_ars_0 thrpt 25 15197879.786 ± 98346.084 ops/s +[info] JmhBench.bench_ssS_nbr_ars_1 thrpt 25 38301.207 ± 9362.340 ops/s +[info] JmhBench.bench_ssS_nbr_ast_0 thrpt 25 13432007.539 ± 405165.436 ops/s +[info] JmhBench.bench_ssS_nbr_ast_1 thrpt 25 32959.315 ± 8359.559 ops/s +[info] JmhBench.bench_ssS_nbr_ils_0 thrpt 25 8549875.457 ± 500035.754 ops/s +[info] JmhBench.bench_ssS_nbr_ils_1 thrpt 25 21605.083 ± 8611.146 ops/s +[info] JmhBench.bench_ssS_nbr_ish_0 thrpt 25 7664446.924 ± 98245.672 ops/s +[info] JmhBench.bench_ssS_nbr_ish_1 thrpt 25 5854.499 ± 28.620 ops/s +[info] JmhBench.bench_ssS_nbr_jix_0 thrpt 25 16089447.761 ± 68029.793 ops/s +[info] JmhBench.bench_ssS_nbr_jix_1 thrpt 25 40651.466 ± 4089.126 ops/s +[info] JmhBench.bench_ssS_nbr_jln_0 thrpt 25 14995175.785 ± 244736.253 ops/s +[info] JmhBench.bench_ssS_nbr_jln_1 thrpt 25 37382.867 ± 1452.421 ops/s +[info] JmhBench.bench_ssS_nbr_lhs_0 thrpt 25 13926273.218 ± 110410.977 ops/s +[info] JmhBench.bench_ssS_nbr_lhs_1 thrpt 25 27298.620 ± 8327.998 ops/s +[info] JmhBench.bench_ssS_nbr_lst_0 thrpt 25 10221445.868 ± 204571.661 ops/s +[info] JmhBench.bench_ssS_nbr_lst_1 thrpt 25 22706.524 ± 127.693 ops/s +[info] JmhBench.bench_ssS_nbr_mhs_0 thrpt 25 9484224.952 ± 83230.676 ops/s +[info] JmhBench.bench_ssS_nbr_mhs_1 thrpt 25 4272.497 ± 16.585 ops/s +[info] JmhBench.bench_ssS_nbr_muq_0 thrpt 25 3306298.286 ± 32629.694 ops/s +[info] JmhBench.bench_ssS_nbr_muq_1 thrpt 25 5674.616 ± 95.096 ops/s +[info] JmhBench.bench_ssS_nbr_prq_0 thrpt 25 13602518.766 ± 182996.531 ops/s +[info] JmhBench.bench_ssS_nbr_prq_1 thrpt 25 8229.425 ± 1387.909 ops/s +[info] JmhBench.bench_ssS_nbr_que_0 thrpt 25 7926786.770 ± 71210.458 ops/s +[info] JmhBench.bench_ssS_nbr_que_1 thrpt 25 12578.198 ± 340.733 ops/s +[info] JmhBench.bench_ssS_nbr_stm_0 thrpt 25 10451796.812 ± 162198.366 ops/s +[info] JmhBench.bench_ssS_nbr_stm_1 thrpt 25 10900.482 ± 876.892 ops/s +[info] JmhBench.bench_ssS_nbr_trs_0 thrpt 25 8243471.097 ± 135268.322 ops/s +[info] JmhBench.bench_ssS_nbr_trs_1 thrpt 25 5423.466 ± 46.213 ops/s +[info] JmhBench.bench_ssS_nbr_vec_0 thrpt 25 11273633.534 ± 133713.186 ops/s +[info] JmhBench.bench_ssS_nbr_vec_1 thrpt 25 22784.871 ± 3851.382 ops/s +[info] JmhBench.bench_ssS_nbr_wra_0 thrpt 25 15100257.953 ± 74244.381 ops/s +[info] JmhBench.bench_ssS_nbr_wra_1 thrpt 25 33805.074 ± 11062.118 ops/s +[info] JmhBench.bench_tpI_sum_arb_0 thrpt 25 26739900.465 ± 335390.195 ops/s +[info] JmhBench.bench_tpI_sum_arb_1 thrpt 25 36127.483 ± 192.396 ops/s +[info] JmhBench.bench_tpI_sum_arr_0 thrpt 25 96980149.604 ± 307301.990 ops/s +[info] JmhBench.bench_tpI_sum_arr_1 thrpt 25 433545.154 ± 505.319 ops/s +[info] JmhBench.bench_tpI_sum_ars_0 thrpt 25 62659319.636 ± 263473.537 ops/s +[info] JmhBench.bench_tpI_sum_ars_1 thrpt 25 134066.476 ± 2016.903 ops/s +[info] JmhBench.bench_tpI_sum_ish_0 thrpt 25 13553901.120 ± 539231.487 ops/s +[info] JmhBench.bench_tpI_sum_ish_1 thrpt 25 7114.146 ± 88.443 ops/s +[info] JmhBench.bench_tpI_sum_mhs_0 thrpt 25 34967900.851 ± 170504.872 ops/s +[info] JmhBench.bench_tpI_sum_mhs_1 thrpt 25 28972.583 ± 4297.660 ops/s +[info] JmhBench.bench_tpI_sum_vec_0 thrpt 25 40722024.527 ± 324420.816 ops/s +[info] JmhBench.bench_tpI_sum_vec_1 thrpt 25 56600.790 ± 453.750 ops/s +[info] JmhBench.bench_tpI_sum_wra_0 thrpt 25 21076023.537 ± 321478.351 ops/s +[info] JmhBench.bench_tpI_sum_wra_1 thrpt 25 21466.089 ± 1622.643 ops/s +[info] JmhBench.bench_tpI_trig_arb_0 thrpt 25 129620.815 ± 139.024 ops/s +[info] JmhBench.bench_tpI_trig_arb_1 thrpt 25 128.952 ± 0.106 ops/s +[info] JmhBench.bench_tpI_trig_arr_0 thrpt 25 129958.638 ± 148.953 ops/s +[info] JmhBench.bench_tpI_trig_arr_1 thrpt 25 129.385 ± 0.112 ops/s +[info] JmhBench.bench_tpI_trig_ars_0 thrpt 25 129745.070 ± 228.564 ops/s +[info] JmhBench.bench_tpI_trig_ars_1 thrpt 25 128.757 ± 0.199 ops/s +[info] JmhBench.bench_tpI_trig_ish_0 thrpt 25 128598.096 ± 207.794 ops/s +[info] JmhBench.bench_tpI_trig_ish_1 thrpt 25 125.427 ± 0.108 ops/s +[info] JmhBench.bench_tpI_trig_mhs_0 thrpt 25 129109.741 ± 173.754 ops/s +[info] JmhBench.bench_tpI_trig_mhs_1 thrpt 25 127.048 ± 0.209 ops/s +[info] JmhBench.bench_tpI_trig_vec_0 thrpt 25 129567.839 ± 205.096 ops/s +[info] JmhBench.bench_tpI_trig_vec_1 thrpt 25 128.955 ± 0.139 ops/s +[info] JmhBench.bench_tpI_trig_wra_0 thrpt 25 129438.595 ± 145.718 ops/s +[info] JmhBench.bench_tpI_trig_wra_1 thrpt 25 128.359 ± 0.198 ops/s +[info] JmhBench.bench_tpS_htrg_arb_0 thrpt 25 100158.018 ± 205.248 ops/s +[info] JmhBench.bench_tpS_htrg_arb_1 thrpt 25 98.649 ± 0.169 ops/s +[info] JmhBench.bench_tpS_htrg_arr_0 thrpt 25 100144.281 ± 158.463 ops/s +[info] JmhBench.bench_tpS_htrg_arr_1 thrpt 25 98.765 ± 0.260 ops/s +[info] JmhBench.bench_tpS_htrg_ars_0 thrpt 25 100096.628 ± 172.960 ops/s +[info] JmhBench.bench_tpS_htrg_ars_1 thrpt 25 98.710 ± 0.179 ops/s +[info] JmhBench.bench_tpS_htrg_ish_0 thrpt 25 99760.501 ± 217.237 ops/s +[info] JmhBench.bench_tpS_htrg_ish_1 thrpt 25 97.228 ± 0.519 ops/s +[info] JmhBench.bench_tpS_htrg_mhs_0 thrpt 25 99806.585 ± 153.342 ops/s +[info] JmhBench.bench_tpS_htrg_mhs_1 thrpt 25 97.412 ± 0.354 ops/s +[info] JmhBench.bench_tpS_htrg_vec_0 thrpt 25 99612.078 ± 530.034 ops/s +[info] JmhBench.bench_tpS_htrg_vec_1 thrpt 25 98.638 ± 0.206 ops/s +[info] JmhBench.bench_tpS_htrg_wra_0 thrpt 25 100084.080 ± 194.389 ops/s +[info] JmhBench.bench_tpS_htrg_wra_1 thrpt 25 98.759 ± 0.217 ops/s +[info] JmhBench.bench_tpS_nbr_arb_0 thrpt 25 27773552.600 ± 107286.891 ops/s +[info] JmhBench.bench_tpS_nbr_arb_1 thrpt 25 26047.916 ± 541.631 ops/s +[info] JmhBench.bench_tpS_nbr_arr_0 thrpt 25 32696587.907 ± 125809.446 ops/s +[info] JmhBench.bench_tpS_nbr_arr_1 thrpt 25 31707.576 ± 1469.663 ops/s +[info] JmhBench.bench_tpS_nbr_ars_0 thrpt 25 27763273.573 ± 75994.385 ops/s +[info] JmhBench.bench_tpS_nbr_ars_1 thrpt 25 25907.969 ± 499.582 ops/s +[info] JmhBench.bench_tpS_nbr_ish_0 thrpt 25 10561733.949 ± 333991.228 ops/s +[info] JmhBench.bench_tpS_nbr_ish_1 thrpt 25 6686.211 ± 38.894 ops/s +[info] JmhBench.bench_tpS_nbr_mhs_0 thrpt 25 20592408.675 ± 290612.904 ops/s +[info] JmhBench.bench_tpS_nbr_mhs_1 thrpt 25 6586.088 ± 57.671 ops/s +[info] JmhBench.bench_tpS_nbr_vec_0 thrpt 25 19918742.462 ± 129361.736 ops/s +[info] JmhBench.bench_tpS_nbr_vec_1 thrpt 25 22393.856 ± 660.971 ops/s +[info] JmhBench.bench_tpS_nbr_wra_0 thrpt 25 27798715.944 ± 399855.662 ops/s +[info] JmhBench.bench_tpS_nbr_wra_1 thrpt 25 26368.583 ± 698.515 ops/s +[info] JmhBench.bench_tsI_sum_ast_0 thrpt 25 29292472.271 ± 378141.088 ops/s +[info] JmhBench.bench_tsI_sum_ast_1 thrpt 25 38732.103 ± 250.264 ops/s +[info] JmhBench.bench_tsI_sum_ils_0 thrpt 25 12612812.138 ± 2285614.348 ops/s +[info] JmhBench.bench_tsI_sum_ils_1 thrpt 25 20618.454 ± 7399.667 ops/s +[info] JmhBench.bench_tsI_sum_lhs_0 thrpt 25 19047956.030 ± 102806.511 ops/s +[info] JmhBench.bench_tsI_sum_lhs_1 thrpt 25 21098.108 ± 1892.775 ops/s +[info] JmhBench.bench_tsI_sum_lst_0 thrpt 25 13250785.213 ± 284214.672 ops/s +[info] JmhBench.bench_tsI_sum_lst_1 thrpt 25 20620.823 ± 7198.647 ops/s +[info] JmhBench.bench_tsI_sum_muq_0 thrpt 25 6186108.761 ± 49405.604 ops/s +[info] JmhBench.bench_tsI_sum_muq_1 thrpt 25 6953.879 ± 68.504 ops/s +[info] JmhBench.bench_tsI_sum_prq_0 thrpt 25 15439239.952 ± 61151.281 ops/s +[info] JmhBench.bench_tsI_sum_prq_1 thrpt 25 15760.730 ± 44.485 ops/s +[info] JmhBench.bench_tsI_sum_que_0 thrpt 25 6544132.929 ± 90771.895 ops/s +[info] JmhBench.bench_tsI_sum_que_1 thrpt 25 7583.197 ± 82.784 ops/s +[info] JmhBench.bench_tsI_sum_stm_0 thrpt 25 12838212.904 ± 40317.104 ops/s +[info] JmhBench.bench_tsI_sum_stm_1 thrpt 25 13428.876 ± 412.327 ops/s +[info] JmhBench.bench_tsI_sum_trs_0 thrpt 25 11018879.369 ± 36863.225 ops/s +[info] JmhBench.bench_tsI_sum_trs_1 thrpt 25 12874.559 ± 320.397 ops/s +[info] JmhBench.bench_tsI_trig_ast_0 thrpt 25 129218.582 ± 247.185 ops/s +[info] JmhBench.bench_tsI_trig_ast_1 thrpt 25 128.730 ± 0.134 ops/s +[info] JmhBench.bench_tsI_trig_ils_0 thrpt 25 128764.813 ± 270.973 ops/s +[info] JmhBench.bench_tsI_trig_ils_1 thrpt 25 128.383 ± 0.229 ops/s +[info] JmhBench.bench_tsI_trig_lhs_0 thrpt 25 129310.531 ± 402.325 ops/s +[info] JmhBench.bench_tsI_trig_lhs_1 thrpt 25 128.862 ± 0.132 ops/s +[info] JmhBench.bench_tsI_trig_lst_0 thrpt 25 128629.859 ± 169.266 ops/s +[info] JmhBench.bench_tsI_trig_lst_1 thrpt 25 128.817 ± 0.136 ops/s +[info] JmhBench.bench_tsI_trig_muq_0 thrpt 25 126882.540 ± 261.902 ops/s +[info] JmhBench.bench_tsI_trig_muq_1 thrpt 25 124.074 ± 0.275 ops/s +[info] JmhBench.bench_tsI_trig_prq_0 thrpt 25 128704.594 ± 132.903 ops/s +[info] JmhBench.bench_tsI_trig_prq_1 thrpt 25 127.264 ± 0.215 ops/s +[info] JmhBench.bench_tsI_trig_que_0 thrpt 25 127027.541 ± 305.857 ops/s +[info] JmhBench.bench_tsI_trig_que_1 thrpt 25 127.115 ± 0.387 ops/s +[info] JmhBench.bench_tsI_trig_stm_0 thrpt 25 128763.321 ± 170.721 ops/s +[info] JmhBench.bench_tsI_trig_stm_1 thrpt 25 127.858 ± 0.341 ops/s +[info] JmhBench.bench_tsI_trig_trs_0 thrpt 25 128251.208 ± 143.219 ops/s +[info] JmhBench.bench_tsI_trig_trs_1 thrpt 25 125.752 ± 0.714 ops/s +[info] JmhBench.bench_tsS_htrg_ast_0 thrpt 25 99993.610 ± 190.884 ops/s +[info] JmhBench.bench_tsS_htrg_ast_1 thrpt 25 98.665 ± 0.229 ops/s +[info] JmhBench.bench_tsS_htrg_ils_0 thrpt 25 99769.301 ± 181.360 ops/s +[info] JmhBench.bench_tsS_htrg_ils_1 thrpt 25 97.749 ± 0.981 ops/s +[info] JmhBench.bench_tsS_htrg_lhs_0 thrpt 25 99843.502 ± 435.773 ops/s +[info] JmhBench.bench_tsS_htrg_lhs_1 thrpt 25 98.554 ± 0.370 ops/s +[info] JmhBench.bench_tsS_htrg_lst_0 thrpt 25 99994.704 ± 271.382 ops/s +[info] JmhBench.bench_tsS_htrg_lst_1 thrpt 25 98.679 ± 0.216 ops/s +[info] JmhBench.bench_tsS_htrg_muq_0 thrpt 25 97832.075 ± 224.268 ops/s +[info] JmhBench.bench_tsS_htrg_muq_1 thrpt 25 96.275 ± 0.219 ops/s +[info] JmhBench.bench_tsS_htrg_prq_0 thrpt 25 100041.101 ± 215.115 ops/s +[info] JmhBench.bench_tsS_htrg_prq_1 thrpt 25 98.142 ± 0.362 ops/s +[info] JmhBench.bench_tsS_htrg_que_0 thrpt 25 99899.045 ± 199.887 ops/s +[info] JmhBench.bench_tsS_htrg_que_1 thrpt 25 98.160 ± 0.193 ops/s +[info] JmhBench.bench_tsS_htrg_stm_0 thrpt 25 99938.866 ± 583.593 ops/s +[info] JmhBench.bench_tsS_htrg_stm_1 thrpt 25 98.389 ± 0.258 ops/s +[info] JmhBench.bench_tsS_htrg_trs_0 thrpt 25 99843.112 ± 278.174 ops/s +[info] JmhBench.bench_tsS_htrg_trs_1 thrpt 25 97.433 ± 0.404 ops/s +[info] JmhBench.bench_tsS_nbr_ast_0 thrpt 25 24754126.558 ± 2252827.519 ops/s +[info] JmhBench.bench_tsS_nbr_ast_1 thrpt 25 25470.616 ± 2313.648 ops/s +[info] JmhBench.bench_tsS_nbr_ils_0 thrpt 25 18815243.091 ± 229054.186 ops/s +[info] JmhBench.bench_tsS_nbr_ils_1 thrpt 25 18405.753 ± 1106.520 ops/s +[info] JmhBench.bench_tsS_nbr_lhs_0 thrpt 25 23611132.342 ± 214340.942 ops/s +[info] JmhBench.bench_tsS_nbr_lhs_1 thrpt 25 19916.336 ± 750.264 ops/s +[info] JmhBench.bench_tsS_nbr_lst_0 thrpt 25 16162287.601 ± 386166.719 ops/s +[info] JmhBench.bench_tsS_nbr_lst_1 thrpt 25 15050.506 ± 225.637 ops/s +[info] JmhBench.bench_tsS_nbr_muq_0 thrpt 25 3990516.577 ± 72332.103 ops/s +[info] JmhBench.bench_tsS_nbr_muq_1 thrpt 25 3957.072 ± 47.475 ops/s +[info] JmhBench.bench_tsS_nbr_prq_0 thrpt 25 24071415.301 ± 190014.780 ops/s +[info] JmhBench.bench_tsS_nbr_prq_1 thrpt 25 12006.143 ± 668.510 ops/s +[info] JmhBench.bench_tsS_nbr_que_0 thrpt 25 11035865.936 ± 125073.361 ops/s +[info] JmhBench.bench_tsS_nbr_que_1 thrpt 25 10895.451 ± 82.204 ops/s +[info] JmhBench.bench_tsS_nbr_stm_0 thrpt 25 15774294.393 ± 161310.226 ops/s +[info] JmhBench.bench_tsS_nbr_stm_1 thrpt 25 12751.885 ± 218.859 ops/s +[info] JmhBench.bench_tsS_nbr_trs_0 thrpt 25 12164073.361 ± 417198.078 ops/s +[info] JmhBench.bench_tsS_nbr_trs_1 thrpt 25 9425.149 ± 212.728 ops/s +[success] Total time: 42760 s, completed Jan 6, 2016 11:28:41 AM +> diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 7563a88..4e206ce 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -9,12 +9,13 @@ object Generator { val annotated = "arr ish! lst* ils*! que* stm* trs*! vec arb ars ast* mhs! lhs*! prq*! muq* wra jix jln".split(' ') // Parallel version if any appears after / + // Trailing % means that operation creates new collections and thus can't be used with Stepper (sequential ops only) // Trailing ! means that collection must maintain original order (i.e. don't use if collection is marked !) - val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc!"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc!")) + val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc%/pfmc mdtc!%"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc%/pfmc mdtc!%")) def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { - case Array(x) => (x.takeWhile(_.isLetter), None, x contains "!") - case Array(x,y) => (x.takeWhile(_.isLetter), Some(y.takeWhile(_.isLetter)), (x+y) contains "!") + case Array(x) => (x.takeWhile(_.isLetter), None, x contains "!", x contains "%") + case Array(x,y) => (x.takeWhile(_.isLetter), Some(y.takeWhile(_.isLetter)), (x+y) contains "!", x contains "%") }) val names = annotated.map(_.takeWhile(_.isLetter)) @@ -60,23 +61,29 @@ object Generator { names.foreach{ n => pr( s" { // Scope for operations $o collection $n") pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) - parsefs(fs).foreach{ case (f, pf, ord) => + parsefs(fs).foreach{ case (f, pf, ord, nu) => if (ordname(n) || !ord) { pr( """ for (i <- 0 until m) {""") pr( s" val z = $o.$f(x.arr.c$t(i))") if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)") pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + if (pf.isDefined) + pr( s" check(z, $o.${pf.get}(x.$n.c$t(i).par), ${q}i$t ${pf.get} $n ${q}+i.toString)") } - if (sqnname(n)) { + if (sqnname(n) || parname(n)) { pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") - if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + if (nojname(n) && !nu) { + if (sqnname(n)) + pr( s" check(z, $o.$f(x.$n.ts$t(i)), ${q}ts$t $f $n ${q}+i.toString)") + else + pr( s" check(z, $o.$f(x.$n.tp$t(i)), ${q}tp$t $f $n ${q}+i.toString)") + } } if (parname(n) && pf.isDefined) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") - if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.${pf.get}(x.$n.sp$t(i)), ${q}sp$t ${pf.get} $n ${q}+i.toString)") + if (nojname(n) && !nu) + pr( s" check(z, $o.${pf.get}(x.$n.zp$t(i)), ${q}zp$t ${pf.get} $n ${q}+i.toString)") } pr( s" }") } @@ -136,11 +143,17 @@ object Generator { names.foreach{ n => pr( s" { // Scope for operations $o collection $n") pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) - parsefs(fs).foreach{ case (f, pf, ord) => + parsefs(fs).foreach{ case (f, pf, ord, nu) => if (ordname(n) || !ord) { if (nojname(n)) { pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n${q})"); pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n${q})") + if (!nu) { + if (sqnname(n)) + pr( s" timings(x, i => $o.$f(x.$n.ts$t(i)), ${q}ts$t $f $n${q})"); + else + pr( s" timings(x, i => $o.$f(x.$n.tp$t(i)), ${q}tp$t $f $n${q})"); + } } if (sqnname(n)) { pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n${q})") @@ -184,20 +197,26 @@ object Generator { val m = sizes.map(_.length).getOrElse(new bench.generate.Things().N) allops.foreach{ case (o, t, fs) => names.foreach{ n => - parsefs(fs).foreach{ case (f, pf, ord) => + parsefs(fs).foreach{ case (f, pf, ord, nu) => for (i <- 0 until m) { if (ordname(n) || !ord) { if (nojname(n)) { - pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))"); + pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))") pr( s" @Benchmark def bench_i${t}_${f}_${n}_$i() = $o.$f(x.$n.i$t($i))") + if (!nu) { + if (sqnname(n)) + pr( s" @Benchmark def bench_ts${t}_${f}_${n}_$i() = $o.$f(x.$n.ts$t($i))") + else + pr( s" @Benchmark def bench_tp${t}_${f}_${n}_$i() = $o.$f(x.$n.tp$t($i))") + } } - if (sqnname(n)) { - pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))") - //if (nojname(n)) - // pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))") - } + pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))") + //if (nojname(n)) + // pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))") if (parname(n) && pf.isDefined) { - pr( s" @Benchmark def bench_sp${t}_${f}_${n}_$i() = $o.$f(x.$n.sp$t($i))") + if (nojname(n)) + pr( s" @Benchmark def bench_cp${t}_${pf.get}_${n}_$i() = $o.${pf.get}(x.$n.c$t($i).par)") + pr( s" @Benchmark def bench_sp${t}_${pf.get}_${n}_$i() = $o.${pf.get}(x.$n.sp$t($i))") //if (nojname(n)) // pr( s" @Benchmark def bench_zp${t}_${f}_${n}_$i() = $o.$f(x.$n.zp$t($i))") } diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala index 38c3f4c..6208ac4 100644 --- a/benchmark/src/main/scala/bench/Operations.scala +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -2,6 +2,9 @@ package bench.operate import java.util.stream._ import java.util.{function => jf} + +import scala.collection.parallel.ParIterable + import scala.compat.java8.StreamConverters._ import scala.compat.java8.converterImpl._ import scala.compat.java8.collectionImpl._ @@ -25,16 +28,16 @@ object OnInt { def sum(i: Iterator[Int]): Int = i.sum def sum(s: IntStepper): Int = s.fold(0)(_ + _) def sum(s: IntStream): Int = s.sum - def psum(i: Iterable[Int]): Int = i.par.sum - def psum(s: IntStream): Int = s.parallel.sum + def psum(i: ParIterable[Int]): Int = i.sum + def psum(s: IntStream): Int = s.sum def trig(a: Array[Int]): Double = { var i = 0; var s = 0.0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } def trig(t: Traversable[Int]): Double = t.map(expensive).sum def trig(i: Iterator[Int]): Double = i.map(expensive).sum def trig(s: IntStepper): Double = s.fold(0.0)((x,i) => x + expensive(i)) def trig(s: IntStream): Double = s.mapToDouble(new jf.IntToDoubleFunction{ def applyAsDouble(i: Int) = expensive(i) }).sum - def ptrig(i: Iterable[Int]): Double = i.par.map(expensive).sum - def ptrig(s: IntStream): Double = trig(s.parallel) + def ptrig(i: ParIterable[Int]): Double = i.map(expensive).sum + def ptrig(s: IntStream): Double = trig(s) def fmc(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { if (i%7 == 1) s += (i/7)*i; i += 1 }; s } def fmc(t: Traversable[Int]): Int = t.filter(x => (x%7) == 1).map(x => (x/7)*x).sum @@ -43,8 +46,8 @@ object OnInt { filter(new jf.IntPredicate { def test(x: Int) = (x%7) == 1 }). map(new jf.IntUnaryOperator{ def applyAsInt(x: Int) = (x/7)*x }). sum - def pfmc(i: Iterable[Int]): Int = i.par.filter(x => (x%7) == 1).map(x => (x/7)*x).sum - def pfmc(s: IntStream): Int = fmc(s.parallel) + def pfmc(i: ParIterable[Int]): Int = i.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def pfmc(s: IntStream): Int = fmc(s) def mdtc(a: Array[Int]): Int = { var i = 1; while(i < a.length) { if ((a(i) << 1) >= 42) return i-1; i += 1 }; i - 1 } def mdtc(t: Traversable[Int]): Int = t.map(_ << 1).drop(1).takeWhile(_ < 42).size @@ -65,16 +68,16 @@ object OnString { def nbr(i: Iterator[String]): Int = i.count(s => s.charAt(s.length-1) < '5') def nbr(p: Stepper[String]): Int = p.fold(0)((i,s) => if (s.charAt(s.length-1) < '5') i+1 else i) def nbr(q: Stream[String]): Int = q.filter(new jf.Predicate[String] { def test(s: String) = s.charAt(s.length-1) < '5' }).count.toInt - def pnbr(i: Iterable[String]): Int = i.par.count(s => s.charAt(s.length-1) < '5') - def pnbr(q: Stream[String]): Int = nbr(q.parallel) + def pnbr(i: ParIterable[String]): Int = i.count(s => s.charAt(s.length-1) < '5') + def pnbr(q: Stream[String]): Int = nbr(q) def htrg(a: Array[String]): Double = { var s = 0.0; var i = 0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } def htrg(t: Traversable[String]): Double = t.map(expensive).sum def htrg(i: Iterator[String]): Double = i.map(expensive).sum def htrg(p: Stepper[String]): Double = p.fold(0.0)((x,s) => x + expensive(s)) def htrg(q: Stream[String]): Double = q.mapToDouble(new jf.ToDoubleFunction[String]{ def applyAsDouble(s: String) = expensive(s) }).sum - def phtrg(i: Iterable[String]): Double = i.par.map(expensive).sum - def phtrg(q: Stream[String]): Double = htrg(q.parallel) + def phtrg(i: ParIterable[String]): Double = i.map(expensive).sum + def phtrg(q: Stream[String]): Double = htrg(q) def fmc(a: Array[String]): Int = { var s, i = 0 @@ -94,9 +97,9 @@ object OnString { map[String](new jf.Function[String, String]{ def apply(x: String) = if (x.charAt(0) == '-') x.substring(1) else x }). filter(new jf.Predicate[String]{ def test(x: String) = x.length > 1 }). count.toInt - def pfmc(i: Iterable[String]): Int = - i.par.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) - def pfmc(q: Stream[String]): Int = fmc(q.parallel) + def pfmc(i: ParIterable[String]): Int = + i.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def pfmc(q: Stream[String]): Int = fmc(q) def mdtc(a: Array[String]): Int = { var i = 1 diff --git a/benchmark/src/main/scala/bench/ParseJmhLog.scala b/benchmark/src/main/scala/bench/ParseJmhLog.scala new file mode 100644 index 0000000..df45ee9 --- /dev/null +++ b/benchmark/src/main/scala/bench/ParseJmhLog.scala @@ -0,0 +1,146 @@ +package bench.examine + +import scala.util._ +import scala.util.control.NonFatal + +object ParseJmhLog { + // Manual path to the log file (which may have been put there manually) + val logLocation = "results/jmhbench.log" + + // Warning--this is maintained manually! Please take care to keep it up to date. + val collectionNames = Map( + "arb" -> "collection.mutable.ArrayBuffer", + "arr" -> "Array", + "ars" -> "collection.mutable.ArraySeq", + "ast" -> "collection.mutable.ArrayStack", + "ils" -> "collection.immutable.ListSet", + "ish" -> "collection.immutable.HashSet", + "lhs" -> "collection.mutable.LinkedHashSet", + "lst" -> "collection.immutable.List", + "mhs" -> "collection.mutable.HashSet", + "muq" -> "collection.mutable.Queue", + "prq" -> "collection.mutable.PriorityQueue", + "que" -> "collection.immutable.Queue", + "stm" -> "collection.immutable.Stream", + "trs" -> "collection.immutable.TreeSet", + "vec" -> "collection.immutable.Vector", + "wra" -> "collection.mutable.WrappedArray", + "jix" -> "java.util.ArrayList", + "jln" -> "java.util.LinkedList" + ) + + // Warning--this is maintained manually! Please take care to keep it up to date. + val dataNames = Map( + "cI" -> "Int, base collection", + "cpI" -> "Int, par collection", + "iI" -> "Int, iterator on coll", + "ssI" -> "Int, serial stream", + "spI" -> "Int, parallel stream", + "tpI" -> "Int Stepper (can par)", + "tsI" -> "Int Stepper (seq only)", + "cS" -> "String, base collection", + "cpS" -> "String, par collection", + "iS" -> "String, iterator on coll", + "ssS" -> "String, serial stream", + "spS" -> "String, parallel stream", + "tpS" -> "String Stepper (can par)", + "tsS" -> "String Stepper (seq only)" + ) + val dataColumnWidth = dataNames.map(_._2).map(_.length).max + 1 + + // Warning--this is maintained manually! Please take care to keep it up to date. + val operationNames = Map( + "sum" -> "fast summation", + "psum" -> "fast parallel summation", + "nbr" -> "fast sum of lengths", + "pnbr" -> "fast parallel sum of lengths", + "trig" -> "slow trigonometry", + "ptrig" -> "slow parallel trigonometry", + "htrg" -> "slow trig on hashCode", + "phtrg" -> "slow parallel trig on hashCode", + "fmc" -> "filter/map/sum trio", + "pfmc" -> "parallel filter/map/sum trio", + "mdtc" -> "map/filter/take trio" + ) + + private def ensure(satisfied: Boolean)(not: => Unit) { + if (!satisfied) { + not + assert(satisfied) + } + } + + private def indicate(cols: Int, value: Double): String = { + val one = math.min((3*cols)/4, cols-5) + val me = math.rint(one*3*value).toInt + if (me <= 3*(cols-1)) { + val filled = + if ((me%3) != 0) "#"*(me/3) + (if ((me%3) == 1) "-" else "=") + else "#"*(me/3) + filled + " "*(cols - filled.length) + } + else "#"*(cols-4) + "~~# " + } + + case class Entry(op: String, coll: String, big: Boolean, data: String, speed: Double, errbar: Double) { + ensure(collectionNames contains coll){ println(coll) } + ensure(dataNames contains data){ println(data) } + ensure(operationNames contains op){ println(op) } + } + + def apply(f: java.io.File = new java.io.File(logLocation)) = { + val lines = { + val s = scala.io.Source.fromFile(f) + try { s.getLines().toVector } finally { s.close } + } + + val relevant = lines. + dropWhile(x => !(x contains "Run complete.")). + dropWhile(x => !(x contains "JmhBench.bench_")). + takeWhile(x => x contains "JmhBench.bench_"). + map{ x => + val ys = x.split("\\s+") + ys(1).split('_').drop(1) match { + case Array(dat, op, coll, n) => Entry (op, coll, n == "1", dat, ys(4).toDouble, ys(6).toDouble) + case _ => throw new Exception("Bad benchmark log line, please investigate manually.") + } + }. + toArray + + val normalized = relevant. + groupBy(e => (e.op, e.big, e.data.takeRight(1))). + mapValues{ vs => + val one = vs.find(e => e.coll == "arr" && e.data.startsWith("c")).get.speed + vs.map(v => v.copy(speed = v.speed/one, errbar = 100 * v.errbar/v.speed)) // Error bar in percent error from mean + }. + map(_._2). + toArray. + sortBy(_(0) match { case Entry(o, _, b, d, _, _) => (o, d.takeRight(1), b) }). + map(_.sortBy{ case Entry(_, c, _, d, _, _) => (c, d.dropRight(1)) }) + + normalized.foreach{ es => + println + println(">"*79) + println + var remaining = es.toList + while (remaining.nonEmpty) { + val (esa, esb) = remaining.span(_.coll == remaining.head.coll) + remaining = esb + println(operationNames(esa.head.op)) + println(if (esa.head.big) "10000 elements" else "10 elements") + println(collectionNames(esa.head.coll)) + esa.foreach{ e => + println( + s" %-${dataColumnWidth}s ".format(dataNames(e.data)) + + indicate(79 - (dataColumnWidth+3) - 16, e.speed) + + "%5.3f +- %5.1f %%".format(e.speed, e.errbar) + ) + } + if (remaining.nonEmpty) println + } + } + println + println("-"*79) + println + } +} diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index ed7607d..698bc23 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -11,7 +11,7 @@ trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends } /** Classes or objects implementing this trait create streams suitable for parallel use */ -trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { +trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any with MakesSequentialStream[A, SS] { def parStream: SS } From af5de577b0f56cf7a93a56eb105b55c5142bf2a5 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 8 Jan 2016 13:08:35 -0800 Subject: [PATCH 55/56] Example of Scala collection to Java 8 Stream from within Java. Also added a unit test to make sure the example compiles. --- .../java8/StreamConvertersExampleTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/java/scala/compat/java8/StreamConvertersExampleTest.java diff --git a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java new file mode 100644 index 0000000..e34a4d1 --- /dev/null +++ b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 Typesafe Inc. + */ + +import org.junit.Test; + +import scala.collection.mutable.ArrayBuffer; +import scala.compat.java8.ScalaStreaming; + + +public class StreamConvertersExampleTest { + @Test + public void MakeAndUseArrayBuffer() { + ArrayBuffer ab = new ArrayBuffer(); + ab.$plus$eq("salmon"); + ab.$plus$eq("herring"); + assert( ScalaStreaming.from(ab).mapToInt(x -> x.length()).sum() == 13 ); + } +} + From d3606b7896cb6383ec0057e05fcd647beaa94570 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 17 Feb 2016 17:57:21 -0800 Subject: [PATCH 56/56] Describe how to get a Stream from Scala colls in Java. Also fixed the Scala example to actually run. --- README.md | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6f7b472..54fe1b1 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ obtain Java 8 Streams from Scala collections from within Java. For sequential operations, Scala's `iterator` almost always equals or exceeds the performance of a Java 8 stream. Thus, one should favor `iterator` (and its richer set of operations) over `seqStream` for general use. However, long -chains of processing of primitive types can sometimes benefit from the manually specialized methods in `DoubleStream`, +chains of processing of primitive types can sometimes benefit from the manually specialized methods in `DoubleStream`, `IntStream`, and `LongStream`. Note that although `iterator` typically has superior performance in a sequential context, the advantage is modest @@ -173,13 +173,14 @@ object Test { val m = collection.immutable.HashMap("fish" -> 2, "bird" -> 4) val s = m.parValueStream.sum // 6, potientially computed in parallel val t = m.seqKeyStream.toScala[List] // List("fish", "bird") - val a = t.accumulate // Accumulator[(String, Int)] + val a = m.accumulate // Accumulator[(String, Int)] - val n = a.splitter.fold(0)(_ + _._1.length) + + val n = a.stepper.fold(0)(_ + _._1.length) + a.parStream.count // 8 + 2 = 10 val b = java.util.Arrays.stream(Array(2L, 3L, 4L)). accumulate // LongAccumulator + val l = b.to[List] // List(2L, 3L, 4L) } ``` @@ -216,6 +217,34 @@ def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = #### Java Usage Example +To convert a Scala collection to a Java 8 Stream from within Java, it usually +suffices to call `ScalaStreaming.from(xs)` on your collection `xs`. If `xs` is +a map, you may wish to get the keys or values alone by using `fromKeys` or +`fromValues`. If the collection has an underlying representation that is not +efficiently parallelized (e.g. `scala.collection.immutable.List`), then +`fromAccumulated` (and `fromAccumulatedKeys` and `fromAccumulatedValues`) will +first gather the collection into an `Accumulator` and then return a stream over +that accumulator. If not running in parallel, `from` is preferable (faster and +less memory usage). + +Note that a Scala `Iterator` cannot fulfill the contract of a Java 8 Stream +(because it cannot support `trySplit` if it is called). Presently, one must +call `fromAccumulated` on the `Iterator` to cache it, even if the Stream will +be evaluated sequentially, or wrap it as a Java Iterator and use static +methods in `Spliterator` to wrap that as a `Spliterator` and then a `Stream`. + +Here is an example of conversion of a Scala collection within Java 8: + ```java -// TODO -- write converter and create example +import scala.collection.mutable.ArrayBuffer; +import scala.compat.java8.ScalaStreaming; + +public class StreamConvertersExample { + public int MakeAndUseArrayBuffer() { + ArrayBuffer ab = new ArrayBuffer(); + ab.$plus$eq("salmon"); + ab.$plus$eq("herring"); + return ScalaStreaming.from(ab).mapToInt(x -> x.length()).sum(); // 6+7 = 13 + } +} ```