use super::{AliasScore, Extent, plan::Plan};
use crate::buffer::Buffer;
use crate::error::CollapseError;
use crate::label::{Detail, Label, Source};
use crate::profile::Profile;
pub fn added(
parts: Vec<Plan>,
rate: u32,
extent: Extent,
profile: &Profile,
len: usize,
score: AliasScore,
) -> Result<(Buffer, Label), CollapseError> {
let mut collapsed = Vec::with_capacity(parts.len());
for part in parts {
collapsed.push(super::run(part, rate, extent, profile, len, score)?);
}
let width = collapsed
.iter()
.map(|(buffer, _)| buffer.width)
.max()
.expect("a sum row is built from its addends, and a sum has at least one");
let mut planes = vec![vec![0.0; len]; width];
for (buffer, _) in &collapsed {
for (c, plane) in planes.iter_mut().enumerate() {
let lane = match buffer.width {
1 => 0,
_ => c,
};
if lane >= buffer.width {
continue;
}
for (out, held) in plane.iter_mut().zip(buffer.plane(lane)) {
*out += held;
}
}
}
let labels: Vec<Label> = collapsed.into_iter().map(|(_, label)| label).collect();
Ok((
Buffer {
rate,
start: extent.start,
width,
planes,
},
label(&labels, profile, rate),
))
}
fn label(parts: &[Label], profile: &Profile, rate: u32) -> Label {
let source = match parts.iter().all(|p| p.source == Source::Exact) {
true => Source::Exact,
false => Source::Measured,
};
Label::new(
source,
profile.name,
rate,
Detail::Added {
parts: parts.iter().map(|p| p.detail.clone()).collect(),
},
)
}