formualizer-eval 0.7.0

High-performance Arrow-backed Excel formula engine with dependency graph and incremental recalculation
Documentation
use formualizer_common::{ExcelError, ExcelErrorKind};

pub type Shape2D = (usize, usize);

pub fn broadcast_shape(shapes: &[Shape2D]) -> Result<Shape2D, ExcelError> {
    if shapes.is_empty() {
        return Ok((1, 1));
    }
    let mut rows = 1usize;
    let mut cols = 1usize;
    for &(r, c) in shapes {
        rows = broadcast_dim(rows, r)?;
        cols = broadcast_dim(cols, c)?;
    }
    Ok((rows, cols))
}

fn broadcast_dim(a: usize, b: usize) -> Result<usize, ExcelError> {
    if a == b || a == 1 {
        return Ok(b.max(a));
    }
    if b == 1 {
        return Ok(a.max(b));
    }
    Err(ExcelError::new(ExcelErrorKind::Value).with_message(format!(
        "Incompatible dimensions for broadcasting: {a} vs {b}"
    )))
}

#[inline]
pub fn project_index(idx: (usize, usize), shape: Shape2D) -> (usize, usize) {
    let (r, c) = shape;
    let rr = if r == 1 { 0 } else { idx.0 };
    let cc = if c == 1 { 0 } else { idx.1 };
    (rr, cc)
}