1use super::{atan2, cossin};
2use core::num::Wrapping;
3use core::ops::{Add, 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: Copy> Complex<T> {
30 pub const fn new(re: T, im: T) -> Self {
32 Self([re, im])
33 }
34
35 pub fn re(&self) -> T {
37 self.0[0]
38 }
39
40 pub fn im(&self) -> T {
42 self.0[1]
43 }
44}
45
46impl<T: Copy + core::ops::Neg<Output = T>> Complex<T> {
47 pub fn conj(self) -> Self {
49 Self([self.0[0], -self.0[1]])
50 }
51}
52
53macro_rules! fwd_binop {
54 ($tr:ident::$meth:ident) => {
55 impl<T: Copy + core::ops::$tr<Output = T>> core::ops::$tr for Complex<T> {
56 type Output = Self;
57 fn $meth(self, rhs: Self) -> Self {
58 Self([self.0[0].$meth(rhs.0[0]), self.0[1].$meth(rhs.0[1])])
59 }
60 }
61 };
62}
63fwd_binop!(Add::add);
64fwd_binop!(Sub::sub);
65fwd_binop!(BitAnd::bitand);
66fwd_binop!(BitOr::bitor);
67fwd_binop!(BitXor::bitxor);
68
69macro_rules! fwd_binop_inner {
70 ($tr:ident::$meth:ident) => {
71 impl<T: Copy + core::ops::$tr<Output = T>> core::ops::$tr<T> for Complex<T> {
72 type Output = Self;
73 fn $meth(self, rhs: T) -> Self {
74 Self([self.0[0].$meth(rhs), self.0[1].$meth(rhs)])
75 }
76 }
77 };
78}
79fwd_binop_inner!(Mul::mul);
80fwd_binop_inner!(Div::div);
81fwd_binop_inner!(Rem::rem);
82fwd_binop_inner!(BitAnd::bitand);
83fwd_binop_inner!(BitOr::bitor);
84fwd_binop_inner!(BitXor::bitxor);
85
86macro_rules! fwd_unop {
87 ($tr:ident::$meth:ident) => {
88 impl<T: Copy + core::ops::$tr<Output = T>> core::ops::$tr for Complex<T> {
89 type Output = Self;
90 fn $meth(self) -> Self {
91 Self([self.0[0].$meth(), self.0[1].$meth()])
92 }
93 }
94 };
95}
96fwd_unop!(Not::not);
97fwd_unop!(Neg::neg);
98
99impl<T: 'static + Copy + Mul<Output = A>, A: Add<Output = A> + Sub<Output = A> + AsPrimitive<T>> Mul
100 for Complex<T>
101{
102 type Output = Self;
103 fn mul(self, rhs: Self) -> Self {
104 Self([
105 (self.0[0] * rhs.0[0] - self.0[1] * rhs.0[1]).as_(),
106 (self.0[0] * rhs.0[1] + self.0[1] * rhs.0[0]).as_(),
107 ])
108 }
109}
110
111impl<T> core::iter::Sum for Complex<T>
112where
113 Self: Default + Add<Output = Self>,
114{
115 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
116 iter.fold(Default::default(), |c, i| c + i)
117 }
118}
119
120impl<T> core::iter::Product for Complex<T>
121where
122 Self: Default + Mul<Output = Self>,
123{
124 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
125 iter.fold(Default::default(), |c, i| c * i)
126 }
127}
128
129impl Complex<Q32<31>> {
130 pub fn from_angle(angle: Wrapping<i32>) -> Self {
142 let (c, s) = cossin(angle.0);
143 Self::new(Q32::new(c), Q32::new(s))
144 }
145}
146
147impl Complex<i32> {
148 pub fn norm_sqr(&self) -> P32<31> {
168 let [x, y] = self.0.map(|x| x as i64 * x as i64);
169 P32::new(((x + y) >> 31) as _)
170 }
171
172 pub fn log2(&self) -> i32 {
189 let [x, y] = self.0.map(|x| x as i64 * x as i64);
190 -(x.wrapping_add(y).leading_zeros() as i32)
191 }
192
193 pub fn arg(&self) -> Wrapping<i32> {
206 Wrapping(atan2(self.im(), self.re()))
207 }
208}