case class Vect3(x: Double, y: Double, z: Double) { def +(v: Vect3) = Vect3(x+v.x, y+v.y, z+v.z) def -(v: Vect3) = Vect3(x-v.x, y-v.y, z-v.z) def *(c: Double) = Vect3(x*c, y*c, z*c) def /(c: Double) = Vect3(x/c, y/c, z/c) } case class ImmutableBody(p: Vect3, v: Vect3, mass: Double) { def step(a: Vect3, dt: Double) = { val nv = v+a*dt ImmutableBody(p+nv*dt, nv, mass) } } class NBodyImmutableClass(val numBodies: Int, val dt: Double) { private val bodies = initBodies() def initBodies(): Array[ImmutableBody] = { Array.tabulate(numBodies) { i => ImmutableBody(Vect3(i,0,0), Vect3(0,math.sqrt(1.0/i),0), if(i==0) 1 else 1e-10) } } def forSim(steps: Int): Unit = { for(_ <- 1 to steps) { val accel = Array.fill(numBodies)(Vect3(0,0,0)) for { i <- 0 until numBodies j <- i+1 until numBodies } { val pi = bodies(i) val pj = bodies(j) val d = pi.p - pj.p val dist = math.sqrt(d.x*d.x+d.y*d.y+d.z*d.z) accel(i) -= d*(pj.mass/(dist*dist*dist)) accel(j) += d*(pi.mass/(dist*dist*dist)) } for(i <- 0 until numBodies) { bodies(i) = bodies(i).step(accel(i), dt) } } } }