Shared Rust kernels
catalogue/math
All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.
raw · 5 lines · calc-func/src/catalogue/math.rs on GitHub/// A one-argument kernel whose raw result Excel publishes under `policy`.
fn raw(site: &Site<'_>, a: &[CalcValue], policy: ExcelRealPolicy, kernel: fn(f64) -> f64) -> Step<CalcValue> {
let x = num(site, a, 0)?;
out(site, policy.publish(x, kernel(x)))
}
Used by 9 functions.
unary · 5 lines · calc-func/src/catalogue/math.rs on GitHub/// A one-argument kernel that publishes its own result.
fn unary(site: &Site<'_>, a: &[CalcValue], kernel: fn(f64) -> Result<f64, WorksheetErrorCode>) -> Step<CalcValue> {
let x = num(site, a, 0)?;
out(site, kernel(x))
}
Used by 17 functions.
binary · 10 lines · calc-func/src/catalogue/math.rs on GitHub/// A two-argument kernel.
fn binary(
site: &Site<'_>,
a: &[CalcValue],
kernel: fn(f64, f64) -> Result<f64, WorksheetErrorCode>,
) -> Step<CalcValue> {
let x = num(site, a, 0)?;
let y = num(site, a, 1)?;
out(site, kernel(x, y))
}
Used by 3 functions.
integer_groups · 47 lines · calc-func/src/catalogue/math.rs on GitHub/// GCD's and LCM's integers: each argument's numbers (a held logical is #VALUE!, a blank cell of
/// a multi-cell argument is 0 and a direct omitted argument after the first is skipped), each at
/// least 0 and at most 2^53, truncated.
fn integer_groups(
site: &Site<'_>,
a: &[CalcValue],
services: &mut crate::call::EvalServices<'_>,
) -> Step<Vec<i64>> {
let mut numbers = Vec::new();
let mut any = false;
for (index, argument) in a.iter().enumerate() {
if argument.is_missing() {
if index == 0 {
return fail(WorksheetErrorCode::NA);
}
continue;
}
let Grid { cells, held, .. } = grid(site, a, index, services)?;
let multi = cells.len() > 1;
for cell in &cells {
match cell.core_ref() {
CoreRef::Empty | CoreRef::Missing => {
if multi {
numbers.push(0.0);
any = true;
}
}
CoreRef::Logical(_) => return fail(WorksheetErrorCode::Value),
_ => {
numbers.push(site.number_argument(index, cell)?);
any = true;
}
}
}
let _ = held;
}
if !any {
return fail(WorksheetErrorCode::Value);
}
if numbers
.iter()
.any(|n| !n.is_finite() || *n < 0.0 || *n > k::gcd_lcm_common::GCD_LCM_LIMIT)
{
return fail(WorksheetErrorCode::Num);
}
Ok(numbers.into_iter().map(|n| n.trunc() as i64).collect())
}
Used by 2 functions.
sum_pairwise · 27 lines · calc-func/src/catalogue/math.rs on GitHub/// SUMX2MY2, SUMX2PY2 and SUMXMY2: `term` summed over the positions where both arguments hold a
/// number; arguments of different shapes are #N/A, an error is the result, and no such position
/// is #DIV/0!.
fn sum_pairwise(
site: &Site<'_>,
a: &[CalcValue],
services: &mut crate::call::EvalServices<'_>,
term: fn(f64, f64) -> f64,
) -> Step<CalcValue> {
let left = numeric_cells(site, a, 0, services)?;
let right = numeric_cells(site, a, 1, services)?;
if left.0 != right.0 {
return fail(WorksheetErrorCode::NA);
}
let mut seen = false;
let mut sum = 0.0;
for (x, y) in left.1.iter().zip(&right.1) {
if let (Some(x), Some(y)) = (x, y) {
seen = true;
sum += term(*x, *y);
}
}
if !seen {
return fail(WorksheetErrorCode::Div0);
}
site.number(sum)
}
Used by 3 functions.
numeric_cells · 19 lines · calc-func/src/catalogue/math.rs on GitHub/// An argument's shape and, per cell, its number (`None` for text, a logical or a blank); an
/// error cell is the result.
fn numeric_cells(
site: &Site<'_>,
a: &[CalcValue],
index: usize,
services: &mut crate::call::EvalServices<'_>,
) -> Step<NumericCells> {
let g = grid(site, a, index, services)?;
let mut cells = Vec::with_capacity(g.cells.len());
for cell in &g.cells {
cells.push(match cell.core_ref() {
CoreRef::Number(n) => Some(n),
CoreRef::Error(code) => return fail(code),
_ => None,
});
}
Ok(((g.rows, g.cols), cells))
}
Used by 3 functions.
matrix · 23 lines · calc-func/src/catalogue/math.rs on GitHub/// An argument as a matrix of numbers: every cell must hold a number (an error cell is the
/// result, anything else #VALUE!); a single direct value must be a number.
fn matrix(
site: &Site<'_>,
a: &[CalcValue],
index: usize,
services: &mut crate::call::EvalServices<'_>,
) -> Step<Vec<Vec<f64>>> {
let g = grid(site, a, index, services)?;
let mut rows = Vec::with_capacity(g.rows);
for r in 0..g.rows {
let mut row = Vec::with_capacity(g.cols);
for cell in &g.cells[r * g.cols..(r + 1) * g.cols] {
match cell.core_ref() {
CoreRef::Number(n) => row.push(n),
CoreRef::Error(code) => return fail(code),
_ => return fail(WorksheetErrorCode::Value),
}
}
rows.push(row);
}
Ok(rows)
}
Used by 3 functions.