use crate::{Complex, DivisionAlgebra, One, RealField, Zero};
impl<T: RealField> Complex<T> {
#[inline]
pub fn norm(&self) -> T {
self.norm_sqr().sqrt()
}
#[inline]
pub fn arg(&self) -> T {
self.im.atan2(self.re)
}
#[inline]
pub fn powi(&self, n: i32) -> Self {
if n == 0 {
return Self::one();
}
let mut res = Self::one();
let mut base = *self;
let mut n_abs = n.abs();
while n_abs > 0 {
if n_abs % 2 == 1 {
res *= base;
}
base = base * base;
n_abs /= 2;
}
if n < 0 { res._inverse_impl() } else { res }
}
#[inline]
pub fn powf(&self, n: T) -> Self {
let r_pow_n = self.norm().powf(n);
let n_theta = self.arg() * n;
Self::new(r_pow_n * n_theta.cos(), r_pow_n * n_theta.sin())
}
#[inline]
pub fn powc(&self, n: Self) -> Self {
(n * self.ln()).exp()
}
#[inline]
pub fn sqrt(self) -> Self {
if self.is_zero() {
return Self::zero();
}
let norm = self.norm();
let half = T::one() / (T::one() + T::one());
let re_sqrt = ((norm + self.re) * half).sqrt();
let im_sqrt = ((norm - self.re) * half).sqrt();
if self.im >= T::zero() {
Self::new(re_sqrt, im_sqrt)
} else {
Self::new(re_sqrt, -im_sqrt)
}
}
#[inline]
pub fn exp(self) -> Self {
let exp_re = self.re.exp();
Self::new(exp_re * self.im.cos(), exp_re * self.im.sin())
}
#[inline]
pub fn ln(self) -> Self {
Self::new(self.norm().ln(), self.arg())
}
#[inline]
pub fn sin(self) -> Self {
Self::new(
self.re.sin() * self.im.cosh(),
self.re.cos() * self.im.sinh(),
)
}
#[inline]
pub fn cos(self) -> Self {
Self::new(
self.re.cos() * self.im.cosh(),
-self.re.sin() * self.im.sinh(),
)
}
#[inline]
pub fn tan(self) -> Self {
self.sin() / self.cos()
}
#[inline]
pub fn sinh(self) -> Self {
Self::new(
self.re.sinh() * self.im.cos(),
self.re.cosh() * self.im.sin(),
)
}
#[inline]
pub fn cosh(self) -> Self {
Self::new(
self.re.cosh() * self.im.cos(),
self.re.sinh() * self.im.sin(),
)
}
#[inline]
pub fn tanh(self) -> Self {
self.sinh() / self.cosh()
}
}