Ah, doesn't matter; this is actually incorrect, because it is leaving values in `partials` that shouldn't be there (that is, `partials` never gets shorter, even though it is supposed to). A (rather extreme) test case that demonstrates:

```rust
fn main() {
    // 2.0^i for i = -1000, -900, ..., 900, 1000
    let pos = std::iter::range_step(-1000, 1001, 100)
        .map(|i| 2f64.pow(&(i as f64))).to_owned_vec();
    // the negation of the above, to cancel them out
    let neg = ascending.iter().map(|&v| -v).to_owned_vec();

    let mut v = pos + &[10.0] + neg;
    assert_eq!(v.sum(), 10.0);
}
```

(In this test case, `partials` should grow by 1 at each step (since each element of `pos` is in a completely new "size class" (that is, it not within of floating-point epsilon of any other value) until it reaches the end of the `pos` part of the vector, and then contract by one for each element of the `neg` part (as they progressively cancel out the parts the `pos` vector).)

Replacing everything after `for (f1, partial) ... ` with:

```rust
    modifications.push(x);
    util::swap(&mut modifications, &mut partials);
```

works perfectly. That is, it just put the value of `modifications` as the new `partials` (since this is exactly what it is doing, storing the new values of `partials`), and reuses the old `partials` buffer to avoid allocating. (FWIW, renaming `modifications` to something like `next_partials` would make this clearer.)

Also, I think `i` is even less necessary with this scheme.