An example of how to implement a generic primes generator that you can use with any numerical type. Of course, performances will be impacted by your choice :

  • howlongfor(intPrimes.drop(25000).head) // res0: (String, Int) = (459ms,287137)
  • howlongfor(longPrimes.drop(25000).head) // res1: (String, Long) = (1349ms,287137)
  • howlongfor(bigIntPrimes.drop(25000).head) // res2: (String, BigInt) = (4361ms,287137)

My primes project can be found here.

Simplified source code

package experiments
object Primes {
class Generator[NUM](implicit numops: Integral[NUM]) {
import annotation.tailrec
import numops._
private val two = one + one
private val three = one + one + one
private def sqrt(number: NUM) = { //https://issues.scala-lang.org/browse/SI-3739
def next(n: NUM, i: NUM): NUM = (n + i / n) / two
var n = one
var n1 = next(n, number)
while ((n1 - n).abs > one) {
n = n1
n1 = next(n, number)
}
while (n1 * n1 > number) {
n1 -= one
}
n1
}
def isPrime(v: NUM): Boolean = {
val upTo = sqrt(v)
@tailrec
def checkUpTo(from: NUM): Boolean = {
if (v % from == 0) false
else if (from == upTo) true else checkUpTo(from + one)
}
(v <= three) || checkUpTo(two)
}
def integers = {
def next(cur: NUM): Stream[NUM] = cur #:: next(cur + one)
next(one)
}
def candidates = integers.tail
def primes =
candidates
.filter(isPrime(_))
}
def howlongfor[T](proc: => T): Tuple2[String, T] = {
def now = System.currentTimeMillis
now match {
case start =>
val result = proc
(s"${now - start}ms", result)
}
}
def intPrimes = (new Generator[Int]).primes
def longPrimes = (new Generator[Long]).primes
def bigIntPrimes = (new Generator[BigInt]).primes
howlongfor(intPrimes.drop(25000).head) // res0: (String, Int) = (459ms,287137)
howlongfor(longPrimes.drop(25000).head) // res1: (String, Long) = (1349ms,287137)
howlongfor(bigIntPrimes.drop(25000).head) // res2: (String, BigInt) = (4361ms,287137)
}
view raw Primes.sc hosted with ❤ by GitHub