Assignment 6 Done

This commit is contained in:
static
2024-10-09 16:55:01 +00:00
parent a6f41960ad
commit dd37d10595
2 changed files with 221 additions and 43 deletions

View File

@@ -33,55 +33,55 @@ pub fn from_usize<T: Semiring>(value: usize) -> T {
impl Semiring for u64 {
fn zero() -> Self {
todo!()
0
}
fn one() -> Self {
todo!()
1
}
fn add(&self, rhs: &Self) -> Self {
todo!()
self + rhs
}
fn mul(&self, rhs: &Self) -> Self {
todo!()
self * rhs
}
}
impl Semiring for i64 {
fn zero() -> Self {
todo!()
0
}
fn one() -> Self {
todo!()
1
}
fn add(&self, rhs: &Self) -> Self {
todo!()
self + rhs
}
fn mul(&self, rhs: &Self) -> Self {
todo!()
self * rhs
}
}
impl Semiring for f64 {
fn zero() -> Self {
todo!()
0.0
}
fn one() -> Self {
todo!()
1.0
}
fn add(&self, rhs: &Self) -> Self {
todo!()
self + rhs
}
fn mul(&self, rhs: &Self) -> Self {
todo!()
self * rhs
}
}
@@ -105,42 +105,91 @@ pub struct Polynomial<C: Semiring> {
impl<C: Semiring> Semiring for Polynomial<C> {
fn zero() -> Self {
todo!()
Self {
coefficients: HashMap::new(),
}
}
fn one() -> Self {
todo!()
Self {
coefficients: HashMap::from([(0, C::one())]),
}
}
fn add(&self, rhs: &Self) -> Self {
todo!()
let mut coefficients = self.coefficients.clone();
for (deg, coef) in &rhs.coefficients {
_ = coefficients
.entry(*deg)
.and_modify(|value| *value = value.add(coef))
.or_insert(coef.clone());
}
coefficients.retain(|_, coef| *coef != C::zero());
Self { coefficients }
}
fn mul(&self, rhs: &Self) -> Self {
todo!()
let mut coefficients: HashMap<u64, C> = HashMap::new();
for (ldeg, lcoef) in &self.coefficients {
for (rdeg, rcoef) in &rhs.coefficients {
let coef = lcoef.mul(rcoef);
_ = coefficients
.entry(ldeg + rdeg)
.and_modify(|value| *value = value.add(&coef))
.or_insert(coef);
}
}
coefficients.retain(|_, coef| *coef != C::zero());
Self { coefficients }
}
}
impl<C: Semiring> Polynomial<C> {
/// Constructs polynomial `x`.
pub fn x() -> Self {
todo!()
Self {
coefficients: HashMap::from([(1, C::one())]),
}
}
/// Evaluates the polynomial with the given value.
pub fn eval(&self, value: C) -> C {
todo!()
let mut result = C::zero();
for (deg, coef) in &self.coefficients {
let mut xn = C::one();
let mut n = 0;
while n < *deg {
xn = xn.mul(&value);
n += 1;
}
result = result.add(&coef.mul(&xn));
}
result
}
/// Constructs polynomial `ax^n`.
pub fn term(a: C, n: u64) -> Self {
todo!()
Self {
coefficients: HashMap::from([(n, a)]),
}
}
}
impl<C: Semiring> From<C> for Polynomial<C> {
fn from(value: C) -> Self {
todo!()
Self {
coefficients: HashMap::from([(0, value)]),
}
}
}
@@ -164,6 +213,30 @@ impl<C: Semiring> std::str::FromStr for Polynomial<C> {
type Err = (); // Ignore this for now...
fn from_str(s: &str) -> Result<Self, Self::Err> {
todo!()
let mut coefficients: HashMap<u64, C> = HashMap::new();
for term in s.split(" + ") {
let has_x: bool = term.contains('x');
let has_power = term.contains('^');
let deg: u64 = if has_power {
term.split("^").nth(1).unwrap().parse().unwrap()
} else if has_x {
1
} else {
0
};
let coef: usize = if has_x && term.find("x").unwrap() == 0 {
1
} else if has_x {
term.split("x").nth(0).unwrap().parse().unwrap()
} else {
term.parse().unwrap()
};
let _unused = coefficients.insert(deg, from_usize(coef));
}
Ok(Self { coefficients })
}
}

View File

@@ -38,11 +38,39 @@ impl Rational {
}
}
fn gcd(a: isize, b: isize) -> isize {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
fn lcm(a: isize, b: isize) -> isize {
(a * b) / gcd(a, b)
}
fn normalize(r: &Rational) -> Rational {
let factor = if r.denominator < 0 { -1 } else { 1 };
Rational {
numerator: r.numerator * factor,
denominator: r.denominator * factor,
}
}
impl Add for Rational {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
todo!()
let lcm = lcm(self.denominator, rhs.denominator);
let num =
self.numerator * (lcm / self.denominator) + rhs.numerator * (lcm / rhs.denominator);
let gcd = gcd(num, lcm);
normalize(&Self {
numerator: num / gcd,
denominator: lcm / gcd,
})
}
}
@@ -50,7 +78,14 @@ impl Mul for Rational {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
todo!()
let num = self.numerator * rhs.numerator;
let den = self.denominator * rhs.denominator;
let gcd = gcd(num, den) * (if den < 0 { -1 } else { 1 });
normalize(&Self {
numerator: num / gcd,
denominator: den / gcd,
})
}
}
@@ -58,7 +93,7 @@ impl Sub for Rational {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
todo!()
self + (MINUS_ONE * rhs)
}
}
@@ -66,7 +101,10 @@ impl Div for Rational {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
todo!()
self.mul(Self {
numerator: rhs.denominator,
denominator: rhs.numerator,
})
}
}
@@ -84,7 +122,7 @@ pub trait Differentiable: Clone {
impl Differentiable for Rational {
/// HINT: Consult <https://en.wikipedia.org/wiki/Differentiation_rules#Constant_term_rule>
fn diff(&self) -> Self {
todo!()
ZERO
}
}
@@ -108,19 +146,31 @@ pub enum SingletonPolynomial {
impl SingletonPolynomial {
/// Creates a new const polynomial.
pub fn new_c(r: Rational) -> Self {
todo!()
SingletonPolynomial::Const(r)
}
/// Creates a new polynomial.
pub fn new_poly(coeff: Rational, power: Rational) -> Self {
todo!()
SingletonPolynomial::Polynomial { coeff, power }
}
}
impl Differentiable for SingletonPolynomial {
/// HINT: Consult <https://en.wikipedia.org/wiki/Power_rule>
fn diff(&self) -> Self {
todo!()
match self {
Self::Const(_) => Self::Const(ZERO),
Self::Polynomial { coeff, power } => {
if *power == ONE {
Self::Const(*coeff)
} else {
Self::Polynomial {
coeff: *coeff * *power,
power: *power - ONE,
}
}
}
}
}
}
@@ -131,7 +181,7 @@ pub struct Exp;
impl Exp {
/// Creates a new exponential function.
pub fn new() -> Self {
todo!()
Exp {}
}
}
@@ -144,7 +194,7 @@ impl Default for Exp {
impl Differentiable for Exp {
/// HINT: Consult <https://en.wikipedia.org/wiki/Differentiation_rules#Derivatives_of_exponential_and_logarithmic_functions>
fn diff(&self) -> Self {
todo!()
*self
}
}
@@ -168,19 +218,24 @@ pub enum Trignometric {
impl Trignometric {
/// Creates a new sine function.
pub fn new_sine(coeff: Rational) -> Self {
todo!()
Trignometric::Sine { coeff }
}
/// Creates a new cosine function.
pub fn new_cosine(coeff: Rational) -> Self {
todo!()
Trignometric::Cosine { coeff }
}
}
impl Differentiable for Trignometric {
/// HINT: Consult <https://en.wikipedia.org/wiki/Differentiation_rules#Derivatives_of_trigonometric_functions>
fn diff(&self) -> Self {
todo!()
match self {
Self::Sine { coeff } => Self::Cosine { coeff: *coeff },
Self::Cosine { coeff } => Self::Sine {
coeff: MINUS_ONE * *coeff,
},
}
}
}
@@ -199,7 +254,12 @@ pub enum BaseFuncs {
impl Differentiable for BaseFuncs {
fn diff(&self) -> Self {
todo!()
match self {
Self::Const(_) => Self::Const(ZERO),
Self::Poly(p) => Self::Poly(p.diff()),
Self::Exp(e) => Self::Exp(e.diff()),
Self::Trig(t) => Self::Trig(t.diff()),
}
}
}
@@ -222,14 +282,41 @@ pub enum ComplexFuncs<F> {
impl<F: Differentiable> Differentiable for Box<F> {
fn diff(&self) -> Self {
todo!()
Box::new(self.deref().diff())
}
}
impl<F: Differentiable> Differentiable for ComplexFuncs<F> {
/// HINT: Consult <https://en.wikipedia.org/wiki/Differentiation_rules#Elementary_rules_of_differentiation>
fn diff(&self) -> Self {
todo!()
match self {
Self::Func(f) => Self::Func(f.diff()),
Self::Add(lhs, rhs) => Self::Add(lhs.diff(), rhs.diff()),
Self::Sub(lhs, rhs) => Self::Sub(lhs.diff(), rhs.diff()),
Self::Mul(lhs, rhs) => {
let diff_lhs = lhs.diff();
let diff_rhs = rhs.diff();
Self::Add(
Box::new(Self::Mul(diff_lhs, rhs.clone())),
Box::new(Self::Mul(lhs.clone(), diff_rhs)),
)
}
Self::Div(lhs, rhs) => {
let diff_lhs = lhs.diff();
let diff_rhs = rhs.diff();
Self::Div(
Box::new(Self::Sub(
Box::new(Self::Mul(diff_lhs, rhs.clone())),
Box::new(Self::Mul(lhs.clone(), diff_rhs)),
)),
Box::new(Self::Mul(rhs.clone(), rhs.clone())),
)
}
Self::Comp(outer, inner) => Self::Mul(
Box::new(Self::Comp(outer.diff(), inner.clone())),
inner.diff(),
),
}
}
}
@@ -241,37 +328,55 @@ pub trait Evaluate {
impl Evaluate for Rational {
fn evaluate(&self, x: f64) -> f64 {
todo!()
(self.numerator as f64) / (self.denominator as f64)
}
}
impl Evaluate for SingletonPolynomial {
fn evaluate(&self, x: f64) -> f64 {
todo!()
match self {
Self::Const(r) => r.evaluate(x),
Self::Polynomial { coeff, power } => x.powf(power.evaluate(x)) * coeff.evaluate(x),
}
}
}
impl Evaluate for Exp {
fn evaluate(&self, x: f64) -> f64 {
todo!()
x.exp()
}
}
impl Evaluate for Trignometric {
fn evaluate(&self, x: f64) -> f64 {
todo!()
match self {
Self::Sine { coeff } => coeff.evaluate(x) * x.sin(),
Self::Cosine { coeff } => coeff.evaluate(x) * x.cos(),
}
}
}
impl Evaluate for BaseFuncs {
fn evaluate(&self, x: f64) -> f64 {
todo!()
match self {
Self::Const(r) => r.evaluate(x),
Self::Poly(p) => p.evaluate(x),
Self::Exp(e) => e.evaluate(x),
Self::Trig(t) => t.evaluate(x),
}
}
}
impl<F: Evaluate> Evaluate for ComplexFuncs<F> {
fn evaluate(&self, x: f64) -> f64 {
todo!()
match self {
Self::Func(f) => f.evaluate(x),
Self::Add(lhs, rhs) => lhs.evaluate(x) + rhs.evaluate(x),
Self::Sub(lhs, rhs) => lhs.evaluate(x) - rhs.evaluate(x),
Self::Mul(lhs, rhs) => lhs.evaluate(x) * rhs.evaluate(x),
Self::Div(lhs, rhs) => lhs.evaluate(x) / rhs.evaluate(x),
Self::Comp(outer, inner) => outer.evaluate(inner.evaluate(x)),
}
}
}