Minimize unsafe in advance, make main safe
This commit is contained in:
parent
fd9ac09655
commit
a61113711f
67
src/main.rs
67
src/main.rs
@ -23,7 +23,7 @@ const SOLAR_MASS: f64 = 4. * PI * PI;
|
||||
const DAYS_PER_YEAR: f64 = 365.24;
|
||||
const BODIES_COUNT: usize = 5;
|
||||
|
||||
static mut solar_Bodies: [body; BODIES_COUNT] = [
|
||||
const STARTING_STATE: [body; BODIES_COUNT] = [
|
||||
body {
|
||||
// Sun
|
||||
mass: SOLAR_MASS,
|
||||
@ -181,7 +181,8 @@ fn output_Energy(bodies: &mut [body; BODIES_COUNT]) {
|
||||
// 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.
|
||||
unsafe fn advance(
|
||||
#[cfg(target_feature = "sse2")]
|
||||
fn advance(
|
||||
bodies: &mut [body; BODIES_COUNT],
|
||||
position_Deltas: &mut [Interactions; 3],
|
||||
magnitudes: &mut Interactions,
|
||||
@ -205,19 +206,21 @@ unsafe fn advance(
|
||||
// ROUNDED_INTERACTIONS_COUNT/2 iterations are done.
|
||||
for i in 0..ROUNDED_INTERACTIONS_COUNT / 2 {
|
||||
// Load position_Deltas of two bodies into position_Delta.
|
||||
let mut position_Delta = [_mm_setzero_pd(); 3];
|
||||
let mut position_Delta = [unsafe { _mm_setzero_pd() }; 3];
|
||||
|
||||
for m in 0..3 {
|
||||
position_Delta[m] = position_Deltas[m].as_vectors()[i];
|
||||
}
|
||||
|
||||
let distance_Squared: __m128d = _mm_add_pd(
|
||||
let distance_Squared: __m128d = unsafe {
|
||||
_mm_add_pd(
|
||||
_mm_mul_pd(position_Delta[0], position_Delta[0]),
|
||||
_mm_mul_pd(position_Delta[1], position_Delta[1]),
|
||||
),
|
||||
_mm_mul_pd(position_Delta[2], position_Delta[2]),
|
||||
);
|
||||
_mm_add_pd(
|
||||
_mm_mul_pd(position_Delta[0], position_Delta[0]),
|
||||
_mm_mul_pd(position_Delta[1], position_Delta[1]),
|
||||
),
|
||||
_mm_mul_pd(position_Delta[2], position_Delta[2]),
|
||||
)
|
||||
};
|
||||
|
||||
// Doing square roots normally using double precision floating point
|
||||
// math can be quite time consuming so SSE's much faster single
|
||||
@ -226,23 +229,25 @@ unsafe fn advance(
|
||||
// acceptable results so two iterations of the Newton–Raphson method are
|
||||
// done to improve precision further.
|
||||
let mut distance_Reciprocal: __m128d =
|
||||
_mm_cvtps_pd(_mm_rsqrt_ps(_mm_cvtpd_ps(distance_Squared)));
|
||||
unsafe { _mm_cvtps_pd(_mm_rsqrt_ps(_mm_cvtpd_ps(distance_Squared))) };
|
||||
|
||||
for _ in 0..2 {
|
||||
// Normally the last four multiplications in this equation would
|
||||
// have to be done sequentially but by placing the last
|
||||
// multiplication in parentheses, a compiler can then schedule that
|
||||
// multiplication earlier.
|
||||
distance_Reciprocal = _mm_sub_pd(
|
||||
_mm_mul_pd(distance_Reciprocal, _mm_set1_pd(1.5)),
|
||||
_mm_mul_pd(
|
||||
distance_Reciprocal = unsafe {
|
||||
_mm_sub_pd(
|
||||
_mm_mul_pd(distance_Reciprocal, _mm_set1_pd(1.5)),
|
||||
_mm_mul_pd(
|
||||
_mm_mul_pd(_mm_set1_pd(0.5), distance_Squared),
|
||||
distance_Reciprocal,
|
||||
_mm_mul_pd(
|
||||
_mm_mul_pd(_mm_set1_pd(0.5), distance_Squared),
|
||||
distance_Reciprocal,
|
||||
),
|
||||
_mm_mul_pd(distance_Reciprocal, distance_Reciprocal),
|
||||
),
|
||||
_mm_mul_pd(distance_Reciprocal, distance_Reciprocal),
|
||||
),
|
||||
);
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Calculate the magnitudes of force between the bodies. Typically this
|
||||
@ -253,10 +258,12 @@ unsafe fn advance(
|
||||
// distance_Squared which was already calculated earlier. Additionally
|
||||
// this method is probably a little more accurate due to less rounding
|
||||
// as well.
|
||||
magnitudes.as_vectors()[i] = _mm_mul_pd(
|
||||
_mm_div_pd(_mm_set1_pd(0.01), distance_Squared),
|
||||
distance_Reciprocal,
|
||||
);
|
||||
magnitudes.as_vectors()[i] = unsafe {
|
||||
_mm_mul_pd(
|
||||
_mm_div_pd(_mm_set1_pd(0.01), distance_Squared),
|
||||
distance_Reciprocal,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Use the calculated magnitudes of force to update the velocities for all
|
||||
@ -285,7 +292,7 @@ unsafe fn advance(
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// These are new:
|
||||
let mut solar_Bodies = STARTING_STATE;
|
||||
let mut position_Deltas: [Interactions; 3] = [Interactions {
|
||||
scalars: [0.; ROUNDED_INTERACTIONS_COUNT],
|
||||
}; 3];
|
||||
@ -293,13 +300,11 @@ fn main() {
|
||||
scalars: [0.; ROUNDED_INTERACTIONS_COUNT],
|
||||
};
|
||||
|
||||
unsafe {
|
||||
offset_Momentum(&mut solar_Bodies);
|
||||
output_Energy(&mut solar_Bodies);
|
||||
let c = std::env::args().nth(1).unwrap().parse().unwrap();
|
||||
for _ in 0..c {
|
||||
advance(&mut solar_Bodies, &mut position_Deltas, &mut magnitudes);
|
||||
}
|
||||
output_Energy(&mut solar_Bodies);
|
||||
offset_Momentum(&mut solar_Bodies);
|
||||
output_Energy(&mut solar_Bodies);
|
||||
let c = std::env::args().nth(1).unwrap().parse().unwrap();
|
||||
for _ in 0..c {
|
||||
advance(&mut solar_Bodies, &mut position_Deltas, &mut magnitudes);
|
||||
}
|
||||
output_Energy(&mut solar_Bodies);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user