diff --git a/README.md b/README.md index b3f11ba..54fe1b1 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,134 @@ 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. + +#### 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 +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 = m.accumulate // Accumulator[(String, Int)] + + 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) +} +``` + +#### 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 + +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 +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 + } +} +``` 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/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..c5220d0 --- /dev/null +++ b/benchmark/project/plugins.sbt @@ -0,0 +1 @@ +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 new file mode 100644 index 0000000..4e206ce --- /dev/null +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -0,0 +1,234 @@ +package bench.codegen + +import scala.util._ +import control.NonFatal + +object Generator { + // 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 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!%")) + + def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { + 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)) + val nojname = names.filterNot(_ startsWith "j").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 + 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 { + 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 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) {""") + 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" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) + 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.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) || parname(n)) { + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$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.${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" }") + } + } + pr( s" x = null // Allow GC" ) + pr( s" } // End scope for operations $o collection $n") + } + } + 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]] = 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( """import ichi.bench.Thyme""") + pr( """""") + 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 += ((""") + pr( """ b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6""") + pr( """ ))""") + pr( """ }""") + pr( """ val sb = new StringBuilder""") + pr( """ sb ++= name + ":" """) + pr( """ if (sb.length < 16) sb ++= " " * (16 - sb.length)""") + pr( """ ts.foreach{ case (c, lo, 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" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) + 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})") + if (nojname(n)) + 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})") + if (nojname(n)) + pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n${q})") + } + } + } + pr( s" x = null // Allow GC" ) + 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 _ => + } + } + + 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, 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_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))") + } + } + 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) { + 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))") + } + } + } + } + } + } + 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 new file mode 100644 index 0000000..689aa42 --- /dev/null +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -0,0 +1,285 @@ +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 + } + + 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 + } + + // 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 + } + } + + 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") {} + + 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 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/*, 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) + 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) + lazy val jix = new JixThings(sizes) + lazy val jln = new JlnThings(sizes) + } +} diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala new file mode 100644 index 0000000..6208ac4 --- /dev/null +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -0,0 +1,120 @@ +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._ + +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: 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: 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 + 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: 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 + 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: 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: 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 + 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: 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 + 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 + } +} 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/java/scala/compat/java8/ScalaStreaming.java b/src/main/java/scala/compat/java8/ScalaStreaming.java new file mode 100644 index 0000000..9367361 --- /dev/null +++ b/src/main/java/scala/compat/java8/ScalaStreaming.java @@ -0,0 +1,905 @@ +package scala.compat.java8; + +import scala.compat.java8.converterImpl.*; +import scala.compat.java8.collectionImpl.*; +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.converterImpl.RichBitSetCanStep rbscs = + new scala.compat.java8.converterImpl.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.converterImpl.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/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java new file mode 100644 index 0000000..ba6f6a6 --- /dev/null +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -0,0 +1,23 @@ +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(); } + 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(); } + 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/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala new file mode 100644 index 0000000..1babaf3 --- /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: AnyStepper[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: DoubleStepper = Stepper.ofSpliterator(underlying) + } + implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { + def stepper: IntStepper = Stepper.ofSpliterator(underlying) + } + implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { + def stepper: LongStepper = Stepper.ofSpliterator(underlying) + } +} 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..3999761 --- /dev/null +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -0,0 +1,339 @@ +package scala.compat.java8 + +import language.implicitConversions + +import java.util.stream._ +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.converterImpl._ + +trait PrimitiveStreamAccumulator[S, AA] { + def streamAccumulate(stream: S): AA +} + +trait PrimitiveStreamUnboxer[A, S] { + def apply(boxed: Stream[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]) + 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]) { + 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 Priority4StreamConverters extends Priority5StreamConverters { + 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) + 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) + 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) { + 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 Priority3StreamConverters extends Priority4StreamConverters { + 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) + } + 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 Priority2StreamConverters extends Priority3StreamConverters { + 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) + } + 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 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 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) + } + 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) + 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) + } + 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 Priority1StreamConverters extends Priority2StreamConverters { + 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`. + * 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 + * 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. 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. + * + * 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] + * 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] + * + * val x = List(1L, 2L, 3L, 4L).stepper.parStream.sum // 10, potentially computed in parallel + * }}} + */ +object StreamConverters +extends Priority1StreamConverters +with converterImpl.Priority1StepConverters +with converterImpl.Priority1AccumulatorConverters +{ + 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]) + 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]) + 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 + } + + 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() + } + } + } + + 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/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala new file mode 100644 index 0000000..e67ca79 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -0,0 +1,344 @@ +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 } } + + /** 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] { + 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..b99ba7d --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -0,0 +1,339 @@ +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 } } + + /** 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 { + 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..253119e --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -0,0 +1,346 @@ +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 } } + + /** 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 { + 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..270d400 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -0,0 +1,340 @@ +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 } } + + /** 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 { + 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/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala new file mode 100644 index 0000000..73c9740 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -0,0 +1,545 @@ +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 `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`. + * + * 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. + * + * 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] 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.converterImpl.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 + * 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 => + /** 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 + + /** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */ + def anticipateParallelism: this.type = this + + + //// + // 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, though if `knownSize` is non-negative, it won't actually + * iterate over the elements. + */ + 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. + */ + 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 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. + */ + def foreach(f: A => Unit) { while (hasStep) f(nextStep) } + + /** 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 + } + + /** 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() + } +} + + +/** 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 + 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`. + * 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 + protected def myCache_=(a: A): Unit + protected final var myCacheIsFull = false + private def load(): Boolean = { + myCacheIsFull = tryStep(myCache = _) + myCacheIsFull + } + final def hasStep = myCacheIsFull || load() + final def nextStep = { + if (!myCacheIsFull) { + load() + if (!myCacheIsFull) Stepper.throwNSEE + } + val ans = myCache + myCacheIsFull = false + 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) } + 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] { + 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`. */ +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 + 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 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) + 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. */ +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() + 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 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) + 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. */ +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() + 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 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) + 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. */ +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() + 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 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) + def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, true) +} + + +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[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] { + 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) throwNSEE + val ans = cache + cache = null.asInstanceOf[A] + cached = false + ans + } + def substep(): AnyStepper[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) + } + + 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 } + + 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) throwNSEE + val ans = cache + cached = false + ans + } + def substep(): DoubleStepper = { + 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) + } + + 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 } + + 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) throwNSEE + val ans = cache + cached = false + ans + } + def substep(): IntStepper = { + 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) + } + + 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 } + + 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) throwNSEE + val ans = cache + cached = false + ans + } + def substep(): LongStepper = { + 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) + } + + /** Creates a `Stepper` over a generic `Spliterator`. */ + 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 = sp match { + case ds: DoubleStepper => ds + case _ => new OfDoubleSpliterator(sp) + } + + /** Creates a `Stepper` over an `IntSpliterator`. */ + 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 = sp match { + case ls: LongStepper => ls + case _ => new OfLongSpliterator(sp) + } + +} diff --git a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala new file mode 100644 index 0000000..2affeb9 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala @@ -0,0 +1,78 @@ +package scala.compat.java8.converterImpl + +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] + 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/converterImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala new file mode 100644 index 0000000..8a43fd6 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -0,0 +1,35 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ + +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 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/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala new file mode 100644 index 0000000..698bc23 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -0,0 +1,160 @@ +package scala.compat.java8.converterImpl + +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 with MakesSequentialStream[A, SS] { + 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 */ + 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/converterImpl/StepConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala new file mode 100644 index 0000000..1269f94 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala @@ -0,0 +1,131 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +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) + + 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) +} + diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala new file mode 100644 index 0000000..e19e7ec --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -0,0 +1,126 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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 + 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) +} + +////////////////////////// +// 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/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala new file mode 100644 index 0000000..b4ab4ea --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -0,0 +1,70 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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) + 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 +} + +///////////////////////// +// 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/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala new file mode 100644 index 0000000..5b8a55a --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -0,0 +1,68 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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 } + 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) +} + +////////////////////////// +// 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/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala new file mode 100644 index 0000000..d1d611b --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -0,0 +1,259 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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) { + 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) +} + + +////////////////////////// +// 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/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala new file mode 100644 index 0000000..5cd58cb --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -0,0 +1,158 @@ +package scala.compat.java8.converterImpl + +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 + +///////////////////////////// +// 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) { + 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 +} + +////////////////////////// +// 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/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala new file mode 100644 index 0000000..2fdfce6 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -0,0 +1,56 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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) + 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 } +} + +////////////////////////// +// 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/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala new file mode 100644 index 0000000..6209121 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -0,0 +1,56 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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 + 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) +} + +////////////////////////// +// 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/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala new file mode 100644 index 0000000..8e1e494 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala @@ -0,0 +1,27 @@ +package scala.compat.java8.converterImpl + +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/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala new file mode 100644 index 0000000..a87f28d --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala @@ -0,0 +1,57 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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) + 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 +} + +////////////////////////// +// 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/converterImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala new file mode 100644 index 0000000..0bb741b --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala @@ -0,0 +1,71 @@ +package scala.compat.java8.converterImpl + +import annotation.tailrec + +import scala.compat.java8.collectionImpl._ +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`.) + */ +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 + 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. + */ +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 +{} + +/** 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`. + */ +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 +{} + +/** 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`. + */ +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 +{} + +/** 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`. + */ +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/converterImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala new file mode 100644 index 0000000..6f4d0c9 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala @@ -0,0 +1,55 @@ +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. + */ +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 + 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 + } +} + +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] +{} + +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] +{} + +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] +{} + +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/converterImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala new file mode 100644 index 0000000..175cf0d --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -0,0 +1,51 @@ +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 */ +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 + def hasNext(): Boolean = i0 < iN + def substep(): Sub = { + 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 */ +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 */ +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 */ +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 */ +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/converterImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala new file mode 100644 index 0000000..116e921 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala @@ -0,0 +1,108 @@ +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. */ +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! + 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) */ +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] +{ + 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) */ +private[java8] 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) */ +private[java8] 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) */ +private[java8] 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/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala new file mode 100644 index 0000000..4ec9b74 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -0,0 +1,46 @@ +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. + */ +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 + 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 */ +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 */ +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 */ +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 */ +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/converterImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala new file mode 100644 index 0000000..6565dd8 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala @@ -0,0 +1,49 @@ +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. + */ +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 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") } + val ans = demiclone(pre, pn) + i += pn + underlying = post + i0 = i + ans + case _ => null + } +} + +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] +{} + +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] +{} + +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] +{} + +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/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala new file mode 100644 index 0000000..d310560 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -0,0 +1,64 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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 + 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) +} + +////////////////////////// +// 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/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala new file mode 100644 index 0000000..e5c072b --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.converterImpl + +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/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala new file mode 100644 index 0000000..bde77dc --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -0,0 +1,56 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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 + 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) +} + +////////////////////////// +// 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/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala new file mode 100644 index 0000000..a281068 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -0,0 +1,44 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +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 + 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 + } +} + +///////////////////////// +// 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/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala new file mode 100644 index 0000000..e3188f0 --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -0,0 +1,151 @@ +package scala.compat.java8.converterImpl + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +///////////////////////////// +// Stepper implementations // +///////////////////////////// + +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 + } +} + +////////////////////////// +// 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) +} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala new file mode 100644 index 0000000..0fcc12b --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala @@ -0,0 +1,87 @@ +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. + * 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! + */ +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 + 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 */ +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 */ +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 */ +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 */ +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/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 ); + } +} + 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..2f09927 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -0,0 +1,572 @@ +package scala.compat.java8 + +import org.junit.Test +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 } + + def isAcc[X](x: X): Boolean = x match { + case _: AccumulatorStepper[_] => true + case _: DoubleAccumulatorStepper => true + case _: IntAccumulatorStepper => true + case _: LongAccumulatorStepper => true + 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) } + } + + 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[_]]) + assert(correctSpec(x)) + assert(isAcc(x)) + } + + def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + assert(!isAcc(x)) + 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)) + assert(!isAcc(x)) + assert(!isLin(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 + Okay( co.Iterator[String]("salmon").buffered.stepper ) + good( co.IndexedSeq[String]("salmon").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 ) + Okay( co.Map[String, String]("fish" -> "salmon").stepper ) + Okay( co.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.Map[String, String]("fish" -> "salmon").valueStepper ) + 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 ) + 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 + 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 ) + good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) + good( ci.HashSet[String]("salmon").stepper ) + good( ci.IndexedSeq[String]("salmon").stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) + Okay( ci.Iterable[String]("salmon").stepper ) + Okay( ci.LinearSeq[String]("salmon").stepper ) + Okay( ci.List[String]("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 ) + Okay( ci.ListSet[String]("salmon").stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) + 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 ) + 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 ) + 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").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 ) + Okay( ci.TreeSet[String]("salmon").stepper ) + good( ci.Vector[String]("salmon").stepper ) + + // Mutable section + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + Okay( cm.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) + 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 ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.PriorityQueue[String]("salmon").stepper ) + Okay( cm.Queue[String]("salmon").stepper ) + good( cm.ResizableArray[String]("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 ) + + // Java 6 converters section + + // Concurrent section + Okay( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) + 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 ) + } + + @Test + def comprehensivelyDouble() { + implicit val spec = SpecCheck(_.isInstanceOf[DoubleStepper]) + //Double-specific tests + + // Collection section + Okay( co.Iterator[Double](3.14159).buffered.stepper ) + good( co.IndexedSeq[Double](3.14159).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 ) + 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 ) + 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 + 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 ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( ci.HashSet[Double](3.14159).stepper ) + good( ci.IndexedSeq[Double](3.14159).stepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) + 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 ) + 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 ) + 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 ) + 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).accumulate.stepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.TreeSet[Double](3.14159).stepper ) + good( ci.Vector[Double](3.14159).stepper ) + + // Mutable section + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + Okay( cm.PriorityQueue[Double](3.14159).stepper ) + Okay( cm.Queue[Double](3.14159).stepper ) + good( cm.ResizableArray[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 ) + + // Java 6 converters section + + // Concurrent section + 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 + def comprehensivelyInt() { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) + + // Int-specific tests + good( co.BitSet(42).stepper ) + good( ci.BitSet(42).stepper ) + good( ci.NumericRange(123456, 123458, 1).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 ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) + + // Collection section + Okay( co.Iterator[Int](654321).buffered.stepper ) + good( co.IndexedSeq[Int](654321).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 ) + 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 ) + 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 + 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 ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + 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 ) + 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 ) + 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 ) + 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 ) + 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).accumulate.stepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.TreeSet[Int](654321).stepper ) + good( ci.Vector[Int](654321).stepper ) + + // Mutable section + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + Okay( cm.PriorityQueue[Int](654321).stepper ) + Okay( cm.Queue[Int](654321).stepper ) + good( cm.ResizableArray[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 ) + + // Java 6 converters section + + // Concurrent section + 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 + def comprehensivelyLong() { + implicit val spec = SpecCheck(_.isInstanceOf[LongStepper]) + + // Long-specific tests + good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + 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 + Okay( co.Iterator[Long](0x123456789L).buffered.stepper ) + good( co.IndexedSeq[Long](0x123456789L).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 ) + 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 ) + 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 + 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 ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( ci.HashSet[Long](0x123456789L).stepper ) + good( ci.IndexedSeq[Long](0x123456789L).stepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) + 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 ) + 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 ) + 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 ) + 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).accumulate.stepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.TreeSet[Long](0x123456789L).stepper ) + good( ci.Vector[Long](0x123456789L).stepper ) + + // Mutable section + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + 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 ) + Okay( cm.PriorityQueue[Long](0x123456789L).stepper ) + Okay( cm.Queue[Long](0x123456789L).stepper ) + good( cm.ResizableArray[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 ) + + // Java 6 converters section + + // Concurrent section + 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 + def comprehensivelySpecific() { + implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + + good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) + _eh_( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) + good( ("salmon": ci.StringOps).stepper ) + good( ("salmon": ci.WrappedString).stepper ) + } +} 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..18cbc10 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -0,0 +1,316 @@ +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 = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + def knownSize = math.max(0L, size0 - i) + def hasStep = i < size0 + def nextStep() = { i += 1; (i - 1).toInt } + def substep() = if (knownSize <= 1) null else { + val sub = new IncStepperA(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + def typedPrecisely = this +} + +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 = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + 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 <= 1) null else { + val sub = new IncStepperB(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + def typedPrecisely = this +} + +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) + 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() + 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: 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() { + 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) + 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) } + 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 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) } + } + + @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) + } + } +} + 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..b1ad2f5 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -0,0 +1,237 @@ +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]) + } + + 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 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) { + val arrO = arrayO(n) + 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]) + 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]) + 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)) + + val arrD = arrayD(n) + 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.stepper.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]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + 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]) + assert(hsD.parStream.isInstanceOf[DoubleStream]) + + val arrI = arrayI(n) + 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.stepper.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]) + assertEq(seqI, wrI.seqStream.toScala[Seq]) + 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]) + assert(hsI.parStream.isInstanceOf[IntStream]) + + val arrL = arrayL(n) + 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.stepper.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]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + 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]) + assert(hsL.parStream.isInstanceOf[LongStream]) + } + } +}