use num::{FromPrimitive, One, Signed, Zero};
use std::any::Any;
use std::fmt::{Debug, Display};
use std::ops::Neg;
use std::{f32, f64};
use crate::scalar::{Field, RealField, SubsetOf, SupersetOf};
#[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))]
use num::Float;
#[macro_use]
macro_rules! complex_trait_methods(
($RealField: ident $(, $prefix: ident)*) => {
paste::item! {
fn [<from_ $($prefix)* real>](re: Self::$RealField) -> Self;
fn [<$($prefix)* real>](self) -> Self::$RealField;
fn [<$($prefix)* imaginary>](self) -> Self::$RealField;
fn [<$($prefix)* modulus>](self) -> Self::$RealField;
fn [<$($prefix)* modulus_squared>](self) -> Self::$RealField;
fn [<$($prefix)* argument>](self) -> Self::$RealField;
fn [<$($prefix)* norm1>](self) -> Self::$RealField;
fn [<$($prefix)* scale>](self, factor: Self::$RealField) -> Self;
fn [<$($prefix)* unscale>](self, factor: Self::$RealField) -> Self;
fn [<$($prefix)* to_polar>](self) -> (Self::$RealField, Self::$RealField) {
(self.[<$($prefix)* modulus>](), self.[<$($prefix)* argument>]())
}
fn [<$($prefix)* to_exp>](self) -> (Self::$RealField, Self) {
let m = self.[<$($prefix)* modulus>]();
if !m.is_zero() {
(m, self.[<$($prefix)* unscale>](m))
} else {
(Self::$RealField::zero(), Self::one())
}
}
fn [<$($prefix)* signum>](self) -> Self {
self.[<$($prefix)* to_exp>]().1
}
fn [<$($prefix)* floor>](self) -> Self;
fn [<$($prefix)* ceil>](self) -> Self;
fn [<$($prefix)* round>](self) -> Self;
fn [<$($prefix)* trunc>](self) -> Self;
fn [<$($prefix)* fract>](self) -> Self;
fn [<$($prefix)* mul_add>](self, a: Self, b: Self) -> Self;
fn [<$($prefix)* abs>](self) -> Self::$RealField;
fn [<$($prefix)* hypot>](self, other: Self) -> Self::$RealField;
fn [<$($prefix)* recip>](self) -> Self;
fn [<$($prefix)* conjugate>](self) -> Self;
fn [<$($prefix)* sin>](self) -> Self;
fn [<$($prefix)* cos>](self) -> Self;
fn [<$($prefix)* sin_cos>](self) -> (Self, Self);
#[inline]
fn [<$($prefix)* sinh_cosh>](self) -> (Self, Self) {
(self.[<$($prefix)* sinh>](), self.[<$($prefix)* cosh>]())
}
fn [<$($prefix)* tan>](self) -> Self;
fn [<$($prefix)* asin>](self) -> Self;
fn [<$($prefix)* acos>](self) -> Self;
fn [<$($prefix)* atan>](self) -> Self;
fn [<$($prefix)* sinh>](self) -> Self;
fn [<$($prefix)* cosh>](self) -> Self;
fn [<$($prefix)* tanh>](self) -> Self;
fn [<$($prefix)* asinh>](self) -> Self;
fn [<$($prefix)* acosh>](self) -> Self;
fn [<$($prefix)* atanh>](self) -> Self;
#[inline]
fn [<$($prefix)* sinc>](self) -> Self {
if self.is_zero() {
Self::one()
} else {
self.[<$($prefix)* sin>]() / self
}
}
#[inline]
fn [<$($prefix)* sinhc>](self) -> Self {
if self.is_zero() {
Self::one()
} else {
self.[<$($prefix)* sinh>]() / self
}
}
#[inline]
fn [<$($prefix)* cosc>](self) -> Self {
if self.is_zero() {
Self::one()
} else {
self.[<$($prefix)* cos>]() / self
}
}
#[inline]
fn [<$($prefix)* coshc>](self) -> Self {
if self.is_zero() {
Self::one()
} else {
self.[<$($prefix)* cosh>]() / self
}
}
fn [<$($prefix)* log>](self, base: Self::$RealField) -> Self;
fn [<$($prefix)* log2>](self) -> Self;
fn [<$($prefix)* log10>](self) -> Self;
fn [<$($prefix)* ln>](self) -> Self;
fn [<$($prefix)* ln_1p>](self) -> Self;
fn [<$($prefix)* sqrt>](self) -> Self;
fn [<$($prefix)* exp>](self) -> Self;
fn [<$($prefix)* exp2>](self) -> Self;
fn [<$($prefix)* exp_m1>](self) -> Self;
fn [<$($prefix)* powi>](self, n: i32) -> Self;
fn [<$($prefix)* powf>](self, n: Self::$RealField) -> Self;
fn [<$($prefix)* powc>](self, n: Self) -> Self;
fn [<$($prefix)* cbrt>](self) -> Self;
}
}
);
#[allow(missing_docs)]
pub trait ComplexField:
SubsetOf<Self>
+ SupersetOf<f64>
+ Field<Element = Self, SimdBool = bool>
+ Copy
+ Neg<Output = Self>
+ Send
+ Sync
+ Any
+ 'static
+ Debug
+ FromPrimitive
+ Display
{
type RealField: RealField;
complex_trait_methods!(RealField);
fn is_finite(&self) -> bool;
fn try_sqrt(self) -> Option<Self>;
}
#[cfg(not(feature = "libm_force"))]
macro_rules! impl_complex(
($($T:ty, $M:ident, $libm: ident);*) => ($(
impl ComplexField for $T {
type RealField = $T;
#[inline]
fn from_real(re: Self::RealField) -> Self {
re
}
#[inline]
fn real(self) -> Self::RealField {
self
}
#[inline]
fn imaginary(self) -> Self::RealField {
Self::zero()
}
#[inline]
fn norm1(self) -> Self::RealField {
$libm::abs(self)
}
#[inline]
fn modulus(self) -> Self::RealField {
$libm::abs(self)
}
#[inline]
fn modulus_squared(self) -> Self::RealField {
self * self
}
#[inline]
fn argument(self) -> Self::RealField {
if self >= Self::zero() {
Self::zero()
} else {
Self::pi()
}
}
#[inline]
fn to_exp(self) -> (Self, Self) {
if self >= Self::zero() {
(self, Self::one())
} else {
(-self, -Self::one())
}
}
#[inline]
fn recip(self) -> Self {
$M::recip(self)
}
#[inline]
fn conjugate(self) -> Self {
self
}
#[inline]
fn scale(self, factor: Self::RealField) -> Self {
self * factor
}
#[inline]
fn unscale(self, factor: Self::RealField) -> Self {
self / factor
}
#[inline]
fn floor(self) -> Self {
$libm::floor(self)
}
#[inline]
fn ceil(self) -> Self {
$libm::ceil(self)
}
#[inline]
fn round(self) -> Self {
$libm::round(self)
}
#[inline]
fn trunc(self) -> Self {
$libm::trunc(self)
}
#[inline]
fn fract(self) -> Self {
$libm::fract(self)
}
#[inline]
fn abs(self) -> Self {
$libm::abs(self)
}
#[inline]
fn signum(self) -> Self {
Signed::signum(&self)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
$libm::mul_add(self, a, b)
}
#[cfg(feature = "std")]
#[inline]
fn powi(self, n: i32) -> Self {
self.powi(n)
}
#[cfg(not(feature = "std"))]
#[inline]
fn powi(self, n: i32) -> Self {
$libm::powf(self, n as $T)
}
#[inline]
fn powf(self, n: Self) -> Self {
$libm::powf(self, n)
}
#[inline]
fn powc(self, n: Self) -> Self {
$libm::powf(self, n)
}
#[inline]
fn sqrt(self) -> Self {
$libm::sqrt(self)
}
#[inline]
fn try_sqrt(self) -> Option<Self> {
if self >= Self::zero() {
Some($libm::sqrt(self))
} else {
None
}
}
#[inline]
fn exp(self) -> Self {
$libm::exp(self)
}
#[inline]
fn exp2(self) -> Self {
$libm::exp2(self)
}
#[inline]
fn exp_m1(self) -> Self {
$libm::exp_m1(self)
}
#[inline]
fn ln_1p(self) -> Self {
$libm::ln_1p(self)
}
#[inline]
fn ln(self) -> Self {
$libm::ln(self)
}
#[inline]
fn log(self, base: Self) -> Self {
$libm::log(self, base)
}
#[inline]
fn log2(self) -> Self {
$libm::log2(self)
}
#[inline]
fn log10(self) -> Self {
$libm::log10(self)
}
#[inline]
fn cbrt(self) -> Self {
$libm::cbrt(self)
}
#[inline]
fn hypot(self, other: Self) -> Self::RealField {
$libm::hypot(self, other)
}
#[inline]
fn sin(self) -> Self {
$libm::sin(self)
}
#[inline]
fn cos(self) -> Self {
$libm::cos(self)
}
#[inline]
fn tan(self) -> Self {
$libm::tan(self)
}
#[inline]
fn asin(self) -> Self {
$libm::asin(self)
}
#[inline]
fn acos(self) -> Self {
$libm::acos(self)
}
#[inline]
fn atan(self) -> Self {
$libm::atan(self)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
$libm::sin_cos(self)
}
#[inline]
fn sinh(self) -> Self {
$libm::sinh(self)
}
#[inline]
fn cosh(self) -> Self {
$libm::cosh(self)
}
#[inline]
fn tanh(self) -> Self {
$libm::tanh(self)
}
#[inline]
fn asinh(self) -> Self {
$libm::asinh(self)
}
#[inline]
fn acosh(self) -> Self {
$libm::acosh(self)
}
#[inline]
fn atanh(self) -> Self {
$libm::atanh(self)
}
#[inline]
fn is_finite(&self) -> bool {
$M::is_finite(*self)
}
}
)*)
);
#[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))]
impl_complex!(
f32, f32, Float;
f64, f64, Float
);
#[cfg(all(feature = "std", not(feature = "libm_force")))]
impl_complex!(
f32,f32,f32;
f64,f64,f64
);
#[cfg(feature = "libm_force")]
impl ComplexField for f32 {
type RealField = f32;
#[inline]
fn from_real(re: Self::RealField) -> Self {
re
}
#[inline]
fn real(self) -> Self::RealField {
self
}
#[inline]
fn imaginary(self) -> Self::RealField {
Self::zero()
}
#[inline]
fn norm1(self) -> Self::RealField {
libm_force::fabsf(self)
}
#[inline]
fn modulus(self) -> Self::RealField {
libm_force::fabsf(self)
}
#[inline]
fn modulus_squared(self) -> Self::RealField {
self * self
}
#[inline]
fn argument(self) -> Self::RealField {
if self >= Self::zero() {
Self::zero()
} else {
Self::pi()
}
}
#[inline]
fn to_exp(self) -> (Self, Self) {
if self >= Self::zero() {
(self, Self::one())
} else {
(-self, -Self::one())
}
}
#[inline]
fn recip(self) -> Self {
f32::recip(self)
}
#[inline]
fn conjugate(self) -> Self {
self
}
#[inline]
fn scale(self, factor: Self::RealField) -> Self {
self * factor
}
#[inline]
fn unscale(self, factor: Self::RealField) -> Self {
self / factor
}
#[inline]
fn floor(self) -> Self {
libm_force::floorf(self)
}
#[inline]
fn ceil(self) -> Self {
libm_force::ceilf(self)
}
#[inline]
fn round(self) -> Self {
libm_force::roundf(self)
}
#[inline]
fn trunc(self) -> Self {
libm_force::truncf(self)
}
#[inline]
fn fract(self) -> Self {
self - libm_force::truncf(self)
}
#[inline]
fn abs(self) -> Self {
libm_force::fabsf(self)
}
#[inline]
fn signum(self) -> Self {
Signed::signum(&self)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
libm_force::fmaf(self, a, b)
}
#[inline]
fn powi(self, n: i32) -> Self {
libm_force::powf(self, n as f32)
}
#[inline]
fn powf(self, n: Self) -> Self {
libm_force::powf(self, n)
}
#[inline]
fn powc(self, n: Self) -> Self {
libm_force::powf(self, n)
}
#[inline]
fn sqrt(self) -> Self {
libm_force::sqrtf(self)
}
#[inline]
fn try_sqrt(self) -> Option<Self> {
if self >= Self::zero() {
Some(libm_force::sqrtf(self))
} else {
None
}
}
#[inline]
fn exp(self) -> Self {
libm_force::expf(self)
}
#[inline]
fn exp2(self) -> Self {
libm_force::exp2f(self)
}
#[inline]
fn exp_m1(self) -> Self {
libm_force::expm1f(self)
}
#[inline]
fn ln_1p(self) -> Self {
libm_force::log1pf(self)
}
#[inline]
fn ln(self) -> Self {
libm_force::logf(self)
}
#[inline]
fn log(self, base: Self) -> Self {
libm_force::logf(self) / libm_force::logf(base)
}
#[inline]
fn log2(self) -> Self {
libm_force::log2f(self)
}
#[inline]
fn log10(self) -> Self {
libm_force::log10f(self)
}
#[inline]
fn cbrt(self) -> Self {
libm_force::cbrtf(self)
}
#[inline]
fn hypot(self, other: Self) -> Self::RealField {
libm_force::hypotf(self, other)
}
#[inline]
fn sin(self) -> Self {
libm_force::sinf(self)
}
#[inline]
fn cos(self) -> Self {
libm_force::cosf(self)
}
#[inline]
fn tan(self) -> Self {
libm_force::tanf(self)
}
#[inline]
fn asin(self) -> Self {
libm_force::asinf(self)
}
#[inline]
fn acos(self) -> Self {
libm_force::acosf(self)
}
#[inline]
fn atan(self) -> Self {
libm_force::atanf(self)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
libm_force::sincosf(self)
}
#[inline]
fn sinh(self) -> Self {
libm_force::sinhf(self)
}
#[inline]
fn cosh(self) -> Self {
libm_force::coshf(self)
}
#[inline]
fn tanh(self) -> Self {
libm_force::tanhf(self)
}
#[inline]
fn asinh(self) -> Self {
libm_force::asinhf(self)
}
#[inline]
fn acosh(self) -> Self {
libm_force::acoshf(self)
}
#[inline]
fn atanh(self) -> Self {
libm_force::atanhf(self)
}
#[inline]
fn is_finite(&self) -> bool {
f32::is_finite(*self)
}
}
#[cfg(feature = "libm_force")]
impl ComplexField for f64 {
type RealField = f64;
#[inline]
fn from_real(re: Self::RealField) -> Self {
re
}
#[inline]
fn real(self) -> Self::RealField {
self
}
#[inline]
fn imaginary(self) -> Self::RealField {
Self::zero()
}
#[inline]
fn norm1(self) -> Self::RealField {
libm_force::fabs(self)
}
#[inline]
fn modulus(self) -> Self::RealField {
libm_force::fabs(self)
}
#[inline]
fn modulus_squared(self) -> Self::RealField {
self * self
}
#[inline]
fn argument(self) -> Self::RealField {
if self >= Self::zero() {
Self::zero()
} else {
Self::pi()
}
}
#[inline]
fn to_exp(self) -> (Self, Self) {
if self >= Self::zero() {
(self, Self::one())
} else {
(-self, -Self::one())
}
}
#[inline]
fn recip(self) -> Self {
f64::recip(self)
}
#[inline]
fn conjugate(self) -> Self {
self
}
#[inline]
fn scale(self, factor: Self::RealField) -> Self {
self * factor
}
#[inline]
fn unscale(self, factor: Self::RealField) -> Self {
self / factor
}
#[inline]
fn floor(self) -> Self {
libm_force::floor(self)
}
#[inline]
fn ceil(self) -> Self {
libm_force::ceil(self)
}
#[inline]
fn round(self) -> Self {
libm_force::round(self)
}
#[inline]
fn trunc(self) -> Self {
libm_force::trunc(self)
}
#[inline]
fn fract(self) -> Self {
self - libm_force::trunc(self)
}
#[inline]
fn abs(self) -> Self {
libm_force::fabs(self)
}
#[inline]
fn signum(self) -> Self {
Signed::signum(&self)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
libm_force::fma(self, a, b)
}
#[inline]
fn powi(self, n: i32) -> Self {
libm_force::pow(self, n as f64)
}
#[inline]
fn powf(self, n: Self) -> Self {
libm_force::pow(self, n)
}
#[inline]
fn powc(self, n: Self) -> Self {
libm_force::pow(self, n)
}
#[inline]
fn sqrt(self) -> Self {
libm_force::sqrt(self)
}
#[inline]
fn try_sqrt(self) -> Option<Self> {
if self >= Self::zero() {
Some(libm_force::sqrt(self))
} else {
None
}
}
#[inline]
fn exp(self) -> Self {
libm_force::exp(self)
}
#[inline]
fn exp2(self) -> Self {
libm_force::exp2(self)
}
#[inline]
fn exp_m1(self) -> Self {
libm_force::expm1(self)
}
#[inline]
fn ln_1p(self) -> Self {
libm_force::log1p(self)
}
#[inline]
fn ln(self) -> Self {
libm_force::log(self)
}
#[inline]
fn log(self, base: Self) -> Self {
libm_force::log(self) / libm_force::log(base)
}
#[inline]
fn log2(self) -> Self {
libm_force::log2(self)
}
#[inline]
fn log10(self) -> Self {
libm_force::log10(self)
}
#[inline]
fn cbrt(self) -> Self {
libm_force::cbrt(self)
}
#[inline]
fn hypot(self, other: Self) -> Self::RealField {
libm_force::hypot(self, other)
}
#[inline]
fn sin(self) -> Self {
libm_force::sin(self)
}
#[inline]
fn cos(self) -> Self {
libm_force::cos(self)
}
#[inline]
fn tan(self) -> Self {
libm_force::tan(self)
}
#[inline]
fn asin(self) -> Self {
libm_force::asin(self)
}
#[inline]
fn acos(self) -> Self {
libm_force::acos(self)
}
#[inline]
fn atan(self) -> Self {
libm_force::atan(self)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
libm_force::sincos(self)
}
#[inline]
fn sinh(self) -> Self {
libm_force::sinh(self)
}
#[inline]
fn cosh(self) -> Self {
libm_force::cosh(self)
}
#[inline]
fn tanh(self) -> Self {
libm_force::tanh(self)
}
#[inline]
fn asinh(self) -> Self {
libm_force::asinh(self)
}
#[inline]
fn acosh(self) -> Self {
libm_force::acosh(self)
}
#[inline]
fn atanh(self) -> Self {
libm_force::atanh(self)
}
#[inline]
fn is_finite(&self) -> bool {
f64::is_finite(*self)
}
}
impl<N: RealField + PartialOrd> ComplexField for num_complex::Complex<N> {
type RealField = N;
#[inline]
fn from_real(re: Self::RealField) -> Self {
Self::new(re, Self::RealField::zero())
}
#[inline]
fn real(self) -> Self::RealField {
self.re
}
#[inline]
fn imaginary(self) -> Self::RealField {
self.im
}
#[inline]
fn argument(self) -> Self::RealField {
self.im.atan2(self.re)
}
#[inline]
fn modulus(self) -> Self::RealField {
self.re.hypot(self.im)
}
#[inline]
fn modulus_squared(self) -> Self::RealField {
self.re * self.re + self.im * self.im
}
#[inline]
fn norm1(self) -> Self::RealField {
self.re.abs() + self.im.abs()
}
#[inline]
fn recip(self) -> Self {
Self::one() / self
}
#[inline]
fn conjugate(self) -> Self {
self.conj()
}
#[inline]
fn scale(self, factor: Self::RealField) -> Self {
self * factor
}
#[inline]
fn unscale(self, factor: Self::RealField) -> Self {
self / factor
}
#[inline]
fn floor(self) -> Self {
Self::new(self.re.floor(), self.im.floor())
}
#[inline]
fn ceil(self) -> Self {
Self::new(self.re.ceil(), self.im.ceil())
}
#[inline]
fn round(self) -> Self {
Self::new(self.re.round(), self.im.round())
}
#[inline]
fn trunc(self) -> Self {
Self::new(self.re.trunc(), self.im.trunc())
}
#[inline]
fn fract(self) -> Self {
Self::new(self.re.fract(), self.im.fract())
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
self * a + b
}
#[inline]
fn abs(self) -> Self::RealField {
self.modulus()
}
#[inline]
fn exp2(self) -> Self {
let _2 = N::one() + N::one();
num_complex::Complex::new(_2, N::zero()).powc(self)
}
#[inline]
fn exp_m1(self) -> Self {
self.exp() - Self::one()
}
#[inline]
fn ln_1p(self) -> Self {
(Self::one() + self).ln()
}
#[inline]
fn log2(self) -> Self {
let _2 = N::one() + N::one();
self.log(_2)
}
#[inline]
fn log10(self) -> Self {
let _10 = N::from_subset(&10.0f64);
self.log(_10)
}
#[inline]
fn cbrt(self) -> Self {
let one_third = N::from_subset(&(1.0 / 3.0));
self.powf(one_third)
}
#[inline]
fn powi(self, n: i32) -> Self {
let n = N::from_subset(&(n as f64));
self.powf(n)
}
#[inline]
fn is_finite(&self) -> bool {
self.re.is_finite() && self.im.is_finite()
}
#[inline]
fn exp(self) -> Self {
complex_from_polar(self.re.exp(), self.im)
}
#[inline]
fn ln(self) -> Self {
let (r, theta) = self.to_polar();
Self::new(r.ln(), theta)
}
#[inline]
fn sqrt(self) -> Self {
let two = N::one() + N::one();
let (r, theta) = self.to_polar();
complex_from_polar(r.sqrt(), theta / two)
}
#[inline]
fn try_sqrt(self) -> Option<Self> {
Some(self.sqrt())
}
#[inline]
fn hypot(self, b: Self) -> Self::RealField {
(self.modulus_squared() + b.modulus_squared()).sqrt()
}
#[inline]
fn powf(self, exp: Self::RealField) -> Self {
let (r, theta) = self.to_polar();
complex_from_polar(r.powf(exp), theta * exp)
}
#[inline]
fn log(self, base: N) -> Self {
let (r, theta) = self.to_polar();
Self::new(r.log(base), theta / base.ln())
}
#[inline]
fn powc(self, exp: Self) -> Self {
let (r, theta) = self.to_polar();
complex_from_polar(
r.powf(exp.re) * (-exp.im * theta).exp(),
exp.re * theta + exp.im * r.ln(),
)
}
#[inline]
fn sin(self) -> Self {
Self::new(
self.re.sin() * self.im.cosh(),
self.re.cos() * self.im.sinh(),
)
}
#[inline]
fn cos(self) -> Self {
Self::new(
self.re.cos() * self.im.cosh(),
-self.re.sin() * self.im.sinh(),
)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
let (rsin, rcos) = self.re.sin_cos();
let (isinh, icosh) = self.im.sinh_cosh();
let sin = Self::new(rsin * icosh, rcos * isinh);
let cos = Self::new(rcos * icosh, -rsin * isinh);
(sin, cos)
}
#[inline]
fn tan(self) -> Self {
let (two_re, two_im) = (self.re + self.re, self.im + self.im);
Self::new(two_re.sin(), two_im.sinh()).unscale(two_re.cos() + two_im.cosh())
}
#[inline]
fn asin(self) -> Self {
let i = Self::i();
-i * ((Self::one() - self * self).sqrt() + i * self).ln()
}
#[inline]
fn acos(self) -> Self {
let i = Self::i();
-i * (i * (Self::one() - self * self).sqrt() + self).ln()
}
#[inline]
fn atan(self) -> Self {
let i = Self::i();
let one = Self::one();
let two = one + one;
if self == i {
return Self::new(N::zero(), N::one() / N::zero());
} else if self == -i {
return Self::new(N::zero(), -N::one() / N::zero());
}
((one + i * self).ln() - (one - i * self).ln()) / (two * i)
}
#[inline]
fn sinh(self) -> Self {
Self::new(
self.re.sinh() * self.im.cos(),
self.re.cosh() * self.im.sin(),
)
}
#[inline]
fn cosh(self) -> Self {
Self::new(
self.re.cosh() * self.im.cos(),
self.re.sinh() * self.im.sin(),
)
}
#[inline]
fn sinh_cosh(self) -> (Self, Self) {
let (rsinh, rcosh) = self.re.sinh_cosh();
let (isin, icos) = self.im.sin_cos();
let sin = Self::new(rsinh * icos, rcosh * isin);
let cos = Self::new(rcosh * icos, rsinh * isin);
(sin, cos)
}
#[inline]
fn tanh(self) -> Self {
let (two_re, two_im) = (self.re + self.re, self.im + self.im);
Self::new(two_re.sinh(), two_im.sin()).unscale(two_re.cosh() + two_im.cos())
}
#[inline]
fn asinh(self) -> Self {
let one = Self::one();
(self + (one + self * self).sqrt()).ln()
}
#[inline]
fn acosh(self) -> Self {
let one = Self::one();
let two = one + one;
two * (((self + one) / two).sqrt() + ((self - one) / two).sqrt()).ln()
}
#[inline]
fn atanh(self) -> Self {
let one = Self::one();
let two = one + one;
if self == one {
return Self::new(N::one() / N::zero(), N::zero());
} else if self == -one {
return Self::new(-N::one() / N::zero(), N::zero());
}
((one + self).ln() - (one - self).ln()) / two
}
}
#[inline]
fn complex_from_polar<N: RealField>(r: N, theta: N) -> num_complex::Complex<N> {
num_complex::Complex::new(r * theta.cos(), r * theta.sin())
}