style(simulation): fmt + clippy fixes for the measurement batch (gate bounce)

cargo fmt across the four new files; needless_range_loop x2 (enumerate /
iter_mut) and identity_op in hydrology_equilibrium.rs. cargo test was green
on the bounced push — lint-only fixes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 19:25:08 +02:00
co-authored by Claude Fable 5
parent 473b654787
commit 976d4016e9
4 changed files with 129 additions and 71 deletions
+45 -34
View File
@@ -219,9 +219,9 @@ pub fn solve(
let mut spill_cell: Vec<Option<usize>> = vec![None; basin_count];
let mut spill_rim_elev: Vec<i64> = vec![i64::MAX; basin_count];
let mut basin_cells: Vec<Vec<usize>> = vec![Vec::new(); basin_count];
for idx in 0..n {
if let Some(b) = basin_of[idx] {
basin_cells[b as usize].push(idx);
for (idx, entry) in basin_of.iter().enumerate().take(n) {
if let Some(b) = entry {
basin_cells[*b as usize].push(idx);
}
}
for idx in 0..n {
@@ -345,11 +345,9 @@ pub fn solve(
cells: basin_cells[b].clone(),
spill_level_scaled: spill_level[b],
spill_cell: spill_cell[b].unwrap_or(0),
outcome: outcomes[b]
.clone()
.unwrap_or(BasinOutcome::Endorheic {
reason: EndorheicReason::MoistureGoverned,
}),
outcome: outcomes[b].clone().unwrap_or(BasinOutcome::Endorheic {
reason: EndorheicReason::MoistureGoverned,
}),
})
.collect();
@@ -569,7 +567,10 @@ fn cheapest_overflow_path(
// open plain. This is intentionally the same bucket as
// EdgeUnreachable's shape (no further basin/sea structure)
// but WITH a real path, so callers still get carving data.
return (reconstruct_path(&came, idx), DownstreamTarget::EdgeUnreachable);
return (
reconstruct_path(&came, idx),
DownstreamTarget::EdgeUnreachable,
);
}
}
@@ -757,7 +758,11 @@ mod tests {
fn bowl_grid_produces_at_least_one_lake_basin() {
let elev = bowl_grid(64, 32);
let result = solve(&elev, 64, 32, 0.0, default_climate());
let nonempty: Vec<_> = result.basins.iter().filter(|b| !b.cells.is_empty()).collect();
let nonempty: Vec<_> = result
.basins
.iter()
.filter(|b| !b.cells.is_empty())
.collect();
assert!(
!nonempty.is_empty(),
"a bowl-shaped depression must fill to at least one lake basin"
@@ -787,13 +792,23 @@ mod tests {
let elev = slope_grid(128, 64);
let r1 = solve(&elev, 128, 64, 0.3, default_climate());
let r2 = solve(&elev, 128, 64, 0.3, default_climate());
assert_eq!(r1.filled_scaled, r2.filled_scaled, "filled surface must be deterministic");
assert_eq!(
r1.filled_scaled, r2.filled_scaled,
"filled surface must be deterministic"
);
assert_eq!(
r1.channel_depth_scaled, r2.channel_depth_scaled,
"carved channel depth must be deterministic"
);
assert_eq!(r1.cliff_edge, r2.cliff_edge, "cliff-edge flags must be deterministic");
assert_eq!(r1.basins.len(), r2.basins.len(), "basin count must be deterministic");
assert_eq!(
r1.cliff_edge, r2.cliff_edge,
"cliff-edge flags must be deterministic"
);
assert_eq!(
r1.basins.len(),
r2.basins.len(),
"basin count must be deterministic"
);
for (a, b) in r1.basins.iter().zip(r2.basins.iter()) {
assert_eq!(a.basin_id, b.basin_id);
assert_eq!(a.cells, b.cells);
@@ -838,13 +853,7 @@ mod tests {
fn overflowing_basin_has_nonempty_outlet_path() {
let elev = bowl_grid(64, 32);
// Force overflow classification via high moisture.
let result = solve(
&elev,
64,
32,
0.0,
ClimateInputs { moisture_q: 90 },
);
let result = solve(&elev, 64, 32, 0.0, ClimateInputs { moisture_q: 90 });
let overflowed: Vec<_> = result
.basins
.iter()
@@ -857,7 +866,10 @@ mod tests {
);
for basin in overflowed {
if let BasinOutcome::Overflow { outlet_path, .. } = &basin.outcome {
assert!(!outlet_path.is_empty(), "overflow basin must have a search path");
assert!(
!outlet_path.is_empty(),
"overflow basin must have a search path"
);
}
}
}
@@ -865,13 +877,7 @@ mod tests {
#[test]
fn large_dry_basin_classifies_endorheic() {
let elev = bowl_grid(96, 48);
let result = solve(
&elev,
96,
48,
0.0,
ClimateInputs { moisture_q: 10 },
);
let result = solve(&elev, 96, 48, 0.0, ClimateInputs { moisture_q: 10 });
let has_endorheic = result
.basins
.iter()
@@ -905,7 +911,10 @@ mod tests {
for basin in &result.basins {
let mut sorted = basin.cells.clone();
sorted.sort_unstable();
assert_eq!(basin.cells, sorted, "basin cells must be in ascending row-major order");
assert_eq!(
basin.cells, sorted,
"basin cells must be in ascending row-major order"
);
}
}
@@ -964,8 +973,7 @@ mod tests {
original[14] = 50_000; // valid open-low-ground terminus (row2,col4)
let mut basin_of: Vec<Option<u32>> = vec![None; w * h];
basin_of[12] = Some(0);
let (path, target) =
cheapest_overflow_path(12, 100_000, &original, &basin_of, 0, -1, w, h);
let (path, target) = cheapest_overflow_path(12, 100_000, &original, &basin_of, 0, -1, w, h);
assert_eq!(
target,
DownstreamTarget::EdgeUnreachable,
@@ -995,8 +1003,8 @@ mod tests {
let w = 20usize;
let h = 2usize;
let mut original = vec![999_999i64; w * h];
for c in 0..w {
original[c] = 50_000; // row 0, the corridor
for cell in original.iter_mut().take(w) {
*cell = 50_000; // row 0, the corridor
}
original[1] = 0; // spill cell (row0,col1)
original[7] = -10_000; // sea-level terminus (row0,col7)
@@ -1014,7 +1022,10 @@ mod tests {
// level (0) — this is the exact shape `solve()`'s carving step
// consumes: `original[cell] - spill_level` for each path cell.
for &cell in &path[1..path.len() - 1] {
assert!(original[cell] - 0 > 0, "intermediate cells must be above spill level");
assert!(
original[cell] > 0,
"intermediate cells must be above spill level (spill level is 0 here)"
);
}
}