Shared Rust kernels

ported/bit_common

All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.

coerce_bit_operand · 8 lines · calc-func/src/ported/bit_common.rs on GitHub
pub fn coerce_bit_operand(n: f64) -> Result<u64, WorksheetErrorCode> {
    // Excel's bit operands must already be integers. Truncation is only
    // permitted for a shift count, not for the number being shifted/masked.
    if !n.is_finite() || n < 0.0 || n > BIT_MAX as f64 || n != n.trunc() {
        return Err(WorksheetErrorCode::Num);
    }
    Ok(n as u64)
}

Used by 5 functions.

coerce_shift_count · 7 lines · calc-func/src/ported/bit_common.rs on GitHub
pub fn coerce_shift_count(n: f64) -> Result<i32, WorksheetErrorCode> {
    let truncated = n.trunc();
    if !n.is_finite() || truncated.abs() > BIT_SHIFT_MAX as f64 {
        return Err(WorksheetErrorCode::Num);
    }
    Ok(truncated as i32)
}

Used by 2 functions.

bit_shift_kernel · 30 lines · calc-func/src/ported/bit_common.rs on GitHub
/// Common BITLSHIFT/BITRSHIFT graph observed in Excel 16.0 build 20430, CV2.
/// A zero operand bypasses the finite shift-count range check; an admitted
/// truncated count with magnitude 49..=53 publishes zero in either direction.
/// These are empirical exceptions to the published <=53/48-bit description.
/// Evidence: w111-broad-20260929 BITLSHIFT/BITRSHIFT Value2 witness sets.
pub fn bit_shift_kernel(number: f64, shift: f64, left: bool) -> Result<f64, WorksheetErrorCode> {
    let number = coerce_bit_operand(number)?;
    if !shift.is_finite() {
        return Err(WorksheetErrorCode::Num);
    }
    if number == 0 {
        return Ok(0.0);
    }
    let shift = coerce_shift_count(shift)?;
    if shift.abs() > 48 {
        return Ok(0.0);
    }
    let shift = if left { shift } else { -shift };
    let result = if shift >= 0 {
        // checked_shl only checks whether the count is >=64: it does not
        // detect discarded high bits. Check the Excel 48-bit bound first.
        if number > BIT_MAX >> shift {
            return Err(WorksheetErrorCode::Num);
        }
        number << shift
    } else {
        number >> -shift
    };
    Ok(result as f64)
}

Used by 2 functions.