use std::ops::{Add, Mul, Sub};
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Complex64 {
pub re: f32,
pub im: f32,
}
impl Complex64 {
#[inline]
pub fn new(re: f32, im: f32) -> Self {
Self { re, im }
}
#[inline]
pub fn from_polar(r: f32, theta: f32) -> Self {
Self {
re: r * theta.cos(),
im: r * theta.sin(),
}
}
#[inline]
pub fn conj(self) -> Self {
Self {
re: self.re,
im: -self.im,
}
}
#[inline]
pub fn norm(self) -> f32 {
self.re.hypot(self.im)
}
#[inline]
pub fn norm_sqr(self) -> f32 {
self.re * self.re + self.im * self.im
}
#[inline]
pub fn arg(self) -> f32 {
self.im.atan2(self.re)
}
#[inline]
pub fn scale(self, k: f32) -> Self {
Self {
re: self.re * k,
im: self.im * k,
}
}
}
impl Add for Complex64 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self {
re: self.re + rhs.re,
im: self.im + rhs.im,
}
}
}
impl Sub for Complex64 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self {
re: self.re - rhs.re,
im: self.im - rhs.im,
}
}
}
impl Mul for Complex64 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
Self {
re: self.re * rhs.re - self.im * rhs.im,
im: self.re * rhs.im + self.im * rhs.re,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn polar_roundtrip() {
let c = Complex64::from_polar(2.0, std::f32::consts::FRAC_PI_4);
assert!((c.norm() - 2.0).abs() < 1e-6);
assert!((c.arg() - std::f32::consts::FRAC_PI_4).abs() < 1e-6);
}
#[test]
fn mul_matches_definition() {
let a = Complex64::new(1.0, 2.0);
let b = Complex64::new(3.0, -1.0);
let product = a * b;
assert_eq!(product, Complex64::new(1.0 * 3.0 - -2.0, -1.0 + 2.0 * 3.0));
}
}