1use num_traits::Float;
3use std::fmt::{self, Debug, Display};
4
5#[derive(Debug, PartialEq, Clone, Copy)]
7pub struct Complex<T: Float> {
8 real: T,
9 imag: T,
10}
11
12pub type CC<T> = Complex<T>;
14trait Numbers: Float {
17 fn two() -> Self;
18 fn ten() -> Self;
19 fn half() -> Self;
20}
21
22impl<T: Float> Numbers for T {
23 fn two() -> T {
24 T::one() + T::one()
25 }
26 fn ten() -> T {
27 T::two() * (T::two() * T::two() + T::one())
28 }
29 fn half() -> T {
30 T::one() / T::two()
31 }
32}
33
34impl<T: Float> Complex<T> {
35 pub fn new(real: T, imag: T) -> Self {
37 Self { real, imag }
38 }
39
40 pub fn i() -> Self {
42 Self::new(T::zero(), T::one())
43 }
44
45 fn two_i() -> Self {
47 Self::new(T::zero(), T::two())
48 }
49
50 pub fn real(self) -> T {
52 self.real
53 }
54
55 pub fn imag(self) -> T {
57 self.imag
58 }
59
60 pub fn conj(self) -> Self {
62 Self::new(self.real, -self.imag)
63 }
64
65 pub fn square_abs(self) -> T {
67 self.real.powi(2) + self.imag.powi(2)
68 }
69
70 pub fn abs(self) -> T {
72 Self::square_abs(self).sqrt()
73 }
74
75 pub fn arg(self) -> T {
77 if self == Self::new(T::zero(), T::zero()) {
78 T::zero()
79 } else {
80 self.imag.signum() * T::acos(self.real / Self::abs(self))
81 }
82 }
83
84 pub fn sqrt(self) -> Self {
86 Self::new(
87 ((self.real + self.abs()) / T::two()).sqrt(),
88 self.imag.signum() * ((-self.real + self.abs()) / T::two()).sqrt(),
89 )
90 }
91
92 pub fn inv(self) -> Self {
94 Self::conj(self) / Self::square_abs(self)
95 }
96
97 pub fn powi(self, exponent: i64) -> Self {
99 match exponent {
100 0 => Self::new(T::one(), T::zero()),
101 1 => self,
102 -1 => self.inv(),
103 _ => {
104 let mut result = self;
105 for _ in 2..=exponent.abs() {
106 result *= self;
107 }
108 if exponent < 0 { result.inv() } else { result }
109 }
110 }
111 }
112 pub fn powf(self, exponent: T) -> Self {
116 let arg_exponent = self.arg() * exponent;
117 Self::new(T::cos(arg_exponent), T::sin(arg_exponent)) * T::powf(Self::abs(self), exponent)
118 }
119
120 pub fn powc(self, exponent: Self) -> Self {
122 Self::powf(self, exponent.real) * Self::exp(self.ln() * Self::new(T::zero(), exponent.imag))
123 }
124
125 pub fn exp(self) -> Self {
127 Self::new(T::cos(self.imag), T::sin(self.imag)) * T::exp(self.real)
128 }
129
130 pub fn expf(self, base: T) -> Self {
132 if base == T::zero() {
133 Self::new(T::zero(), T::zero())
134 } else {
135 Self::exp(self * T::ln(base))
136 }
137 }
138
139 pub fn ln_abs(self) -> T {
141 T::ln(Self::square_abs(self)) / T::two()
142 }
143
144 pub fn ln(self) -> Self {
146 Self::new(Self::ln_abs(self), Self::arg(self))
147 }
148
149 pub fn log(self) -> Self {
151 Self::ln(self) / T::ln(T::ten())
152 }
153
154 pub fn logn(self, base: T) -> Self {
156 Self::ln(self) / T::ln(base)
157 }
158}
159
160impl<T: Float + Debug> Complex<T> {
162 pub fn sin(self) -> Self {
164 Self::new(
165 T::sin(self.real) * T::cosh(self.imag),
166 T::cos(self.real) * T::sinh(self.imag),
167 )
168 }
169
170 pub fn cos(self) -> Self {
172 Self::new(
173 T::cos(self.real) * T::cosh(self.imag),
174 -T::sin(self.real) * T::sinh(self.imag),
175 )
176 }
177
178 pub fn tan(self) -> Self {
180 Self::sin(self) / Self::cos(self)
181 }
182
183 pub fn cot(self) -> Self {
185 Self::cos(self) / Self::sin(self)
186 }
187
188 pub fn sec(self) -> Self {
190 Self::cos(self).inv()
191 }
192
193 pub fn csc(self) -> Self {
195 Self::sin(self).inv()
196 }
197
198 pub fn arcsin(self) -> Self {
202 -Self::i() * Self::ln(Self::sqrt(-self.powi(2) + T::one()) + Self::i() * self)
203 }
204
205 pub fn arccos(self) -> Self {
207 Self::i() * Self::ln(Self::sqrt(-self.powi(2) + T::one()) / Self::i() + self)
208 }
209
210 pub fn arctan(self) -> Self {
212 Self::two_i().inv()
213 * Self::ln((Self::i() * self + T::one()) / (-Self::i() * self + T::one()))
214 }
215
216 pub fn arccot(self) -> Self {
218 Self::arctan(Self::inv(self))
219 }
220
221 pub fn arcsec(self) -> Self {
223 Self::arccos(Self::inv(self))
224 }
225
226 pub fn arccsc(self) -> Self {
228 Self::arcsin(Self::inv(self))
229 }
230
231 pub fn sinh(self) -> Self {
235 Self::new(
236 T::sinh(self.real) * T::cos(self.imag),
237 T::cosh(self.real) * T::sin(self.imag),
238 )
239 }
240
241 pub fn cosh(self) -> Self {
243 Self::new(
244 T::cosh(self.real) * T::cos(self.imag),
245 T::sinh(self.real) * T::sin(self.imag),
246 )
247 }
248
249 pub fn tanh(self) -> Self {
251 Self::sinh(self) / Self::cosh(self)
252 }
253
254 pub fn coth(self) -> Self {
256 Self::cosh(self) / Self::sinh(self)
257 }
258
259 pub fn sech(self) -> Self {
261 Self::cosh(self).inv()
262 }
263
264 pub fn csch(self) -> Self {
266 Self::sinh(self).inv()
267 }
268
269 pub fn arcsinh(self) -> Self {
273 Self::ln(Self::sqrt(self.powi(2) + T::one()) + self)
274 }
275
276 pub fn arccosh(self) -> Self {
278 Self::ln(Self::sqrt(self.powi(2) - T::one()) + self)
279 }
280
281 pub fn arctanh(self) -> Self {
283 Self::ln((self + T::one()) / (-self + T::one())) * T::half()
284 }
285
286 pub fn arccoth(self) -> Self {
288 Self::arctanh(Self::inv(self))
289 }
290
291 pub fn arcsech(self) -> Self {
293 Self::arccosh(Self::inv(self))
294 }
295
296 pub fn arccsch(self) -> Self {
298 Self::arcsinh(Self::inv(self))
299 }
300}
301
302impl<T: Float + Display> fmt::Display for Complex<T> {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 if self.imag >= T::zero() {
309 write!(f, "{} + {}i", self.real, self.imag)
310 } else {
311 write!(f, "{} - {}i", self.real, self.imag)
312 }
313 }
314}
315
316mod overloading;
317
318#[cfg(test)]
319mod tests;