Fix for JRUBY-2882. Handle error messages related to constructors better
[jruby.git] / bench / shootout / nbody.jruby-2.jruby
blob533044c6d79b4e94a602334d7f5c53a75fcc282e
1 # The Computer Language Shootout
2 # http://shootout.alioth.debian.org
4 # Optimized for Ruby by Jesse Millikan
5 # From version ported by Michael Neumann from the C gcc version, 
6 # which was written by Christoph Bauer. 
8 SOLAR_MASS = 4 * Math::PI**2
9 DAYS_PER_YEAR = 365.24
11 class Planet
12  attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass
14  def initialize(x, y, z, vx, vy, vz, mass)
15   @x, @y, @z = x, y, z
16   @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR 
17   @mass = mass * SOLAR_MASS
18  end
20  def move_from_i(bodies, nbodies, dt, i)
21   while i < nbodies
22    b2 = bodies[i]
23    dx = @x - b2.x
24    dy = @y - b2.y
25    dz = @z - b2.z
27    distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
28    mag = dt / (distance * distance * distance)
29    b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
31    @vx -= dx * b2_mass_mag
32    @vy -= dy * b2_mass_mag
33    @vz -= dz * b2_mass_mag
34    b2.vx += dx * b_mass_mag
35    b2.vy += dy * b_mass_mag
36    b2.vz += dz * b_mass_mag
37    i += 1 
38   end
40   @x += dt * @vx
41   @y += dt * @vy
42   @z += dt * @vz
43  end
44 end
46 def energy(bodies)
47   e = 0.0
48   nbodies = bodies.size
50   for i in 0 ... nbodies 
51     b = bodies[i]
52     e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz)
53     for j in (i + 1) ... nbodies
54       b2 = bodies[j]
55       dx = b.x - b2.x
56       dy = b.y - b2.y
57       dz = b.z - b2.z
58       distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
59       e -= (b.mass * b2.mass) / distance
60     end
61   end
62   e
63 end
65 def offset_momentum(bodies)
66   px, py, pz = 0.0, 0.0, 0.0
68   for b in bodies
69     m = b.mass
70     px += b.vx * m
71     py += b.vy * m
72     pz += b.vz * m
73   end
75   b = bodies[0]
76   b.vx = - px / SOLAR_MASS
77   b.vy = - py / SOLAR_MASS
78   b.vz = - pz / SOLAR_MASS
79 end
81 BODIES = [
82   # sun
83   Planet.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
85   # jupiter
86   Planet.new(
87     4.84143144246472090e+00,
88     -1.16032004402742839e+00,
89     -1.03622044471123109e-01,
90     1.66007664274403694e-03,
91     7.69901118419740425e-03,
92     -6.90460016972063023e-05,
93     9.54791938424326609e-04),
95   # saturn
96   Planet.new(
97     8.34336671824457987e+00,
98     4.12479856412430479e+00,
99     -4.03523417114321381e-01,
100     -2.76742510726862411e-03,
101     4.99852801234917238e-03,
102     2.30417297573763929e-05,
103     2.85885980666130812e-04),
105   # uranus
106   Planet.new(
107     1.28943695621391310e+01,
108     -1.51111514016986312e+01,
109     -2.23307578892655734e-01,
110     2.96460137564761618e-03,
111     2.37847173959480950e-03,
112     -2.96589568540237556e-05,
113     4.36624404335156298e-05),
115   # neptune
116   Planet.new(
117     1.53796971148509165e+01,
118     -2.59193146099879641e+01,
119     1.79258772950371181e-01,
120     2.68067772490389322e-03,
121     1.62824170038242295e-03,
122     -9.51592254519715870e-05,
123     5.15138902046611451e-05)
127 n = Integer(ARGV[0])
129 offset_momentum(BODIES)
131 puts "%.9f" % energy(BODIES)
133 nbodies = BODIES.size
134 dt = 0.01
136 n.times do
137   i = 0
138   while i < nbodies
139     b = BODIES[i]
140     b.move_from_i(BODIES, nbodies, dt, i + 1)
141     i += 1
142   end
145 puts "%.9f" % energy(BODIES)