mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-15 22:48:45 +00:00
copy-paste problems
This commit is contained in:
360
src/assignments/assignment06/symbolic_differentiation.rs
Normal file
360
src/assignments/assignment06/symbolic_differentiation.rs
Normal file
@@ -0,0 +1,360 @@
|
||||
//! Symbolic differentiation with rational coefficents.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::*;
|
||||
|
||||
/// Rational number represented by two isize, numerator and denominator.
|
||||
///
|
||||
/// Each Rational number should be normalized so that `demoninator` is nonnegative and `numerator` and `demoninator` are coprime.
|
||||
/// See [`normalize`] for examples. As a corner case, 0 is represented by Rational { numerator: 0, demoninator: 0 }.
|
||||
///
|
||||
/// For "natural use", Rational also overloads standard arithmetic operations, i.e, `+`, `-`, `*`, `/`.
|
||||
///
|
||||
/// See [here](https://doc.rust-lang.org/core/ops/index.html) for details.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Rational {
|
||||
numerator: isize,
|
||||
denominator: isize,
|
||||
}
|
||||
|
||||
// Some useful constants.
|
||||
|
||||
/// Zero
|
||||
pub const ZERO: Rational = Rational::new(0, 0);
|
||||
/// One
|
||||
pub const ONE: Rational = Rational::new(1, 1);
|
||||
/// Minus one
|
||||
pub const MINUS_ONE: Rational = Rational::new(-1, 1);
|
||||
|
||||
impl Rational {
|
||||
/// Creates a new rational number.
|
||||
pub const fn new(numerator: isize, denominator: isize) -> Self {
|
||||
Self {
|
||||
numerator,
|
||||
denominator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for Rational {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Differentiable functions.
|
||||
///
|
||||
/// For simplicity, we only consider infinitely differentiable functions.
|
||||
pub trait Differentiable: Clone {
|
||||
/// Differentiate.
|
||||
///
|
||||
/// Since the return type is `Self`, this trait can only be implemented
|
||||
/// for types that are closed under differentiation.
|
||||
fn diff(&self) -> Self;
|
||||
}
|
||||
|
||||
impl Differentiable for Rational {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Singleton polynomial.
|
||||
///
|
||||
/// Unlike regular polynomials, this type only represents a single term.
|
||||
/// The `Const` variant is included to make `Polynomial` closed under differentiation.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SingletonPolynomial {
|
||||
/// Constant polynomial.
|
||||
Const(Rational),
|
||||
/// Non-const polynomial.
|
||||
Polynomial {
|
||||
/// coefficent of polynomial. Must be non-zero.
|
||||
coeff: Rational,
|
||||
/// power of polynomial. Must be non-zero.
|
||||
power: Rational,
|
||||
},
|
||||
}
|
||||
|
||||
impl SingletonPolynomial {
|
||||
/// Creates a new const polynomial.
|
||||
pub fn new_c(r: Rational) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Creates a new polynomial.
|
||||
pub fn new_poly(coeff: Rational, power: Rational) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Differentiable for SingletonPolynomial {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Expoential function.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Exp;
|
||||
|
||||
impl Exp {
|
||||
/// Creates a new exponential function.
|
||||
pub fn new() -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Exp {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Differentiable for Exp {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Trigonometric functions.
|
||||
///
|
||||
/// The trig fucntions carry their coefficents to be closed under differntiation.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Trignometric {
|
||||
/// Sine function.
|
||||
Sine {
|
||||
/// Coefficent
|
||||
coeff: Rational,
|
||||
},
|
||||
/// Sine function.
|
||||
Cosine {
|
||||
/// Coefficent
|
||||
coeff: Rational,
|
||||
},
|
||||
}
|
||||
|
||||
impl Trignometric {
|
||||
/// Creates a new sine function.
|
||||
pub fn new_sine(coeff: Rational) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Creates a new cosine function.
|
||||
pub fn new_cosine(coeff: Rational) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Differentiable for Trignometric {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic functions
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BaseFuncs {
|
||||
/// Constant
|
||||
Const(Rational),
|
||||
/// Polynomial
|
||||
Poly(SingletonPolynomial),
|
||||
/// Exponential
|
||||
Exp(Exp),
|
||||
/// Trignometirc
|
||||
Trig(Trignometric),
|
||||
}
|
||||
|
||||
impl Differentiable for BaseFuncs {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Complex functions.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ComplexFuncs<F> {
|
||||
/// Basic functions
|
||||
Func(F),
|
||||
/// Addition
|
||||
Add(Box<ComplexFuncs<F>>, Box<ComplexFuncs<F>>),
|
||||
/// Subtraction
|
||||
Sub(Box<ComplexFuncs<F>>, Box<ComplexFuncs<F>>),
|
||||
/// Multipliciation
|
||||
Mul(Box<ComplexFuncs<F>>, Box<ComplexFuncs<F>>),
|
||||
/// Division
|
||||
Div(Box<ComplexFuncs<F>>, Box<ComplexFuncs<F>>),
|
||||
/// Composition
|
||||
Comp(Box<ComplexFuncs<F>>, Box<ComplexFuncs<F>>),
|
||||
}
|
||||
|
||||
impl<F: Differentiable> Differentiable for Box<F> {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Differentiable> Differentiable for ComplexFuncs<F> {
|
||||
fn diff(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate functions.
|
||||
pub trait Evaluate {
|
||||
/// Evaluate `self` at `x`.
|
||||
fn evaluate(&self, x: f64) -> f64;
|
||||
}
|
||||
|
||||
impl Evaluate for Rational {
|
||||
fn evaluate(&self, x: f64) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for SingletonPolynomial {
|
||||
fn evaluate(&self, x: f64) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for Exp {
|
||||
fn evaluate(&self, x: f64) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for Trignometric {
|
||||
fn evaluate(&self, x: f64) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evaluate for BaseFuncs {
|
||||
fn evaluate(&self, x: f64) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Evaluate> Evaluate for ComplexFuncs<F> {
|
||||
fn evaluate(&self, x: f64) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Rational {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if *self == ZERO {
|
||||
return write!(f, "0");
|
||||
} else if self.denominator == 1 {
|
||||
return write!(f, "{}", self.numerator);
|
||||
}
|
||||
write!(f, "{}/{}", self.numerator, self.denominator)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SingletonPolynomial {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Const(r) => write!(f, "{r}"),
|
||||
Self::Polynomial { coeff, power } => {
|
||||
// coeff or power is zero
|
||||
if *coeff == ZERO {
|
||||
return write!(f, "0");
|
||||
} else if *power == ZERO {
|
||||
return write!(f, "{coeff}");
|
||||
}
|
||||
|
||||
// Standard form of px^q
|
||||
let coeff = if *coeff == ONE {
|
||||
"".to_string()
|
||||
} else if *coeff == MINUS_ONE {
|
||||
"-".to_string()
|
||||
} else {
|
||||
format!("({coeff})")
|
||||
};
|
||||
let var = if *power == ONE {
|
||||
"x".to_string()
|
||||
} else {
|
||||
format!("x^({power})")
|
||||
};
|
||||
write!(f, "{coeff}{var}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Exp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "exp(x)")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Trignometric {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (func, coeff) = match self {
|
||||
Trignometric::Sine { coeff } => ("sin(x)", coeff),
|
||||
Trignometric::Cosine { coeff } => ("cos(x)", coeff),
|
||||
};
|
||||
|
||||
if *coeff == ZERO {
|
||||
write!(f, "0")
|
||||
} else if *coeff == ONE {
|
||||
write!(f, "{func}")
|
||||
} else if *coeff == MINUS_ONE {
|
||||
write!(f, "-{func}")
|
||||
} else {
|
||||
write!(f, "({coeff}){func}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BaseFuncs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Const(r) => write!(f, "{r}"),
|
||||
Self::Poly(p) => write!(f, "{p}"),
|
||||
Self::Exp(e) => write!(f, "{e}"),
|
||||
Self::Trig(t) => write!(f, "{t}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Differentiable + fmt::Display> fmt::Display for ComplexFuncs<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ComplexFuncs::Func(func) => write!(f, "{func}"),
|
||||
ComplexFuncs::Add(l, r) => write!(f, "({l} + {r})"),
|
||||
ComplexFuncs::Sub(l, r) => write!(f, "({l} - {r})"),
|
||||
ComplexFuncs::Mul(l, r) => write!(f, "({l} * {r})"),
|
||||
ComplexFuncs::Div(l, r) => write!(f, "({l} / {r})"),
|
||||
ComplexFuncs::Comp(l, r) => write!(f, "({l} ∘ {r})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user