Skip to content

Commit b1eb511

Browse files
authored
perf(system): eliminate two Planetesimal clones in planetesimals_inte… (#21)
1 parent 80b7fbb commit b1eb511

2 files changed

Lines changed: 25 additions & 6 deletions

File tree

src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,4 +231,13 @@ mod tests {
231231
let system = format!("{:?}", accrete.planet());
232232
assert_eq!(system, fixture);
233233
}
234+
235+
#[test]
236+
fn same_seed_same_system_after_fix_3a() {
237+
let mut a1 = Accrete::new(1);
238+
let s1 = a1.planetary_system();
239+
let mut a2 = Accrete::new(1);
240+
let s2 = a2.planetary_system();
241+
assert_eq!(format!("{:?}", s1), format!("{:?}", s2));
242+
}
234243
}

src/structs/system.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,17 +254,27 @@ pub fn planetesimals_intersect(
254254
if p.is_moon {
255255
*prev_p = coalesce_two_planets(prev_p, p, events_log.as_deref_mut());
256256
} else {
257-
// Check for larger/smaller planetesimal
258-
let (larger, smaller) = match p.mass >= prev_p.mass {
259-
true => (p.clone(), prev_p.clone()),
260-
false => (prev_p.clone(), p.clone()),
257+
// Compute roche_limit from scalars — avoids deep-cloning both bodies
258+
// (each carries Vec<Planetesimal> moons + Vec<Ring> rings) just to read
259+
// three f64s. The original code cloned `larger` and `smaller` purely to
260+
// satisfy the borrow checker. Third arg to roche_limit_au is the
261+
// smaller/moon body's radius (see roche_limit_au doc in utils.rs).
262+
let (larger_mass, smaller_mass, smaller_radius) = if p.mass >= prev_p.mass {
263+
(p.mass, prev_p.mass, prev_p.radius)
264+
} else {
265+
(prev_p.mass, p.mass, p.radius)
261266
};
262-
let roche_limit = roche_limit_au(&larger.mass, &smaller.mass, &smaller.radius);
267+
let roche_limit = roche_limit_au(&larger_mass, &smaller_mass, &smaller_radius);
263268
// Planetesimals collide or one capture another as moon
264269
if (prev_p.a - p.a).abs() <= roche_limit * 2.0 {
265270
*prev_p = coalesce_two_planets(prev_p, p, events_log.as_deref_mut());
266271
} else {
267-
*prev_p = capture_moon(&larger, &smaller, primary_star_mass, rng, events_log.as_deref_mut());
272+
// Ensure prev_p holds the larger body before capture_moon. Use
273+
// `>=` to preserve the original tiebreak (p wins on equal mass).
274+
if p.mass >= prev_p.mass {
275+
std::mem::swap(p, prev_p);
276+
}
277+
*prev_p = capture_moon(prev_p, p, primary_star_mass, rng, events_log.as_deref_mut());
268278
prev_p
269279
.moons
270280
.sort_by(|p1, p2| p1.a.partial_cmp(&p2.a).unwrap());

0 commit comments

Comments
 (0)