1use std::fmt::{Display, Formatter, Result as FmtResult};
2use std::ops::{Add, Div, Mul, Neg, Sub};
3
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct Complex<T> {
6 re: T,
7 im: T,
8}
9
10#[macro_export]
11macro_rules! complex {
12 ($re:expr, $im:expr) => {
13 Complex::<f32>::new($re as f32, $im as f32)
14 };
15 ($re:expr) => {
16 Complex::<f32>::new($re as f32, 0.0)
17 };
18}
19
20#[macro_export]
21macro_rules! im {
22 ($im:expr) => {
23 Complex::<f32>::new(0.0, $im as f32)
24 };
25}
26
27impl<T> Complex<T> {
28 pub fn new(re: T, im: T) -> Self {
37 Self { re, im }
38 }
39}
40
41impl<T: Copy> Complex<T> {
42 pub fn re(&self) -> T {
43 self.re
44 }
45
46 pub fn im(&self) -> T {
47 self.im
48 }
49}
50
51impl Complex<f64> {
52 pub fn modulus(&self) -> f64 {
62 (self.re * self.re + self.im * self.im).sqrt()
63 }
64
65 pub fn argument(&self) -> f64 {
76 self.im.atan2(self.re)
77 }
78 pub fn conjugate(&self) -> Self {
89 Self::new(self.re, -self.im)
90 }
91 pub fn exp(&self) -> Self {
101 let r = self.re.exp();
102 Self::new(r * self.im.cos(), r * self.im.sin())
103 }
104 pub fn ln(&self) -> Self {
114 Complex::new(self.modulus().ln(), self.argument())
115 }
116 pub fn pow(&self, n: f64) -> Self {
126 let r = self.modulus().powf(n);
127 let theta = self.argument() * n;
128 Self::new(r * theta.cos(), r * theta.sin())
129 }
130 pub fn sqrt(&self) -> Self {
140 let r = self.modulus().sqrt();
141 let theta = self.argument() / 2.0;
142 Self::new(r * theta.cos(), r * theta.sin())
143 }
144
145 pub fn sin(&self) -> Self {
146 Self::new(
147 self.re.sin() * self.im.cosh(),
148 self.re.cos() * self.im.sinh(),
149 )
150 }
151
152 pub fn cos(&self) -> Self {
153 Self::new(
154 self.re.cos() * self.im.cosh(),
155 -self.re.sin() * self.im.sinh(),
156 )
157 }
158
159 pub fn tan(&self) -> Self {
160 self.sin() / self.cos()
161 }
162
163 pub fn sinh(&self) -> Self {
164 Self::new(
165 self.re.sinh() * self.im.cos(),
166 self.re.cosh() * self.im.sin(),
167 )
168 }
169
170 pub fn cosh(&self) -> Self {
171 Self::new(
172 self.re.cosh() * self.im.cos(),
173 self.re.sinh() * self.im.sin(),
174 )
175 }
176
177 pub fn tanh(&self) -> Self {
178 self.sinh() / self.cosh()
179 }
180}
181impl<T: Copy + Add<Output = T>> Add for Complex<T> {
182 type Output = Self;
183
184 fn add(self, rhs: Self) -> Self::Output {
185 Self {
186 re: self.re + rhs.re,
187 im: self.im + rhs.im,
188 }
189 }
190}
191
192impl<T: Copy + Sub<Output = T>> Sub for Complex<T> {
193 type Output = Self;
194
195 fn sub(self, rhs: Self) -> Self::Output {
196 Self {
197 re: self.re - rhs.re,
198 im: self.im - rhs.im,
199 }
200 }
201}
202
203impl<T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T>> Mul for Complex<T> {
204 type Output = Self;
205
206 fn mul(self, rhs: Self) -> Self::Output {
207 Self {
208 re: self.re * rhs.re - self.im * rhs.im,
209 im: self.re * rhs.im + self.im * rhs.re,
210 }
211 }
212}
213
214impl<T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Div
215 for Complex<T>
216{
217 type Output = Self;
218
219 fn div(self, rhs: Self) -> Self::Output {
220 let denom = rhs.re * rhs.re + rhs.im * rhs.im;
221 Self {
222 re: (self.re * rhs.re + self.im * rhs.im) / denom,
223 im: (self.im * rhs.re - self.re * rhs.im) / denom,
224 }
225 }
226}
227
228impl<T: Neg<Output = T>> Neg for Complex<T> {
229 type Output = Self;
230
231 fn neg(self) -> Self::Output {
232 Self::new(-self.re, -self.im)
233 }
234}
235
236impl<T: Display> Display for Complex<T> {
237 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
238 write!(f, "{}+{}i", self.re, self.im)
239 }
240}
241
242impl From<f64> for Complex<f64> {
243 fn from(x: f64) -> Self {
244 Self::new(x, 0.0)
245 }
246}
247
248impl From<i32> for Complex<f64> {
249 fn from(x: i32) -> Self {
250 Self::new(x as f64, 0.0)
251 }
252}
253
254impl Complex<f64> {
255 pub const I: Complex<f64> = Complex { re: 0.0, im: 1.0 };
256 pub const ONE: Complex<f64> = Complex { re: 1.0, im: 0.0 };
257 pub const ZERO: Complex<f64> = Complex { re: 0.0, im: 0.0 };
258}
259
260impl Complex<f64> {
261 pub fn from_polar(r: f64, theta: f64) -> Self {
270 Self::new(r * theta.cos(), r * theta.sin())
271 }
272
273 pub fn to_polar(&self) -> (f64, f64) {
283 (self.modulus(), self.argument())
284 }
285}