(* Whether there are any odd factors m of n such that m>=k. Requires: k>=3, n>=1 *) fun noOddFactors(k,n) = k*k > n orelse n mod k <> 0 andalso noOddFactors(k+2,n) (* Whether n is prime. Requires: n>=2 *) fun isPrime(n) : bool = n = 2 orelse n mod 2 = 1 andalso noOddFactors(3,n) fun nextPrime(n) : int = if isPrime(n+1) then n+1 else nextPrime(n+1) val s1 = Stream.make(2, nextPrime) (*** A faster version using a sieve ***) structure AppendableList = struct datatype 'a cons = Cons of 'a * 'a cons option ref type 'a listptr = 'a cons option (* a mutable list of int that supports appending elements. *) type 'a list = 'a listptr * 'a listptr fun singleton(x: 'a) : 'a list = let val node = SOME(Cons(x, ref NONE)) in (node, node) end fun append((head, tail): 'a list, x: 'a):'a list = let val last = SOME(Cons(x, ref NONE)) in case tail of NONE => (last, last) | SOME(Cons(y, r)) => (r := last; (head, last)) end fun isEmpty((head, tail): 'a list): bool = case head of NONE => true | _ => false exception EmptyList fun next((head, tail): 'a list): 'a * 'a list = case head of SOME(Cons(x:'a, r: 'a listptr ref)) => (x, (!r, tail)) | _ => raise EmptyList end type sieve_state = int * int AppendableList.list (* The smallest number larger than p and indivisible by any number less than or equal to sqrt(p) in l. Requires: l is sorted in ascending order. *) fun sieve((p, l) : sieve_state): int = (* Whether p is divisible by any number in l that is <= sqrt(p). *) let fun try_divisors(p, l): bool = let val (n,l') = AppendableList.next(l) in if AppendableList.isEmpty(l) then false else if n*n > p then false else if p mod n = 0 then true else try_divisors(p, l') end in if try_divisors(p+1, l) then sieve(p+1, l) else p+1 end fun update_sieve((p,l): sieve_state): sieve_state = let val p' = sieve(p,l) in (p', AppendableList.append(l, p')) end val s2 = Stream.make2((2, AppendableList.singleton(2)), fn(p,l) => (p,update_sieve(p,l)));