The Computer Language
Benchmarks Game

n-body Kotlin #5 program

source code

/* The Computer Language Benchmarks Game
   http://benchmarksgame.alioth.debian.org/

   mostly auto-converted from Han Kai's Java #5 program
*/

object nbody {
    @JvmStatic fun main(args: Array<String>) {
        val n = Integer.parseInt(args[0])

        val bodies = NBodySystem()
        System.out.printf("%.9f\n", bodies.energy())
        for (i in 0 until n)
            bodies.advance(0.01)
        System.out.printf("%.9f\n", bodies.energy())
    }

    internal class NBodySystem {

        private val _bodies = doubleArrayOf(
                //sun begin
                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS, 0.0,
                //sun end

                //jupiter begin
                4.84143144246472090e+00, //
                -1.16032004402742839e+00, //
                -1.03622044471123109e-01, //
                1.66007664274403694e-03 * DAYS_PER_YEAR, //
                7.69901118419740425e-03 * DAYS_PER_YEAR, //
                -6.90460016972063023e-05 * DAYS_PER_YEAR, //
                9.54791938424326609e-04 * SOLAR_MASS, //
                0.0,
                //jupiter end

                //saturn begin
                8.34336671824457987e+00, //
                4.12479856412430479e+00, //
                -4.03523417114321381e-01, //
                -2.76742510726862411e-03 * DAYS_PER_YEAR, //
                4.99852801234917238e-03 * DAYS_PER_YEAR, //
                2.30417297573763929e-05 * DAYS_PER_YEAR, //
                2.85885980666130812e-04 * SOLAR_MASS, //
                0.0,
                //saturn end

                //uranus begin
                1.28943695621391310e+01, //
                -1.51111514016986312e+01, //
                -2.23307578892655734e-01, //
                2.96460137564761618e-03 * DAYS_PER_YEAR, //
                2.37847173959480950e-03 * DAYS_PER_YEAR, //
                -2.96589568540237556e-05 * DAYS_PER_YEAR, //
                4.36624404335156298e-05 * SOLAR_MASS, //
                0.0,
                //uranus end

                //neptune begin
                1.53796971148509165e+01, //
                -2.59193146099879641e+01, //
                1.79258772950371181e-01, //
                2.68067772490389322e-03 * DAYS_PER_YEAR, //
                1.62824170038242295e-03 * DAYS_PER_YEAR, //
                -9.51592254519715870e-05 * DAYS_PER_YEAR, //
                5.15138902046611451e-05 * SOLAR_MASS, //
                0.0)//neptune end

        init {
            var px = 0.0
            var py = 0.0
            var pz = 0.0

            for (i in 0 until BODY_COUNT) {
                val ioffset = BODY_SIZE * i
                val imass = _bodies[ioffset + mass]

                px += _bodies[ioffset + vx] * imass
                py += _bodies[ioffset + vy] * imass
                pz += _bodies[ioffset + vz] * imass
            }

            _bodies[vx] = -px / SOLAR_MASS
            _bodies[vy] = -py / SOLAR_MASS
            _bodies[vz] = -pz / SOLAR_MASS
        }

        fun advance(dt: Double) {
            val bodies = _bodies

            for (i in 0 until BODY_COUNT) {
                val offset = BODY_SIZE * i

                for (j in i + 1 until BODY_COUNT) {
                    val joffset = BODY_SIZE * j

                    val dx = bodies[offset + x] - bodies[joffset + x]
                    val dy = bodies[offset + y] - bodies[joffset + y]
                    val dz = bodies[offset + z] - bodies[joffset + z]

                    val dSquared = dx * dx + dy * dy + dz * dz
                    val distance = Math.sqrt(dSquared)
                    val mag = dt / (dSquared * distance)

                    val jmass = bodies[joffset + mass]

                    bodies[offset + vx] -= dx * jmass * mag
                    bodies[offset + vy] -= dy * jmass * mag
                    bodies[offset + vz] -= dz * jmass * mag

                    val imass = bodies[offset + mass]
                    bodies[joffset + vx] += dx * imass * mag
                    bodies[joffset + vy] += dy * imass * mag
                    bodies[joffset + vz] += dz * imass * mag
                }
            }

            for (i in 0 until BODY_COUNT) {
                val ioffset = BODY_SIZE * i

                bodies[ioffset + x] += dt * bodies[ioffset + vx]
                bodies[ioffset + y] += dt * bodies[ioffset + vy]
                bodies[ioffset + z] += dt * bodies[ioffset + vz]
            }
        }

        fun energy(): Double {
            val bodies = _bodies

            var dx: Double
            var dy: Double
            var dz: Double
            var distance: Double
            var e = 0.0

            for (i in 0 until BODY_COUNT) {
                val offset = BODY_SIZE * i

                val ivx = bodies[offset + vx]
                val ivy = bodies[offset + vy]
                val ivz = bodies[offset + vz]
                val imass = bodies[offset + mass]

                e += 0.5 * imass * (ivx * ivx + ivy * ivy + ivz * ivz)

                for (j in i + 1 until BODY_COUNT) {
                    val joffset = BODY_SIZE * j

                    val ix = bodies[offset + x]
                    val iy = bodies[offset + y]
                    val iz = bodies[offset + z]

                    dx = ix - bodies[joffset + x]
                    dy = iy - bodies[joffset + y]
                    dz = iz - bodies[joffset + z]

                    distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
                    e -= imass * bodies[joffset + mass] / distance
                }
            }

            return e
        }

        companion object {
            private val PI = 3.141592653589793
            private val SOLAR_MASS = 4.0 * PI * PI
            private val DAYS_PER_YEAR = 365.24
            private val BODY_SIZE = 8
            private val BODY_COUNT = 5

            private val x = 0
            private val y = 1
            private val z = 2
            private val vx = 3
            private val vy = 4
            private val vz = 5
            private val mass = 6
        }

    }

}
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
info: kotlinc-jvm 1.2.0 (JRE 9.0.1+11)
java 9.0.1
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)


Tue, 28 Nov 2017 18:03:11 GMT

MAKE:
mv nbody.kotlin-5.kotlin nbody.kt
/opt/src/kotlin-1.2.0/bin/kotlinc nbody.kt -d nbody.jar
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.intellij.util.text.StringFactory to constructor java.lang.String(char[],boolean)
WARNING: Please consider reporting this to the maintainers of com.intellij.util.text.StringFactory
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

5.93s to complete and log all make actions

COMMAND LINE:
/opt/src/jdk-9.0.1/bin/java -Xbootclasspath/a:/opt/src/kotlin-1.2.0/lib/kotlin-stdlib.jar:./nbody.jar nbody 50000000

PROGRAM OUTPUT:
-0.169075164
-0.169059907