代数 - 複素数

複素数の定義とその演算

/// Algebra - Complex Number
use crate::agroup; // IGNORE
use crate::algebra::group_additive::*;
use crate::algebra::monoid::*;
use crate::algebra::ring::*;
use crate::monoid; // IGNORE

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Complex<X>(pub X, pub X);

impl<X: Copy> Complex<X> {
    pub fn real(&self) -> X {
        self.0
    }
    pub fn imag(&self) -> X {
        self.1
    }
}
agroup! {
    Complex<X> where [X: Copy + AGroup];
    zero = Complex(X::zero(), X::zero());
    add(self, other) = { Complex(self.0 + other.0, self.1 + other.1) };
    neg(self) =  { Complex(-self.0, -self.1) };
}
monoid! {
    Complex<X> where [X: AGroup + Monoid + Copy];
    one = Complex(X::one(), X::zero());
    mul(self,other) = {
        Complex(
            self.0 * other.0 - self.1 * other.1,
            self.0 * other.1 + self.1 * other.0,
        )
    }
}
impl<X: AGroup + Monoid + Copy> Ring for Complex<X> {}
impl<X: AGroup + Monoid + Copy> Complex<X> {
    pub fn i() -> Complex<X> {
        Complex(X::zero(), X::one())
    }
}
impl<X: std::ops::Add<Output = X>> std::ops::Add<X> for Complex<X> {
    type Output = Self;
    fn add(self, x: X) -> Self {
        Complex(self.0 + x, self.1)
    }
}
impl<X: std::ops::Sub<Output = X>> std::ops::Sub<X> for Complex<X> {
    type Output = Self;
    fn sub(self, x: X) -> Self {
        Complex(self.0 - x, self.1)
    }
}
impl<X: std::ops::Mul<Output = X> + Copy> std::ops::Mul<X> for Complex<X> {
    type Output = Self;
    fn mul(self, x: X) -> Self::Output {
        Self(self.0 * x, self.1 * x)
    }
}
impl<X: Ring + std::ops::Div<Output = X> + Copy> std::ops::Div<X> for Complex<X> {
    type Output = Self;
    fn div(self, x: X) -> Self::Output {
        Self(self.0 / x, self.1 / x)
    }
}

#[cfg(test)]
mod test_complex {
    use crate::algebra::complex::*;
    #[test]
    fn test_intish_complex() {
        let x = Complex::<i64>::one();
        assert_eq!(x, Complex(1, 0));
        assert_eq!(x + 2, Complex(3, 0));
        assert_eq!(x - 2, Complex(-1, 0));
        assert_eq!(x + Complex(0, -1), Complex(1, -1));
        assert_eq!(x * 2, Complex(2, 0));
        assert_eq!(x * Complex(-1, 1), Complex(-1, 1));
    }
    #[test]
    fn test_intish_realish() {
        assert_eq!(Complex(1.0, 2.0) / 2.0, Complex(0.5, 1.0));
    }
    #[test]
    fn test_assign() {
        let mut x = Complex(0, 0);
        x += Complex(0, 1);
        x *= Complex(1, 1);
        x -= Complex(0, 1);
        assert_eq!(
            x,
            ((Complex(0, 0) + Complex(0, 1)) * Complex(1, 1)) - Complex(0, 1)
        );
    }
}