30 | | |
31 | | ---- |
32 | | |
33 | | *Python Code:* |
34 | | |
35 | | {{{ |
36 | | # The Computer Language Benchmarks Game |
37 | | # http://shootout.alioth.debian.org/ |
38 | | # |
39 | | # originally by Kevin Carson |
40 | | # modified by Tupteq, Fredrik Johansson, and Daniel Nanz |
41 | | # modified by Maciej Fijalkowski |
42 | | # 2to3 |
43 | | |
44 | | import sys |
45 | | |
46 | | def combinations(l): |
47 | | result = [] |
48 | | for x in range(len(l) - 1): |
49 | | ls = l[x+1:] |
50 | | for y in ls: |
51 | | result.append((l[x],y)) |
52 | | return result |
53 | | |
54 | | PI = 3.14159265358979323 |
55 | | SOLAR_MASS = 4 * PI * PI |
56 | | DAYS_PER_YEAR = 365.24 |
57 | | |
58 | | BODIES = { |
59 | | 'sun': ([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], SOLAR_MASS), |
60 | | |
61 | | 'jupiter': ([4.84143144246472090e+00, |
62 | | -1.16032004402742839e+00, |
63 | | -1.03622044471123109e-01], |
64 | | [1.66007664274403694e-03 * DAYS_PER_YEAR, |
65 | | 7.69901118419740425e-03 * DAYS_PER_YEAR, |
66 | | -6.90460016972063023e-05 * DAYS_PER_YEAR], |
67 | | 9.54791938424326609e-04 * SOLAR_MASS), |
68 | | |
69 | | 'saturn': ([8.34336671824457987e+00, |
70 | | 4.12479856412430479e+00, |
71 | | -4.03523417114321381e-01], |
72 | | [-2.76742510726862411e-03 * DAYS_PER_YEAR, |
73 | | 4.99852801234917238e-03 * DAYS_PER_YEAR, |
74 | | 2.30417297573763929e-05 * DAYS_PER_YEAR], |
75 | | 2.85885980666130812e-04 * SOLAR_MASS), |
76 | | |
77 | | 'uranus': ([1.28943695621391310e+01, |
78 | | -1.51111514016986312e+01, |
79 | | -2.23307578892655734e-01], |
80 | | [2.96460137564761618e-03 * DAYS_PER_YEAR, |
81 | | 2.37847173959480950e-03 * DAYS_PER_YEAR, |
82 | | -2.96589568540237556e-05 * DAYS_PER_YEAR], |
83 | | 4.36624404335156298e-05 * SOLAR_MASS), |
84 | | |
85 | | 'neptune': ([1.53796971148509165e+01, |
86 | | -2.59193146099879641e+01, |
87 | | 1.79258772950371181e-01], |
88 | | [2.68067772490389322e-03 * DAYS_PER_YEAR, |
89 | | 1.62824170038242295e-03 * DAYS_PER_YEAR, |
90 | | -9.51592254519715870e-05 * DAYS_PER_YEAR], |
91 | | 5.15138902046611451e-05 * SOLAR_MASS) } |
92 | | |
93 | | |
94 | | SYSTEM = list(BODIES.values()) |
95 | | PAIRS = combinations(SYSTEM) |
96 | | |
97 | | |
98 | | def advance(dt, n, bodies=SYSTEM, pairs=PAIRS): |
99 | | |
100 | | for i in range(n): |
101 | | for (([x1, y1, z1], v1, m1), |
102 | | ([x2, y2, z2], v2, m2)) in pairs: |
103 | | dx = x1 - x2 |
104 | | dy = y1 - y2 |
105 | | dz = z1 - z2 |
106 | | mag = dt * ((dx * dx + dy * dy + dz * dz) ** (-1.5)) |
107 | | |
108 | | b1m = m1 * mag |
109 | | b2m = m2 * mag |
110 | | v1[0] -= dx * b2m |
111 | | v1[1] -= dy * b2m |
112 | | v1[2] -= dz * b2m |
113 | | v2[0] += dx * b1m |
114 | | v2[1] += dy * b1m |
115 | | v2[2] += dz * b1m |
116 | | for (r, [vx, vy, vz], m) in bodies: |
117 | | r[0] += dt * vx |
118 | | r[1] += dt * vy |
119 | | r[2] += dt * vz |
120 | | |
121 | | |
122 | | def report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0): |
123 | | #print ("Bodies Count:%s\nPairs Count:%s"%(len(bodies),len(pairs))) |
124 | | for (((x1, y1, z1), v1, m1), |
125 | | ((x2, y2, z2), v2, m2)) in pairs: |
126 | | dx = x1 - x2 |
127 | | dy = y1 - y2 |
128 | | dz = z1 - z2 |
129 | | #print (m1*m2) |
130 | | e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5) |
131 | | for (r, [vx, vy, vz], m) in bodies: |
132 | | e += m * (vx * vx + vy * vy + vz * vz) / 2. |
133 | | print("%.9f" % e) |
134 | | |
135 | | def offset_momentum(ref, bodies=SYSTEM): |
136 | | px=0.0 |
137 | | py=0.0 |
138 | | pz=0.0 |
139 | | |
140 | | for (r, [vx, vy, vz], m) in bodies: |
141 | | px -= vx * m |
142 | | py -= vy * m |
143 | | pz -= vz * m |
144 | | (r, v, m) = ref |
145 | | v[0] = px / m |
146 | | v[1] = py / m |
147 | | v[2] = pz / m |
148 | | |
149 | | def main(n, ref='sun'): |
150 | | from time import clock |
151 | | start = clock() |
152 | | report_energy() |
153 | | offset_momentum(BODIES[ref]) |
154 | | report_energy() |
155 | | advance(0.01, n) |
156 | | report_energy() |
157 | | duration = clock() - start |
158 | | |
159 | | print('duration: %s seconds \n\nDone...'%(duration)) |
160 | | if __name__ == '__main__': |
161 | | main(50000) |
162 | | |
163 | | |
164 | | }}} |
165 | | |
166 | | ---- |
167 | | |
168 | | *Initial Cobra Port:* |
169 | | |
170 | | {{{ |
171 | | # The Computer Language Benchmarks Game |
172 | | # http://shootout.alioth.debian.org/ |
173 | | # |
174 | | # originally by Kevin Carson |
175 | | # modified by Tupteq, Fredrik Johansson, and Daniel Nanz |
176 | | # modified by Maciej Fijalkowski |
177 | | # 2to3 |
178 | | #@number float |
179 | | class Triple |
180 | | pro x from var as decimal |
181 | | pro y from var as decimal |
182 | | pro z from var as decimal |
183 | | get squared as decimal |
184 | | return .x*.x + .y*.y + .z*.z |
185 | | |
186 | | cue init(x as decimal, y as decimal, z as decimal) |
187 | | base.init |
188 | | .x = x |
189 | | .y = y |
190 | | .z = z |
191 | | |
192 | | def toString as String is override |
193 | | return "\[[.x], [.y], [.z]\]" |
194 | | |
195 | | class Body |
196 | | pro coord from var as Triple |
197 | | pro velocity from var as Triple |
198 | | pro mass from var as decimal |
199 | | |
200 | | cue init(coord as Triple, velocity as Triple, mass as decimal) |
201 | | base.init |
202 | | .coord = coord |
203 | | .velocity = velocity |
204 | | .mass = mass |
205 | | |
206 | | class BodyPair |
207 | | pro body1 from var as Body |
208 | | pro body2 from var as Body |
209 | | |
210 | | cue init(body1 as Body, body2 as Body) |
211 | | base.init |
212 | | .body1 = body1 |
213 | | .body2 = body2 |
214 | | |
215 | | class Program |
216 | | def combinations(l) as List<of BodyPair> |
217 | | result = List<of BodyPair>() |
218 | | for x in l.count - 1 |
219 | | ls = l[x+1:] |
220 | | for y in ls |
221 | | result.add(BodyPair(l[x],y)) |
222 | | return result |
223 | | |
224 | | var bODIES |
225 | | cue init |
226 | | base.init |
227 | | |
228 | | .bODIES = { |
229 | | 'sun': Body(Triple(0.0, 0.0, 0.0), Triple(0.0, 0.0, 0.0), .sOLAR_MASS), |
230 | | |
231 | | 'jupiter': Body(Triple(4.84143144246472090, |
232 | | -1.16032004402742839, |
233 | | -0.103622044471123109), |
234 | | Triple(0.00166007664274403694 * .dAYS_PER_YEAR, |
235 | | 0.00769901118419740425 * .dAYS_PER_YEAR, |
236 | | -0.0000690460016972063023 * .dAYS_PER_YEAR), |
237 | | 0.000954791938424326609 * .sOLAR_MASS), |
238 | | |
239 | | 'saturn': Body(Triple(8.34336671824457987, |
240 | | 4.12479856412430479, |
241 | | -0.403523417114321381), |
242 | | Triple(-0.00276742510726862411 * .dAYS_PER_YEAR, |
243 | | 0.00499852801234917238 * .dAYS_PER_YEAR, |
244 | | 0.0000230417297573763929 * .dAYS_PER_YEAR), |
245 | | 0.000285885980666130812 * .sOLAR_MASS), |
246 | | |
247 | | 'uranus': Body(Triple(12.8943695621391310, |
248 | | -15.1111514016986312, |
249 | | -0.223307578892655734), |
250 | | Triple(0.00296460137564761618* .dAYS_PER_YEAR, |
251 | | 0.00237847173959480950* .dAYS_PER_YEAR, |
252 | | -0.0000296589568540237556* .dAYS_PER_YEAR), |
253 | | 0.0000436624404335156298* .sOLAR_MASS), |
254 | | |
255 | | 'neptune': Body(Triple(15.3796971148509165, |
256 | | -25.9193146099879641, |
257 | | 0.179258772950371181), |
258 | | Triple(0.00268067772490389322* .dAYS_PER_YEAR, |
259 | | 0.00162824170038242295* .dAYS_PER_YEAR, |
260 | | -0.0000951592254519715870* .dAYS_PER_YEAR), |
261 | | 0.0000515138902046611451* .sOLAR_MASS) |
262 | | } |
263 | | .sYSTEM = [.bODIES['sun'], |
264 | | .bODIES['jupiter'], |
265 | | .bODIES['saturn'], |
266 | | .bODIES['uranus'], |
267 | | .bODIES['neptune'] |
268 | | ] |
269 | | .pAIRS = .combinations(.sYSTEM) |
270 | | var sYSTEM |
271 | | var _pI = 3.14159265358979323 |
272 | | var sOLAR_MASS = 4 * 3.14159265358979323 * 3.14159265358979323 |
273 | | var dAYS_PER_YEAR = 365.24 |
274 | | |
275 | | var pAIRS |
276 | | |
277 | | |
278 | | def advance(dt as decimal, n as int) |
279 | | bodies=.sYSTEM |
280 | | pairs=.pAIRS |
281 | | |
282 | | for i in n |
283 | | for p in pairs |
284 | | x1, y1, z1 = p.body1.coord.x, p.body1.coord.y, p.body1.coord.z |
285 | | x2, y2, z2 = p.body2.coord.x, p.body2.coord.y, p.body2.coord.z |
286 | | m1, m2 = p.body1.mass, p.body2.mass |
287 | | v1, v2 =p.body1.velocity, p.body2.velocity |
288 | | dx = x1 - x2 |
289 | | dy = y1 - y2 |
290 | | dz = z1 - z2 |
291 | | mag = dt * (Math.pow(Convert.toDouble(dx * dx + dy * dy + dz * dz), -1.5f) to decimal) |
292 | | b1m = m1 * mag |
293 | | b2m = m2 * mag |
294 | | v1.x = v1.x - dx * b2m |
295 | | v1.y = v1.y - dy * b2m |
296 | | v1.z = v1.z - dz * b2m |
297 | | v2.x = v2.x + dx * b1m |
298 | | v2.y = v2.y + dy * b1m |
299 | | v2.z = v2.z + dz * b1m |
300 | | for b in bodies |
301 | | r = b.coord |
302 | | vx,vy,vz = b.velocity.x, b.velocity.y, b.velocity.z |
303 | | r.x = r.x + dt * vx |
304 | | r.y = r.y + dt * vy |
305 | | r.z = r.z + dt * vz |
306 | | |
307 | | |
308 | | def report_energy |
309 | | bodies=.sYSTEM |
310 | | pairs=.pAIRS |
311 | | #print "Bodies Count:[bodies.count]\nPairs Count:[pairs.count]" |
312 | | e=0.0 |
313 | | for p in pairs |
314 | | m = p.body1.mass * p.body2.mass |
315 | | #print m |
316 | | dx = p.body1.coord.x - p.body2.coord.x |
317 | | dy = p.body1.coord.y - p.body2.coord.y |
318 | | dz = p.body1.coord.z - p.body2.coord.z |
319 | | sqrs = Convert.toDouble(dx * dx + dy * dy + dz * dz) |
320 | | e = e - (m / Math.pow(sqrs , 0.5f) to decimal) |
321 | | for b in bodies |
322 | | e = e + b.mass * b.velocity.squared / 2.0 |
323 | | print e |
324 | | |
325 | | def offset_momentum(ref1 ) |
326 | | bodies=.sYSTEM |
327 | | px=0.0 |
328 | | py=0.0 |
329 | | pz=0.0 |
330 | | |
331 | | for b in bodies |
332 | | vx ,vy ,vz = b.velocity.x, b.velocity.y,b.velocity.z |
333 | | m = b.mass |
334 | | px = px - vx * m |
335 | | py =py - vy * m |
336 | | pz = pz - vz * m |
337 | | v, m = ref1.velocity, ref1.mass |
338 | | v.x = px / m |
339 | | v.y = py / m |
340 | | v.z = pz / m |
341 | | ref1.velocity = v |
342 | | print v |
343 | | |
344 | | def main |
345 | | sw = System.Diagnostics.Stopwatch() |
346 | | sw.start |
347 | | ref1 = 'sun' |
348 | | .report_energy |
349 | | .offset_momentum( .bODIES[ref1]) |
350 | | .report_energy |
351 | | .advance(0.01, 50000) |
352 | | .report_energy |
353 | | sw.stop |
354 | | print 'duration: [sw.elapsedMilliseconds] ms ' |
355 | | |
356 | | |
357 | | }}} |
358 | | |
359 | | ---- |
360 | | |
361 | | *Performance Improved version of Cobra code:* |
362 | | |
363 | | |
364 | | {{{ |
365 | | # The Computer Language Benchmarks Game |
366 | | # http://shootout.alioth.debian.org/ |
367 | | # |
368 | | # originally by Kevin Carson |
369 | | # modified by Tupteq, Fredrik Johansson, and Daniel Nanz |
370 | | # modified by Maciej Fijalkowski |
371 | | # 2to3 |
372 | | @number float |
373 | | class Triple |
374 | | var x as float |
375 | | var y as float |
376 | | var z as float |
377 | | #pro x from var as float |
378 | | #pro y from var as float |
379 | | #pro z from var as float |
380 | | get squared as float |
381 | | return .x*.x + .y*.y + .z*.z |
382 | | |
383 | | cue init(x as float, y as float, z as float) |
384 | | base.init |
385 | | .x = x |
386 | | .y = y |
387 | | .z = z |
388 | | |
389 | | def toString as String is override |
390 | | return "\[[.x], [.y], [.z]\]" |
391 | | |
392 | | class Body |
393 | | var coord as Triple |
394 | | var velocity as Triple |
395 | | var mass as float |
396 | | #pro coord from var as Triple |
397 | | #pro velocity from var as Triple |
398 | | #pro mass from var as float |
399 | | |
400 | | cue init(coord as Triple, velocity as Triple, mass as float) |
401 | | base.init |
402 | | .coord = coord |
403 | | .velocity = velocity |
404 | | .mass = mass |
405 | | |
406 | | def updateCoordinates(dt as float) |
407 | | .coord.x += dt * .velocity.x |
408 | | .coord.y += dt * .velocity.y |
409 | | .coord.z += dt * .velocity.z |
410 | | |
411 | | |
412 | | class BodyPair |
413 | | var body1 as Body |
414 | | var body2 as Body |
415 | | #pro body1 from var as Body |
416 | | #pro body2 from var as Body |
417 | | |
418 | | cue init(body1 as Body, body2 as Body) |
419 | | base.init |
420 | | .body1 = body1 |
421 | | .body2 = body2 |
422 | | |
423 | | class Program |
424 | | def combinations(l) as List<of BodyPair> |
425 | | result = List<of BodyPair>() |
426 | | for x in l.count - 1 |
427 | | ls = l[x+1:] |
428 | | for y in ls |
429 | | result.add(BodyPair(l[x],y)) |
430 | | return result |
431 | | |
432 | | cue init |
433 | | base.init |
434 | | |
435 | | bodies as Dictionary<of String, Body> = { |
436 | | 'sun': Body(Triple(0.0, 0.0, 0.0), Triple(0.0, 0.0, 0.0), .sOLAR_MASS), |
437 | | |
438 | | 'jupiter': Body(Triple(4.84143144246472090, |
439 | | -1.16032004402742839, |
440 | | -0.103622044471123109), |
441 | | Triple(0.00166007664274403694 * .dAYS_PER_YEAR, |
442 | | 0.00769901118419740425 * .dAYS_PER_YEAR, |
443 | | -0.0000690460016972063023 * .dAYS_PER_YEAR), |
444 | | 0.000954791938424326609 * .sOLAR_MASS), |
445 | | |
446 | | 'saturn': Body(Triple(8.34336671824457987, |
447 | | 4.12479856412430479, |
448 | | -0.403523417114321381), |
449 | | Triple(-0.00276742510726862411 * .dAYS_PER_YEAR, |
450 | | 0.00499852801234917238 * .dAYS_PER_YEAR, |
451 | | 0.0000230417297573763929 * .dAYS_PER_YEAR), |
452 | | 0.000285885980666130812 * .sOLAR_MASS), |
453 | | |
454 | | 'uranus': Body(Triple(12.8943695621391310, |
455 | | -15.1111514016986312, |
456 | | -0.223307578892655734), |
457 | | Triple(0.00296460137564761618* .dAYS_PER_YEAR, |
458 | | 0.00237847173959480950* .dAYS_PER_YEAR, |
459 | | -0.0000296589568540237556* .dAYS_PER_YEAR), |
460 | | 0.0000436624404335156298* .sOLAR_MASS), |
461 | | |
462 | | 'neptune': Body(Triple(15.3796971148509165, |
463 | | -25.9193146099879641, |
464 | | 0.179258772950371181), |
465 | | Triple(0.00268067772490389322* .dAYS_PER_YEAR, |
466 | | 0.00162824170038242295* .dAYS_PER_YEAR, |
467 | | -0.0000951592254519715870* .dAYS_PER_YEAR), |
468 | | 0.0000515138902046611451* .sOLAR_MASS) |
469 | | } |
470 | | .sYSTEM = List<of Body>() |
471 | | .sYSTEM.add(bodies['sun']) |
472 | | .sYSTEM.add(bodies['jupiter']) |
473 | | .sYSTEM.add(bodies['saturn']) |
474 | | .sYSTEM.add(bodies['uranus']) |
475 | | .sYSTEM.add(bodies['neptune']) |
476 | | .pAIRS = .combinations(.sYSTEM) |
477 | | var sYSTEM as List<of Body> |
478 | | var sOLAR_MASS as float = 4 * 3.14159265358979323 * 3.14159265358979323 |
479 | | var dAYS_PER_YEAR as float = 365.24 |
480 | | |
481 | | var pAIRS as List<of BodyPair> |
482 | | |
483 | | |
484 | | def advance(dt as float, n as int) |
485 | | bodies=.sYSTEM |
486 | | pairs=.pAIRS |
487 | | b1 as Body = bodies[0] |
488 | | b2 as Body = bodies[0] |
489 | | v1 as Triple = b1.velocity |
490 | | v2 as Triple = b2.velocity |
491 | | dx as float |
492 | | dy as float |
493 | | dz as float |
494 | | mag as float |
495 | | |
496 | | for i in n |
497 | | for p as BodyPair in pairs |
498 | | b1 = p.body1 |
499 | | b2 = p.body2 |
500 | | v1, v2 =b1.velocity, b2.velocity |
501 | | dx = b1.coord.x - b2.coord.x |
502 | | dy = b1.coord.y - b2.coord.y |
503 | | dz = b1.coord.z - b2.coord.z |
504 | | mag = dt * (Math.pow(dx * dx + dy * dy + dz * dz, -1.5f) ) |
505 | | b1m as float= b1.mass * mag |
506 | | b2m as float = b2.mass * mag |
507 | | v1.x = v1.x - dx * b2m |
508 | | v1.y = v1.y - dy * b2m |
509 | | v1.z = v1.z - dz * b2m |
510 | | v2.x = v2.x + dx * b1m |
511 | | v2.y = v2.y + dy * b1m |
512 | | v2.z = v2.z + dz * b1m |
513 | | for b as Body in bodies |
514 | | b.updateCoordinates(dt) |
515 | | |
516 | | |
517 | | def report_energy |
518 | | bodies=.sYSTEM |
519 | | pairs=.pAIRS |
520 | | #print "Bodies Count:[bodies.count]\nPairs Count:[pairs.count]" |
521 | | e as float=0.0 |
522 | | for p as BodyPair in pairs |
523 | | b1 as Body = p.body1 |
524 | | b2 as Body = p.body2 |
525 | | m = b1.mass * b2.mass |
526 | | #print m |
527 | | dx = b1.coord.x - b2.coord.x |
528 | | dy = b1.coord.y - b2.coord.y |
529 | | dz = b1.coord.z - b2.coord.z |
530 | | sqrs = dx * dx + dy * dy + dz * dz |
531 | | e -= m / Math.sqrt(sqrs ) |
532 | | for b as Body in bodies |
533 | | e += b.mass * b.velocity.squared *0.5 |
534 | | print e |
535 | | |
536 | | def offset_momentum(ref1 as Body) |
537 | | bodies=.sYSTEM |
538 | | px as float=0.0 |
539 | | py as float=0.0 |
540 | | pz as float=0.0 |
541 | | |
542 | | for b as Body in bodies |
543 | | m as float = b.mass |
544 | | px = px- b.velocity.x * m |
545 | | py = py-b.velocity.y * m |
546 | | pz = pz-b.velocity.z * m |
547 | | v, m = ref1.velocity, 1/ ref1.mass |
548 | | v.x = px * m |
549 | | v.y = py * m |
550 | | v.z = pz * m |
551 | | print v |
552 | | |
553 | | def main |
554 | | sw = System.Diagnostics.Stopwatch() |
555 | | sw.start |
556 | | .report_energy |
557 | | .offset_momentum( .sYSTEM[0]) #sun |
558 | | .report_energy |
559 | | .advance(0.01, 50000) |
560 | | .report_energy |
561 | | sw.stop |
562 | | print 'duration: [sw.elapsed] ms ' |
563 | | |
564 | | |
565 | | }}} |