use oxinum_core::OxiNumResult;
use oxinum_float::native::{BigFloat, RoundingMode};
#[derive(Clone)]
pub struct BigComplex {
pub(crate) re: BigFloat,
pub(crate) im: BigFloat,
}
impl BigComplex {
pub fn from_parts(re: BigFloat, im: BigFloat) -> Self {
Self { re, im }
}
pub fn new(re: BigFloat, im: BigFloat) -> Self {
Self::from_parts(re, im)
}
pub fn from_real(re: BigFloat) -> Self {
let prec = re.precision();
Self {
re,
im: BigFloat::zero(prec),
}
}
pub fn from_imag(im: BigFloat) -> Self {
let prec = im.precision();
Self {
re: BigFloat::zero(prec),
im,
}
}
pub fn zero(prec: u32) -> Self {
Self {
re: BigFloat::zero(prec),
im: BigFloat::zero(prec),
}
}
pub fn one(prec: u32, mode: RoundingMode) -> Self {
Self {
re: BigFloat::from_i64(1, prec, mode),
im: BigFloat::zero(prec),
}
}
pub fn i(prec: u32, mode: RoundingMode) -> Self {
Self {
re: BigFloat::zero(prec),
im: BigFloat::from_i64(1, prec, mode),
}
}
pub fn from_f64(re: f64, im: f64, prec: u32) -> OxiNumResult<Self> {
Ok(Self {
re: BigFloat::from_f64(re, prec)?,
im: BigFloat::from_f64(im, prec)?,
})
}
pub fn re(&self) -> &BigFloat {
&self.re
}
pub fn im(&self) -> &BigFloat {
&self.im
}
pub fn real(&self) -> BigFloat {
self.re.clone()
}
pub fn imag(&self) -> BigFloat {
self.im.clone()
}
pub fn into_parts(self) -> (BigFloat, BigFloat) {
(self.re, self.im)
}
pub fn conj(&self) -> Self {
Self {
re: self.re.clone(),
im: -&self.im,
}
}
pub fn norm_sqr(&self) -> BigFloat {
&(&self.re * &self.re) + &(&self.im * &self.im)
}
pub fn is_zero(&self) -> bool {
self.re.is_zero() && self.im.is_zero()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zero_one_i_constructors() {
let z = BigComplex::zero(53);
assert!(z.is_zero());
let one = BigComplex::one(53, RoundingMode::HalfEven);
assert_eq!(one.re().to_f64(), 1.0);
assert_eq!(one.im().to_f64(), 0.0);
let imag = BigComplex::i(53, RoundingMode::HalfEven);
assert_eq!(imag.re().to_f64(), 0.0);
assert_eq!(imag.im().to_f64(), 1.0);
}
#[test]
fn from_parts_round_trip() {
let z = BigComplex::from_f64(2.5, -7.0, 53).expect("finite parts");
let (re, im) = z.clone().into_parts();
assert_eq!(re.to_f64(), 2.5);
assert_eq!(im.to_f64(), -7.0);
assert_eq!(z.real().to_f64(), 2.5);
assert_eq!(z.imag().to_f64(), -7.0);
}
#[test]
fn conj_and_norm_sqr() {
let z = BigComplex::from_f64(3.0, 4.0, 53).expect("finite parts");
let c = z.conj();
assert_eq!(c.re().to_f64(), 3.0);
assert_eq!(c.im().to_f64(), -4.0);
assert_eq!(z.norm_sqr().to_f64(), 25.0);
}
}