Skip to content

Instantly share code, notes, and snippets.

@jenska
Last active June 4, 2021 08:51
Show Gist options
  • Save jenska/b79eb5ac4474dc0cbdb03511bf7a55f0 to your computer and use it in GitHub Desktop.
Save jenska/b79eb5ac4474dc0cbdb03511bf7a55f0 to your computer and use it in GitHub Desktop.
/* The Computer Language Benchmarks Game
https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
contributed by Ralph Ganszky
Added dummy element to tuple (because I read an article that this helps
to block less writing back to memory) and store data in
UnsafedMutablePointer to reduce overhead of array access.
modified by Patrick Sy
modified by Jens Kaiser
*/
import Foundation
import simd
typealias Body = (
r: simd_double3,
v: simd_double3,
m: simd_double1,
d: simd_double1
)
let nPlanets: Int = 5
let solarMass: Double = 4 * Double.pi * Double.pi
let daysPerYear: Double = 365.24
let sun: Body = (
r: simd_double3(x: 0.0, y: 0.0, z: 0.0),
v: simd_double3(x: 0.0, y: 0.0, z: 0.0),
m: solarMass, d: 0.0
)
let jupiter: Body = (
r: simd_double3(x: 4.8414314424647209,
y: -1.16032004402742839,
z: -0.103622044471123109),
v: simd_double3(x: 1.66007664274403694e-03 * daysPerYear,
y: 7.69901118419740425e-03 * daysPerYear,
z: -6.90460016972063023e-05 * daysPerYear),
m: 9.54791938424326609e-04 * solarMass, d: 0.0
)
let saturn: Body = (
r: simd_double3(x: 8.34336671824457987,
y: 4.12479856412430479,
z: -4.03523417114321381e-01),
v: simd_double3(x: -2.76742510726862411e-03 * daysPerYear,
y: 4.99852801234917238e-03 * daysPerYear,
z: 2.30417297573763929e-05 * daysPerYear),
m: 2.85885980666130812e-04 * solarMass, d: 0.0
)
let uranus: Body = (
r: simd_double3(x: 1.28943695621391310e+01,
y: -1.51111514016986312e+01,
z: -2.23307578892655734e-01),
v: simd_double3(x: 2.96460137564761618e-03 * daysPerYear,
y: 2.37847173959480950e-03 * daysPerYear,
z: -2.96589568540237556e-05 * daysPerYear),
m: 4.36624404335156298e-05 * solarMass, d: 0.0
)
let neptune: Body = (
r: simd_double3(x: 1.53796971148509165e+01,
y: -2.59193146099879641e+01,
z: 1.79258772950371181e-01),
v: simd_double3(x: 2.68067772490389322e-03 * daysPerYear,
y: 1.62824170038242295e-03 * daysPerYear,
z: -9.51592254519715870e-05 * daysPerYear),
m: 5.15138902046611451e-05 * solarMass, d: 0.0
)
let bodies: UnsafeMutablePointer<Body> = UnsafeMutablePointer<Body>.allocate(capacity: nPlanets)
defer {
bodies.deallocate()
}
bodies[0] = sun
bodies[1] = jupiter
bodies[2] = saturn
bodies[3] = uranus
bodies[4] = neptune
func advance(dt: simd_double1) {
for i in 0..<nPlanets {
let iBody: Body = bodies[i]
for j in i+1..<nPlanets {
let jBody: Body = bodies[j]
let d: simd_double3 = iBody.r - jBody.r
let dSquared: simd_double1 = simd_length_squared(d)
let mag: simd_double1 = dt / (dSquared * dSquared.squareRoot())
// dSquared.squareRoot() == distance
bodies[i].v -= d * (jBody.m * mag)
bodies[j].v += d * (iBody.m * mag)
}
}
for i in 0..<nPlanets {
bodies[i].r = bodies[i].r + bodies[i].v * dt
}
}
func energy() -> simd_double1 {
var energy: simd_double1 = 0.0
for i in 0..<nPlanets {
let iBody: Body = bodies[i]
energy += 0.5 * iBody.m * simd_length_squared(iBody.v)
for j in i+1..<nPlanets {
let jBody: Body = bodies[j]
let d: simd_double3 = iBody.r - jBody.r
let distance: simd_double1 = simd_length(d)
energy -= (iBody.m * jBody.m) / distance
}
}
return energy
}
var n: Int = 1000
if CommandLine.argc > 1 {
if let m: Int = Int(CommandLine.arguments[1]) {
n = m
}
}
// Adjust momentum of the sun
var p: simd_double3 = simd_double3(x: 0.0, y: 0.0, z: 0.0)
for i in 0..<nPlanets {
p += bodies[i].v * bodies[i].m
}
bodies[0].v = -p / solarMass
print(String(format: "%.9f", energy()))
for _ in 0..<n {
advance(dt: 0.01)
}
print(String(format: "%.9f", energy()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment