Avoid excess allocations during fold operations
This commit is contained in:
parent
ee7ac064c7
commit
35104055d9
@ -450,7 +450,7 @@ impl<'a, N: Number> CountCard<'a, N> {
|
|||||||
|
|
||||||
/// Return the number of ballots across all parcels
|
/// Return the number of ballots across all parcels
|
||||||
pub fn num_ballots(&self) -> N {
|
pub fn num_ballots(&self) -> N {
|
||||||
return self.parcels.iter().fold(N::new(), |acc, p| acc + p.num_ballots());
|
return self.parcels.iter().fold(N::new(), |mut acc, p| { acc += p.num_ballots(); acc });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,7 +468,7 @@ pub struct Parcel<'a, N> {
|
|||||||
impl<'a, N: Number> Parcel<'a, N> {
|
impl<'a, N: Number> Parcel<'a, N> {
|
||||||
/// Return the number of ballots in this parcel
|
/// Return the number of ballots in this parcel
|
||||||
pub fn num_ballots(&self) -> N {
|
pub fn num_ballots(&self) -> N {
|
||||||
return self.votes.iter().fold(N::new(), |acc, v| acc + &v.ballot.orig_value);
|
return self.votes.iter().fold(N::new(), |mut acc, v| { acc += &v.ballot.orig_value; acc });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the value of the votes in this parcel
|
/// Return the value of the votes in this parcel
|
||||||
|
@ -82,7 +82,7 @@ where
|
|||||||
|
|
||||||
// Calculate loss by fraction - if minivoters used
|
// Calculate loss by fraction - if minivoters used
|
||||||
if let Some(orig_total) = &state.election.total_votes {
|
if let Some(orig_total) = &state.election.total_votes {
|
||||||
let mut total_votes = state.candidates.values().fold(N::new(), |acc, cc| acc + &cc.votes);
|
let mut total_votes = state.candidates.values().fold(N::new(), |mut acc, cc| { acc += &cc.votes; acc });
|
||||||
total_votes += &state.exhausted.votes;
|
total_votes += &state.exhausted.votes;
|
||||||
let lbf = orig_total - &total_votes;
|
let lbf = orig_total - &total_votes;
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ where
|
|||||||
|
|
||||||
if !has_surplus.is_empty() {
|
if !has_surplus.is_empty() {
|
||||||
let total_surpluses = has_surplus.iter()
|
let total_surpluses = has_surplus.iter()
|
||||||
.fold(N::new(), |acc, c| acc + &state.candidates[c].votes - quota);
|
.fold(N::new(), |mut acc, c| { acc += &state.candidates[c].votes; acc -= quota; acc });
|
||||||
|
|
||||||
// Determine if surplues can be deferred
|
// Determine if surplues can be deferred
|
||||||
if opts.defer_surpluses {
|
if opts.defer_surpluses {
|
||||||
|
@ -254,11 +254,16 @@ impl<'e, N: Number> TransferTable<'e, N> {
|
|||||||
|
|
||||||
// Sum total votes_out per candidate
|
// Sum total votes_out per candidate
|
||||||
for (candidate, cell) in self.total.cells.iter_mut() {
|
for (candidate, cell) in self.total.cells.iter_mut() {
|
||||||
cell.votes_out = self.columns.iter().fold(N::new(), |acc, col| if let Some(cell) = col.cells.get(candidate) { acc + &cell.votes_out } else { acc });
|
cell.votes_out = self.columns.iter().fold(N::new(), |mut acc, col| {
|
||||||
|
if let Some(cell) = col.cells.get(candidate) {
|
||||||
|
acc += &cell.votes_out
|
||||||
|
}
|
||||||
|
acc
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum total exhausted votes
|
// Sum total exhausted votes
|
||||||
self.total.exhausted.votes_out = self.columns.iter().fold(N::new(), |acc, col| acc + &col.exhausted.votes_out);
|
self.total.exhausted.votes_out = self.columns.iter().fold(N::new(), |mut acc, col| { acc += &col.exhausted.votes_out; acc });
|
||||||
}
|
}
|
||||||
RoundSubtransfersMode::PerBallot => {
|
RoundSubtransfersMode::PerBallot => {
|
||||||
// Calculate votes_out for each column
|
// Calculate votes_out for each column
|
||||||
@ -316,11 +321,16 @@ impl<'e, N: Number> TransferTable<'e, N> {
|
|||||||
|
|
||||||
// Sum total votes_out per candidate
|
// Sum total votes_out per candidate
|
||||||
for (candidate, cell) in self.total.cells.iter_mut() {
|
for (candidate, cell) in self.total.cells.iter_mut() {
|
||||||
cell.votes_out = self.columns.iter().fold(N::new(), |acc, col| if let Some(cell) = col.cells.get(candidate) { acc + &cell.votes_out } else { acc });
|
cell.votes_out = self.columns.iter().fold(N::new(), |mut acc, col| {
|
||||||
|
if let Some(cell) = col.cells.get(candidate) {
|
||||||
|
acc += &cell.votes_out;
|
||||||
|
}
|
||||||
|
acc
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum total exhausted votes
|
// Sum total exhausted votes
|
||||||
self.total.exhausted.votes_out = self.columns.iter().fold(N::new(), |acc, col| acc + &col.exhausted.votes_out);
|
self.total.exhausted.votes_out = self.columns.iter().fold(N::new(), |mut acc, col| { acc += &col.exhausted.votes_out; acc });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ where
|
|||||||
|
|
||||||
// Calculate loss by fraction - if minivoters used
|
// Calculate loss by fraction - if minivoters used
|
||||||
if let Some(orig_total) = &state.election.total_votes {
|
if let Some(orig_total) = &state.election.total_votes {
|
||||||
let mut total_votes = state.candidates.values().fold(N::new(), |acc, cc| acc + &cc.votes);
|
let mut total_votes = state.candidates.values().fold(N::new(), |mut acc, cc| { acc += &cc.votes; acc });
|
||||||
total_votes += &state.exhausted.votes;
|
total_votes += &state.exhausted.votes;
|
||||||
let lbf = orig_total - &total_votes;
|
let lbf = orig_total - &total_votes;
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ where
|
|||||||
// Distribute if the total surplus exceeds the tolerance
|
// Distribute if the total surplus exceeds the tolerance
|
||||||
let quota_tolerance = N::parse(&opts.meek_surplus_tolerance);
|
let quota_tolerance = N::parse(&opts.meek_surplus_tolerance);
|
||||||
let total_surpluses = has_surplus.iter()
|
let total_surpluses = has_surplus.iter()
|
||||||
.fold(N::new(), |acc, c| acc + &state.candidates[c].votes - state.quota.as_ref().unwrap());
|
.fold(N::new(), |mut acc, c| { acc += &state.candidates[c].votes; acc -= state.quota.as_ref().unwrap(); acc });
|
||||||
return total_surpluses > quota_tolerance;
|
return total_surpluses > quota_tolerance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ where
|
|||||||
// Determine if surplues can be deferred
|
// Determine if surplues can be deferred
|
||||||
if opts.defer_surpluses {
|
if opts.defer_surpluses {
|
||||||
let total_surpluses = has_surplus.iter()
|
let total_surpluses = has_surplus.iter()
|
||||||
.fold(N::new(), |acc, c| acc + &state.candidates[c].votes - quota);
|
.fold(N::new(), |mut acc, c| { acc += &state.candidates[c].votes; acc -= quota; acc });
|
||||||
if super::can_defer_surpluses(state, opts, &total_surpluses) {
|
if super::can_defer_surpluses(state, opts, &total_surpluses) {
|
||||||
state.logger.log_literal(format!("Distribution of surpluses totalling {:.dps$} votes will be deferred.", total_surpluses, dps=opts.pp_decimals));
|
state.logger.log_literal(format!("Distribution of surpluses totalling {:.dps$} votes will be deferred.", total_surpluses, dps=opts.pp_decimals));
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
@ -314,7 +314,7 @@ where
|
|||||||
// Determine if surplues can be deferred
|
// Determine if surplues can be deferred
|
||||||
if should_distribute && opts.defer_surpluses {
|
if should_distribute && opts.defer_surpluses {
|
||||||
let total_surpluses = has_surplus.iter()
|
let total_surpluses = has_surplus.iter()
|
||||||
.fold(N::new(), |acc, c| acc + &state.candidates[c].votes - quota);
|
.fold(N::new(), |mut acc, c| { acc += &state.candidates[c].votes; acc -= quota; acc });
|
||||||
if super::can_defer_surpluses(state, opts, &total_surpluses) {
|
if super::can_defer_surpluses(state, opts, &total_surpluses) {
|
||||||
surpluses_deferred = Some(total_surpluses);
|
surpluses_deferred = Some(total_surpluses);
|
||||||
break;
|
break;
|
||||||
|
@ -1093,15 +1093,14 @@ fn elect_sure_winners<'a, N: Number>(state: &mut CountState<'a, N>, opts: &STVOp
|
|||||||
|
|
||||||
let mut total_trailing = N::new();
|
let mut total_trailing = N::new();
|
||||||
// For leading candidates, count only untransferred surpluses
|
// For leading candidates, count only untransferred surpluses
|
||||||
total_trailing += hopefuls.iter().take(num_vacancies).fold(N::new(), |acc, (_, cc)| {
|
total_trailing += hopefuls.iter().take(num_vacancies).fold(N::new(), |mut acc, (_, cc)| {
|
||||||
if &cc.votes > state.quota.as_ref().unwrap() {
|
if &cc.votes > state.quota.as_ref().unwrap() {
|
||||||
acc + &cc.votes - state.quota.as_ref().unwrap()
|
acc += &cc.votes; acc -= state.quota.as_ref().unwrap();
|
||||||
} else {
|
|
||||||
acc
|
|
||||||
}
|
}
|
||||||
|
acc
|
||||||
});
|
});
|
||||||
// For trailing candidates, count all votes
|
// For trailing candidates, count all votes
|
||||||
total_trailing += hopefuls.iter().skip(num_vacancies).fold(N::new(), |acc, (_, cc)| acc + &cc.votes);
|
total_trailing += hopefuls.iter().skip(num_vacancies).fold(N::new(), |mut acc, (_, cc)| { acc += &cc.votes; acc });
|
||||||
// Add finally any votes awaiting transfer
|
// Add finally any votes awaiting transfer
|
||||||
total_trailing += state.candidates.values().fold(N::zero(), |acc, cc| {
|
total_trailing += state.candidates.values().fold(N::zero(), |acc, cc| {
|
||||||
match cc.state {
|
match cc.state {
|
||||||
@ -1298,7 +1297,7 @@ where
|
|||||||
let num_to_exclude = to_exclude.len();
|
let num_to_exclude = to_exclude.len();
|
||||||
if num_to_exclude > 0 {
|
if num_to_exclude > 0 {
|
||||||
let total_excluded = to_exclude.into_iter()
|
let total_excluded = to_exclude.into_iter()
|
||||||
.fold(N::new(), |acc, c| acc + &state.candidates[c].votes);
|
.fold(N::new(), |mut acc, c| { acc += &state.candidates[c].votes; acc });
|
||||||
if total_surpluses >= &(&hopefuls[num_to_exclude].1.votes - &total_excluded) {
|
if total_surpluses >= &(&hopefuls[num_to_exclude].1.votes - &total_excluded) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1497,7 +1496,7 @@ fn hopefuls_to_bulk_exclude<'a, N: Number>(state: &CountState<'a, N>, _opts: &ST
|
|||||||
|
|
||||||
let total_surpluses = state.candidates.iter()
|
let total_surpluses = state.candidates.iter()
|
||||||
.filter(|(_, cc)| !cc.finalised && &cc.votes > state.quota.as_ref().unwrap())
|
.filter(|(_, cc)| !cc.finalised && &cc.votes > state.quota.as_ref().unwrap())
|
||||||
.fold(N::new(), |agg, (_, cc)| agg + &cc.votes - state.quota.as_ref().unwrap());
|
.fold(N::new(), |mut acc, (_, cc)| { acc += &cc.votes; acc -= state.quota.as_ref().unwrap(); acc });
|
||||||
|
|
||||||
// Attempt to exclude as many candidates as possible
|
// Attempt to exclude as many candidates as possible
|
||||||
for i in 0..hopefuls.len() {
|
for i in 0..hopefuls.len() {
|
||||||
@ -1509,7 +1508,7 @@ fn hopefuls_to_bulk_exclude<'a, N: Number>(state: &CountState<'a, N>, _opts: &ST
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not exclude if this could change the order of exclusion
|
// Do not exclude if this could change the order of exclusion
|
||||||
let total_votes = try_exclude.iter().fold(N::new(), |agg, (_, cc)| agg + &cc.votes);
|
let total_votes = try_exclude.iter().fold(N::new(), |mut acc, (_, cc)| { acc += &cc.votes; acc });
|
||||||
if i != 0 && total_votes + &total_surpluses >= hopefuls[hopefuls.len()-i].1.votes {
|
if i != 0 && total_votes + &total_surpluses >= hopefuls[hopefuls.len()-i].1.votes {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ where
|
|||||||
|
|
||||||
if opts.sample == SampleMethod::StratifyLR {
|
if opts.sample == SampleMethod::StratifyLR {
|
||||||
// Round remainders to remove loss by fraction
|
// Round remainders to remove loss by fraction
|
||||||
let transferred = candidate_transfers_remainders.values().fold(N::new(), |acc, (t, _)| acc + t);
|
let transferred = candidate_transfers_remainders.values().fold(N::new(), |mut acc, (t, _)| { acc += t; acc });
|
||||||
let loss_fraction = &surplus - &transferred;
|
let loss_fraction = &surplus - &transferred;
|
||||||
if !loss_fraction.is_zero() && surplus_fraction.is_some() {
|
if !loss_fraction.is_zero() && surplus_fraction.is_some() {
|
||||||
let n_to_round: usize = format!("{:.0}", loss_fraction).parse().expect("Loss by fraction overflows usize");
|
let n_to_round: usize = format!("{:.0}", loss_fraction).parse().expect("Loss by fraction overflows usize");
|
||||||
|
Loading…
Reference in New Issue
Block a user