1229 lines
46 KiB
Rust
1229 lines
46 KiB
Rust
use core::fmt;
|
|
use std::array::IntoIter;
|
|
|
|
use crate::{
|
|
calc_result::CalcResult,
|
|
expressions::{parser::Node, token::Error, types::CellReferenceIndex},
|
|
model::Model,
|
|
};
|
|
|
|
pub(crate) mod binary_search;
|
|
mod date_and_time;
|
|
mod engineering;
|
|
mod financial;
|
|
mod financial_util;
|
|
mod information;
|
|
mod logical;
|
|
mod lookup_and_reference;
|
|
mod mathematical;
|
|
mod statistical;
|
|
mod subtotal;
|
|
mod text;
|
|
mod text_util;
|
|
pub(crate) mod util;
|
|
mod xlookup;
|
|
|
|
/// List of all implemented functions
|
|
#[derive(PartialEq, Clone, Debug)]
|
|
pub enum Function {
|
|
// Logical
|
|
And,
|
|
False,
|
|
If,
|
|
Iferror,
|
|
Ifna,
|
|
Ifs,
|
|
Not,
|
|
Or,
|
|
Switch,
|
|
True,
|
|
Xor,
|
|
|
|
// Mathematical and trigonometry
|
|
Abs,
|
|
Acos,
|
|
Acosh,
|
|
Asin,
|
|
Asinh,
|
|
Atan,
|
|
Atan2,
|
|
Atanh,
|
|
Choose,
|
|
Column,
|
|
Columns,
|
|
Cos,
|
|
Cosh,
|
|
Max,
|
|
Min,
|
|
Pi,
|
|
Power,
|
|
Product,
|
|
Rand,
|
|
Randbetween,
|
|
Round,
|
|
Rounddown,
|
|
Roundup,
|
|
Sin,
|
|
Sinh,
|
|
Sqrt,
|
|
Sqrtpi,
|
|
Sum,
|
|
Sumif,
|
|
Sumifs,
|
|
Tan,
|
|
Tanh,
|
|
|
|
// Information
|
|
ErrorType,
|
|
Formulatext,
|
|
Isblank,
|
|
Iserr,
|
|
Iserror,
|
|
Iseven,
|
|
Isformula,
|
|
Islogical,
|
|
Isna,
|
|
Isnontext,
|
|
Isnumber,
|
|
Isodd,
|
|
Isref,
|
|
Istext,
|
|
Na,
|
|
Sheet,
|
|
Type,
|
|
|
|
// Lookup and reference
|
|
Hlookup,
|
|
Index,
|
|
Indirect,
|
|
Lookup,
|
|
Match,
|
|
Offset,
|
|
Row,
|
|
Rows,
|
|
Vlookup,
|
|
Xlookup,
|
|
|
|
// Text
|
|
Concat,
|
|
Concatenate,
|
|
Exact,
|
|
Find,
|
|
Left,
|
|
Len,
|
|
Lower,
|
|
Mid,
|
|
Rept,
|
|
Right,
|
|
Search,
|
|
Substitute,
|
|
T,
|
|
Text,
|
|
Textafter,
|
|
Textbefore,
|
|
Textjoin,
|
|
Trim,
|
|
Unicode,
|
|
Upper,
|
|
Value,
|
|
Valuetotext,
|
|
|
|
// Statistical
|
|
Average,
|
|
Averagea,
|
|
Averageif,
|
|
Averageifs,
|
|
Count,
|
|
Counta,
|
|
Countblank,
|
|
Countif,
|
|
Countifs,
|
|
Maxifs,
|
|
Minifs,
|
|
Geomean,
|
|
|
|
// Date and time
|
|
Date,
|
|
Day,
|
|
Edate,
|
|
Eomonth,
|
|
Month,
|
|
Now,
|
|
Today,
|
|
Year,
|
|
|
|
// Financial
|
|
Cumipmt,
|
|
Cumprinc,
|
|
Db,
|
|
Ddb,
|
|
Dollarde,
|
|
Dollarfr,
|
|
Effect,
|
|
Fv,
|
|
Ipmt,
|
|
Irr,
|
|
Ispmt,
|
|
Mirr,
|
|
Nominal,
|
|
Nper,
|
|
Npv,
|
|
Pduration,
|
|
Pmt,
|
|
Ppmt,
|
|
Pv,
|
|
Rate,
|
|
Rri,
|
|
Sln,
|
|
Syd,
|
|
Tbilleq,
|
|
Tbillprice,
|
|
Tbillyield,
|
|
Xirr,
|
|
Xnpv,
|
|
|
|
// Engineering: Bessel and transcendental functions
|
|
Besseli,
|
|
Besselj,
|
|
Besselk,
|
|
Bessely,
|
|
Erf,
|
|
Erfc,
|
|
ErfcPrecise,
|
|
ErfPrecise,
|
|
|
|
// Engineering: Number systems
|
|
Bin2dec,
|
|
Bin2hex,
|
|
Bin2oct,
|
|
Dec2Bin,
|
|
Dec2hex,
|
|
Dec2oct,
|
|
Hex2bin,
|
|
Hex2dec,
|
|
Hex2oct,
|
|
Oct2bin,
|
|
Oct2dec,
|
|
Oct2hex,
|
|
|
|
// Engineering: Bit functions
|
|
Bitand,
|
|
Bitlshift,
|
|
Bitor,
|
|
Bitrshift,
|
|
Bitxor,
|
|
|
|
// Engineering: Complex functions
|
|
Complex,
|
|
Imabs,
|
|
Imaginary,
|
|
Imargument,
|
|
Imconjugate,
|
|
Imcos,
|
|
Imcosh,
|
|
Imcot,
|
|
Imcsc,
|
|
Imcsch,
|
|
Imdiv,
|
|
Imexp,
|
|
Imln,
|
|
Imlog10,
|
|
Imlog2,
|
|
Impower,
|
|
Improduct,
|
|
Imreal,
|
|
Imsec,
|
|
Imsech,
|
|
Imsin,
|
|
Imsinh,
|
|
Imsqrt,
|
|
Imsub,
|
|
Imsum,
|
|
Imtan,
|
|
|
|
// Engineering: Misc function
|
|
Convert,
|
|
Delta,
|
|
Gestep,
|
|
Subtotal,
|
|
}
|
|
|
|
impl Function {
|
|
pub fn into_iter() -> IntoIter<Function, 195> {
|
|
[
|
|
Function::And,
|
|
Function::False,
|
|
Function::If,
|
|
Function::Iferror,
|
|
Function::Ifna,
|
|
Function::Ifs,
|
|
Function::Not,
|
|
Function::Or,
|
|
Function::Switch,
|
|
Function::True,
|
|
Function::Xor,
|
|
Function::Sin,
|
|
Function::Cos,
|
|
Function::Tan,
|
|
Function::Asin,
|
|
Function::Acos,
|
|
Function::Atan,
|
|
Function::Sinh,
|
|
Function::Cosh,
|
|
Function::Tanh,
|
|
Function::Asinh,
|
|
Function::Acosh,
|
|
Function::Atanh,
|
|
Function::Abs,
|
|
Function::Pi,
|
|
Function::Sqrt,
|
|
Function::Sqrtpi,
|
|
Function::Atan2,
|
|
Function::Power,
|
|
Function::Max,
|
|
Function::Min,
|
|
Function::Product,
|
|
Function::Rand,
|
|
Function::Randbetween,
|
|
Function::Round,
|
|
Function::Rounddown,
|
|
Function::Roundup,
|
|
Function::Sum,
|
|
Function::Sumif,
|
|
Function::Sumifs,
|
|
Function::Choose,
|
|
Function::Column,
|
|
Function::Columns,
|
|
Function::Index,
|
|
Function::Indirect,
|
|
Function::Hlookup,
|
|
Function::Lookup,
|
|
Function::Match,
|
|
Function::Offset,
|
|
Function::Row,
|
|
Function::Rows,
|
|
Function::Vlookup,
|
|
Function::Xlookup,
|
|
Function::Concatenate,
|
|
Function::Exact,
|
|
Function::Value,
|
|
Function::T,
|
|
Function::Valuetotext,
|
|
Function::Concat,
|
|
Function::Find,
|
|
Function::Left,
|
|
Function::Len,
|
|
Function::Lower,
|
|
Function::Mid,
|
|
Function::Right,
|
|
Function::Search,
|
|
Function::Text,
|
|
Function::Trim,
|
|
Function::Unicode,
|
|
Function::Upper,
|
|
Function::Isnumber,
|
|
Function::Isnontext,
|
|
Function::Istext,
|
|
Function::Islogical,
|
|
Function::Isblank,
|
|
Function::Iserr,
|
|
Function::Iserror,
|
|
Function::Isna,
|
|
Function::Na,
|
|
Function::Isref,
|
|
Function::Isodd,
|
|
Function::Iseven,
|
|
Function::ErrorType,
|
|
Function::Formulatext,
|
|
Function::Isformula,
|
|
Function::Type,
|
|
Function::Sheet,
|
|
Function::Average,
|
|
Function::Averagea,
|
|
Function::Averageif,
|
|
Function::Averageifs,
|
|
Function::Count,
|
|
Function::Counta,
|
|
Function::Countblank,
|
|
Function::Countif,
|
|
Function::Countifs,
|
|
Function::Maxifs,
|
|
Function::Minifs,
|
|
Function::Geomean,
|
|
Function::Year,
|
|
Function::Day,
|
|
Function::Month,
|
|
Function::Eomonth,
|
|
Function::Date,
|
|
Function::Edate,
|
|
Function::Today,
|
|
Function::Now,
|
|
Function::Pmt,
|
|
Function::Pv,
|
|
Function::Rate,
|
|
Function::Nper,
|
|
Function::Fv,
|
|
Function::Ppmt,
|
|
Function::Ipmt,
|
|
Function::Npv,
|
|
Function::Mirr,
|
|
Function::Irr,
|
|
Function::Xirr,
|
|
Function::Xnpv,
|
|
Function::Rept,
|
|
Function::Textafter,
|
|
Function::Textbefore,
|
|
Function::Textjoin,
|
|
Function::Substitute,
|
|
Function::Ispmt,
|
|
Function::Rri,
|
|
Function::Sln,
|
|
Function::Syd,
|
|
Function::Nominal,
|
|
Function::Effect,
|
|
Function::Pduration,
|
|
Function::Tbillyield,
|
|
Function::Tbillprice,
|
|
Function::Tbilleq,
|
|
Function::Dollarde,
|
|
Function::Dollarfr,
|
|
Function::Ddb,
|
|
Function::Db,
|
|
Function::Cumprinc,
|
|
Function::Cumipmt,
|
|
Function::Besseli,
|
|
Function::Besselj,
|
|
Function::Besselk,
|
|
Function::Bessely,
|
|
Function::Erf,
|
|
Function::ErfPrecise,
|
|
Function::Erfc,
|
|
Function::ErfcPrecise,
|
|
Function::Bin2dec,
|
|
Function::Bin2hex,
|
|
Function::Bin2oct,
|
|
Function::Dec2Bin,
|
|
Function::Dec2hex,
|
|
Function::Dec2oct,
|
|
Function::Hex2bin,
|
|
Function::Hex2dec,
|
|
Function::Hex2oct,
|
|
Function::Oct2bin,
|
|
Function::Oct2dec,
|
|
Function::Oct2hex,
|
|
Function::Bitand,
|
|
Function::Bitlshift,
|
|
Function::Bitor,
|
|
Function::Bitrshift,
|
|
Function::Bitxor,
|
|
Function::Complex,
|
|
Function::Imabs,
|
|
Function::Imaginary,
|
|
Function::Imargument,
|
|
Function::Imconjugate,
|
|
Function::Imcos,
|
|
Function::Imcosh,
|
|
Function::Imcot,
|
|
Function::Imcsc,
|
|
Function::Imcsch,
|
|
Function::Imdiv,
|
|
Function::Imexp,
|
|
Function::Imln,
|
|
Function::Imlog10,
|
|
Function::Imlog2,
|
|
Function::Impower,
|
|
Function::Improduct,
|
|
Function::Imreal,
|
|
Function::Imsec,
|
|
Function::Imsech,
|
|
Function::Imsin,
|
|
Function::Imsinh,
|
|
Function::Imsqrt,
|
|
Function::Imsub,
|
|
Function::Imsum,
|
|
Function::Imtan,
|
|
Function::Convert,
|
|
Function::Delta,
|
|
Function::Gestep,
|
|
Function::Subtotal,
|
|
]
|
|
.into_iter()
|
|
}
|
|
}
|
|
|
|
impl Function {
|
|
/// Some functions in Excel like CONCAT are stringified as `_xlfn.CONCAT`.
|
|
pub fn to_xlsx_string(&self) -> String {
|
|
match self {
|
|
Function::Concat => "_xlfn.CONCAT".to_string(),
|
|
Function::Ifna => "_xlfn.IFNA".to_string(),
|
|
Function::Ifs => "_xlfn.IFS".to_string(),
|
|
Function::Maxifs => "_xlfn.MAXIFS".to_string(),
|
|
Function::Minifs => "_xlfn.MINIFS".to_string(),
|
|
Function::Switch => "_xlfn.SWITCH".to_string(),
|
|
Function::Xlookup => "_xlfn.XLOOKUP".to_string(),
|
|
Function::Xor => "_xlfn.XOR".to_string(),
|
|
Function::Textbefore => "_xlfn.TEXTBEFORE".to_string(),
|
|
Function::Textafter => "_xlfn.TEXTAFTER".to_string(),
|
|
Function::Textjoin => "_xlfn.TEXTJOIN".to_string(),
|
|
Function::Unicode => "_xlfn.UNICODE".to_string(),
|
|
Function::Rri => "_xlfn.RRI".to_string(),
|
|
Function::Pduration => "_xlfn.PDURATION".to_string(),
|
|
Function::Bitand => "_xlfn.BITAND".to_string(),
|
|
Function::Bitor => "_xlfn.BITOR".to_string(),
|
|
Function::Bitxor => "_xlfn.BITXOR".to_string(),
|
|
Function::Bitlshift => "_xlfn.BITLSHIFT".to_string(),
|
|
Function::Bitrshift => "_xlfn.BITRSHIFT".to_string(),
|
|
Function::Imtan => "_xlfn.IMTAN".to_string(),
|
|
Function::Imsinh => "_xlfn.IMSINH".to_string(),
|
|
Function::Imcosh => "_xlfn.IMCOSH".to_string(),
|
|
Function::Imcot => "_xlfn.IMCOT".to_string(),
|
|
Function::Imcsc => "_xlfn.IMCSC".to_string(),
|
|
Function::Imcsch => "_xlfn.IMCSCH".to_string(),
|
|
Function::Imsec => "_xlfn.IMSEC".to_string(),
|
|
Function::ErfcPrecise => "_xlfn.ERFC.PRECISE".to_string(),
|
|
Function::ErfPrecise => "_xlfn.ERF.PRECISE".to_string(),
|
|
Function::Valuetotext => "_xlfn.VALUETOTEXT".to_string(),
|
|
Function::Isformula => "_xlfn.ISFORMULA".to_string(),
|
|
Function::Sheet => "_xlfn.SHEET".to_string(),
|
|
Function::Formulatext => "_xlfn.FORMULATEXT".to_string(),
|
|
_ => self.to_string(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn returns_reference(&self) -> bool {
|
|
matches!(self, Function::Indirect | Function::Offset)
|
|
}
|
|
/// Gets the function from the name.
|
|
/// Note that in Excel some (modern) functions are prefixed by `_xlfn.`
|
|
pub fn get_function(name: &str) -> Option<Function> {
|
|
match name.to_ascii_uppercase().as_str() {
|
|
"AND" => Some(Function::And),
|
|
"FALSE" => Some(Function::False),
|
|
"IF" => Some(Function::If),
|
|
"IFERROR" => Some(Function::Iferror),
|
|
"IFNA" | "_XLFN.IFNA" => Some(Function::Ifna),
|
|
"IFS" | "_XLFN.IFS" => Some(Function::Ifs),
|
|
"NOT" => Some(Function::Not),
|
|
"OR" => Some(Function::Or),
|
|
"SWITCH" | "_XLFN.SWITCH" => Some(Function::Switch),
|
|
"TRUE" => Some(Function::True),
|
|
"XOR" | "_XLFN.XOR" => Some(Function::Xor),
|
|
|
|
"SIN" => Some(Function::Sin),
|
|
"COS" => Some(Function::Cos),
|
|
"TAN" => Some(Function::Tan),
|
|
|
|
"ASIN" => Some(Function::Asin),
|
|
"ACOS" => Some(Function::Acos),
|
|
"ATAN" => Some(Function::Atan),
|
|
|
|
"SINH" => Some(Function::Sinh),
|
|
"COSH" => Some(Function::Cosh),
|
|
"TANH" => Some(Function::Tanh),
|
|
|
|
"ASINH" => Some(Function::Asinh),
|
|
"ACOSH" => Some(Function::Acosh),
|
|
"ATANH" => Some(Function::Atanh),
|
|
|
|
"PI" => Some(Function::Pi),
|
|
"ABS" => Some(Function::Abs),
|
|
"SQRT" => Some(Function::Sqrt),
|
|
"SQRTPI" => Some(Function::Sqrtpi),
|
|
"POWER" => Some(Function::Power),
|
|
"ATAN2" => Some(Function::Atan2),
|
|
|
|
"MAX" => Some(Function::Max),
|
|
"MIN" => Some(Function::Min),
|
|
"PRODUCT" => Some(Function::Product),
|
|
"RAND" => Some(Function::Rand),
|
|
"RANDBETWEEN" => Some(Function::Randbetween),
|
|
"ROUND" => Some(Function::Round),
|
|
"ROUNDDOWN" => Some(Function::Rounddown),
|
|
"ROUNDUP" => Some(Function::Roundup),
|
|
"SUM" => Some(Function::Sum),
|
|
"SUMIF" => Some(Function::Sumif),
|
|
"SUMIFS" => Some(Function::Sumifs),
|
|
|
|
// Lookup and Reference
|
|
"CHOOSE" => Some(Function::Choose),
|
|
"COLUMN" => Some(Function::Column),
|
|
"COLUMNS" => Some(Function::Columns),
|
|
"INDEX" => Some(Function::Index),
|
|
"INDIRECT" => Some(Function::Indirect),
|
|
"HLOOKUP" => Some(Function::Hlookup),
|
|
"LOOKUP" => Some(Function::Lookup),
|
|
"MATCH" => Some(Function::Match),
|
|
"OFFSET" => Some(Function::Offset),
|
|
"ROW" => Some(Function::Row),
|
|
"ROWS" => Some(Function::Rows),
|
|
"VLOOKUP" => Some(Function::Vlookup),
|
|
"XLOOKUP" | "_XLFN.XLOOKUP" => Some(Function::Xlookup),
|
|
|
|
"CONCATENATE" => Some(Function::Concatenate),
|
|
"EXACT" => Some(Function::Exact),
|
|
"VALUE" => Some(Function::Value),
|
|
"T" => Some(Function::T),
|
|
"VALUETOTEXT" | "_XLFN.VALUETOTEXT" => Some(Function::Valuetotext),
|
|
"CONCAT" | "_XLFN.CONCAT" => Some(Function::Concat),
|
|
"FIND" => Some(Function::Find),
|
|
"LEFT" => Some(Function::Left),
|
|
"LEN" => Some(Function::Len),
|
|
"LOWER" => Some(Function::Lower),
|
|
"MID" => Some(Function::Mid),
|
|
"RIGHT" => Some(Function::Right),
|
|
"SEARCH" => Some(Function::Search),
|
|
"TEXT" => Some(Function::Text),
|
|
"TRIM" => Some(Function::Trim),
|
|
"UNICODE" | "_XLFN.UNICODE" => Some(Function::Unicode),
|
|
"UPPER" => Some(Function::Upper),
|
|
|
|
"REPT" => Some(Function::Rept),
|
|
"TEXTAFTER" | "_XLFN.TEXTAFTER" => Some(Function::Textafter),
|
|
"TEXTBEFORE" | "_XLFN.TEXTBEFORE" => Some(Function::Textbefore),
|
|
"TEXTJOIN" | "_XLFN.TEXTJOIN" => Some(Function::Textjoin),
|
|
"SUBSTITUTE" => Some(Function::Substitute),
|
|
|
|
"ISNUMBER" => Some(Function::Isnumber),
|
|
"ISNONTEXT" => Some(Function::Isnontext),
|
|
"ISTEXT" => Some(Function::Istext),
|
|
"ISLOGICAL" => Some(Function::Islogical),
|
|
"ISBLANK" => Some(Function::Isblank),
|
|
"ISERR" => Some(Function::Iserr),
|
|
"ISERROR" => Some(Function::Iserror),
|
|
"ISNA" => Some(Function::Isna),
|
|
"NA" => Some(Function::Na),
|
|
"ISREF" => Some(Function::Isref),
|
|
"ISODD" => Some(Function::Isodd),
|
|
"ISEVEN" => Some(Function::Iseven),
|
|
"ERROR.TYPE" => Some(Function::ErrorType),
|
|
"FORMULATEXT" | "_XLFN.FORMULATEXT" => Some(Function::Formulatext),
|
|
"ISFORMULA" | "_XLFN.ISFORMULA" => Some(Function::Isformula),
|
|
"TYPE" => Some(Function::Type),
|
|
"SHEET" | "_XLFN.SHEET" => Some(Function::Sheet),
|
|
|
|
"AVERAGE" => Some(Function::Average),
|
|
"AVERAGEA" => Some(Function::Averagea),
|
|
"AVERAGEIF" => Some(Function::Averageif),
|
|
"AVERAGEIFS" => Some(Function::Averageifs),
|
|
"COUNT" => Some(Function::Count),
|
|
"COUNTA" => Some(Function::Counta),
|
|
"COUNTBLANK" => Some(Function::Countblank),
|
|
"COUNTIF" => Some(Function::Countif),
|
|
"COUNTIFS" => Some(Function::Countifs),
|
|
"MAXIFS" | "_XLFN.MAXIFS" => Some(Function::Maxifs),
|
|
"MINIFS" | "_XLFN.MINIFS" => Some(Function::Minifs),
|
|
"GEOMEAN" => Some(Function::Geomean),
|
|
// Date and Time
|
|
"YEAR" => Some(Function::Year),
|
|
"DAY" => Some(Function::Day),
|
|
"EOMONTH" => Some(Function::Eomonth),
|
|
"MONTH" => Some(Function::Month),
|
|
"DATE" => Some(Function::Date),
|
|
"EDATE" => Some(Function::Edate),
|
|
"TODAY" => Some(Function::Today),
|
|
"NOW" => Some(Function::Now),
|
|
// Financial
|
|
"PMT" => Some(Function::Pmt),
|
|
"PV" => Some(Function::Pv),
|
|
"RATE" => Some(Function::Rate),
|
|
"NPER" => Some(Function::Nper),
|
|
"FV" => Some(Function::Fv),
|
|
"PPMT" => Some(Function::Ppmt),
|
|
"IPMT" => Some(Function::Ipmt),
|
|
"NPV" => Some(Function::Npv),
|
|
"XNPV" => Some(Function::Xnpv),
|
|
"MIRR" => Some(Function::Mirr),
|
|
"IRR" => Some(Function::Irr),
|
|
"XIRR" => Some(Function::Xirr),
|
|
"ISPMT" => Some(Function::Ispmt),
|
|
"RRI" | "_XLFN.RRI" => Some(Function::Rri),
|
|
|
|
"SLN" => Some(Function::Sln),
|
|
"SYD" => Some(Function::Syd),
|
|
"NOMINAL" => Some(Function::Nominal),
|
|
"EFFECT" => Some(Function::Effect),
|
|
"PDURATION" | "_XLFN.PDURATION" => Some(Function::Pduration),
|
|
|
|
"TBILLYIELD" => Some(Function::Tbillyield),
|
|
"TBILLPRICE" => Some(Function::Tbillprice),
|
|
"TBILLEQ" => Some(Function::Tbilleq),
|
|
|
|
"DOLLARDE" => Some(Function::Dollarde),
|
|
"DOLLARFR" => Some(Function::Dollarfr),
|
|
|
|
"DDB" => Some(Function::Ddb),
|
|
"DB" => Some(Function::Db),
|
|
|
|
"CUMPRINC" => Some(Function::Cumprinc),
|
|
"CUMIPMT" => Some(Function::Cumipmt),
|
|
|
|
"BESSELI" => Some(Function::Besseli),
|
|
"BESSELJ" => Some(Function::Besselj),
|
|
"BESSELK" => Some(Function::Besselk),
|
|
"BESSELY" => Some(Function::Bessely),
|
|
"ERF" => Some(Function::Erf),
|
|
"ERF.PRECISE" | "_XLFN.ERF.PRECISE" => Some(Function::ErfPrecise),
|
|
"ERFC" => Some(Function::Erfc),
|
|
"ERFC.PRECISE" | "_XLFN.ERFC.PRECISE" => Some(Function::ErfcPrecise),
|
|
"BIN2DEC" => Some(Function::Bin2dec),
|
|
"BIN2HEX" => Some(Function::Bin2hex),
|
|
"BIN2OCT" => Some(Function::Bin2oct),
|
|
"DEC2BIN" => Some(Function::Dec2Bin),
|
|
"DEC2HEX" => Some(Function::Dec2hex),
|
|
"DEC2OCT" => Some(Function::Dec2oct),
|
|
"HEX2BIN" => Some(Function::Hex2bin),
|
|
"HEX2DEC" => Some(Function::Hex2dec),
|
|
"HEX2OCT" => Some(Function::Hex2oct),
|
|
"OCT2BIN" => Some(Function::Oct2bin),
|
|
"OCT2DEC" => Some(Function::Oct2dec),
|
|
"OCT2HEX" => Some(Function::Oct2hex),
|
|
"BITAND" | "_XLFN.BITAND" => Some(Function::Bitand),
|
|
"BITLSHIFT" | "_XLFN.BITLSHIFT" => Some(Function::Bitlshift),
|
|
"BITOR" | "_XLFN.BITOR" => Some(Function::Bitor),
|
|
"BITRSHIFT" | "_XLFN.BITRSHIFT" => Some(Function::Bitrshift),
|
|
"BITXOR" | "_XLFN.BITXOR" => Some(Function::Bitxor),
|
|
"COMPLEX" => Some(Function::Complex),
|
|
"IMABS" => Some(Function::Imabs),
|
|
"IMAGINARY" => Some(Function::Imaginary),
|
|
"IMARGUMENT" => Some(Function::Imargument),
|
|
"IMCONJUGATE" => Some(Function::Imconjugate),
|
|
"IMCOS" => Some(Function::Imcos),
|
|
"IMCOSH" | "_XLFN.IMCOSH" => Some(Function::Imcosh),
|
|
"IMCOT" | "_XLFN.IMCOT" => Some(Function::Imcot),
|
|
"IMCSC" | "_XLFN.IMCSC" => Some(Function::Imcsc),
|
|
"IMCSCH" | "_XLFN.IMCSCH" => Some(Function::Imcsch),
|
|
"IMDIV" => Some(Function::Imdiv),
|
|
"IMEXP" => Some(Function::Imexp),
|
|
"IMLN" => Some(Function::Imln),
|
|
"IMLOG10" => Some(Function::Imlog10),
|
|
"IMLOG2" => Some(Function::Imlog2),
|
|
"IMPOWER" => Some(Function::Impower),
|
|
"IMPRODUCT" => Some(Function::Improduct),
|
|
"IMREAL" => Some(Function::Imreal),
|
|
"IMSEC" | "_XLFN.IMSEC" => Some(Function::Imsec),
|
|
"IMSECH" | "_XLFN.IMSECH" => Some(Function::Imsech),
|
|
"IMSIN" => Some(Function::Imsin),
|
|
"IMSINH" | "_XLFN.IMSINH" => Some(Function::Imsinh),
|
|
"IMSQRT" => Some(Function::Imsqrt),
|
|
"IMSUB" => Some(Function::Imsub),
|
|
"IMSUM" => Some(Function::Imsum),
|
|
"IMTAN" | "_XLFN.IMTAN" => Some(Function::Imtan),
|
|
"CONVERT" => Some(Function::Convert),
|
|
"DELTA" => Some(Function::Delta),
|
|
"GESTEP" => Some(Function::Gestep),
|
|
|
|
"SUBTOTAL" => Some(Function::Subtotal),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Function {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Function::And => write!(f, "AND"),
|
|
Function::False => write!(f, "FALSE"),
|
|
Function::If => write!(f, "IF"),
|
|
Function::Iferror => write!(f, "IFERROR"),
|
|
Function::Ifna => write!(f, "IFNA"),
|
|
Function::Ifs => write!(f, "IFS"),
|
|
Function::Not => write!(f, "NOT"),
|
|
Function::Or => write!(f, "OR"),
|
|
Function::Switch => write!(f, "SWITCH"),
|
|
Function::True => write!(f, "TRUE"),
|
|
Function::Xor => write!(f, "XOR"),
|
|
Function::Sin => write!(f, "SIN"),
|
|
Function::Cos => write!(f, "COS"),
|
|
Function::Tan => write!(f, "TAN"),
|
|
Function::Asin => write!(f, "ASIN"),
|
|
Function::Acos => write!(f, "ACOS"),
|
|
Function::Atan => write!(f, "ATAN"),
|
|
Function::Sinh => write!(f, "SINH"),
|
|
Function::Cosh => write!(f, "COSH"),
|
|
Function::Tanh => write!(f, "TANH"),
|
|
Function::Asinh => write!(f, "ASINH"),
|
|
Function::Acosh => write!(f, "ACOSH"),
|
|
Function::Atanh => write!(f, "ATANH"),
|
|
Function::Abs => write!(f, "ABS"),
|
|
Function::Pi => write!(f, "PI"),
|
|
Function::Sqrt => write!(f, "SQRT"),
|
|
Function::Sqrtpi => write!(f, "SQRTPI"),
|
|
Function::Atan2 => write!(f, "ATAN2"),
|
|
Function::Power => write!(f, "POWER"),
|
|
Function::Max => write!(f, "MAX"),
|
|
Function::Min => write!(f, "MIN"),
|
|
Function::Product => write!(f, "PRODUCT"),
|
|
Function::Rand => write!(f, "RAND"),
|
|
Function::Randbetween => write!(f, "RANDBETWEEN"),
|
|
Function::Round => write!(f, "ROUND"),
|
|
Function::Rounddown => write!(f, "ROUNDDOWN"),
|
|
Function::Roundup => write!(f, "ROUNDUP"),
|
|
Function::Sum => write!(f, "SUM"),
|
|
Function::Sumif => write!(f, "SUMIF"),
|
|
Function::Sumifs => write!(f, "SUMIFS"),
|
|
Function::Choose => write!(f, "CHOOSE"),
|
|
Function::Column => write!(f, "COLUMN"),
|
|
Function::Columns => write!(f, "COLUMNS"),
|
|
Function::Index => write!(f, "INDEX"),
|
|
Function::Indirect => write!(f, "INDIRECT"),
|
|
Function::Hlookup => write!(f, "HLOOKUP"),
|
|
Function::Lookup => write!(f, "LOOKUP"),
|
|
Function::Match => write!(f, "MATCH"),
|
|
Function::Offset => write!(f, "OFFSET"),
|
|
Function::Row => write!(f, "ROW"),
|
|
Function::Rows => write!(f, "ROWS"),
|
|
Function::Vlookup => write!(f, "VLOOKUP"),
|
|
Function::Xlookup => write!(f, "XLOOKUP"),
|
|
Function::Concatenate => write!(f, "CONCATENATE"),
|
|
Function::Exact => write!(f, "EXACT"),
|
|
Function::Value => write!(f, "VALUE"),
|
|
Function::T => write!(f, "T"),
|
|
Function::Valuetotext => write!(f, "VALUETOTEXT"),
|
|
Function::Concat => write!(f, "CONCAT"),
|
|
Function::Find => write!(f, "FIND"),
|
|
Function::Left => write!(f, "LEFT"),
|
|
Function::Len => write!(f, "LEN"),
|
|
Function::Lower => write!(f, "LOWER"),
|
|
Function::Mid => write!(f, "MID"),
|
|
Function::Right => write!(f, "RIGHT"),
|
|
Function::Search => write!(f, "SEARCH"),
|
|
Function::Text => write!(f, "TEXT"),
|
|
Function::Trim => write!(f, "TRIM"),
|
|
Function::Unicode => write!(f, "UNICODE"),
|
|
Function::Upper => write!(f, "UPPER"),
|
|
Function::Isnumber => write!(f, "ISNUMBER"),
|
|
Function::Isnontext => write!(f, "ISNONTEXT"),
|
|
Function::Istext => write!(f, "ISTEXT"),
|
|
Function::Islogical => write!(f, "ISLOGICAL"),
|
|
Function::Isblank => write!(f, "ISBLANK"),
|
|
Function::Iserr => write!(f, "ISERR"),
|
|
Function::Iserror => write!(f, "ISERROR"),
|
|
Function::Isna => write!(f, "ISNA"),
|
|
Function::Na => write!(f, "NA"),
|
|
Function::Isref => write!(f, "ISREF"),
|
|
Function::Isodd => write!(f, "ISODD"),
|
|
Function::Iseven => write!(f, "ISEVEN"),
|
|
Function::ErrorType => write!(f, "ERROR.TYPE"),
|
|
Function::Formulatext => write!(f, "FORMULATEXT"),
|
|
Function::Isformula => write!(f, "ISFORMULA"),
|
|
Function::Type => write!(f, "TYPE"),
|
|
Function::Sheet => write!(f, "SHEET"),
|
|
|
|
Function::Average => write!(f, "AVERAGE"),
|
|
Function::Averagea => write!(f, "AVERAGEA"),
|
|
Function::Averageif => write!(f, "AVERAGEIF"),
|
|
Function::Averageifs => write!(f, "AVERAGEIFS"),
|
|
Function::Count => write!(f, "COUNT"),
|
|
Function::Counta => write!(f, "COUNTA"),
|
|
Function::Countblank => write!(f, "COUNTBLANK"),
|
|
Function::Countif => write!(f, "COUNTIF"),
|
|
Function::Countifs => write!(f, "COUNTIFS"),
|
|
Function::Maxifs => write!(f, "MAXIFS"),
|
|
Function::Minifs => write!(f, "MINIFS"),
|
|
Function::Geomean => write!(f, "GEOMEAN"),
|
|
Function::Year => write!(f, "YEAR"),
|
|
Function::Day => write!(f, "DAY"),
|
|
Function::Month => write!(f, "MONTH"),
|
|
Function::Eomonth => write!(f, "EOMONTH"),
|
|
Function::Date => write!(f, "DATE"),
|
|
Function::Edate => write!(f, "EDATE"),
|
|
Function::Today => write!(f, "TODAY"),
|
|
Function::Now => write!(f, "NOW"),
|
|
Function::Pmt => write!(f, "PMT"),
|
|
Function::Pv => write!(f, "PV"),
|
|
Function::Rate => write!(f, "RATE"),
|
|
Function::Nper => write!(f, "NPER"),
|
|
Function::Fv => write!(f, "FV"),
|
|
Function::Ppmt => write!(f, "PPMT"),
|
|
Function::Ipmt => write!(f, "IPMT"),
|
|
Function::Npv => write!(f, "NPV"),
|
|
Function::Mirr => write!(f, "MIRR"),
|
|
Function::Irr => write!(f, "IRR"),
|
|
Function::Xirr => write!(f, "XIRR"),
|
|
Function::Xnpv => write!(f, "XNPV"),
|
|
Function::Rept => write!(f, "REPT"),
|
|
Function::Textafter => write!(f, "TEXTAFTER"),
|
|
Function::Textbefore => write!(f, "TEXTBEFORE"),
|
|
Function::Textjoin => write!(f, "TEXTJOIN"),
|
|
Function::Substitute => write!(f, "SUBSTITUTE"),
|
|
Function::Ispmt => write!(f, "ISPMT"),
|
|
Function::Rri => write!(f, "RRI"),
|
|
Function::Sln => write!(f, "SLN"),
|
|
Function::Syd => write!(f, "SYD"),
|
|
Function::Nominal => write!(f, "NOMINAL"),
|
|
Function::Effect => write!(f, "EFFECT"),
|
|
Function::Pduration => write!(f, "PDURATION"),
|
|
Function::Tbillyield => write!(f, "TBILLYIELD"),
|
|
Function::Tbillprice => write!(f, "TBILLPRICE"),
|
|
Function::Tbilleq => write!(f, "TBILLEQ"),
|
|
Function::Dollarde => write!(f, "DOLLARDE"),
|
|
Function::Dollarfr => write!(f, "DOLLARFR"),
|
|
Function::Ddb => write!(f, "DDB"),
|
|
Function::Db => write!(f, "DB"),
|
|
Function::Cumprinc => write!(f, "CUMPRINC"),
|
|
Function::Cumipmt => write!(f, "CUMIPMT"),
|
|
Function::Besseli => write!(f, "BESSELI"),
|
|
Function::Besselj => write!(f, "BESSELJ"),
|
|
Function::Besselk => write!(f, "BESSELK"),
|
|
Function::Bessely => write!(f, "BESSELY"),
|
|
Function::Erf => write!(f, "ERF"),
|
|
Function::ErfPrecise => write!(f, "ERF.PRECISE"),
|
|
Function::Erfc => write!(f, "ERFC"),
|
|
Function::ErfcPrecise => write!(f, "ERFC.PRECISE"),
|
|
Function::Bin2dec => write!(f, "BIN2DEC"),
|
|
Function::Bin2hex => write!(f, "BIN2HEX"),
|
|
Function::Bin2oct => write!(f, "BIN2OCT"),
|
|
Function::Dec2Bin => write!(f, "DEC2BIN"),
|
|
Function::Dec2hex => write!(f, "DEC2HEX"),
|
|
Function::Dec2oct => write!(f, "DEC2OCT"),
|
|
Function::Hex2bin => write!(f, "HEX2BIN"),
|
|
Function::Hex2dec => write!(f, "HEX2DEC"),
|
|
Function::Hex2oct => write!(f, "HEX2OCT"),
|
|
Function::Oct2bin => write!(f, "OCT2BIN"),
|
|
Function::Oct2dec => write!(f, "OCT2DEC"),
|
|
Function::Oct2hex => write!(f, "OCT2HEX"),
|
|
Function::Bitand => write!(f, "BITAND"),
|
|
Function::Bitlshift => write!(f, "BITLSHIFT"),
|
|
Function::Bitor => write!(f, "BITOR"),
|
|
Function::Bitrshift => write!(f, "BITRSHIFT"),
|
|
Function::Bitxor => write!(f, "BITXOR"),
|
|
Function::Complex => write!(f, "COMPLEX"),
|
|
Function::Imabs => write!(f, "IMABS"),
|
|
Function::Imaginary => write!(f, "IMAGINARY"),
|
|
Function::Imargument => write!(f, "IMARGUMENT"),
|
|
Function::Imconjugate => write!(f, "IMCONJUGATE"),
|
|
Function::Imcos => write!(f, "IMCOS"),
|
|
Function::Imcosh => write!(f, "IMCOSH"),
|
|
Function::Imcot => write!(f, "IMCOT"),
|
|
Function::Imcsc => write!(f, "IMCSC"),
|
|
Function::Imcsch => write!(f, "IMCSCH"),
|
|
Function::Imdiv => write!(f, "IMDIV"),
|
|
Function::Imexp => write!(f, "IMEXP"),
|
|
Function::Imln => write!(f, "IMLN"),
|
|
Function::Imlog10 => write!(f, "IMLOG10"),
|
|
Function::Imlog2 => write!(f, "IMLOG2"),
|
|
Function::Impower => write!(f, "IMPOWER"),
|
|
Function::Improduct => write!(f, "IMPRODUCT"),
|
|
Function::Imreal => write!(f, "IMREAL"),
|
|
Function::Imsec => write!(f, "IMSEC"),
|
|
Function::Imsech => write!(f, "IMSECH"),
|
|
Function::Imsin => write!(f, "IMSIN"),
|
|
Function::Imsinh => write!(f, "IMSINH"),
|
|
Function::Imsqrt => write!(f, "IMSQRT"),
|
|
Function::Imsub => write!(f, "IMSUB"),
|
|
Function::Imsum => write!(f, "IMSUM"),
|
|
Function::Imtan => write!(f, "IMTAN"),
|
|
Function::Convert => write!(f, "CONVERT"),
|
|
Function::Delta => write!(f, "DELTA"),
|
|
Function::Gestep => write!(f, "GESTEP"),
|
|
|
|
Function::Subtotal => write!(f, "SUBTOTAL"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Documentation for one function
|
|
pub struct Documentation {
|
|
pub name: String,
|
|
}
|
|
|
|
impl Model {
|
|
/// Produces documentation for all implemented functions
|
|
pub fn documentation() -> Vec<Documentation> {
|
|
let mut doc = Vec::new();
|
|
for function in Function::into_iter() {
|
|
doc.push(Documentation {
|
|
name: function.to_string(),
|
|
});
|
|
}
|
|
doc
|
|
}
|
|
|
|
pub(crate) fn evaluate_function(
|
|
&mut self,
|
|
kind: &Function,
|
|
args: &[Node],
|
|
cell: CellReferenceIndex,
|
|
) -> CalcResult {
|
|
match kind {
|
|
// Logical
|
|
Function::And => self.fn_and(args, cell),
|
|
Function::False => CalcResult::Boolean(false),
|
|
Function::If => self.fn_if(args, cell),
|
|
Function::Iferror => self.fn_iferror(args, cell),
|
|
Function::Ifna => self.fn_ifna(args, cell),
|
|
Function::Ifs => self.fn_ifs(args, cell),
|
|
Function::Not => self.fn_not(args, cell),
|
|
Function::Or => self.fn_or(args, cell),
|
|
Function::Switch => self.fn_switch(args, cell),
|
|
Function::True => CalcResult::Boolean(true),
|
|
Function::Xor => self.fn_xor(args, cell),
|
|
// Math and trigonometry
|
|
Function::Sin => self.fn_sin(args, cell),
|
|
Function::Cos => self.fn_cos(args, cell),
|
|
Function::Tan => self.fn_tan(args, cell),
|
|
|
|
Function::Asin => self.fn_asin(args, cell),
|
|
Function::Acos => self.fn_acos(args, cell),
|
|
Function::Atan => self.fn_atan(args, cell),
|
|
|
|
Function::Sinh => self.fn_sinh(args, cell),
|
|
Function::Cosh => self.fn_cosh(args, cell),
|
|
Function::Tanh => self.fn_tanh(args, cell),
|
|
|
|
Function::Asinh => self.fn_asinh(args, cell),
|
|
Function::Acosh => self.fn_acosh(args, cell),
|
|
Function::Atanh => self.fn_atanh(args, cell),
|
|
|
|
Function::Pi => self.fn_pi(args, cell),
|
|
Function::Abs => self.fn_abs(args, cell),
|
|
|
|
Function::Sqrt => self.fn_sqrt(args, cell),
|
|
Function::Sqrtpi => self.fn_sqrtpi(args, cell),
|
|
Function::Atan2 => self.fn_atan2(args, cell),
|
|
Function::Power => self.fn_power(args, cell),
|
|
|
|
Function::Max => self.fn_max(args, cell),
|
|
Function::Min => self.fn_min(args, cell),
|
|
Function::Product => self.fn_product(args, cell),
|
|
Function::Rand => self.fn_rand(args, cell),
|
|
Function::Randbetween => self.fn_randbetween(args, cell),
|
|
Function::Round => self.fn_round(args, cell),
|
|
Function::Rounddown => self.fn_rounddown(args, cell),
|
|
Function::Roundup => self.fn_roundup(args, cell),
|
|
Function::Sum => self.fn_sum(args, cell),
|
|
Function::Sumif => self.fn_sumif(args, cell),
|
|
Function::Sumifs => self.fn_sumifs(args, cell),
|
|
|
|
// Lookup and Reference
|
|
Function::Choose => self.fn_choose(args, cell),
|
|
Function::Column => self.fn_column(args, cell),
|
|
Function::Columns => self.fn_columns(args, cell),
|
|
Function::Index => self.fn_index(args, cell),
|
|
Function::Indirect => self.fn_indirect(args, cell),
|
|
Function::Hlookup => self.fn_hlookup(args, cell),
|
|
Function::Lookup => self.fn_lookup(args, cell),
|
|
Function::Match => self.fn_match(args, cell),
|
|
Function::Offset => self.fn_offset(args, cell),
|
|
Function::Row => self.fn_row(args, cell),
|
|
Function::Rows => self.fn_rows(args, cell),
|
|
Function::Vlookup => self.fn_vlookup(args, cell),
|
|
Function::Xlookup => self.fn_xlookup(args, cell),
|
|
// Text
|
|
Function::Concatenate => self.fn_concatenate(args, cell),
|
|
Function::Exact => self.fn_exact(args, cell),
|
|
Function::Value => self.fn_value(args, cell),
|
|
Function::T => self.fn_t(args, cell),
|
|
Function::Valuetotext => self.fn_valuetotext(args, cell),
|
|
Function::Concat => self.fn_concat(args, cell),
|
|
Function::Find => self.fn_find(args, cell),
|
|
Function::Left => self.fn_left(args, cell),
|
|
Function::Len => self.fn_len(args, cell),
|
|
Function::Lower => self.fn_lower(args, cell),
|
|
Function::Mid => self.fn_mid(args, cell),
|
|
Function::Right => self.fn_right(args, cell),
|
|
Function::Search => self.fn_search(args, cell),
|
|
Function::Text => self.fn_text(args, cell),
|
|
Function::Trim => self.fn_trim(args, cell),
|
|
Function::Unicode => self.fn_unicode(args, cell),
|
|
Function::Upper => self.fn_upper(args, cell),
|
|
// Information
|
|
Function::Isnumber => self.fn_isnumber(args, cell),
|
|
Function::Isnontext => self.fn_isnontext(args, cell),
|
|
Function::Istext => self.fn_istext(args, cell),
|
|
Function::Islogical => self.fn_islogical(args, cell),
|
|
Function::Isblank => self.fn_isblank(args, cell),
|
|
Function::Iserr => self.fn_iserr(args, cell),
|
|
Function::Iserror => self.fn_iserror(args, cell),
|
|
Function::Isna => self.fn_isna(args, cell),
|
|
Function::Na => CalcResult::new_error(Error::NA, cell, "".to_string()),
|
|
Function::Isref => self.fn_isref(args, cell),
|
|
Function::Isodd => self.fn_isodd(args, cell),
|
|
Function::Iseven => self.fn_iseven(args, cell),
|
|
Function::ErrorType => self.fn_errortype(args, cell),
|
|
Function::Formulatext => self.fn_formulatext(args, cell),
|
|
Function::Isformula => self.fn_isformula(args, cell),
|
|
Function::Type => self.fn_type(args, cell),
|
|
Function::Sheet => self.fn_sheet(args, cell),
|
|
// Statistical
|
|
Function::Average => self.fn_average(args, cell),
|
|
Function::Averagea => self.fn_averagea(args, cell),
|
|
Function::Averageif => self.fn_averageif(args, cell),
|
|
Function::Averageifs => self.fn_averageifs(args, cell),
|
|
Function::Count => self.fn_count(args, cell),
|
|
Function::Counta => self.fn_counta(args, cell),
|
|
Function::Countblank => self.fn_countblank(args, cell),
|
|
Function::Countif => self.fn_countif(args, cell),
|
|
Function::Countifs => self.fn_countifs(args, cell),
|
|
Function::Maxifs => self.fn_maxifs(args, cell),
|
|
Function::Minifs => self.fn_minifs(args, cell),
|
|
Function::Geomean => self.fn_geomean(args, cell),
|
|
// Date and Time
|
|
Function::Year => self.fn_year(args, cell),
|
|
Function::Day => self.fn_day(args, cell),
|
|
Function::Eomonth => self.fn_eomonth(args, cell),
|
|
Function::Month => self.fn_month(args, cell),
|
|
Function::Date => self.fn_date(args, cell),
|
|
Function::Edate => self.fn_edate(args, cell),
|
|
Function::Today => self.fn_today(args, cell),
|
|
Function::Now => self.fn_now(args, cell),
|
|
// Financial
|
|
Function::Pmt => self.fn_pmt(args, cell),
|
|
Function::Pv => self.fn_pv(args, cell),
|
|
Function::Rate => self.fn_rate(args, cell),
|
|
Function::Nper => self.fn_nper(args, cell),
|
|
Function::Fv => self.fn_fv(args, cell),
|
|
Function::Ppmt => self.fn_ppmt(args, cell),
|
|
Function::Ipmt => self.fn_ipmt(args, cell),
|
|
Function::Npv => self.fn_npv(args, cell),
|
|
Function::Mirr => self.fn_mirr(args, cell),
|
|
Function::Irr => self.fn_irr(args, cell),
|
|
Function::Xirr => self.fn_xirr(args, cell),
|
|
Function::Xnpv => self.fn_xnpv(args, cell),
|
|
Function::Rept => self.fn_rept(args, cell),
|
|
Function::Textafter => self.fn_textafter(args, cell),
|
|
Function::Textbefore => self.fn_textbefore(args, cell),
|
|
Function::Textjoin => self.fn_textjoin(args, cell),
|
|
Function::Substitute => self.fn_substitute(args, cell),
|
|
Function::Ispmt => self.fn_ispmt(args, cell),
|
|
Function::Rri => self.fn_rri(args, cell),
|
|
Function::Sln => self.fn_sln(args, cell),
|
|
Function::Syd => self.fn_syd(args, cell),
|
|
Function::Nominal => self.fn_nominal(args, cell),
|
|
Function::Effect => self.fn_effect(args, cell),
|
|
Function::Pduration => self.fn_pduration(args, cell),
|
|
Function::Tbillyield => self.fn_tbillyield(args, cell),
|
|
Function::Tbillprice => self.fn_tbillprice(args, cell),
|
|
Function::Tbilleq => self.fn_tbilleq(args, cell),
|
|
Function::Dollarde => self.fn_dollarde(args, cell),
|
|
Function::Dollarfr => self.fn_dollarfr(args, cell),
|
|
Function::Ddb => self.fn_ddb(args, cell),
|
|
Function::Db => self.fn_db(args, cell),
|
|
Function::Cumprinc => self.fn_cumprinc(args, cell),
|
|
Function::Cumipmt => self.fn_cumipmt(args, cell),
|
|
// Engineering
|
|
Function::Besseli => self.fn_besseli(args, cell),
|
|
Function::Besselj => self.fn_besselj(args, cell),
|
|
Function::Besselk => self.fn_besselk(args, cell),
|
|
Function::Bessely => self.fn_bessely(args, cell),
|
|
Function::Erf => self.fn_erf(args, cell),
|
|
Function::ErfPrecise => self.fn_erfprecise(args, cell),
|
|
Function::Erfc => self.fn_erfc(args, cell),
|
|
Function::ErfcPrecise => self.fn_erfcprecise(args, cell),
|
|
Function::Bin2dec => self.fn_bin2dec(args, cell),
|
|
Function::Bin2hex => self.fn_bin2hex(args, cell),
|
|
Function::Bin2oct => self.fn_bin2oct(args, cell),
|
|
Function::Dec2Bin => self.fn_dec2bin(args, cell),
|
|
Function::Dec2hex => self.fn_dec2hex(args, cell),
|
|
Function::Dec2oct => self.fn_dec2oct(args, cell),
|
|
Function::Hex2bin => self.fn_hex2bin(args, cell),
|
|
Function::Hex2dec => self.fn_hex2dec(args, cell),
|
|
Function::Hex2oct => self.fn_hex2oct(args, cell),
|
|
Function::Oct2bin => self.fn_oct2bin(args, cell),
|
|
Function::Oct2dec => self.fn_oct2dec(args, cell),
|
|
Function::Oct2hex => self.fn_oct2hex(args, cell),
|
|
Function::Bitand => self.fn_bitand(args, cell),
|
|
Function::Bitlshift => self.fn_bitlshift(args, cell),
|
|
Function::Bitor => self.fn_bitor(args, cell),
|
|
Function::Bitrshift => self.fn_bitrshift(args, cell),
|
|
Function::Bitxor => self.fn_bitxor(args, cell),
|
|
Function::Complex => self.fn_complex(args, cell),
|
|
Function::Imabs => self.fn_imabs(args, cell),
|
|
Function::Imaginary => self.fn_imaginary(args, cell),
|
|
Function::Imargument => self.fn_imargument(args, cell),
|
|
Function::Imconjugate => self.fn_imconjugate(args, cell),
|
|
Function::Imcos => self.fn_imcos(args, cell),
|
|
Function::Imcosh => self.fn_imcosh(args, cell),
|
|
Function::Imcot => self.fn_imcot(args, cell),
|
|
Function::Imcsc => self.fn_imcsc(args, cell),
|
|
Function::Imcsch => self.fn_imcsch(args, cell),
|
|
Function::Imdiv => self.fn_imdiv(args, cell),
|
|
Function::Imexp => self.fn_imexp(args, cell),
|
|
Function::Imln => self.fn_imln(args, cell),
|
|
Function::Imlog10 => self.fn_imlog10(args, cell),
|
|
Function::Imlog2 => self.fn_imlog2(args, cell),
|
|
Function::Impower => self.fn_impower(args, cell),
|
|
Function::Improduct => self.fn_improduct(args, cell),
|
|
Function::Imreal => self.fn_imreal(args, cell),
|
|
Function::Imsec => self.fn_imsec(args, cell),
|
|
Function::Imsech => self.fn_imsech(args, cell),
|
|
Function::Imsin => self.fn_imsin(args, cell),
|
|
Function::Imsinh => self.fn_imsinh(args, cell),
|
|
Function::Imsqrt => self.fn_imsqrt(args, cell),
|
|
Function::Imsub => self.fn_imsub(args, cell),
|
|
Function::Imsum => self.fn_imsum(args, cell),
|
|
Function::Imtan => self.fn_imtan(args, cell),
|
|
Function::Convert => self.fn_convert(args, cell),
|
|
Function::Delta => self.fn_delta(args, cell),
|
|
Function::Gestep => self.fn_gestep(args, cell),
|
|
|
|
Function::Subtotal => self.fn_subtotal(args, cell),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#![allow(clippy::unwrap_used)]
|
|
use std::{
|
|
fs::File,
|
|
io::{BufRead, BufReader},
|
|
};
|
|
|
|
use crate::functions::Function;
|
|
|
|
#[test]
|
|
fn function_iterator() {
|
|
// This checks that the number of functions in the enum is the same
|
|
// as the number of functions in the Iterator.
|
|
|
|
// This is tricky. In Rust we cannot loop over all the members of an enum.
|
|
// There are alternatives like using an external crate like strum.
|
|
// But I am not in the mood for that.
|
|
|
|
// What we do here is read this file , extract the functions in the enum
|
|
// and check they are the same as in the iterator
|
|
let file = File::open("src/functions/mod.rs").unwrap();
|
|
let reader = BufReader::new(file);
|
|
let mut start = false;
|
|
let mut list = Vec::new();
|
|
|
|
for line in reader.lines() {
|
|
let text = line.unwrap();
|
|
let text = text.trim().trim_end_matches(',');
|
|
if text == "pub enum Function {" {
|
|
start = true;
|
|
continue;
|
|
}
|
|
if start {
|
|
if text == "}" {
|
|
break;
|
|
}
|
|
if text.starts_with("//") {
|
|
// skip comments
|
|
continue;
|
|
}
|
|
if text.is_empty() {
|
|
// skip empty lines
|
|
continue;
|
|
}
|
|
list.push(text.to_owned());
|
|
}
|
|
}
|
|
// We make a list with their functions names, but we escape ".": ERROR.TYPE => ERRORTYPE
|
|
let iter_list = Function::into_iter()
|
|
.map(|f| format!("{}", f).replace('.', ""))
|
|
.collect::<Vec<_>>();
|
|
|
|
let len = iter_list.len();
|
|
|
|
assert_eq!(list.len(), len);
|
|
// We still need to check there are no duplicates. This will fail if a function in iter_list
|
|
// is included twice and one is missing
|
|
for function in list {
|
|
assert!(iter_list.contains(&function.to_uppercase()));
|
|
}
|
|
}
|
|
}
|