package brian;

import brian.functional.InfIterator;
import brian.functional.Memoization;
import brian.utils.list.IntList;
import brian.utils.list.LongList;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.LongStream;

public class Prime {
    private static Set<Long> primes = new HashSet<>(Collections.singletonList(2L));

    public static Predicate<Number> primeQ = (Number num) -> {
        Long n = num.longValue();
        if (primes.contains(n)) return true;
        else if (primes.stream()
                       .filter(p -> p <= Math.round(Math.sqrt(n)) + 1)
                       .noneMatch(p -> n % p == 0)) {
            primes.add(n);
            return true;
        }
        return false;
    };

    public static Predicate<Number> memPrimeQ = Memoization.memoize(primeQ);

    /**
     * Generates primes from 2 up
     *
     * @return IntStream of primes
     */
    public static LongStream primes() {
        return LongStream.iterate(2, i -> i + 1).filter(primeQ::test);
    }

    /**
     * Generates a list of primes
     *
     * @param n
     *        {@code Integer} length of the list
     *
     * @return List of primes
     */
    public static LongList primeList(Number n) {
        return new LongList(primes().limit(n.longValue()));
    }

    /**
     * Get the <i>n</i>th prime
     * @param n
     *        Index
     * @return The <i>n</i>th prime assuming a 1 based index
     */
    public static Long primeN(Number n) {
        return primes()
                .limit(n.longValue())
                .skip(n.longValue() - 1)
                .findFirst()
                .getAsLong();
    }

    public InfIterator<Long> primeIterator() {
        return new InfIterator<Long>() {
            private Set<Long> primes = new HashSet<>(Collections.singletonList(2L));
            private Long prime = 2L;

            private Long nextPrime(Long n) {
                if (primes.contains(n)) return nextPrime(n+2);
                else if (primes.stream().filter(p -> p <= Math.round(Math.sqrt(n)) + 1).noneMatch(p -> n % p == 0)) {
                    primes.add(n);
                    return n;
                }
                else return nextPrime(n+2);
            }

            @Override
            public Long next() {
                Long ret = prime;
                if (prime.equals(2L)) prime = nextPrime(prime+1);
                prime = nextPrime(prime);
                return ret;
            }
        };
    }
}

@@ -151,16 +151,41 @@
 gList;%0A%0A
+import java.util.Arrays;%0A
 import j
@@ -250,24 +250,64 @@
 a.util.Set;%0A
+import java.util.function.LongSupplier;%0A
 import java.
@@ -331,16 +331,52 @@
 dicate;%0A
+import java.util.function.Supplier;%0A
 import j
@@ -481,56 +481,107 @@
 t%3C%3E(
-Collections.singletonList(2
+Arrays.asList(2L, 3L, 5L, 7L, 11
 L));%0A
-%0A
     p
-ublic stat
+rivate LongSupplier supplier = primeSupplier();%0A%0A    publ
 ic P
@@ -804,17 +804,17 @@
 t(n)) + 
-1
+2
 )%0A      
@@ -831,20 +831,19 @@
        .
-none
+any
 Match(p 
@@ -875,58 +875,284 @@
     
+ 
- primes.add(n);%0A            return true;%0A        %7D
+return false;%0A        %7D%0A        long p = supplier.getAsLong();%0A        primes.add(p);%0A        while (p %3C= Math.round(Math.sqrt(n))+2) %7B%0A            if (n %25 p == 0) return false;%0A            p = supplier.getAsLong();%0A            primes.add(p);%0A        %7D%0A        primes.add(n);
 %0A   
@@ -1159,28 +1159,27 @@
      return 
-fals
+tru
 e;%0A    %7D;%0A%0A 
@@ -1188,23 +1188,16 @@
  public 
-static 
 Predicat
@@ -1347,31 +1347,24 @@
 %0A    public 
-static 
 LongStream p
@@ -1403,50 +1403,32 @@
 eam.
-it
+gen
 erate(
-2, i -%3E i + 1).filter(primeQ::test
+primeSupplier()
 );%0A 
@@ -1599,31 +1599,24 @@
 %0A    public 
-static 
 LongList pri
@@ -1857,23 +1857,16 @@
  public 
-static 
 Long pri
@@ -2046,24 +2046,158 @@
 g();%0A    %7D%0A%0A
+    public LongSupplier primeSupplier() %7B%0A        InfIterator%3CLong%3E iterator = primeIterator();%0A        return iterator::next;%0A    %7D%0A%0A
     public I

Fix primeQ