diff --git a/crates/comet_math/src/lib.rs b/crates/comet_math/src/lib.rs index a882c28..be7742f 100644 --- a/crates/comet_math/src/lib.rs +++ b/crates/comet_math/src/lib.rs @@ -1,15 +1,17 @@ -pub(crate) use utilities::*; pub use point::*; pub use vector::*; pub use matrix::*; pub use bezier::*; pub use easings::*; +pub use polynomial::*; +pub use interpolation::*; -mod utilities; pub mod point; pub mod vector; pub mod matrix; pub mod quaternion; pub mod bezier; pub mod easings; -pub mod noise; \ No newline at end of file +pub mod noise; +pub mod polynomial; +pub mod interpolation; \ No newline at end of file diff --git a/crates/comet_math/src/polynomial.rs b/crates/comet_math/src/polynomial.rs new file mode 100644 index 0000000..d78df45 --- /dev/null +++ b/crates/comet_math/src/polynomial.rs @@ -0,0 +1,129 @@ +use std::ops::*; + +pub struct Polynomial { + coefficients: Vec, + degree: usize +} + +impl Polynomial { + pub fn new(coefficients: Vec) -> Self { + let degree = coefficients.len() - 1; + Self { + coefficients, + degree + } + } + + pub fn evaluate(&self, x: f32) -> f32 { + let mut result = 0.0; + for c in &self.coefficients { + result = result * x + c; + } + result + } + + pub fn differentiate(&self) -> Self { + let mut new_coefficients = Vec::new(); + for (i, &c) in self.coefficients.iter().enumerate() { + if i != 0 { + new_coefficients.push(c * i as f32); + } + } + Self::new(new_coefficients) + } + + pub fn integrate(&self) -> Self { + let mut new_coefficients = Vec::new(); + new_coefficients.push(0.0); + for (i, &c) in self.coefficients.iter().enumerate() { + new_coefficients.push(c / (i + 1) as f32); + } + Self::new(new_coefficients) + } +} + +impl Add for Polynomial { + type Output = Self; + + fn add(self, other: Self) -> Self { + let mut new_coefficients = Vec::new(); + let mut i = 0; + while i < self.coefficients.len() || i < other.coefficients.len() { + let a = if i < self.coefficients.len() { self.coefficients[i] } else { 0.0 }; + let b = if i < other.coefficients.len() { other.coefficients[i] } else { 0.0 }; + new_coefficients.push(a + b); + i += 1; + } + Self::new(new_coefficients) + } +} + +impl Sub for Polynomial { + type Output = Self; + + fn sub(self, other: Self) -> Self { + let mut new_coefficients = Vec::new(); + let mut i = 0; + while i < self.coefficients.len() || i < other.coefficients.len() { + let a = if i < self.coefficients.len() { self.coefficients[i] } else { 0.0 }; + let b = if i < other.coefficients.len() { other.coefficients[i] } else { 0.0 }; + new_coefficients.push(a - b); + i += 1; + } + Self::new(new_coefficients) + } +} + +impl Mul for Polynomial { + type Output = Self; + + fn mul(self, other: Self) -> Self { + let mut new_coefficients = vec![0.0; self.degree + other.degree + 1]; + for (i, &a) in self.coefficients.iter().enumerate() { + for (j, &b) in other.coefficients.iter().enumerate() { + new_coefficients[i + j] += a * b; + } + } + Self::new(new_coefficients) + } +} + +impl Div for Polynomial { + type Output = Self; + + fn div(self, other: Self) -> Self { + let mut new_coefficients = vec![0.0; self.degree - other.degree + 1]; + let mut dividend = self.coefficients.clone(); + let divisor = other.coefficients.clone(); + while dividend.len() >= divisor.len() { + let mut quotient = vec![0.0; dividend.len() - divisor.len() + 1]; + let mut i = dividend.len() - divisor.len(); + quotient[i] = dividend.last().unwrap() / divisor.last().unwrap(); + for (j, &d) in divisor.iter().enumerate() { + dividend[i + j] -= quotient[i] * d; + } + new_coefficients[i] = quotient[i]; + dividend.pop(); + } + Self::new(new_coefficients) + } +} + +impl std::fmt::Display for Polynomial { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let terms: Vec = self.coefficients.iter() + .enumerate() + .filter(|(_, &c)| c != 0.0) + .map(|(i, &c)| { + if i == 0 { + format!("{}", c) + } else if i == 1 { + format!("{}x", c) + } else { + format!("{}x^{}", c, i) + } + }) + .collect(); + write!(f, "{}", terms.join(" + ")) + } +} \ No newline at end of file