mod iter; use iter::Iter; use std::fmt; use std::ops::{Add, Mul, Sub}; #[derive(PartialEq, Debug, Clone)] pub struct Poly { data: Vec, degree: usize, } impl Poly { pub fn new(data: Vec) -> Poly { if data.len() > 0 { let mut i = data.len() - 1; while data[i] == 0.0 && i > 0 { i -= 1; } Poly { data, degree: i } } else { Poly { data, degree: 0 } } } pub fn degree(&self) -> usize { self.degree } fn iter(&self) -> Iter { Iter::new(self.data.clone(), self.degree()) } } impl Add for &Poly { type Output = Poly; fn add(self, other: Self) -> Poly { Poly::new(self.iter().zip(other.iter()).map(|(x, y)| x + y).collect()) } } impl Sub for &Poly { type Output = Poly; fn sub(self, other: Self) -> Poly { Poly::new(self.iter().zip(other.iter()).map(|(x, y)| x - y).collect()) } } impl Mul for &Poly { type Output = Poly; fn mul(self, other: Self) -> Poly { let mut r = Vec::new(); for i in 0..other.degree() + 1 { let mut prefix = vec![0.0; i]; let mut suffix: Vec = self .iter() .take(self.degree() + 1) .map(|x| x * other.data[i]) .collect(); prefix.append(&mut suffix); r.push(Poly::new(prefix)); } r.iter().fold(Poly::new(vec![0.0]), |acc, x| &acc + x) } } impl fmt::Display for &Poly { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = String::new(); for i in 0..self.data.len() { s.push_str(&self.data[i].clone().to_string()); if i < self.data.len() - 1 { s.push_str(", "); } } write!(f, "{}", s) } } #[cfg(test)] mod tests { use super::*; #[test] fn mul_test() { let a = Poly::new(vec![1.0, 2.0, 3.0]); let b = Poly::new(vec![1.0, 2.0]); assert_eq!(&a * &b, Poly::new(vec![1.0, 4.0, 7.0, 6.0])); } #[test] fn add_test() { let a = Poly::new(vec![1.0]); let b = Poly::new(vec![0.0, 0.0, 0.0, 1.0]); assert_eq!(&a + &b, Poly::new(vec![1.0, 0.0, 0.0, 1.0])); } #[test] fn sub_test() { let a = Poly::new(vec![1.0, 2.0, 3.0]); let b = Poly::new(vec![1.0, 1.0, 1.0]); assert_eq!(&a - &b, Poly::new(vec![0.0, 1.0, 2.0])); } #[test] fn degree_is_five() { let p = Poly::new(vec![0.0, 0.0, 0.0, 0.0, 0.0, 2.0]); assert_eq!(p.degree(), 5); } #[test] fn degree_is_zero() { let p = Poly::new(vec![0.0; 6]); assert_eq!(p.degree(), 0); } }