// The Computer Language Benchmarks Game // https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ // // Contributed by Mark C. Lewis. // Modified slightly by Chad Whipkey. // Converted from Java to C++ and added SSE support by Branimir Maksimovic. // Converted from C++ to C by Alexey Medvedchikov. // Modified by Jeremy Zerfas. #include #include #include #include #include // intptr_t should be the native integer type on most sane systems. typedef intptr_t intnative_t; typedef struct{ double position[3], velocity[3], mass; } body; #define SOLAR_MASS (4*M_PI*M_PI) #define DAYS_PER_YEAR 365.24 #define BODIES_COUNT 5 static body solar_Bodies[]={ { // Sun .mass=SOLAR_MASS }, { // Jupiter { 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 }, { // Saturn { 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 }, { // Uranus { 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 }, { // Neptune { 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 } }; // Advance all the bodies in the system by one timestep. Calculate the // interactions between all the bodies, update each body's velocity based on // those interactions, and update each body's position by the distance it // travels in a timestep at it's updated velocity. static void advance(body bodies[]){ // Figure out how many total different interactions there are between each // body and every other body. Some of the calculations for these // interactions will be calculated two at a time by using x86 SSE // instructions and because of that it will also be useful to have a // ROUNDED_INTERACTIONS_COUNT that is equal to the next highest even number // which is equal to or greater than INTERACTIONS_COUNT. #define INTERACTIONS_COUNT (BODIES_COUNT*(BODIES_COUNT-1)/2) #define ROUNDED_INTERACTIONS_COUNT (INTERACTIONS_COUNT+INTERACTIONS_COUNT%2) // It's useful to have two arrays to keep track of the position_Deltas // and magnitudes of force between the bodies for each interaction. For the // position_Deltas array, instead of using a one dimensional array of // structures that each contain the X, Y, and Z components for a position // delta, a two dimensional array is used instead which consists of three // arrays that each contain all of the X, Y, and Z components for all of the // position_Deltas. This allows for more efficient loading of this data into // SSE registers. Both of these arrays are also set to contain // ROUNDED_INTERACTIONS_COUNT elements to simplify one of the following // loops and to also keep the second and third arrays in position_Deltas // aligned properly. static alignas(__m128d) double position_Deltas[3][ROUNDED_INTERACTIONS_COUNT], magnitudes[ROUNDED_INTERACTIONS_COUNT]; // Calculate the position_Deltas between the bodies for each interaction. for(intnative_t i=0, k=0; i