Scala trial: write benchmark

This commit is contained in:
Aaron Fenyes 2024-08-08 00:26:26 -07:00
parent 0bd025dd14
commit 6b0fad89dc
7 changed files with 136 additions and 0 deletions

View File

@ -0,0 +1,2 @@
target
sbt.json

View File

@ -0,0 +1,9 @@
enablePlugins(ScalaJSPlugin)
name := "Circular Law"
scalaVersion := "3.4.2"
scalaJSUseMainModuleInitializer := true
libraryDependencies += "com.raquo" %%% "laminar" % "17.0.0"
libraryDependencies += "ai.dragonfly" %%% "slash" % "0.3.1"
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.8.0"

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>The circular law</title>
<script type="text/javascript" src="./target/scala-3.4.2/circular-law-fastopt/main.js"></script>
<link rel="stylesheet" href="main.css"/>
</head>
<body></body>
</html>

View File

@ -0,0 +1,22 @@
body {
margin-left: 20px;
margin-top: 20px;
color: #fcfcfc;
background-color: #202020;
}
#app {
display: flex;
flex-direction: column;
width: 600px;
}
canvas {
float: left;
background-color: #020202;
border-radius: 10px;
}
input {
margin-top: 5px;
}

View File

@ -0,0 +1 @@
sbt.version=1.10.1

View File

@ -0,0 +1 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")

View File

@ -0,0 +1,91 @@
import com.raquo.laminar.api.L.{*, given}
import narr.*
import org.scalajs.dom
import org.scalajs.dom.document
import scala.math.{cos, sin}
import slash.matrix.Matrix
import slash.matrix.decomposition.Eigen
object CircularLawApp:
val canvas = canvasTag(widthAttr := 600, heightAttr := 600)
val ctx = canvas.ref.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]
val (eigvalSeries, runTimeReport) = randomEigvalSeries[60]()
val timeVar = Var("0")
def draw(timeStr: String): Unit =
// center and normalize the coordinate system
val width = canvas.ref.width
val height = canvas.ref.height
ctx.setTransform(1d, 0d, 0d, -1d, 0.5*width, 0.5*height)
// clear the previous frame
ctx.clearRect(-0.5*width, -0.5*width, width, height)
// find the resolution
val rDisp: Double = 1.5
val res = width / (2*rDisp)
// draw the eigenvalues
val eigvals = eigvalSeries(timeStr.toInt)
for n <- 0 to eigvals(0).length-1 do
ctx.beginPath()
ctx.arc(
res * eigvals(0)(n),
res * eigvals(1)(n),
3d,
0d, 2*math.Pi
)
ctx.fill()
def eigvalsRotated[N <: Int](A: Matrix[N, N], time: Double)(using ValueOf[N]): (NArray[Double], NArray[Double]) =
// create transformation
val maxFreq = 4
val T = Matrix.identity[N, N]
val dim: Int = valueOf[N]
for n <- 0 to dim by 2 do
val a = cos(math.Pi * time * (n % maxFreq))
val b = sin(math.Pi * time * (n % maxFreq))
T(n, n) = a
T(n+1, n) = b
T(n, n+1) = -b
T(n+1, n+1) = a
// find eigenvalues
val eigen = Eigen(T*A)
(
eigen.realEigenvalues.asInstanceOf[NArray[Double]],
eigen.imaginaryEigenvalues.asInstanceOf[NArray[Double]]
)
def randomEigvalSeries[N <: Int]()(using ValueOf[N]): (List[(NArray[Double], NArray[Double])], String) =
val timeRes = 100
val dim: Int = valueOf[N]
val startTime = System.currentTimeMillis()
val A = new Matrix[N, N](
NArray.tabulate(dim*dim)(k => (math.E*k*k) % 2 - 1)
).times(math.sqrt(3d / dim))
val series = List.tabulate(timeRes)(t => eigvalsRotated(A, t.toDouble / timeRes))
val endTime = System.currentTimeMillis()
val runTime = endTime - startTime
(series, runTime.toString() + " ms")
def main(args: Array[String]): Unit =
ctx.fillStyle = "white"
lazy val app = div(
idAttr := "app",
div(runTimeReport),
canvas,
input(
typ := "range",
minAttr := "0",
maxAttr := (eigvalSeries.length-1).toString,
controlled(
value <-- timeVar.signal,
onInput.mapToValue --> timeVar.writer
),
timeVar.signal --> draw
)
)
renderOnDomContentLoaded(document.body, app)