Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active August 29, 2015 13:55
Show Gist options
  • Save dacr/8754206 to your computer and use it in GitHub Desktop.
Save dacr/8754206 to your computer and use it in GitHub Desktop.
Generic primes generator
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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment