use rand::prelude::*;
use serde::{
Deserialize,
Serialize
};
use std::{
io::{
Read,
Write
},
ops::{
Add,
AddAssign,
Div,
DivAssign,
Mul,
MulAssign,
Neg,
Sub,
SubAssign
}
};
use super::{
real::Real,
rwbin::{
ReadBin,
WriteBin
}
};
#[derive(Clone, Copy, PartialEq, Debug, Deserialize, Serialize)]
pub struct Complex {
pub re: f64,
pub im: f64
}
#[allow(dead_code)]
pub const COMPLEX_UNIT: Complex = Complex{re: 1.0, im: 0.0};
#[allow(dead_code)]
pub const COMPLEX_ZERO: Complex = Complex{re: 0.0, im: 0.0};
impl Complex {
#[allow(dead_code)]
pub fn new(re: f64, im: f64) -> Self {
Self{re, im}
}
#[allow(dead_code)]
pub fn new_default() -> Self {
COMPLEX_ZERO
}
#[allow(dead_code)]
pub fn new_random(ampl: f64, irng: &mut impl Rng) -> Self {
Self {
re: irng.random_range(-ampl..=ampl),
im: irng.random_range(-ampl..=ampl)
}
}
#[allow(dead_code)]
pub fn absqr(&self) -> Real {
Real(self.re * self.re + self.im * self.im)
}
#[allow(dead_code)]
pub fn abs(&self) -> Real {
Real((self.re * self.re + self.im * self.im).sqrt())
}
#[allow(dead_code)]
pub fn arg(&self) -> Real {
Real(self.im.atan2(self.re))
}
#[allow(dead_code)]
pub fn conj(&self) -> Self {
Self{
re: self.re,
im: -self.im
}
}
#[allow(dead_code)]
pub fn swap(&self) -> Self {
Self{
re: self.im,
im: self.re
}
}
#[allow(dead_code)]
pub fn deim(&self) -> Self {
Self{
re: self.re,
im: 0.0
}
}
#[allow(dead_code)]
pub fn sqr(&self) -> Self {
Self{
re: self.re * self.re - self.im * self.im,
im: 2.0 * self.re * self.im
}
}
#[allow(dead_code)]
pub fn exp(&self) -> Self {
let modulus = self.re.exp();
Self{
re: modulus * self.im.cos(),
im: modulus * self.im.sin()
}
}
}
impl From<(f64, f64)> for Complex {
fn from((re, im): (f64, f64)) -> Self {
Self{
re,
im
}
}
}
impl Add for Complex {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
re: self.re + rhs.re,
im: self.im + rhs.im
}
}
}
impl AddAssign for Complex {
fn add_assign(&mut self, rhs: Self) {
self.re += rhs.re;
self.im += rhs.im;
}
}
impl Div for Complex {
type Output = Self;
fn div(self, rhs: Self) -> Self {
let modulusqr = rhs.re * rhs.re + rhs.im * rhs.im;
Self {
re: (self.re * rhs.re + self.im * rhs.im) / modulusqr,
im: (-self.re * rhs.im + self.im * rhs.re) / modulusqr
}
}
}
impl Div<Real> for Complex {
type Output = Self;
fn div(self, rhs: Real) -> Self {
Self {
re: self.re / rhs.0,
im: self.im / rhs.0
}
}
}
impl DivAssign for Complex {
fn div_assign(&mut self, rhs: Self) {
let modulusqr = rhs.re * rhs.re + rhs.im * rhs.im;
*self = Self {
re: (self.re * rhs.re + self.im * rhs.im) / modulusqr,
im: (-self.re * rhs.im + self.im * rhs.re) / modulusqr
}
}
}
impl DivAssign<Real> for Complex {
fn div_assign(&mut self, rhs: Real) {
self.re /= rhs.0;
self.im /= rhs.0;
}
}
impl Mul for Complex {
type Output = Self;
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
}
}
}
impl Mul<Real> for Complex {
type Output = Self;
fn mul(self, rhs: Real) -> Self {
Self {
re: self.re * rhs.0,
im: self.im * rhs.0
}
}
}
impl MulAssign for Complex {
fn mul_assign(&mut self, rhs: Self) {
*self = Self {
re: self.re * rhs.re - self.im * rhs.im,
im: self.re * rhs.im + self.im * rhs.re
}
}
}
impl MulAssign<Real> for Complex {
fn mul_assign(&mut self, rhs: Real) {
self.re *= rhs.0;
self.im *= rhs.0;
}
}
impl Neg for Complex {
type Output = Self;
fn neg(self) -> Self {
Self{
re: -self.re,
im: -self.im
}
}
}
impl Sub for Complex {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self {
re: self.re - rhs.re,
im: self.im - rhs.im
}
}
}
impl SubAssign for Complex {
fn sub_assign(&mut self, rhs: Self) {
self.re -= rhs.re;
self.im -= rhs.im;
}
}
impl<W: Write> WriteBin<&Complex> for W {
fn write_bin(&mut self, x: &Complex) -> Result<(), String> {
self.write_bin(x.re)?;
self.write_bin(x.im)?;
Ok(())
}
}
impl<R: Read> ReadBin<Complex> for R {
fn read_bin(&mut self) -> Result<Complex, String> {
let re = self.read_bin()?;
let im = self.read_bin()?;
Ok(Complex{re, im})
}
}