Created
January 22, 2023 23:30
-
-
Save olleharstedt/07f0172423d167d97d813c954507ac22 to your computer and use it in GitHub Desktop.
PHP+C polyglot nbody benchmark
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//<?php echo "\x08\x08"; ob_start(); ?> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <glib.h> | |
#include <math.h> | |
#include <phollylib.c> | |
#if __PHP__//<?php | |
class GString { public $str; public function __construct($str) { $this->str = $str; } } | |
function g_string_new(string $str) { return new GString($str); } | |
function g_string_append(GString $s1, string $s2) { return new GString($s1->str . $s2); } | |
define("int", "int"); | |
define("float", "float"); | |
define("string", "string"); | |
function array_get($type, $arr, $i) { return $arr[$i]; } | |
function array_make($type, $length, ...$values) { return $values; } | |
function pprintf($format, ...$args) { fwrite( STDOUT, sprintf( $format, ...$args)); } | |
#endif//?> | |
//<?php | |
#__C__ typedef struct Body* Body; | |
class Body { | |
#define public float | |
#define __prop_x $__prop_x | |
public $__prop_x; | |
#undef public | |
#define public float | |
#define __prop_y $__prop_y | |
public $__prop_y; | |
#undef public | |
#define public float | |
#define __prop_z $__prop_z | |
public $__prop_z; | |
#undef public | |
#define public float | |
#define __prop_vx $__prop_vx | |
public $__prop_vx; | |
#undef public | |
#define public float | |
#define __prop_vy $__prop_vy | |
public $__prop_vy; | |
#undef public | |
#define public float | |
#define __prop_vz $__prop_vz | |
public $__prop_vz; | |
#undef public | |
#define public float | |
#define __prop_mass $__prop_mass | |
public $__prop_mass; | |
#undef public | |
#__C__ void (*offsetMomentum) (Body $__self, float $px, float $py, float $pz); | |
// End of C struct def. Class methods are outside the struct. | |
#__C__ }; | |
#__C__ void Body__offsetMomentum (Body $__self, float $px, float $py, float $pz) | |
#if __PHP__ | |
public function offsetMomentum(Body $__self, float $px, float $py, float $pz): void | |
#endif | |
{ | |
#__C__ float | |
$pi = 3.1415926535897931; | |
#__C__ float | |
$solarmass = 4. * $pi * $pi; | |
$__self->__prop_vx = (0. - $px) / $solarmass; | |
$__self->__prop_vy = (0. - $py) / $solarmass; | |
$__self->__prop_vz = (0. - $pz) / $solarmass; | |
} | |
#if __PHP__ | |
// End of PHP class def. | |
}; | |
#endif | |
#if __PHP__ | |
define("Body", "Body"); | |
#endif | |
//?> | |
// Function pointer init | |
Body Body__constructor(Body $p) | |
{ | |
$p->offsetMomentum = &Body__offsetMomentum; | |
return $p; | |
} | |
//<?php | |
#__C__ void advance(array $bodies, float $dt) | |
#if __PHP__ | |
function advance(array &$bodies, float $dt): void | |
#endif | |
{ | |
#__C__ int | |
$i = 0; | |
for (; $i < count($bodies); $i = $i + 1) { | |
#__C__ Body | |
$body = array_get(Body, $bodies, $i); | |
#__C__ array | |
$slice = array_slice($bodies, $i + 1); | |
#__C__ int | |
$__i = 0; | |
for (; $__i < count($slice); $__i = $__i + 1) { | |
#__C__ Body | |
$body2 = array_get(Body, $slice, $__i); | |
#__C__ float | |
$dx = $body->__prop_x - $body2->__prop_x; | |
#__C__ float | |
$dy = $body->__prop_y - $body2->__prop_y; | |
#__C__ float | |
$dz = $body->__prop_z - $body2->__prop_z; | |
#__C__ float | |
$distance = sqrt($dx * $dx + $dy * $dy + $dz * $dz); | |
#__C__ float | |
$mag = $dt / ($distance * $distance * $distance); | |
$body->__prop_vx = $body->__prop_vx - $dx * $body2->__prop_mass * $mag; | |
$body->__prop_vy = $body->__prop_vy - $dy * $body2->__prop_mass * $mag; | |
$body->__prop_vz = $body->__prop_vz - $dz * $body2->__prop_mass * $mag; | |
$body2->__prop_vx = $body2->__prop_vx + $dx * $body->__prop_mass * $mag; | |
$body2->__prop_vy = $body2->__prop_vy + $dy * $body->__prop_mass * $mag; | |
$body2->__prop_vz = $body2->__prop_vz + $dz * $body->__prop_mass * $mag; | |
} | |
} | |
#__C__ int | |
$__i = 0; | |
for (; $__i < count($bodies); $__i = $__i + 1) { | |
#__C__ Body | |
$body3 = array_get(Body, $bodies, $__i); | |
$body3->__prop_x = $body3->__prop_x + $dt * $body3->__prop_vx; | |
$body3->__prop_y = $body3->__prop_y + $dt * $body3->__prop_vy; | |
$body3->__prop_z = $body3->__prop_z + $dt * $body3->__prop_vz; | |
} | |
} | |
#__C__ float energy(array $bodies) | |
#if __PHP__ | |
function energy(array &$bodies): float | |
#endif | |
{ | |
#__C__ float | |
$e = 0.; | |
#__C__ int | |
$i = 0; | |
for (; $i < count($bodies); $i = $i + 1) { | |
#__C__ Body | |
$body = array_get(Body, $bodies, $i); | |
#__C__ float | |
$tmp2 = $body->__prop_vx * $body->__prop_vx + $body->__prop_vy * $body->__prop_vy + $body->__prop_vz * $body->__prop_vz; | |
$e += 0.5 * $body->__prop_mass * $tmp2; | |
#__C__ array | |
$slice = array_slice($bodies, $i + 1); | |
#__C__ int | |
$__i = 0; | |
for (; $__i < count($slice); $__i = $__i + 1) { | |
#__C__ Body | |
$body2 = array_get(Body, $slice, $__i); | |
#__C__ float | |
$dx = $body->__prop_x - $body2->__prop_x; | |
#__C__ float | |
$dy = $body->__prop_y - $body2->__prop_y; | |
#__C__ float | |
$dz = $body->__prop_z - $body2->__prop_z; | |
#__C__ float | |
$distance = sqrt($dx * $dx + $dy * $dy + $dz * $dz); | |
$e -= ($body->__prop_mass * $body2->__prop_mass) / $distance; | |
} | |
} | |
return $e; | |
} | |
#define function int | |
function main() | |
#undef function | |
{ | |
#__C__ float | |
$daysperyear = 365.24; | |
#__C__ float | |
$pi = 3.1415926535897931; | |
#__C__ float | |
$solarmass = 4. * $pi * $pi; | |
#__C__ Body | |
$jupiter = new(Body); | |
$jupiter->__prop_x = 4.8414314424647209; | |
$jupiter->__prop_y = -1.1603200440274284; | |
$jupiter->__prop_z = -0.10362204447112311; | |
$jupiter->__prop_vx = 0.0016600766427440369 * $daysperyear; | |
$jupiter->__prop_vy = 0.0076990111841974043 * $daysperyear; | |
$jupiter->__prop_vz = -6.90460016972063e-05 * $daysperyear; | |
$jupiter->__prop_mass = 0.00095479193842432661 * $solarmass; | |
#__C__ Body | |
$saturn = new(Body); | |
$saturn->__prop_x = 8.34336671824458; | |
$saturn->__prop_y = 4.1247985641243048; | |
$saturn->__prop_z = -0.40352341711432138; | |
$saturn->__prop_vx = -0.0027674251072686241 * $daysperyear; | |
$saturn->__prop_vy = 0.0049985280123491724 * $daysperyear; | |
$saturn->__prop_vz = 2.3041729757376393e-05 * $daysperyear; | |
$saturn->__prop_mass = 0.00028588598066613081 * $solarmass; | |
#__C__ Body | |
$uranus = new(Body); | |
$uranus->__prop_x = 12.894369562139131; | |
$uranus->__prop_y = -15.111151401698631; | |
$uranus->__prop_z = -0.22330757889265573; | |
$uranus->__prop_vx = 0.0029646013756476162 * $daysperyear; | |
$uranus->__prop_vy = 0.0023784717395948095 * $daysperyear; | |
$uranus->__prop_vz = -2.9658956854023756e-05 * $daysperyear; | |
$uranus->__prop_mass = 4.366244043351563e-05 * $solarmass; | |
#__C__ Body | |
$neptune = new(Body); | |
$neptune->__prop_x = 15.379697114850917; | |
$neptune->__prop_y = -25.919314609987964; | |
$neptune->__prop_z = 0.17925877295037118; | |
$neptune->__prop_vx = 0.0026806777249038932 * $daysperyear; | |
$neptune->__prop_vy = 0.001628241700382423 * $daysperyear; | |
$neptune->__prop_vz = -9.5159225451971587e-05 * $daysperyear; | |
$neptune->__prop_mass = 5.1513890204661145e-05 * $solarmass; | |
#__C__ Body | |
$sun = new(Body); | |
$sun->__prop_x = 0.; | |
$sun->__prop_y = 0.; | |
$sun->__prop_z = 0.; | |
$sun->__prop_vx = 0.; | |
$sun->__prop_vy = 0.; | |
$sun->__prop_vz = 0.; | |
$sun->__prop_mass = $solarmass; | |
#__C__ array | |
$bodies = array_make(Body, 5, $sun, $jupiter, $saturn, $uranus, $neptune); | |
#__C__ float | |
$px = 0.; | |
#__C__ float | |
$py = 0.; | |
#__C__ float | |
$pz = 0.; | |
#__C__ int | |
$__i = 0; | |
for (; $__i < count($bodies); $__i = $__i + 1) { | |
#__C__ Body | |
$body2 = array_get(Body, $bodies, $__i); | |
$px += $body2->__prop_vx * $body2->__prop_mass; | |
$py += $body2->__prop_vy * $body2->__prop_mass; | |
$pz += $body2->__prop_vz * $body2->__prop_mass; | |
} | |
#__C__ Body | |
$b = array_get(Body, $bodies, 0); | |
$b->offsetMomentum($b, $px, $py, $pz); | |
#__C__ float | |
$e = energy($bodies); | |
printf("%f\n", $e); | |
#__C__ int | |
$k = 0; | |
do { | |
advance($bodies, 0.01); | |
$k++; | |
} while ($k < 500000); | |
#__C__ float | |
$e2 = energy($bodies); | |
printf("%f\n", $e2); | |
return 0; | |
} | |
// ?> | |
// <?php ob_end_clean(); main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I use the following commands in my Makefile:
But you'd also need the phollylib.c from here: https://github.com/olleharstedt/pholyglot/blob/main/pholly/phollylib.c