1use super::{atan2, cossin};
2use core::num::Wrapping;
3use core::ops::{Add, Deref, DerefMut, Mul, Sub};
4use dsp_fixedpoint::{P32, Q32};
5use num_traits::AsPrimitive;
6
7#[derive(
9 Clone,
10 Copy,
11 Debug,
12 Default,
13 PartialEq,
14 Eq,
15 PartialOrd,
16 Ord,
17 serde::Serialize,
18 serde::Deserialize,
19 bytemuck::Zeroable,
20 bytemuck::Pod,
21)]
22#[repr(transparent)]
23#[serde(transparent)]
24pub struct Complex<T>(
25 pub [T; 2],
27);
28
29impl<T> Deref for Complex<T> {
30 type Target = [T; 2];
31
32 fn deref(&self) -> &Self::Target {
33 &self.0
34 }
35}
36
37impl<T> DerefMut for Complex<T> {
38 fn deref_mut(&mut self) -> &mut Self::Target {
39 &mut self.0
40 }
41}
42
43impl<T: Copy> Complex<T> {
44 pub const fn new(re: T, im: T) -> Self {
46 Self([re, im])
47 }
48
49 pub fn re(&self) -> T {
51 self.0[0]
52 }
53
54 pub fn im(&self) -> T {
56 self.0[1]
57 }
58}
59
60impl<T: Copy + core::ops::Neg<Output = T>> Complex<T> {
61 pub fn conj(self) -> Self {
63 Self([self.0[0], -self.0[1]])
64 }
65}
66
67macro_rules! fwd_binop {
68 ($tr:ident::$meth:ident) => {
69 impl<T: Copy + core::ops::$tr<Output = T>> core::ops::$tr for Complex<T> {
70 type Output = Self;
71 fn $meth(self, rhs: Self) -> Self {
72 Self([self.0[0].$meth(rhs.0[0]), self.0[1].$meth(rhs.0[1])])
73 }
74 }
75 };
76}
77fwd_binop!(Add::add);
78fwd_binop!(Sub::sub);
79fwd_binop!(BitAnd::bitand);
80fwd_binop!(BitOr::bitor);
81fwd_binop!(BitXor::bitxor);
82
83macro_rules! fwd_binop_inner {
84 ($tr:ident::$meth:ident) => {
85 impl<T: Copy + core::ops::$tr<Output = T>> core::ops::$tr<T> for Complex<T> {
86 type Output = Self;
87 fn $meth(self, rhs: T) -> Self {
88 Self([self.0[0].$meth(rhs), self.0[1].$meth(rhs)])
89 }
90 }
91 };
92}
93fwd_binop_inner!(Mul::mul);
94fwd_binop_inner!(Div::div);
95fwd_binop_inner!(Rem::rem);
96fwd_binop_inner!(BitAnd::bitand);
97fwd_binop_inner!(BitOr::bitor);
98fwd_binop_inner!(BitXor::bitxor);
99
100macro_rules! fwd_unop {
101 ($tr:ident::$meth:ident) => {
102 impl<T: Copy + core::ops::$tr<Output = T>> core::ops::$tr for Complex<T> {
103 type Output = Self;
104 fn $meth(self) -> Self {
105 Self([self.0[0].$meth(), self.0[1].$meth()])
106 }
107 }
108 };
109}
110fwd_unop!(Not::not);
111fwd_unop!(Neg::neg);
112
113impl<T: 'static + Copy + Mul<Output = A>, A: Add<Output = A> + Sub<Output = A> + AsPrimitive<T>> Mul
114 for Complex<T>
115{
116 type Output = Self;
117 fn mul(self, rhs: Self) -> Self {
118 Self([
119 (self.0[0] * rhs.0[0] - self.0[1] * rhs.0[1]).as_(),
120 (self.0[0] * rhs.0[1] + self.0[1] * rhs.0[0]).as_(),
121 ])
122 }
123}
124
125impl<T> core::iter::Sum for Complex<T>
126where
127 Self: Default + Add<Output = Self>,
128{
129 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
130 iter.fold(Default::default(), |c, i| c + i)
131 }
132}
133
134impl<T> core::iter::Product for Complex<T>
135where
136 Self: Default + Mul<Output = Self>,
137{
138 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
139 iter.fold(Default::default(), |c, i| c * i)
140 }
141}
142
143impl Complex<Q32<31>> {
144 pub fn from_angle(angle: Wrapping<i32>) -> Self {
156 let (c, s) = cossin(angle.0);
157 Self::new(Q32::new(c), Q32::new(s))
158 }
159}
160
161impl Complex<i32> {
162 pub fn norm_sqr(&self) -> P32<31> {
182 let [x, y] = self.0.map(|x| x as i64 * x as i64);
183 P32::new(((x + y) >> 31) as _)
184 }
185
186 pub fn log2(&self) -> i32 {
203 let [x, y] = self.0.map(|x| x as i64 * x as i64);
204 -(x.wrapping_add(y).leading_zeros() as i32)
205 }
206
207 pub fn arg(&self) -> Wrapping<i32> {
220 Wrapping(atan2(self.im(), self.re()))
221 }
222}