Skip to main content

round_layout_stable

Function round_layout_stable 

Source
pub fn round_layout_stable(
    targets: &[f64],
    total: u16,
    prev: PreviousAllocation,
) -> Vec<u16>
Expand description

Round real-valued layout targets to integer cells with exact sum conservation.

§Mathematical Model

Given real-valued targets r_i (from the constraint solver) and a required integer total, find integer allocations x_i that:

minimize   Σ_i |x_i − r_i|  +  μ · Σ_i |x_i − x_i_prev|
subject to Σ_i x_i = total
           x_i ≥ 0

where x_i_prev is the previous frame’s allocation and μ is the temporal stability weight (default 0.1).

§Algorithm: Largest Remainder with Temporal Tie-Breaking

This uses a variant of the Largest Remainder Method (Hamilton’s method), which provides optimal bounded displacement (|x_i − r_i| < 1 for all i):

  1. Floor phase: Set x_i = floor(r_i) for each element.
  2. Deficit: Compute D = total − Σ floor(r_i) extra cells to distribute.
  3. Priority sort: Rank elements by remainder r_i − floor(r_i) (descending). Break ties using a composite key: a. Prefer elements where x_i_prev = ceil(r_i) (temporal stability). b. Prefer elements with smaller index (determinism).
  4. Distribute: Award one extra cell to each of the top D elements.

§Properties

  1. Sum conservation: Σ x_i = total exactly (proven by construction).
  2. Bounded displacement: |x_i − r_i| < 1 for all i (since each x_i is either floor(r_i) or ceil(r_i)).
  3. Deterministic: Same inputs → identical outputs (temporal tie-break + index tie-break provide total ordering).
  4. Temporal coherence: When targets change slightly, allocations tend to stay the same (preferring the previous frame’s rounding direction).
  5. Optimal displacement: Among all integer allocations summing to total with floor(r_i) ≤ x_i ≤ ceil(r_i), the Largest Remainder Method minimizes total absolute displacement.

§Failure Modes

  • All-zero targets: Returns all zeros. Harmless (empty layout).
  • Negative deficit: Can occur if targets sum to less than total after flooring. The algorithm handles this via the clamp in step 2.
  • Very large N: O(N log N) due to sorting. Acceptable for typical layout counts (< 100 items).

§Example

use ftui_layout::round_layout_stable;

// Targets: [10.4, 20.6, 9.0] must sum to 40
let result = round_layout_stable(&[10.4, 20.6, 9.0], 40, None);
assert_eq!(result.iter().sum::<u16>(), 40);
// 10.4 → 10, 20.6 → 21, 9.0 → 9 = 40 ✓
assert_eq!(result, vec![10, 21, 9]);