Files
gridcraft/crates/functions/src/stat.rs
T

712 lines
30 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Statistical functions: aggregates, order statistics, regression and probability
//! distributions (with their inverses).
use gridcraft_core::{CellError, Value};
use crate::special::{erf, gamma, invert, ln_beta, ln_gamma, norm_cdf, norm_inv, norm_pdf, reg_gamma_p, reg_gamma_q, reg_inc_beta};
use crate::util::{A, R, S, arg, array_numbers, array_val, as_array, boolean, has, num, num_val, numbers, numbers_a, opt_num};
use crate::{Arg, Ctx, FnSpec, VAR};
mod descriptive;
mod distributions;
mod regression;
pub use descriptive::{aggregate_values, aggregate_values_k};
use descriptive::{
arg_nums, arg_pairs, avedev, correl, count_impl, counta_impl, countblank, devsq, frequency, geomean, harmean, intercept, kurt, large, max_of,
mean, median, min_of, mode_mult, mode_numbers, mode_sngl, percentile_exc, percentile_inc, percentrank_impl, prob, quartile_exc, quartile_inc,
rank_impl, skew, skew_p, slope, small, standardize, trimmean, var_p, var_s,
};
use distributions::{
beta_dist, beta_inv, betadist_legacy, binom_dist, binom_dist_range, binom_inv, chisq_dist, chisq_dist_rt, chisq_inv, chisq_inv_rt, chisq_test,
confidence_norm, confidence_t, expon_dist, f_dist, f_dist_rt, f_inv, f_inv_rt, f_test, fisher, gamma_dist, gamma_fn, gamma_inv, gammaln, gauss,
hypgeom_dist, lognorm_dist, lognorm_inv, negbinom_dist, norm_dist, norm_inv_fn, norm_s_dist, norm_s_inv, poisson_dist, t_dist, t_dist_2t,
t_dist_rt, t_inv, t_inv_2t, t_test, tdist_legacy, weibull_dist, z_test,
};
#[cfg(test)]
use regression::{MAX_REGRESSORS, check_regression_size};
use regression::{covariance, forecast, linest_impl, steyx, trend_impl};
type C<'a> = &'a mut dyn Ctx;
// ---------------------------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------------------------
const S_ARR_K: &[bool] = &[false, true];
const S_RANK: &[bool] = &[true, false, true];
const S_PRANK: &[bool] = &[false, true, true];
const S_FORECAST: &[bool] = &[true, false, false];
const S_PROB: &[bool] = &[false, false, true, true];
const S_TTEST: &[bool] = &[false, false, true, true];
pub(crate) fn specs() -> Vec<FnSpec> {
vec![
f!("AVERAGE", 1, VAR, Statistical, A, "AVERAGE(number1, [number2], ...)", "Arithmetic mean of the numbers.", |a: &[Arg], _c: C| num_val(
mean(&numbers(a)?)?
)),
f!(
"AVERAGEA",
1,
VAR,
Statistical,
A,
"AVERAGEA(value1, [value2], ...)",
"Mean counting text as 0 and logical values as 1 or 0.",
|a: &[Arg], _c: C| num_val(mean(&numbers_a(a)?)?)
),
f!("MEDIAN", 1, VAR, Statistical, A, "MEDIAN(number1, [number2], ...)", "Middle value of the numbers.", |a: &[Arg], _c: C| num_val(median(
numbers(a)?
)?)),
f!("MODE", 1, VAR, Compatibility, A, "MODE(number1, [number2], ...)", "Most frequently occurring number.", |a: &[Arg], _c: C| num_val(
mode_sngl(&mode_numbers(a)?)?
)),
f!("MODE.SNGL", 1, VAR, Statistical, A, "MODE.SNGL(number1, [number2], ...)", "Most frequently occurring number.", |a: &[Arg], _c: C| {
num_val(mode_sngl(&mode_numbers(a)?)?)
}),
f!("MODE.MULT", 1, VAR, Statistical, A, "MODE.MULT(number1, [number2], ...)", "Vertical array of all the most frequent numbers.", mode_mult),
f!("STDEV", 1, VAR, Compatibility, A, "STDEV(number1, [number2], ...)", "Sample standard deviation.", |a: &[Arg], _c: C| num_val(
var_s(&numbers(a)?)?.sqrt()
)),
f!("STDEV.S", 1, VAR, Statistical, A, "STDEV.S(number1, [number2], ...)", "Sample standard deviation.", |a: &[Arg], _c: C| num_val(
var_s(&numbers(a)?)?.sqrt()
)),
f!("STDEV.P", 1, VAR, Statistical, A, "STDEV.P(number1, [number2], ...)", "Population standard deviation.", |a: &[Arg], _c: C| num_val(
var_p(&numbers(a)?)?.sqrt()
)),
f!("STDEVP", 1, VAR, Compatibility, A, "STDEVP(number1, [number2], ...)", "Population standard deviation.", |a: &[Arg], _c: C| num_val(
var_p(&numbers(a)?)?.sqrt()
)),
f!(
"STDEVA",
1,
VAR,
Statistical,
A,
"STDEVA(value1, [value2], ...)",
"Sample standard deviation counting text as 0 and logicals as 1/0.",
|a: &[Arg], _c: C| { num_val(var_s(&numbers_a(a)?)?.sqrt()) }
),
f!(
"STDEVPA",
1,
VAR,
Statistical,
A,
"STDEVPA(value1, [value2], ...)",
"Population standard deviation counting text as 0 and logicals as 1/0.",
|a: &[Arg], _c: C| { num_val(var_p(&numbers_a(a)?)?.sqrt()) }
),
f!("VAR", 1, VAR, Compatibility, A, "VAR(number1, [number2], ...)", "Sample variance.", |a: &[Arg], _c: C| num_val(var_s(&numbers(a)?)?)),
f!("VAR.S", 1, VAR, Statistical, A, "VAR.S(number1, [number2], ...)", "Sample variance.", |a: &[Arg], _c: C| num_val(var_s(&numbers(a)?)?)),
f!("VAR.P", 1, VAR, Statistical, A, "VAR.P(number1, [number2], ...)", "Population variance.", |a: &[Arg], _c: C| num_val(var_p(&numbers(
a
)?)?)),
f!("VARP", 1, VAR, Compatibility, A, "VARP(number1, [number2], ...)", "Population variance.", |a: &[Arg], _c: C| num_val(var_p(&numbers(
a
)?)?)),
f!(
"VARA",
1,
VAR,
Statistical,
A,
"VARA(value1, [value2], ...)",
"Sample variance counting text as 0 and logicals as 1/0.",
|a: &[Arg], _c: C| num_val(var_s(&numbers_a(a)?)?)
),
f!(
"VARPA",
1,
VAR,
Statistical,
A,
"VARPA(value1, [value2], ...)",
"Population variance counting text as 0 and logicals as 1/0.",
|a: &[Arg], _c: C| num_val(var_p(&numbers_a(a)?)?)
),
f!("MIN", 0, VAR, Statistical, A, "MIN(number1, [number2], ...)", "Smallest number (0 when there are none).", |a: &[Arg], _c: C| num_val(
min_of(&numbers(a)?)
)),
f!(
"MINA",
1,
VAR,
Statistical,
A,
"MINA(value1, [value2], ...)",
"Smallest value counting text as 0 and logicals as 1/0.",
|a: &[Arg], _c: C| num_val(min_of(&numbers_a(a)?))
),
f!("MAX", 1, VAR, Statistical, A, "MAX(number1, [number2], ...)", "Largest number (0 when there are none).", |a: &[Arg], _c: C| num_val(
max_of(&numbers(a)?)
)),
f!(
"MAXA",
1,
VAR,
Statistical,
A,
"MAXA(value1, [value2], ...)",
"Largest value counting text as 0 and logicals as 1/0.",
|a: &[Arg], _c: C| num_val(max_of(&numbers_a(a)?))
),
f!("LARGE", 2, 2, Statistical, S_ARR_K, "LARGE(array, k)", "The k-th largest number in a data set.", large),
f!("SMALL", 2, 2, Statistical, S_ARR_K, "SMALL(array, k)", "The k-th smallest number in a data set.", small),
f!("RANK", 2, 3, Compatibility, S_RANK, "RANK(number, ref, [order])", "Rank of a number within a list.", |a: &[Arg], _c: C| rank_impl(
a, false
)),
f!(
"RANK.EQ",
2,
3,
Statistical,
S_RANK,
"RANK.EQ(number, ref, [order])",
"Rank of a number within a list; ties share the top rank.",
|a: &[Arg], _c: C| rank_impl(a, false)
),
f!(
"RANK.AVG",
2,
3,
Statistical,
S_RANK,
"RANK.AVG(number, ref, [order])",
"Rank of a number within a list; ties get the average rank.",
|a: &[Arg], _c: C| { rank_impl(a, true) }
),
f!("PERCENTILE", 2, 2, Compatibility, S_ARR_K, "PERCENTILE(array, k)", "k-th percentile, k from 0 to 1 inclusive.", |a: &[Arg], _c: C| {
num_val(percentile_inc(arg_nums(a, 0)?, num(a, 1)?)?)
}),
f!(
"PERCENTILE.INC",
2,
2,
Statistical,
S_ARR_K,
"PERCENTILE.INC(array, k)",
"k-th percentile, k from 0 to 1 inclusive.",
|a: &[Arg], _c: C| num_val(percentile_inc(arg_nums(a, 0)?, num(a, 1)?)?)
),
f!(
"PERCENTILE.EXC",
2,
2,
Statistical,
S_ARR_K,
"PERCENTILE.EXC(array, k)",
"k-th percentile, k strictly between 0 and 1.",
|a: &[Arg], _c: C| num_val(percentile_exc(arg_nums(a, 0)?, num(a, 1)?)?)
),
f!("QUARTILE", 2, 2, Compatibility, S_ARR_K, "QUARTILE(array, quart)", "Quartile (0–4) of a data set.", |a: &[Arg], _c: C| num_val(
quartile_inc(arg_nums(a, 0)?, num(a, 1)?)?
)),
f!(
"QUARTILE.INC",
2,
2,
Statistical,
S_ARR_K,
"QUARTILE.INC(array, quart)",
"Quartile (0–4) of a data set, inclusive method.",
|a: &[Arg], _c: C| num_val(quartile_inc(arg_nums(a, 0)?, num(a, 1)?)?)
),
f!(
"QUARTILE.EXC",
2,
2,
Statistical,
S_ARR_K,
"QUARTILE.EXC(array, quart)",
"Quartile (1–3) of a data set, exclusive method.",
|a: &[Arg], _c: C| num_val(quartile_exc(arg_nums(a, 0)?, num(a, 1)?)?)
),
f!(
"PERCENTRANK",
2,
3,
Compatibility,
S_PRANK,
"PERCENTRANK(array, x, [significance])",
"Relative standing of a value as a fraction of the data set.",
|a: &[Arg], _c: C| { percentrank_impl(a, false) }
),
f!(
"PERCENTRANK.INC",
2,
3,
Statistical,
S_PRANK,
"PERCENTRANK.INC(array, x, [significance])",
"Relative standing of a value from 0 to 1 inclusive.",
|a: &[Arg], _c: C| percentrank_impl(a, false)
),
f!(
"PERCENTRANK.EXC",
2,
3,
Statistical,
S_PRANK,
"PERCENTRANK.EXC(array, x, [significance])",
"Relative standing of a value strictly between 0 and 1.",
|a: &[Arg], _c: C| percentrank_impl(a, true)
),
f!("COUNT", 1, VAR, Statistical, A, "COUNT(value1, [value2], ...)", "Counts the numbers.", |a: &[Arg], _c: C| num_val(count_impl(a))),
f!("COUNTA", 1, VAR, Statistical, A, "COUNTA(value1, [value2], ...)", "Counts the non-empty values.", |a: &[Arg], _c: C| num_val(
counta_impl(a)
)),
f!("COUNTBLANK", 1, 1, Statistical, A, "COUNTBLANK(range)", "Counts empty cells and empty text in a range.", countblank),
f!("CORREL", 2, 2, Statistical, A, "CORREL(array1, array2)", "Correlation coefficient of two data sets.", |a: &[Arg], _c: C| {
let (x, y) = arg_pairs(a, 0, 1)?;
num_val(correl(&x, &y)?)
}),
f!("PEARSON", 2, 2, Statistical, A, "PEARSON(array1, array2)", "Pearson product-moment correlation coefficient.", |a: &[Arg], _c: C| {
let (x, y) = arg_pairs(a, 0, 1)?;
num_val(correl(&x, &y)?)
}),
f!("RSQ", 2, 2, Statistical, A, "RSQ(known_ys, known_xs)", "Square of the correlation coefficient.", |a: &[Arg], _c: C| {
let (y, x) = arg_pairs(a, 0, 1)?;
num_val(correl(&x, &y)?.powi(2))
}),
f!("SLOPE", 2, 2, Statistical, A, "SLOPE(known_ys, known_xs)", "Slope of the least-squares regression line.", |a: &[Arg], _c: C| {
let (y, x) = arg_pairs(a, 0, 1)?;
if y.is_empty() {
return Err(CellError::Div0);
}
num_val(slope(&y, &x)?)
}),
f!(
"INTERCEPT",
2,
2,
Statistical,
A,
"INTERCEPT(known_ys, known_xs)",
"Y-intercept of the least-squares regression line.",
|a: &[Arg], _c: C| {
let (y, x) = arg_pairs(a, 0, 1)?;
if y.is_empty() {
return Err(CellError::Div0);
}
num_val(intercept(&y, &x)?)
}
),
f!("STEYX", 2, 2, Statistical, A, "STEYX(known_ys, known_xs)", "Standard error of predicted y values in a regression.", steyx),
f!("FORECAST", 3, 3, Compatibility, S_FORECAST, "FORECAST(x, known_ys, known_xs)", "Predicts a value along a linear trend.", forecast),
f!(
"FORECAST.LINEAR",
3,
3,
Statistical,
S_FORECAST,
"FORECAST.LINEAR(x, known_ys, known_xs)",
"Predicts a value along a linear trend.",
forecast
),
f!(
"TREND",
1,
4,
Statistical,
A,
"TREND(known_ys, [known_xs], [new_xs], [const])",
"Values along a least-squares linear fit.",
|a: &[Arg], _c: C| trend_impl(a, false)
),
f!(
"GROWTH",
1,
4,
Statistical,
A,
"GROWTH(known_ys, [known_xs], [new_xs], [const])",
"Values along a fitted exponential growth curve.",
|a: &[Arg], _c: C| { trend_impl(a, true) }
),
f!(
"LINEST",
1,
4,
Statistical,
A,
"LINEST(known_ys, [known_xs], [const], [stats])",
"Least-squares line coefficients and optional regression statistics.",
|a: &[Arg], _c: C| { linest_impl(a, false) }
),
f!(
"LOGEST",
1,
4,
Statistical,
A,
"LOGEST(known_ys, [known_xs], [const], [stats])",
"Exponential curve coefficients and optional regression statistics.",
|a: &[Arg], _c: C| { linest_impl(a, true) }
),
f!("COVARIANCE.P", 2, 2, Statistical, A, "COVARIANCE.P(array1, array2)", "Population covariance of paired values.", |a: &[Arg], _c: C| {
covariance(a, false)
}),
f!("COVARIANCE.S", 2, 2, Statistical, A, "COVARIANCE.S(array1, array2)", "Sample covariance of paired values.", |a: &[Arg], _c: C| {
covariance(a, true)
}),
f!("COVAR", 2, 2, Compatibility, A, "COVAR(array1, array2)", "Population covariance of paired values.", |a: &[Arg], _c: C| covariance(
a, false
)),
f!("DEVSQ", 1, VAR, Statistical, A, "DEVSQ(number1, [number2], ...)", "Sum of squared deviations from the mean.", |a: &[Arg], _c: C| {
let v = numbers(a)?;
if v.is_empty() {
return Err(CellError::Num);
}
num_val(devsq(&v))
}),
f!("AVEDEV", 1, VAR, Statistical, A, "AVEDEV(number1, [number2], ...)", "Average absolute deviation from the mean.", |a: &[Arg], _c: C| {
num_val(avedev(&numbers(a)?)?)
}),
f!("GEOMEAN", 1, VAR, Statistical, A, "GEOMEAN(number1, [number2], ...)", "Geometric mean of positive numbers.", |a: &[Arg], _c: C| num_val(
geomean(&numbers(a)?)?
)),
f!("HARMEAN", 1, VAR, Statistical, A, "HARMEAN(number1, [number2], ...)", "Harmonic mean of positive numbers.", |a: &[Arg], _c: C| num_val(
harmean(&numbers(a)?)?
)),
f!("TRIMMEAN", 2, 2, Statistical, S_ARR_K, "TRIMMEAN(array, percent)", "Mean after trimming a fraction of points from both ends.", trimmean),
f!("KURT", 1, VAR, Statistical, A, "KURT(number1, [number2], ...)", "Excess kurtosis of a sample.", |a: &[Arg], _c: C| num_val(kurt(
&numbers(a)?
)?)),
f!("SKEW", 1, VAR, Statistical, A, "SKEW(number1, [number2], ...)", "Sample skewness.", |a: &[Arg], _c: C| num_val(skew(&numbers(a)?)?)),
f!("SKEW.P", 1, VAR, Statistical, A, "SKEW.P(number1, [number2], ...)", "Population skewness.", |a: &[Arg], _c: C| num_val(skew_p(
&numbers(a)?
)?)),
f!("STANDARDIZE", 3, 3, Statistical, S, "STANDARDIZE(x, mean, standard_dev)", "Z-score of a value.", standardize),
f!(
"FREQUENCY",
2,
2,
Statistical,
A,
"FREQUENCY(data_array, bins_array)",
"Counts how many values fall into each bin, as a vertical array.",
frequency
),
f!(
"PROB",
3,
4,
Statistical,
S_PROB,
"PROB(x_range, prob_range, lower_limit, [upper_limit])",
"Probability that values fall between two limits.",
prob
),
f!(
"NORM.DIST",
4,
4,
Statistical,
S,
"NORM.DIST(x, mean, standard_dev, cumulative)",
"Normal distribution density or cumulative probability.",
norm_dist
),
f!(
"NORMDIST",
4,
4,
Compatibility,
S,
"NORMDIST(x, mean, standard_dev, cumulative)",
"Normal distribution density or cumulative probability.",
norm_dist
),
f!(
"NORM.INV",
3,
3,
Statistical,
S,
"NORM.INV(probability, mean, standard_dev)",
"Inverse of the normal cumulative distribution.",
norm_inv_fn
),
f!(
"NORMINV",
3,
3,
Compatibility,
S,
"NORMINV(probability, mean, standard_dev)",
"Inverse of the normal cumulative distribution.",
norm_inv_fn
),
f!("NORM.S.DIST", 2, 2, Statistical, S, "NORM.S.DIST(z, cumulative)", "Standard normal density or cumulative probability.", norm_s_dist),
f!("NORMSDIST", 1, 1, Compatibility, S, "NORMSDIST(z)", "Standard normal cumulative probability.", norm_s_dist),
f!("NORM.S.INV", 1, 1, Statistical, S, "NORM.S.INV(probability)", "Inverse of the standard normal cumulative distribution.", norm_s_inv),
f!("NORMSINV", 1, 1, Compatibility, S, "NORMSINV(probability)", "Inverse of the standard normal cumulative distribution.", norm_s_inv),
f!("T.DIST", 3, 3, Statistical, S, "T.DIST(x, deg_freedom, cumulative)", "Student's t density or left-tailed probability.", t_dist),
f!("T.DIST.2T", 2, 2, Statistical, S, "T.DIST.2T(x, deg_freedom)", "Two-tailed Student's t probability.", t_dist_2t),
f!("T.DIST.RT", 2, 2, Statistical, S, "T.DIST.RT(x, deg_freedom)", "Right-tailed Student's t probability.", t_dist_rt),
f!("TDIST", 3, 3, Compatibility, S, "TDIST(x, deg_freedom, tails)", "One- or two-tailed Student's t probability.", tdist_legacy),
f!("T.INV", 2, 2, Statistical, S, "T.INV(probability, deg_freedom)", "Left-tailed inverse of Student's t distribution.", t_inv),
f!("T.INV.2T", 2, 2, Statistical, S, "T.INV.2T(probability, deg_freedom)", "Two-tailed inverse of Student's t distribution.", t_inv_2t),
f!("TINV", 2, 2, Compatibility, S, "TINV(probability, deg_freedom)", "Two-tailed inverse of Student's t distribution.", t_inv_2t),
f!("T.TEST", 4, 4, Statistical, S_TTEST, "T.TEST(array1, array2, tails, type)", "Probability from Student's t-test.", t_test),
f!("TTEST", 4, 4, Compatibility, S_TTEST, "TTEST(array1, array2, tails, type)", "Probability from Student's t-test.", t_test),
f!(
"CHISQ.DIST",
3,
3,
Statistical,
S,
"CHISQ.DIST(x, deg_freedom, cumulative)",
"Chi-squared density or left-tailed probability.",
chisq_dist
),
f!("CHISQ.DIST.RT", 2, 2, Statistical, S, "CHISQ.DIST.RT(x, deg_freedom)", "Right-tailed chi-squared probability.", chisq_dist_rt),
f!("CHIDIST", 2, 2, Compatibility, S, "CHIDIST(x, deg_freedom)", "Right-tailed chi-squared probability.", chisq_dist_rt),
f!(
"CHISQ.INV",
2,
2,
Statistical,
S,
"CHISQ.INV(probability, deg_freedom)",
"Inverse of the left-tailed chi-squared distribution.",
chisq_inv
),
f!(
"CHISQ.INV.RT",
2,
2,
Statistical,
S,
"CHISQ.INV.RT(probability, deg_freedom)",
"Inverse of the right-tailed chi-squared distribution.",
chisq_inv_rt
),
f!(
"CHIINV",
2,
2,
Compatibility,
S,
"CHIINV(probability, deg_freedom)",
"Inverse of the right-tailed chi-squared distribution.",
chisq_inv_rt
),
f!("CHISQ.TEST", 2, 2, Statistical, A, "CHISQ.TEST(actual_range, expected_range)", "Chi-squared test of independence.", chisq_test),
f!("CHITEST", 2, 2, Compatibility, A, "CHITEST(actual_range, expected_range)", "Chi-squared test of independence.", chisq_test),
f!(
"F.DIST",
4,
4,
Statistical,
S,
"F.DIST(x, deg_freedom1, deg_freedom2, cumulative)",
"F distribution density or left-tailed probability.",
f_dist
),
f!("F.DIST.RT", 3, 3, Statistical, S, "F.DIST.RT(x, deg_freedom1, deg_freedom2)", "Right-tailed F probability.", f_dist_rt),
f!("FDIST", 3, 3, Compatibility, S, "FDIST(x, deg_freedom1, deg_freedom2)", "Right-tailed F probability.", f_dist_rt),
f!("F.INV", 3, 3, Statistical, S, "F.INV(probability, deg_freedom1, deg_freedom2)", "Inverse of the left-tailed F distribution.", f_inv),
f!(
"F.INV.RT",
3,
3,
Statistical,
S,
"F.INV.RT(probability, deg_freedom1, deg_freedom2)",
"Inverse of the right-tailed F distribution.",
f_inv_rt
),
f!("FINV", 3, 3, Compatibility, S, "FINV(probability, deg_freedom1, deg_freedom2)", "Inverse of the right-tailed F distribution.", f_inv_rt),
f!("F.TEST", 2, 2, Statistical, A, "F.TEST(array1, array2)", "Two-tailed probability that two variances do not differ.", f_test),
f!("FTEST", 2, 2, Compatibility, A, "FTEST(array1, array2)", "Two-tailed probability that two variances do not differ.", f_test),
f!("BINOM.DIST", 4, 4, Statistical, S, "BINOM.DIST(number_s, trials, probability_s, cumulative)", "Binomial probability.", binom_dist),
f!("BINOMDIST", 4, 4, Compatibility, S, "BINOMDIST(number_s, trials, probability_s, cumulative)", "Binomial probability.", binom_dist),
f!(
"BINOM.DIST.RANGE",
3,
4,
Statistical,
S,
"BINOM.DIST.RANGE(trials, probability_s, number_s, [number_s2])",
"Probability of a number of successes falling in a range.",
binom_dist_range
),
f!(
"BINOM.INV",
3,
3,
Statistical,
S,
"BINOM.INV(trials, probability_s, alpha)",
"Smallest success count whose cumulative binomial probability reaches alpha.",
binom_inv
),
f!(
"CRITBINOM",
3,
3,
Compatibility,
S,
"CRITBINOM(trials, probability_s, alpha)",
"Smallest success count whose cumulative binomial probability reaches alpha.",
binom_inv
),
f!("POISSON.DIST", 3, 3, Statistical, S, "POISSON.DIST(x, mean, cumulative)", "Poisson probability.", poisson_dist),
f!("POISSON", 3, 3, Compatibility, S, "POISSON(x, mean, cumulative)", "Poisson probability.", poisson_dist),
f!("EXPON.DIST", 3, 3, Statistical, S, "EXPON.DIST(x, lambda, cumulative)", "Exponential distribution density or probability.", expon_dist),
f!("EXPONDIST", 3, 3, Compatibility, S, "EXPONDIST(x, lambda, cumulative)", "Exponential distribution density or probability.", expon_dist),
f!("GAMMA", 1, 1, Statistical, S, "GAMMA(number)", "The gamma function.", gamma_fn),
f!("GAMMA.DIST", 4, 4, Statistical, S, "GAMMA.DIST(x, alpha, beta, cumulative)", "Gamma distribution density or probability.", gamma_dist),
f!("GAMMADIST", 4, 4, Compatibility, S, "GAMMADIST(x, alpha, beta, cumulative)", "Gamma distribution density or probability.", gamma_dist),
f!("GAMMA.INV", 3, 3, Statistical, S, "GAMMA.INV(probability, alpha, beta)", "Inverse of the gamma cumulative distribution.", gamma_inv),
f!("GAMMAINV", 3, 3, Compatibility, S, "GAMMAINV(probability, alpha, beta)", "Inverse of the gamma cumulative distribution.", gamma_inv),
f!("GAMMALN", 1, 1, Statistical, S, "GAMMALN(x)", "Natural log of the gamma function.", gammaln),
f!("GAMMALN.PRECISE", 1, 1, Statistical, S, "GAMMALN.PRECISE(x)", "Natural log of the gamma function.", gammaln),
f!(
"BETA.DIST",
4,
6,
Statistical,
S,
"BETA.DIST(x, alpha, beta, cumulative, [A], [B])",
"Beta distribution density or probability.",
beta_dist
),
f!("BETADIST", 3, 5, Compatibility, S, "BETADIST(x, alpha, beta, [A], [B])", "Cumulative beta probability.", betadist_legacy),
f!(
"BETA.INV",
3,
5,
Statistical,
S,
"BETA.INV(probability, alpha, beta, [A], [B])",
"Inverse of the cumulative beta distribution.",
beta_inv
),
f!(
"BETAINV",
3,
5,
Compatibility,
S,
"BETAINV(probability, alpha, beta, [A], [B])",
"Inverse of the cumulative beta distribution.",
beta_inv
),
f!(
"LOGNORM.DIST",
4,
4,
Statistical,
S,
"LOGNORM.DIST(x, mean, standard_dev, cumulative)",
"Lognormal density or probability.",
lognorm_dist
),
f!("LOGNORMDIST", 3, 3, Compatibility, S, "LOGNORMDIST(x, mean, standard_dev)", "Cumulative lognormal probability.", lognorm_dist),
f!(
"LOGNORM.INV",
3,
3,
Statistical,
S,
"LOGNORM.INV(probability, mean, standard_dev)",
"Inverse of the cumulative lognormal distribution.",
lognorm_inv
),
f!(
"LOGINV",
3,
3,
Compatibility,
S,
"LOGINV(probability, mean, standard_dev)",
"Inverse of the cumulative lognormal distribution.",
lognorm_inv
),
f!("WEIBULL.DIST", 4, 4, Statistical, S, "WEIBULL.DIST(x, alpha, beta, cumulative)", "Weibull density or probability.", weibull_dist),
f!("WEIBULL", 4, 4, Compatibility, S, "WEIBULL(x, alpha, beta, cumulative)", "Weibull density or probability.", weibull_dist),
f!(
"HYPGEOM.DIST",
5,
5,
Statistical,
S,
"HYPGEOM.DIST(sample_s, number_sample, population_s, number_pop, cumulative)",
"Hypergeometric probability.",
hypgeom_dist
),
f!(
"HYPGEOMDIST",
4,
4,
Compatibility,
S,
"HYPGEOMDIST(sample_s, number_sample, population_s, number_pop)",
"Hypergeometric probability of an exact count.",
hypgeom_dist
),
f!(
"NEGBINOM.DIST",
4,
4,
Statistical,
S,
"NEGBINOM.DIST(number_f, number_s, probability_s, cumulative)",
"Negative binomial probability.",
negbinom_dist
),
f!(
"NEGBINOMDIST",
3,
3,
Compatibility,
S,
"NEGBINOMDIST(number_f, number_s, probability_s)",
"Negative binomial probability.",
negbinom_dist
),
f!(
"CONFIDENCE",
3,
3,
Compatibility,
S,
"CONFIDENCE(alpha, standard_dev, size)",
"Confidence interval half-width using the normal distribution.",
confidence_norm
),
f!(
"CONFIDENCE.NORM",
3,
3,
Statistical,
S,
"CONFIDENCE.NORM(alpha, standard_dev, size)",
"Confidence interval half-width using the normal distribution.",
confidence_norm
),
f!(
"CONFIDENCE.T",
3,
3,
Statistical,
S,
"CONFIDENCE.T(alpha, standard_dev, size)",
"Confidence interval half-width using Student's t distribution.",
confidence_t
),
f!("Z.TEST", 2, 3, Statistical, S_PRANK, "Z.TEST(array, x, [sigma])", "One-tailed probability of a z-test.", z_test),
f!("ZTEST", 2, 3, Compatibility, S_PRANK, "ZTEST(array, x, [sigma])", "One-tailed probability of a z-test.", z_test),
f!("FISHER", 1, 1, Statistical, S, "FISHER(x)", "Fisher transformation.", fisher),
f!("FISHERINV", 1, 1, Statistical, S, "FISHERINV(y)", "Inverse of the Fisher transformation.", |a: &[Arg], _c: C| num_val(num(a, 0)?.tanh())),
f!("PHI", 1, 1, Statistical, S, "PHI(x)", "Standard normal density.", |a: &[Arg], _c: C| num_val(norm_pdf(num(a, 0)?))),
f!("GAUSS", 1, 1, Statistical, S, "GAUSS(z)", "Probability that a standard normal value falls between the mean and z.", gauss),
]
}
#[cfg(test)]
mod tests;