Skip to content

Instantly share code, notes, and snippets.

@lolgab
Created October 25, 2018 13:18
Show Gist options
  • Save lolgab/903a1492d42c274087472a36fd0051a6 to your computer and use it in GitHub Desktop.
Save lolgab/903a1492d42c274087472a36fd0051a6 to your computer and use it in GitHub Desktop.
Test changing for loops with while loops.
import scalanative.native._
import stdlib.malloc
object implicits {
type MVect3 = CStruct3[Double, Double, Double]
type MutableBody = CStruct3[MVect3, MVect3, Double]
implicit class MVect3Ops(val ptr: Ptr[MVect3]) extends AnyVal {
def x: Double = !ptr._1
def y: Double = !ptr._2
def z: Double = !ptr._3
def x_=(v: Double): Unit = !ptr ._1 = v
def y_=(v: Double): Unit = !ptr ._2 = v
def z_=(v: Double): Unit = !ptr ._3 = v
def zero(): Unit = {
x = 0.0
y = 0.0
z = 0.0
}
}
implicit class MutableBodyOps(val ptr: Ptr[MutableBody]) extends AnyVal {
def p: Ptr[MVect3] = ptr._1
def v: Ptr[MVect3] = ptr._2
def mass: Double = !ptr._3
def mass_=(v: Double): Unit = !ptr._3 = v
}
}
class NBodyMutableClass(val numBodies: Int, val dt: Double) {
import implicits._
private val bodies = malloc(numBodies * sizeof[MutableBody]).cast[Ptr[MutableBody]]
for(i <- 0 until numBodies) (bodies + i).mass = 1e-10
private val accel = malloc(numBodies * sizeof[MVect3]).cast[Ptr[MVect3]]
initBodies()
def initBodies(): Unit = {
bodies.mass = 1.0
for(i <- 1 until numBodies) {
(bodies + i).p.x = i
(bodies + i).v.y = math.sqrt(1.0/i)
}
}
def forSim(steps: Int): Unit = {
var s = 1
while(s <= steps) {
var i = 0
while(i < numBodies) {
(accel + i).zero()
i+=1
}
i = 0
while(i < numBodies) {
val pi = bodies + i
val acceli = accel + i
for (j <- i+1 until numBodies) {
val pj = bodies + j
val dx = pi.p.x-pj.p.x
val dy = pi.p.y-pj.p.y
val dz = pi.p.z-pj.p.z
val dist = math.sqrt(dx*dx+dy*dy+dz*dz)
val magi = pj.mass/(dist*dist*dist)
val magj = pi.mass/(dist*dist*dist)
acceli.x -= magi*dx
acceli.y -= magi*dy
acceli.z -= magi*dz
val accelj = (accel + j)
accelj.x += magj*dx
accelj.y += magj*dy
accelj.z += magj*dz
}
i+=1
}
i = 0
while(i < numBodies) {
val p = bodies + i
val acceli = (accel + i)
p.v.x += acceli.x*dt
p.v.y += acceli.y*dt
p.v.z += acceli.z*dt
p.p.x += p.v.x*dt
p.p.y += p.v.y*dt
p.p.z += p.v.z*dt
i+=1
}
s+=1
}
}
}
object MainTiming extends App {
val numBodies = 1000
val dt = 0.01
val mutSim = new NBodyMutableClass(numBodies, dt)
println("Mutable Class:")
val timeRuns = 20
val times = new Array[Double](timeRuns)
var time = 0
while(time < timeRuns) {
val start = System.nanoTime()
mutSim.forSim(100)
times(time) = (System.nanoTime()-start)*1e-9
time += 1
}
val mean = times.sum/times.length
val rms = math.sqrt(times.map(x => (x-mean)*(x-mean)).sum/times.length)
println(s"mean = $mean, rms = $rms")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment