Skip to content

Instantly share code, notes, and snippets.

@aalexandrov
Created November 9, 2016 15:14
Show Gist options
  • Save aalexandrov/42fac927ad1cf7ca8bbe5160fb5604fb to your computer and use it in GitHub Desktop.
Save aalexandrov/42fac927ad1cf7ca8bbe5160fb5604fb to your computer and use it in GitHub Desktop.
import scala.util.control.TailCalls._
def time[R](block: => R): (Long, R) = {
val t0 = System.nanoTime()
val result = block // call-by-name
val t1 = System.nanoTime()
(t1 - t0, result)
}
val sin1 = (x: Double) => {
val K = 13
val xsq = x * x
var k = 1
var num = x
var den = 1
var S = 0.0
var i = 0
do {
i += 1
val frac = num / den
if (k % 2 == 0) S -= frac
else S += frac
k += 1
num *= xsq
den *= (2 * k - 2) * (2 * k - 1)
} while (i < 5000)
S
}
val sin2 = (x: Double) => {
val K = 13
val xsq = x * x
val k$1 = 1
val num$1 = x
val den$1 = 1
val S$1 = 0.0
val i$1 = 0
def B$2(S$2: Double, den$2: Int, k$2: Int, num$2: Double, i$2: Int): TailRec[Double] = {
val frac = num$2 / den$2
val c$1 = k$2 % 2 == 0
def B$3(): TailRec[Double] = {
val S$3 = S$2 - frac
tailcall(B$5(S$3))
}
def B$4(): TailRec[Double] = {
val S$4 = S$2 + frac
tailcall(B$5(S$4))
}
def B$5(S$5: Double): TailRec[Double] = {
val i$3 = i$2 + 1
val k$3 = k$2 + 1
val num$3 = num$2 * xsq
val den$3 = den$2 * ((2 * k$3 - 2) * (2 * k$3 - 1))
val c$2 = i$3 < 5000// k$3 < K
def B$6(): TailRec[Double] = {
done(S$5)
}
if (c$2) tailcall(B$2(S$5, den$3, k$3, num$3, i$3))
else tailcall(B$6())
}
if (c$1) tailcall(B$3()) else tailcall(B$4())
}
B$2(S$1, den$1, k$1, num$1, i$1).result
}
def isEven(xs: List[Int]): TailRec[Boolean] =
if (xs.isEmpty) done(true) else tailcall(isOdd(xs.tail))
def isOdd(xs: List[Int]): TailRec[Boolean] =
if (xs.isEmpty) done(false) else tailcall(isEven(xs.tail))
isEven((1 to 5001).toList).result
def fib0(n: Int): Int =
if (n < 2) n
else fib0(n-2) + fib0(n-1)
def fib1(n: Int): TailRec[Int] =
if (n < 2) done(n) else for {
x <- tailcall(fib1(n - 1))
y <- tailcall(fib1(n - 2))
} yield x + y
def fib2(n: Int): TailRec[Int] =
if (n < 2) done(n) else {
val x = tailcall(fib2(n - 1)).result
val y = tailcall(fib2(n - 2)).result
done(x + y)
}
lazy val fib3: Stream[Int] =
0 #::
1 #::
fib3.zip(fib3.tail).map { case (x, y) => x + y }
val trs = Seq(
time(sin1(Math.PI / 2)), // Emma Source
time(sin2(Math.PI / 2)), // Emma Core with trampolines
time(fib0(40)), // without trampolines
time(fib1(40).result), // with trampolines in a monad
time(fib2(40).result), // with trampolines in a block
time(fib3(40)) // as stream
)
for (((t, r), i) <- trs.zipWithIndex)
println(s"t$i = ${t / 1000000.0}ms")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment