fn accumulate_nonzero_probabilities<Symbol, Probability, S, P, Op, const PRECISION: usize>(
    mut symbols: S,
    probabilities: P,
    mut operation: Op,
    infer_last_probability: bool,
) -> Result<S, ()>
where
    Probability: BitArray,
    S: Iterator<Item = Symbol>,
    P: Iterator,
    P::Item: Borrow<Probability>,
    Op: FnMut(Symbol, Probability, Probability) -> Result<(), ()>,
{
    assert!(PRECISION > 0);
    assert!(PRECISION <= Probability::BITS);

    // We accumulate all validity checks into single branches at the end in order to
    // keep the loop itself branchless.
    let mut laps_or_zeros = 0usize;
    let mut accum = Probability::zero();

    for probability in probabilities {
        let old_accum = accum;
        accum = accum.wrapping_add(probability.borrow());
        laps_or_zeros += (accum <= old_accum) as usize;
        let symbol = symbols.next().ok_or(())?;
        operation(symbol, old_accum, *probability.borrow())?;
    }

    let total = wrapping_pow2::<Probability>(PRECISION);

    if infer_last_probability {
        if accum >= total || laps_or_zeros != 0 {
            return Err(());
        }
        let symbol = symbols.next().ok_or(())?;
        let probability = total.wrapping_sub(&accum);
        operation(symbol, accum, probability)?;
    } else if accum != total || laps_or_zeros != (PRECISION == Probability::BITS) as usize {
        return Err(());
    }

    Ok(symbols)
}
/// Note: does not check if `symbols` is exhausted (this is so that you one can provide an
/// infinite iterator for `symbols` to optimize out the bounds check on it).
does not check if `symbols` is exhausted (this is so that you one can provide an
infinite iterator for `symbols` to optimize out the bounds check on it).
does not check if ` symbols ` is exhausted ( this is so that you one can provide an infinite iterator for ` symbols ` to optimize out the bounds check on it ) .
fn accumulate_nonzero_probabilities<Symbol, Probability, S, P, Op, const PRECISION: usize>(
    mut symbols: S,
    probabilities: P,
    mut operation: Op,
    infer_last_probability: bool,
) -> Result<S, ()>
where
    Probability: BitArray,
    S: Iterator<Item = Symbol>,
    P: Iterator,
    P::Item: Borrow<Probability>,
    Op: FnMut(Symbol, Probability, Probability) -> Result<(), ()>,
{
    assert!(PRECISION > 0);
    assert!(PRECISION <= Probability::BITS);
    // We accumulate all validity checks into single branches at the end in order to
    // keep the loop itself branchless.
    let mut laps_or_zeros = 0usize;
    let mut accum = Probability::zero();
    for probability in probabilities {
        let old_accum = accum;
        accum = accum.wrapping_add(probability.borrow());
        laps_or_zeros += (accum <= old_accum) as usize;
        let symbol = symbols.next().ok_or(())?;
        operation(symbol, old_accum, *probability.borrow())?;
    }
    let total = wrapping_pow2::<Probability>(PRECISION);
    if infer_last_probability {
        if accum >= total || laps_or_zeros != 0 {
            return Err(());
        }
        let symbol = symbols.next().ok_or(())?;
        let probability = total.wrapping_sub(&accum);
        operation(symbol, accum, probability)?;
    } else if accum != total || laps_or_zeros != (PRECISION == Probability::BITS) as usize {
        return Err(());
    }
    Ok(symbols)
}
fn accumulate_nonzero_probabilities < Symbol , Probability , S , P , Op , const PRECISION : usize > ( mut symbols : S , probabilities : P , mut operation : Op , infer_last_probability : bool , ) -> Result < S , ( ) > where Probability : BitArray , S : Iterator < Item = Symbol > , P : Iterator , P :: Item : Borrow < Probability > , Op : FnMut ( Symbol , Probability , Probability ) -> Result < ( ) , ( ) > , { assert ! ( PRECISION 0 ) ; assert ! ( PRECISION Probability BITS ) ; // We accumulate all validity checks into single branches at the end in order to // keep the loop itself branchless. let mut laps_or_zeros = 0usize ; let mut accum = Probability :: zero ( ) ; for probability in probabilities { let old_accum = accum ; accum = accum . wrapping_add ( probability . borrow ( ) ) ; laps_or_zeros += ( accum <= old_accum ) as usize ; let symbol = symbols . next ( ) . ok_or ( ( ) ) ? ; operation ( symbol , old_accum , * probability . borrow ( ) ) ? ; } let total = wrapping_pow2 :: < Probability > ( PRECISION ) ; if infer_last_probability { if accum >= total || laps_or_zeros != 0 { return Err ( ( ) ) ; } let symbol = symbols . next ( ) . ok_or ( ( ) ) ? ; let probability = total . wrapping_sub ( & accum ) ; operation ( symbol , accum , probability ) ? ; } else if accum != total || laps_or_zeros != ( PRECISION == Probability :: BITS ) as usize { return Err ( ( ) ) ; } Ok ( symbols ) }
Note: does not check if `symbols` is exhausted (this is so that you one can provide an
infinite iterator for `symbols` to optimize out the bounds check on it).
Note : does not check if ` symbols ` is exhausted ( this is so that you one can provide an infinite iterator for ` symbols ` to optimize out the bounds check on it ) .
symbols
S
probabilities
P
operation
Op
infer_last_probability
bool
symbols
S
probabilities
P
operation
Op
infer_last_probability
bool