// Path: src/main/java/streams/algebras/ExecTakeStreamAlg.java
// public interface ExecTakeStreamAlg<E, C> extends TakeStreamAlg<C>, ExecStreamAlg<E, C> {
// }
// 
// Path: src/main/java/streams/higher/Id.java
// public class Id<T> implements App<Id.t, T> {
// 
//     public final T value;
// 
//     public Id(T value) {
//         this.value = value;
//     }
// 
//     public static <A> Id<A> prj(App<Id.t, A> app) {
//         return (Id<A>) app;
//     }
// 
//     public static <A> App<Id.t, A> inj(Id<A> app) {
//         return (App<Id.t, A>) app;
//     }
// 
//     public static class t {
//     }
// }
// 
// Path: src/main/java/streams/higher/Pull.java
// public interface Pull<T> extends App<Pull.t, T>, Iterator<T> {
// 
//     static <A> Pull<A> prj(App<Pull.t, A> app) {
//         return (Pull<A>) app;
//     }
// 
//     static class t {
// 
//     }
// }
// 
// Path: src/main/java/streams/higher/Push.java
// public interface Push<T> extends App<Push.t, T> {
// 
//     static <A> Push<A> prj(App<Push.t, A> app) {
//         return (Push<A>) app;
//     }
// 
//     void invoke(Consumer<T> k);
// 
//     static class t {
// 
//     }
// }


import org.openjdk.jmh.annotations.*;
import streams.algebras.ExecTakeStreamAlg;
import streams.factories.*;
import streams.higher.Id;
import streams.higher.Pull;
import streams.higher.Push;
import java.util.stream.Stream;
    // Java 8 Benchmarks (Pull)
    @Benchmark
    public Long limit_count_iterate_Java8Streams() {
        RefCell<Long> acc = new RefCell<>(0L);

        Stream.of(v_small)
                .flatMap(x -> Stream.of(v).map(y -> y * x))
                .limit(N_limit)
                .iterator()
                .forEachRemaining(i -> acc.value++);

        return acc.value;
    }

    // Pull Factory Benchmarks
    @Benchmark
    public Long limit_count_AlgebrasPull() {
        ExecTakeStreamAlg<Id.t, Pull.t> alg = new ExecPullWithTakeFactory<>(new ExecPullFactory());

        Long value = Id.prj(
                alg.count(
                        alg.take(N_limit,
                                alg.flatMap(x -> alg.map(y -> x * y, alg.source(v)), alg.source(v_small))))).value;

        return value;
    }

    // Push Factory Benchmarks
    @Benchmark
    public Long limit_count_AlgebrasPush() {
// Path: src/main/java/streams/algebras/ExecTakeStreamAlg.java
// public interface ExecTakeStreamAlg<E, C> extends TakeStreamAlg<C>, ExecStreamAlg<E, C> {
// }
// 
// Path: src/main/java/streams/higher/Id.java
// public class Id<T> implements App<Id.t, T> {
// 
//     public final T value;
// 
//     public Id(T value) {
//         this.value = value;
//     }
// 
//     public static <A> Id<A> prj(App<Id.t, A> app) {
//         return (Id<A>) app;
//     }
// 
//     public static <A> App<Id.t, A> inj(Id<A> app) {
//         return (App<Id.t, A>) app;
//     }
// 
//     public static class t {
//     }
// }
// 
// Path: src/main/java/streams/higher/Pull.java
// public interface Pull<T> extends App<Pull.t, T>, Iterator<T> {
// 
//     static <A> Pull<A> prj(App<Pull.t, A> app) {
//         return (Pull<A>) app;
//     }
// 
//     static class t {
// 
//     }
// }
// 
// Path: src/main/java/streams/higher/Push.java
// public interface Push<T> extends App<Push.t, T> {
// 
//     static <A> Push<A> prj(App<Push.t, A> app) {
//         return (Push<A>) app;
//     }
// 
//     void invoke(Consumer<T> k);
// 
//     static class t {
// 
//     }
// }


// Path: src/main/java/benchmarks/Benchmark_TakePipelines.java
import org.openjdk.jmh.annotations.*;
import streams.algebras.ExecTakeStreamAlg;
import streams.factories.*;
import streams.higher.Id;
import streams.higher.Pull;
import streams.higher.Push;
import java.util.stream.Stream;

    // Java 8 Benchmarks (Pull)
    @Benchmark
    public Long limit_count_iterate_Java8Streams() {
        RefCell<Long> acc = new RefCell<>(0L);

        Stream.of(v_small)
                .flatMap(x -> Stream.of(v).map(y -> y * x))
                .limit(N_limit)
                .iterator()
                .forEachRemaining(i -> acc.value++);

        return acc.value;
    }

    // Pull Factory Benchmarks
    @Benchmark
    public Long limit_count_AlgebrasPull() {
        ExecTakeStreamAlg<Id.t, Pull.t> alg = new ExecPullWithTakeFactory<>(new ExecPullFactory());

        Long value = Id.prj(
                alg.count(
                        alg.take(N_limit,
                                alg.flatMap(x -> alg.map(y -> x * y, alg.source(v)), alg.source(v_small))))).value;

        return value;
    }

    // Push Factory Benchmarks
    @Benchmark
    public Long limit_count_AlgebrasPush() {
        ExecTakeStreamAlg<Id.t, Push.t> alg = new ExecPushWithTakeFactory<>(new ExecPushFactory());