package javastream; import java.time.Duration; import java.util.AbstractMap; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map.Entry; import java.util.Objects; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.IntStream; import javastream.Main.Config; public abstract class JavaStream { public static final class Data { final T[] a, b, c; public Data(T[] a, T[] b, T[] c) { this.a = Objects.requireNonNull(a); this.b = Objects.requireNonNull(b); this.c = Objects.requireNonNull(c); } } static final class Timings { final List copy = new ArrayList<>(); final List mul = new ArrayList<>(); final List add = new ArrayList<>(); final List triad = new ArrayList<>(); final List dot = new ArrayList<>(); } protected final Config config; protected JavaStream(Config config) { this.config = config; } protected abstract List listDevices(); protected abstract void initArrays(); protected abstract void copy(); protected abstract void mul(); protected abstract void add(); protected abstract void triad(); protected abstract void nstream(); protected abstract T dot(); protected abstract Data data(); public static class EnumeratedStream extends JavaStream { protected final JavaStream actual; private final Entry, JavaStream>>[] options; @SafeVarargs @SuppressWarnings("varargs") public EnumeratedStream( Config config, Entry, JavaStream>>... options) { super(config); this.actual = options[config.options.device].getValue().apply(config); this.options = options; } @Override protected List listDevices() { return Arrays.stream(options).map(Entry::getKey).collect(Collectors.toList()); } @Override public void initArrays() { actual.initArrays(); } @Override public void copy() { actual.copy(); } @Override public void mul() { actual.mul(); } @Override public void add() { actual.add(); } @Override public void triad() { actual.triad(); } @Override public void nstream() { actual.nstream(); } @Override public T dot() { return actual.dot(); } @Override public Data data() { return actual.data(); } } public static Double[] boxed(double[] xs) { return Arrays.stream(xs).boxed().toArray(Double[]::new); } public static Float[] boxed(float[] xs) { return IntStream.range(0, xs.length).mapToObj(i -> xs[i]).toArray(Float[]::new); } private static AbstractMap.SimpleImmutableEntry timed(Supplier f) { long start = System.nanoTime(); T r = f.get(); long end = System.nanoTime(); return new AbstractMap.SimpleImmutableEntry<>(Duration.ofNanos(end - start), r); } private static Duration timed(Runnable f) { long start = System.nanoTime(); f.run(); long end = System.nanoTime(); return Duration.ofNanos(end - start); } final SimpleImmutableEntry, T> runAll(int times) { Timings timings = new Timings<>(); T lastSum = null; for (int i = 0; i < times; i++) { timings.copy.add(timed(this::copy)); timings.mul.add(timed(this::mul)); timings.add.add(timed(this::add)); timings.triad.add(timed(this::triad)); SimpleImmutableEntry dot = timed(this::dot); timings.dot.add(dot.getKey()); lastSum = dot.getValue(); } return new SimpleImmutableEntry<>(timings, lastSum); } final Duration runTriad(int times) { return timed( () -> { for (int i = 0; i < times; i++) { triad(); } }); } final List runNStream(int times) { return IntStream.range(0, times) .mapToObj(i -> timed(this::nstream)) .collect(Collectors.toList()); } }