use super::PolynomialSeries;
use ndarray_linalg::Scalar;
#[repr(transparent)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Basis(usize);
impl Basis {
pub(crate) const fn new(degree: usize) -> Self {
Self(degree)
}
pub(crate) const fn degree(&self) -> usize {
self.0
}
}
pub trait Polynomial<E: Scalar<Real = E> + PartialOrd> {
fn polynomials(&self, t: E) -> Vec<E>;
}
pub trait ConstrainedPolynomial<E: Scalar<Real = E> + PartialOrd, S: PolynomialSeries<E>>:
Polynomial<E>
{
fn polynomials_with_constraint(&self, t: E, multiplicative_constraint: &S) -> Vec<E> {
let mut polynomials_in_basis = self.polynomials(t);
let constraint_value = multiplicative_constraint.evaluate(t);
polynomials_in_basis
.iter_mut()
.for_each(|polynomial_in_basis| *polynomial_in_basis *= constraint_value);
polynomials_in_basis
}
}
impl<E: Scalar<Real = E> + PartialOrd> Polynomial<E> for Basis {
fn polynomials(&self, t: E) -> Vec<E> {
match self.degree() {
0 => vec![E::one()],
1 => vec![E::one(), t],
_ => {
let mut vals = vec![E::one(), t];
for ii in 1..self.degree() {
vals.push((E::one() + E::one()) * t * vals[ii] - vals[ii - 1]);
}
vals
}
}
}
}
impl<E: Scalar<Real = E> + PartialOrd, S: PolynomialSeries<E>> ConstrainedPolynomial<E, S>
for Basis
{
}