diff options
Diffstat (limited to 'src/complex.rs')
| -rw-r--r-- | src/complex.rs | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/complex.rs b/src/complex.rs new file mode 100644 index 0000000..642122f --- /dev/null +++ b/src/complex.rs @@ -0,0 +1,191 @@ +use std::num::ParseFloatError; +use std::str::FromStr; +use std::f64::consts::E; + +#[derive(Clone, Copy, Default)] +pub struct Complex { + pub real: f64, + pub imag: f64, +} + +impl Complex { + pub fn new(real: f64, imag: f64) -> Self { + Self { real, imag } + } + + pub fn div(&mut self, other: &Self) { + let z = other.real * other.real + other.imag * other.imag; + self.real = self.real * other.real + self.imag * other.imag; + self.real /= z; + self.imag = self.imag * other.real - self.real * other.imag; + self.imag /= z; + } + + pub fn abs(&self) -> f64 { + (self.real.powi(2) + self.imag.powi(2)).sqrt() + } + + pub fn pow(&self, rhs: Self) -> Self { + let r = self.abs(); + let x = (self.imag / self.real).atan(); + let lnr = r.ln(); + let alpha = lnr * rhs.imag + x * rhs.real; + let e_exp = E.powf(lnr * rhs.real - rhs.imag * x); + Complex::new(e_exp * alpha.cos(), e_exp * alpha.sin()) + } + + pub fn sqrt(&self) -> Self { + self.pow(Complex::new(0.5, 0.0)) + } + + pub fn cos(&self) -> Self { + let e : Complex = E.into(); + let i = Complex::new(0.0, 1.0); + + Complex::new(e.pow(&i * self).real, 0.0) + } + + pub fn sin(&self) -> Self { + let e : Complex = E.into(); + let i = Complex::new(0.0, 1.0); + + Complex::new(e.pow(&i * self).imag, 0.0) + } + + pub fn tan(&self) -> Self { + self.sin() / self.cos() + } +} + +impl std::fmt::Display for Complex { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if self.imag == 0.0 { + write!(f, "{}", self.real) + } else if self.real == 0.0 { + if self.imag == 1.0 { + write!(f, "i") + } else { + write!(f, "{}i", self.imag) + } + } else { + if self.imag == 1.0 { + write!(f, "{} + i", self.real) + } else { + write!(f, "{} + {}i", self.real, self.imag) + } + } + } +} + +#[derive(Debug)] +pub struct ComplexParseError; + +impl From<ParseFloatError> for ComplexParseError { + fn from(_: ParseFloatError) -> Self { + Self {} + } +} + +impl FromStr for Complex { + type Err = ComplexParseError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + let mut c = Complex::default(); + let s = s.replace(' ', ""); + if s.contains('+') { + let (a, b) = s.split_once('+').unwrap(); + if a.contains('i') { + c.imag = a[..a.len() - 1].parse()?; + c.real = b.parse()?; + } else { + c.real = a.parse()?; + c.imag = b[..b.len() - 1].parse()?; + } + } else { + if s.contains('i') { + c.imag = s[..s.len() - 1].parse()?; + } else { + c.real = s.parse()?; + } + } + + Ok(c) + } +} + +impl Into<Complex> for f64 { + fn into(self) -> Complex { + Complex::new(self, 0.0) + } +} + +impl std::ops::Add for &Complex { + type Output = Complex; + + fn add(self, rhs: Self) -> Self::Output { + Complex::new(self.real + rhs.real, self.imag + rhs.imag) + } +} + +impl std::ops::Add for Complex { + type Output = Complex; + + fn add(self, rhs: Self) -> Self::Output { + &self + &rhs + } +} + +impl std::ops::Sub for &Complex { + type Output = Complex; + + fn sub(self, rhs: Self) -> Self::Output { + Complex::new(self.real - rhs.real, self.imag - rhs.imag) + } +} + +impl std::ops::Sub for Complex { + type Output = Complex; + + fn sub(self, rhs: Self) -> Self::Output { + &self - &rhs + } +} + +impl std::ops::Mul for &Complex { + type Output = Complex; + + fn mul(self, rhs: Self) -> Self::Output { + Complex::new( + self.real * rhs.real - self.imag * rhs.imag, + self.real * rhs.imag + self.imag * rhs.real, + ) + } +} + +impl std::ops::Mul for Complex { + type Output = Complex; + + fn mul(self, rhs: Self) -> Self::Output { + &self * &rhs + } +} + +impl std::ops::Div for &Complex { + type Output = Complex; + + fn div(self, rhs: Self) -> Self::Output { + let z = rhs.real * rhs.real + rhs.imag * rhs.imag; + Complex::new( + (self.real * rhs.real + self.imag * rhs.imag) / z, + (self.imag * rhs.real - self.real * rhs.imag) / z, + ) + } +} + +impl std::ops::Div for Complex { + type Output = Complex; + + fn div(self, rhs: Self) -> Self::Output { + &self / &rhs + } +} |