const_poly 0.0.5

Evaluate any multivariable equation or polynomial at compile time with high accuracy and zero runtime overhead.
Documentation
use crate::function_approximations::*;

/// Enum representing the mathematical function applied to a variable in a term.
///
/// Each variant corresponds to a supported unary function that can be applied
/// to a variable within a polynomial term.
///
/// Variants:
/// - `Identity`: the variable itself (no function applied)
/// - `Pow(u32)`: power function `x^n` where `n` is the exponent
/// - `Sin`: sine function
/// - `Cos`: cosine function
/// - `Tan`: tangent function
/// - `Exp`: exponential function (e^x)
/// - `Ln`: natural logarithm
/// - `Sqrt`: square root function
/// - `Arctan`: arctangent function
/// - `Sinh`: hyperbolic sine function
/// - `Cosh`: hyperbolic cosine function
#[derive(Clone, Copy)]
pub enum VarFunction {
    Identity, // x
    Pow(i32), // x^n
    Sin,      // sin(x)
    Cos,      // cos(x)
    Tan,      // tan(x)
    Exp,      // exp(x)
    Ln,       // ln(x)
    Sqrt,     // sqrt(x)
    Arctan,   // arctan(x)
    Sinh,     // sinh(x)
    Cosh,     // cosh(x)
}

/// Represents a single term in a polynomial with NUM_VARIABLES variables.
///
/// A term consists of a coefficient and an array of `VarFunction`s, each
/// applied to a corresponding variable in the input.
///
/// For example, for `NUM_VARIABLES = 2`:
/// ```
/// use const_poly::{Term, VarFunction::*};
/// const TERM: Term<2> = Term::new(3.0, [Sin, Pow(2)]);
/// ```
/// represents the term `3 * sin(x_0) * (x_1)^2`.
#[derive(Copy, Clone)]
pub struct Term<const NUM_VARIABLES: usize> {
    coeff: f64,
    functions: [VarFunction; NUM_VARIABLES],
}

impl<const NUM_VARIABLES: usize> Term<NUM_VARIABLES> {
    /// Creates a new `Term` with the specified coefficient and functions.
    ///
    /// # Parameters
    ///
    /// - `coefficient`: The scalar multiplier for the term.
    /// - `functions`: An array of `VarFunction`s, one per variable.
    ///
    /// # Returns
    ///
    /// A new `Term` instance.
    ///
    /// # Example
    ///
    /// ```
    /// use const_poly::{Term, VarFunction::*};
    /// const TERM: Term<2> = Term::new(2.0, [Sin, Pow(3)]);
    /// ```
    /// represents the term `2.0 * sin(x_0) * (x_1)^3`.
    pub const fn new(coefficient: f64, functions: [VarFunction; NUM_VARIABLES]) -> Self {
        Self {
            coeff: coefficient,
            functions,
        }
    }

    /// Evaluates the term for the given variables.
    ///
    /// Applies each function in `functions` to the corresponding variable,
    /// then multiplies all results together with the coefficient.
    ///
    /// # Parameters
    ///
    /// - `vars`: An array of variables of length `NUM_VARIABLES`.
    ///
    /// # Returns
    ///
    /// The floating-point result of evaluating the term.
    ///
    /// # Example
    ///
    /// ```
    /// use const_poly::{Term, VarFunction::*};
    /// const TERM: Term<1> = Term::new(2.0, [Sin]);
    /// const val: f64 = TERM.evaluate(&[1.57079632679]); // Approx sin(pi/2)
    /// assert!((val - 2.0).abs() < 1e-6);
    /// ```
    pub const fn evaluate(&self, vars: &[f64; NUM_VARIABLES]) -> f64 {
        let mut result = self.coeff;
        let mut i = 0;

        while i < NUM_VARIABLES {
            let value = match self.functions[i] {
                VarFunction::Identity => vars[i],
                VarFunction::Pow(exp) => static_powi(vars[i], exp),
                VarFunction::Sin => sin_approx(vars[i]),
                VarFunction::Cos => cos_approx(vars[i]),
                VarFunction::Tan => tan_approx(vars[i]),
                VarFunction::Exp => exp_approx(vars[i]),
                VarFunction::Ln => ln_approx(vars[i]),
                VarFunction::Sqrt => sqrt_approx(vars[i]),
                VarFunction::Arctan => arctan_approx(vars[i]),
                VarFunction::Sinh => sinh_approx(vars[i]),
                VarFunction::Cosh => cosh_approx(vars[i]),
            };

            result *= value;
            i += 1;
        }

        result
    }
}