Shared Rust kernels
catalogue/information
All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.
unary · 17 lines · calc-func/src/catalogue/information.rs on GitHub/// An eager named call of one argument.
const fn unary(
id: FunctionId,
spelling: &'static str,
parameters: &'static [Parameter],
kernel: EagerKernel,
) -> CatalogueEntry {
CatalogueEntry {
id,
spelling,
notation: Notation::Call,
arity: CallableArityShape::exact(1),
parameters,
demand: ArgumentDemand::Eager,
kernel: Kernel::Eager(kernel),
}
}
Used by 15 functions.
scalar · 11 lines · calc-func/src/catalogue/information.rs on GitHub/// The argument's worksheet value, or the refusal of a value no kernel here reads: an omitted
/// argument, an array (lifted or intersected by array evaluation), a callable and a number that is
/// not finite (see the module documentation).
fn scalar<'v>(site: &Site<'_>, value: &'v CalcValue) -> Step<CoreRef<'v>> {
match value.core_ref() {
_ if value.callable_value().is_some() => Err(site.not_modelled(Some(0))),
CoreRef::Missing | CoreRef::Array(_) => Err(site.not_modelled(Some(0))),
CoreRef::Number(n) if !n.is_finite() && !value.is_excel_overflow() => Err(site.not_modelled(Some(0))),
core => Ok(core),
}
}
Used by 15 functions.
known · 5 lines · calc-func/src/catalogue/information.rs on GitHub/// The argument's worksheet value as [`scalar`] reads it; #BLOCKED! and #CONNECT! are errors like
/// any other (see the module documentation).
fn known<'v>(site: &Site<'_>, value: &'v CalcValue) -> Step<CoreRef<'v>> {
scalar(site, value)
}
Used by 15 functions.
predicate · 13 lines · calc-func/src/catalogue/information.rs on GitHub/// An IS predicate: `holds` applied to the argument's value as `read` gives it, which is not
/// converted (a number held as text is text, as Microsoft's IS functions page states). The caller
/// has dereferenced a reference to one cell, so a blank cell arrives as the empty value.
fn predicate(
id: FunctionId,
arguments: &[CalcValue],
services: &EvalServices<'_>,
read: Read,
holds: fn(CoreRef<'_>) -> bool,
) -> Result<CalcValue, FunctionFault> {
let site = Site::new(id, services);
Site::finish(read(&site, &arguments[0]).map(|core| CalcValue::logical(holds(core))))
}
Used by 8 functions.
each · 27 lines · calc-func/src/catalogue/information.rs on GitHub/// `apply` to the argument, or to each element of an array argument, giving the array of the
/// results with each element's error in its place (see the module documentation). An element
/// whose result is refused refuses the call.
fn each(
site: &Site<'_>,
argument: &CalcValue,
services: &mut EvalServices<'_>,
apply: fn(&Site<'_>, &CalcValue, &mut EvalServices<'_>) -> Step<CalcValue>,
) -> Step<CalcValue> {
let CoreRef::Array(array) = argument.core_ref() else {
return apply(site, argument, services);
};
if argument.callable_value().is_some() {
return Err(site.not_modelled(Some(0)));
}
let mut cells = Vec::with_capacity(array.cell_count());
for element in array.iter_row_major() {
cells.push(match apply(site, element, services) {
Ok(value) => value,
Err(Exit::Error(code)) => CalcValue::error(code),
Err(fault) => return Err(fault),
});
}
CalcArray::new(array.shape(), cells)
.map(CalcValue::array)
.ok_or_else(|| site.not_modelled(Some(0)))
}
Used by 15 functions.
odd · 24 lines · calc-func/src/catalogue/information.rs on GitHub/// Whether the argument of ISEVEN or ISODD is odd. A reference to one cell is read as the cell's
/// value; a reference of several areas is #VALUE!, and so is a range of several cells, in a legacy
/// formula placed within the range's rows (no intersection) and in a dynamic-array formula (no
/// lifting) alike.
/// The value is read as a number through worksheet coercion, number text included (Excel reads
/// text such as "2" and "1e3" both typed and in a cell), except that a logical is #VALUE!, typed
/// or in a cell, as Microsoft's page says of a value that is not numeric; a blank cell is 0 and an
/// error is the result. The magnitude plus [`PARITY_TOLERANCE`] is an arithmetic site, which
/// rounds; its truncation toward zero and the remainder by 2 are exact. Every binary64 of 2^53 or
/// more is an even integer.
fn odd(site: &Site<'_>, argument: &CalcValue, services: &mut EvalServices<'_>) -> Step<bool> {
let value = match argument.core_ref() {
CoreRef::Reference(reference) => match one_cell(reference) {
Some(area) => referenced(site, area, services)?,
None => return Err(Exit::Error(WorksheetErrorCode::Value)),
},
_ => argument.clone(),
};
let number = match scalar(site, &value)? {
CoreRef::Logical(_) => return Err(Exit::Error(WorksheetErrorCode::Value)),
_ => site.number_argument(0, &value)?,
};
Ok(site.add(number.abs(), PARITY_TOLERANCE)?.trunc() % 2.0 != 0.0)
}
Used by 2 functions.
n · 11 lines · calc-func/src/catalogue/information.rs on GitHub/// N: a number as it is, TRUE as 1 and FALSE as 0, an error as itself, and anything else, text
/// and a blank cell among them, as 0 (Microsoft's page; a date is a number here). A reference is
/// read at the first cell of its first area, of any size: Excel loads a range given to N without
/// `@`, and reads its first cell in a legacy formula placed within the range's rows and in a
/// dynamic-array formula alike. A number Excel's handling of which is not modelled (a subnormal)
/// is refused, as the number rule refuses one, and so are #BLOCKED! and #CONNECT! (see
/// [`known`]).
fn n(arguments: &[CalcValue], services: &mut EvalServices<'_>) -> Result<CalcValue, FunctionFault> {
let site = Site::new(N, services);
Site::finish(each(&site, &arguments[0], services, n_of))
}
Used by 15 functions.
n_of · 22 lines · calc-func/src/catalogue/information.rs on GitHub/// N of one argument or array element.
fn n_of(site: &Site<'_>, argument: &CalcValue, services: &mut EvalServices<'_>) -> Step<CalcValue> {
let value = match argument.core_ref() {
CoreRef::Reference(reference) => {
let first = GridArea::cell(reference.areas()[0].first());
referenced(site, first, services)?
}
_ => argument.clone(),
};
known(site, &value).and_then(|core| match core {
CoreRef::Number(_) if value.is_excel_overflow() => Ok(value.clone()),
CoreRef::Number(x) => site
.argument(0, coerce::operand(x))
.and_then(|x| site.number(x)),
CoreRef::Logical(b) => Ok(CalcValue::number(if b { 1.0 } else { 0.0 })),
CoreRef::Error(code) => Err(Exit::Error(code)),
CoreRef::Text(_) | CoreRef::Empty => Ok(CalcValue::number(0.0)),
CoreRef::Missing | CoreRef::Array(_) | CoreRef::Reference(_) => {
Err(site.not_modelled(Some(0)))
}
})
}
Used by 15 functions.
one_cell · 7 lines · calc-func/src/catalogue/information.rs on GitHub/// The one area of `reference` when it is a single cell.
fn one_cell(reference: &ReferenceLike) -> Option<GridArea> {
match reference.areas() {
[area] if area.cell_count() == 1 => Some(*area),
_ => None,
}
}
Used by 3 functions.
referenced · 17 lines · calc-func/src/catalogue/information.rs on GitHub/// The value of the cell `area` names, as the services' cell reader supplies it: the empty value
/// for a cell it does not visit. The reference is argument 0.
fn referenced(site: &Site<'_>, area: GridArea, services: &mut EvalServices<'_>) -> Step<CalcValue> {
let cells = reader(site, services, 0)?;
let mut value = CalcValue::empty();
read_reference(
site,
cells,
&ReferenceLike::area(area),
0,
&mut |_, _, held| {
value = held.clone();
Ok(())
},
)?;
Ok(value)
}
Used by 15 functions.