use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Arity {
Fixed(u8),
Range {
min: u8,
max: u8,
},
}
impl Arity {
pub const fn accepts(self, n: usize) -> bool {
match self {
Arity::Fixed(k) => n == k as usize,
Arity::Range { min, max } => min as usize <= n && n <= max as usize,
}
}
}
macro_rules! lib_fns {
($( $(#[$doc:meta])* $variant:ident = $name:literal / $arity:literal ; )*) => {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum LibFn {
$( $(#[$doc])* $variant, )*
}
impl LibFn {
pub const ALL: &[LibFn] = &[ $( LibFn::$variant, )* ];
pub const fn name(self) -> &'static str {
match self { $( LibFn::$variant => $name, )* }
}
pub fn from_name(s: &str) -> Option<LibFn> {
match s { $( $name => Some(LibFn::$variant), )* _ => None }
}
pub const fn arity(self) -> Arity {
match self { $( LibFn::$variant => Arity::Fixed($arity), )* }
}
}
};
}
lib_fns! {
Factorial2 = "factorial2" / 1;
Subfactorial = "subfactorial" / 1;
RisingFactorial = "rising_factorial" / 2;
FallingFactorial = "falling_factorial" / 2;
Fibonacci = "fibonacci" / 1;
Lucas = "lucas" / 1;
Bernoulli = "bernoulli" / 1;
Harmonic = "harmonic" / 1;
Catalan = "catalan" / 1;
Bell = "bell" / 1;
EulerNumber = "euler_number" / 1;
Stirling1 = "stirling1" / 2;
Stirling2 = "stirling2" / 2;
PartitionCount = "partition_count" / 1;
LambertW = "lambertw" / 1;
BesselJ = "besselj" / 2;
BesselY = "bessely" / 2;
BesselI = "besseli" / 2;
BesselK = "besselk" / 2;
Legendre = "legendre" / 2;
ChebyshevT = "chebyshev_t" / 2;
ChebyshevU = "chebyshev_u" / 2;
Hermite = "hermite" / 2;
Laguerre = "laguerre" / 2;
Erfi = "erfi" / 1;
ErfInv = "erfinv" / 1;
ErfcInv = "erfcinv" / 1;
ExpInt = "expint" / 2;
Shi = "Shi" / 1;
Chi = "Chi" / 1;
FresnelS = "fresnels" / 1;
FresnelC = "fresnelc" / 1;
LowerGamma = "lowergamma" / 2;
UpperGamma = "uppergamma" / 2;
PolyLog = "polylog" / 2;
DirichletEta = "dirichlet_eta" / 1;
AiryAi = "airyai" / 1;
AiryBi = "airybi" / 1;
AiryAiPrime = "airyaiprime" / 1;
AiryBiPrime = "airybiprime" / 1;
EllipticK = "elliptic_k" / 1;
EllipticE = "elliptic_e" / 1;
EllipticF = "elliptic_f" / 2;
EllipticPi = "elliptic_pi" / 2;
Gegenbauer = "gegenbauer" / 3;
Jacobi = "jacobi" / 4;
AssocLegendre = "assoc_legendre" / 3;
AssocLaguerre = "assoc_laguerre" / 3;
BetaInc = "betainc" / 4;
BetaIncRegularized = "betainc_regularized" / 4;
}
impl LibFn {
pub fn from_name_ignore_ascii_case(s: &str) -> Option<LibFn> {
LibFn::ALL
.iter()
.copied()
.find(|f| f.name().eq_ignore_ascii_case(s))
}
}
impl fmt::Display for LibFn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}