const_poly/
term.rs

1use crate::function_approximations::*;
2
3/// Enum representing the mathematical function applied to a variable in a term.
4///
5/// Each variant corresponds to a supported unary function that can be applied
6/// to a variable within a polynomial term.
7///
8/// Variants:
9/// - `Identity`: the variable itself (no function applied)
10/// - `Pow(u32)`: power function `x^n` where `n` is the exponent
11/// - `Sin`: sine function
12/// - `Cos`: cosine function
13/// - `Tan`: tangent function
14/// - `Exp`: exponential function (e^x)
15/// - `Ln`: natural logarithm
16/// - `Sqrt`: square root function
17/// - `Arctan`: arctangent function
18/// - `Sinh`: hyperbolic sine function
19/// - `Cosh`: hyperbolic cosine function
20#[derive(Clone, Copy)]
21pub enum VarFunction {
22    Identity, // x
23    Pow(i32), // x^n
24    Sin,      // sin(x)
25    Cos,      // cos(x)
26    Tan,      // tan(x)
27    Exp,      // exp(x)
28    Ln,       // ln(x)
29    Sqrt,     // sqrt(x)
30    Arctan,   // arctan(x)
31    Sinh,     // sinh(x)
32    Cosh,     // cosh(x)
33}
34
35/// Represents a single term in a polynomial with NUM_VARIABLES variables.
36///
37/// A term consists of a coefficient and an array of `VarFunction`s, each
38/// applied to a corresponding variable in the input.
39///
40/// For example, for `NUM_VARIABLES = 2`:
41/// ```
42/// use const_poly::{Term, VarFunction::*};
43/// const TERM: Term<2> = Term::new(3.0, [Sin, Pow(2)]);
44/// ```
45/// represents the term `3 * sin(x_0) * (x_1)^2`.
46#[derive(Copy, Clone)]
47pub struct Term<const NUM_VARIABLES: usize> {
48    coeff: f64,
49    functions: [VarFunction; NUM_VARIABLES],
50}
51
52impl<const NUM_VARIABLES: usize> Term<NUM_VARIABLES> {
53    /// Creates a new `Term` with the specified coefficient and functions.
54    ///
55    /// # Parameters
56    ///
57    /// - `coefficient`: The scalar multiplier for the term.
58    /// - `functions`: An array of `VarFunction`s, one per variable.
59    ///
60    /// # Returns
61    ///
62    /// A new `Term` instance.
63    ///
64    /// # Example
65    ///
66    /// ```
67    /// use const_poly::{Term, VarFunction::*};
68    /// const TERM: Term<2> = Term::new(2.0, [Sin, Pow(3)]);
69    /// ```
70    /// represents the term `2.0 * sin(x_0) * (x_1)^3`.
71    pub const fn new(coefficient: f64, functions: [VarFunction; NUM_VARIABLES]) -> Self {
72        Self {
73            coeff: coefficient,
74            functions,
75        }
76    }
77
78    /// Evaluates the term for the given variables.
79    ///
80    /// Applies each function in `functions` to the corresponding variable,
81    /// then multiplies all results together with the coefficient.
82    ///
83    /// # Parameters
84    ///
85    /// - `vars`: An array of variables of length `NUM_VARIABLES`.
86    ///
87    /// # Returns
88    ///
89    /// The floating-point result of evaluating the term.
90    ///
91    /// # Example
92    ///
93    /// ```
94    /// use const_poly::{Term, VarFunction::*};
95    /// const TERM: Term<1> = Term::new(2.0, [Sin]);
96    /// const val: f64 = TERM.evaluate([1.57079632679]); // Approx sin(pi/2)
97    /// assert!((val - 2.0).abs() < 1e-6);
98    /// ```
99    pub const fn evaluate(&self, vars: [f64; NUM_VARIABLES]) -> f64 {
100        let mut result = self.coeff;
101        let mut i = 0;
102
103        while i < NUM_VARIABLES {
104            let value = match self.functions[i] {
105                VarFunction::Identity => vars[i],
106                VarFunction::Pow(exp) => static_powi(vars[i], exp),
107                VarFunction::Sin => sin_approx(vars[i]),
108                VarFunction::Cos => cos_approx(vars[i]),
109                VarFunction::Tan => tan_approx(vars[i]),
110                VarFunction::Exp => exp_approx(vars[i]),
111                VarFunction::Ln => ln_approx(vars[i]),
112                VarFunction::Sqrt => sqrt_approx(vars[i]),
113                VarFunction::Arctan => arctan_approx(vars[i]),
114                VarFunction::Sinh => sinh_approx(vars[i]),
115                VarFunction::Cosh => cosh_approx(vars[i]),
116            };
117
118            result *= value;
119            i += 1;
120        }
121
122        result
123    }
124}