15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* The Great Computer Language Shootout
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   http://shootout.alioth.debian.org/
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   contributed by Isaac Gouy */
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var PI = 3.141592653589793;
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var SOLAR_MASS = 4 * PI * PI;
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var DAYS_PER_YEAR = 365.24;
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Body(x,y,z,vx,vy,vz,mass){
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.x = x;
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.y = y;
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.z = z;
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.vx = vx;
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.vy = vy;
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.vz = vz;
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.mass = mass;
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Body.prototype.offsetMomentum = function(px,py,pz) {
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.vx = -px / SOLAR_MASS;
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.vy = -py / SOLAR_MASS;
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.vz = -pz / SOLAR_MASS;
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return this;
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Jupiter(){
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return new Body(
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      4.84143144246472090e+00,
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -1.16032004402742839e+00,
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -1.03622044471123109e-01,
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      1.66007664274403694e-03 * DAYS_PER_YEAR,
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      7.69901118419740425e-03 * DAYS_PER_YEAR,
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -6.90460016972063023e-05 * DAYS_PER_YEAR,
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      9.54791938424326609e-04 * SOLAR_MASS
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   );
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Saturn(){
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return new Body(
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      8.34336671824457987e+00,
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      4.12479856412430479e+00,
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -4.03523417114321381e-01,
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -2.76742510726862411e-03 * DAYS_PER_YEAR,
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      4.99852801234917238e-03 * DAYS_PER_YEAR,
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      2.30417297573763929e-05 * DAYS_PER_YEAR,
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      2.85885980666130812e-04 * SOLAR_MASS
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   );
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Uranus(){
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return new Body(
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      1.28943695621391310e+01,
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -1.51111514016986312e+01,
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -2.23307578892655734e-01,
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      2.96460137564761618e-03 * DAYS_PER_YEAR,
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      2.37847173959480950e-03 * DAYS_PER_YEAR,
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -2.96589568540237556e-05 * DAYS_PER_YEAR,
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      4.36624404335156298e-05 * SOLAR_MASS
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   );
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Neptune(){
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return new Body(
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      1.53796971148509165e+01,
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -2.59193146099879641e+01,
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      1.79258772950371181e-01,
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      2.68067772490389322e-03 * DAYS_PER_YEAR,
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      1.62824170038242295e-03 * DAYS_PER_YEAR,
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      -9.51592254519715870e-05 * DAYS_PER_YEAR,
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      5.15138902046611451e-05 * SOLAR_MASS
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   );
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Sun(){
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function NBodySystem(bodies){
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.bodies = bodies;
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var px = 0.0;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var py = 0.0;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var pz = 0.0;
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var size = this.bodies.length;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   for (var i=0; i<size; i++){
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var b = this.bodies[i];
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var m = b.mass;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      px += b.vx * m;
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      py += b.vy * m;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      pz += b.vz * m;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   this.bodies[0].offsetMomentum(px,py,pz);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)NBodySystem.prototype.advance = function(dt){
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var dx, dy, dz, distance, mag;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var size = this.bodies.length;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   for (var i=0; i<size; i++) {
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var bodyi = this.bodies[i];
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var j=i+1; j<size; j++) {
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         var bodyj = this.bodies[j];
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dx = bodyi.x - bodyj.x;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dy = bodyi.y - bodyj.y;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dz = bodyi.z - bodyj.z;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         mag = dt / (distance * distance * distance);
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         bodyi.vx -= dx * bodyj.mass * mag;
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         bodyi.vy -= dy * bodyj.mass * mag;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         bodyi.vz -= dz * bodyj.mass * mag;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         bodyj.vx += dx * bodyi.mass * mag;
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         bodyj.vy += dy * bodyi.mass * mag;
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         bodyj.vz += dz * bodyi.mass * mag;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   for (var i=0; i<size; i++) {
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var body = this.bodies[i];
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      body.x += dt * body.vx;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      body.y += dt * body.vy;
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      body.z += dt * body.vz;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)NBodySystem.prototype.energy = function(){
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var dx, dy, dz, distance;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var e = 0.0;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   var size = this.bodies.length;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   for (var i=0; i<size; i++) {
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      var bodyi = this.bodies[i];
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      e += 0.5 * bodyi.mass *
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         ( bodyi.vx * bodyi.vx
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         + bodyi.vy * bodyi.vy
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         + bodyi.vz * bodyi.vz );
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (var j=i+1; j<size; j++) {
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         var bodyj = this.bodies[j];
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dx = bodyi.x - bodyj.x;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dy = bodyi.y - bodyj.y;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         dz = bodyi.z - bodyj.z;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         e -= (bodyi.mass * bodyj.mass) / distance;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return e;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var ret;
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)for ( var n = 3; n <= 24; n *= 2 ) {
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    (function(){
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var bodies = new NBodySystem( Array(
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ));
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var max = n * 100;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ret = bodies.energy();
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i=0; i<max; i++){
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bodies.advance(0.01);
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ret = bodies.energy();
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    })();
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
170