Skip to main content

deep_causality_num/complex/complex_number/
ops.rs

1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) 2023 - 2026. The DeepCausality Authors and Contributors. All Rights Reserved.
4 */
5use crate::{Complex, DivisionAlgebra, One, RealField, Zero};
6
7impl<T: RealField> Complex<T> {
8    /// Computes the norm (magnitude or absolute value) of the complex number.
9    #[inline]
10    pub fn norm(&self) -> T {
11        self.norm_sqr().sqrt()
12    }
13
14    /// Computes the argument (phase angle) of the complex number in radians.
15    #[inline]
16    pub fn arg(&self) -> T {
17        self.im.atan2(self.re)
18    }
19
20    /// Raises to an integer power.
21    #[inline]
22    pub fn powi(&self, n: i32) -> Self {
23        if n == 0 {
24            return Self::one();
25        }
26        let mut res = Self::one();
27        let mut base = *self;
28        let mut n_abs = n.abs();
29
30        while n_abs > 0 {
31            if n_abs % 2 == 1 {
32                res *= base;
33            }
34            base = base * base;
35            n_abs /= 2;
36        }
37
38        if n < 0 { res._inverse_impl() } else { res }
39    }
40
41    /// Raises a to a real (scalar) power.
42    #[inline]
43    pub fn powf(&self, n: T) -> Self {
44        // (r * (cos(t) + i*sin(t)))^n = r^n * (cos(n*t) + i*sin(n*t))
45        let r_pow_n = self.norm().powf(n);
46        let n_theta = self.arg() * n;
47        Self::new(r_pow_n * n_theta.cos(), r_pow_n * n_theta.sin())
48    }
49
50    /// Raises to a complex power.
51    #[inline]
52    pub fn powc(&self, n: Self) -> Self {
53        // z^w = exp(w * ln(z))
54        (n * self.ln()).exp()
55    }
56
57    /// Computes the principal square root of a complex number.
58    #[inline]
59    pub fn sqrt(self) -> Self {
60        if self.is_zero() {
61            return Self::zero();
62        }
63        let norm = self.norm();
64        let half = T::one() / (T::one() + T::one());
65        let re_sqrt = ((norm + self.re) * half).sqrt();
66        let im_sqrt = ((norm - self.re) * half).sqrt();
67
68        if self.im >= T::zero() {
69            Self::new(re_sqrt, im_sqrt)
70        } else {
71            Self::new(re_sqrt, -im_sqrt)
72        }
73    }
74
75    /// Computes `e^(self)`, where `e` is the base of the natural logarithm.
76    #[inline]
77    pub fn exp(self) -> Self {
78        // e^(a + bi) = e^a * (cos(b) + i * sin(b))
79        let exp_re = self.re.exp();
80        Self::new(exp_re * self.im.cos(), exp_re * self.im.sin())
81    }
82
83    /// Computes the natural logarithm of a complex number.
84    #[inline]
85    pub fn ln(self) -> Self {
86        // ln(z) = ln(|z|) + i * arg(z)
87        Self::new(self.norm().ln(), self.arg())
88    }
89
90    /// Computes the sine of a complex number.
91    #[inline]
92    pub fn sin(self) -> Self {
93        Self::new(
94            self.re.sin() * self.im.cosh(),
95            self.re.cos() * self.im.sinh(),
96        )
97    }
98
99    /// Computes the cosine of a complex number.
100    #[inline]
101    pub fn cos(self) -> Self {
102        Self::new(
103            self.re.cos() * self.im.cosh(),
104            -self.re.sin() * self.im.sinh(),
105        )
106    }
107
108    /// Computes the tangent of a complex number.
109    #[inline]
110    pub fn tan(self) -> Self {
111        self.sin() / self.cos()
112    }
113
114    /// Computes the hyperbolic sine of a complex number.
115    #[inline]
116    pub fn sinh(self) -> Self {
117        Self::new(
118            self.re.sinh() * self.im.cos(),
119            self.re.cosh() * self.im.sin(),
120        )
121    }
122
123    /// Computes the hyperbolic cosine of a complex number.
124    #[inline]
125    pub fn cosh(self) -> Self {
126        Self::new(
127            self.re.cosh() * self.im.cos(),
128            self.re.sinh() * self.im.sin(),
129        )
130    }
131
132    /// Computes the hyperbolic tangent of a complex number.
133    #[inline]
134    pub fn tanh(self) -> Self {
135        self.sinh() / self.cosh()
136    }
137}