kalc_lib/types/
complex.rs

1use super::{
2    CDecimal, CF32, CF64, Decimal, Float, Integer, NewVal, ParseU, Prec, Special, SpecialValues,
3    SpecialValuesDeci, Type, WithVal, WithValDeci,
4};
5use crate::macros::impls::{
6    impl_complex, impl_from_complex_tuple, impl_neg, impl_new_val, impl_self_ops,
7};
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10use std::fmt::{Display, Formatter};
11use std::ops::{Add, Div, Mul};
12#[derive(Clone, PartialEq)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub enum Complex {
15    Rug(rug::Complex),
16    Fastnum(CDecimal),
17    F64(CF64),
18    F32(CF32),
19}
20
21impl Prec for Complex {
22    fn prec(&self) -> u32 {
23        match self {
24            Self::Rug(a) => a.prec().0,
25            Self::Fastnum(a) => a.prec(),
26            Self::F64(a) => a.prec(),
27            Self::F32(a) => a.prec(),
28        }
29    }
30    fn set_prec(&mut self, new_prec: u32) {
31        match self {
32            Self::Rug(a) => a.set_prec(new_prec),
33            Self::Fastnum(a) => a.set_prec(new_prec),
34            Self::F64(_) => {}
35            Self::F32(_) => {}
36        }
37    }
38}
39
40impl ParseU<&str> for Complex {
41    fn parse(t: Type, prec: u32, s: &str) -> Option<Self> {
42        match t {
43            Type::Rug => Float::parse(t, prec, s).map(|a| a.into()),
44            Type::Fastnum => Float::parse(t, prec, s).map(|a| a.into()),
45            Type::F64 => Float::parse(t, prec, s).map(|a| a.into()),
46            Type::F32 => Float::parse(t, prec, s).map(|a| a.into()),
47        }
48    }
49    fn parse_radix(t: Type, prec: u32, s: &str, base: i32) -> Option<Self> {
50        match t {
51            Type::Rug => Float::parse_radix(t, prec, s, base).map(|a| a.into()),
52            Type::Fastnum => Float::parse_radix(t, prec, s, base).map(|a| a.into()),
53            Type::F64 => Float::parse_radix(t, prec, s, base).map(|a| a.into()),
54            Type::F32 => Float::parse_radix(t, prec, s, base).map(|a| a.into()),
55        }
56    }
57}
58
59impl SpecialValues for Complex {
60    fn pi(t: Type, prec: u32) -> Self {
61        match t {
62            Type::Rug => Self::Rug(rug::Complex::with_val(prec, rug::float::Constant::Pi)),
63            Type::Fastnum => Self::Fastnum(Decimal::pi(prec).into()),
64            Type::F64 => Self::F64(f64::pi(prec).into()),
65            Type::F32 => Self::F32(f32::pi(prec).into()),
66        }
67    }
68    fn nan(t: Type, prec: u32) -> Self {
69        match t {
70            Type::Rug => Self::Rug(rug::Complex::with_val(prec, rug::float::Special::Nan)),
71            Type::Fastnum => Self::Fastnum(Decimal::nan(prec).into()),
72            Type::F64 => Self::F64(f64::nan(prec).into()),
73            Type::F32 => Self::F32(f32::nan(prec).into()),
74        }
75    }
76    fn inf(t: Type, prec: u32) -> Self {
77        match t {
78            Type::Rug => Self::Rug(rug::Complex::with_val(prec, rug::float::Special::Infinity)),
79            Type::Fastnum => Self::Fastnum(Decimal::inf(prec).into()),
80            Type::F64 => Self::F64(f64::inf(prec).into()),
81            Type::F32 => Self::F32(f32::inf(prec).into()),
82        }
83    }
84}
85
86impl From<Float> for Complex {
87    fn from(value: Float) -> Self {
88        match value {
89            Float::Rug(a) => Complex::Rug(a.into()),
90            Float::Fastnum(a) => Complex::Fastnum(a.into()),
91            Float::F64(a) => Complex::F64(a.into()),
92            Float::F32(a) => Complex::F32(a.into()),
93        }
94    }
95}
96
97impl From<(Float, Float)> for Complex {
98    fn from(value: (Float, Float)) -> Self {
99        match value {
100            (Float::Rug(a), Float::Rug(b)) => Complex::Rug((a, b).into()),
101            (Float::Fastnum(a), Float::Fastnum(b)) => Complex::Fastnum((a, b).into()),
102            (Float::F64(a), Float::F64(b)) => Complex::F64((a, b).into()),
103            (Float::F32(a), Float::F32(b)) => Complex::F32((a, b).into()),
104            _ => unreachable!(),
105        }
106    }
107}
108
109impl Add<Float> for Complex {
110    type Output = Self;
111    fn add(self, rhs: Float) -> Self::Output {
112        self + Complex::from(rhs)
113    }
114}
115impl Add<Complex> for Float {
116    type Output = Complex;
117    fn add(self, rhs: Complex) -> Self::Output {
118        Complex::from(self) + rhs
119    }
120}
121impl Mul<Float> for Complex {
122    type Output = Self;
123    fn mul(self, rhs: Float) -> Self::Output {
124        self * Complex::from(rhs)
125    }
126}
127impl Mul<Complex> for Float {
128    type Output = Complex;
129    fn mul(self, rhs: Complex) -> Self::Output {
130        Complex::from(self) * rhs
131    }
132}
133
134impl Display for Complex {
135    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
136        match self {
137            Self::Rug(a) => a.fmt(f),
138            Self::Fastnum(a) => a.fmt(f),
139            Self::F32(a) => a.fmt(f),
140            Self::F64(a) => a.fmt(f),
141        }
142    }
143}
144impl Complex {
145    pub fn real(&self) -> Float {
146        match self {
147            Self::Rug(a) => Float::Rug(a.real().clone()),
148            Self::Fastnum(a) => Float::Fastnum(a.0),
149            Self::F64(a) => Float::F64(a.0),
150            Self::F32(a) => Float::F32(a.0),
151        }
152    }
153    pub fn imag(&self) -> Float {
154        match self {
155            Self::Rug(a) => Float::Rug(a.imag().clone()),
156            Self::Fastnum(a) => Float::Fastnum(a.1),
157            Self::F64(a) => Float::F64(a.1),
158            Self::F32(a) => Float::F32(a.1),
159        }
160    }
161    pub fn real_imag(self) -> (Float, Float) {
162        match self {
163            Self::Rug(a) => {
164                let (a, b) = a.into_real_imag();
165                (Float::Rug(a), Float::Rug(b))
166            }
167            Self::Fastnum(a) => (Float::Fastnum(a.0), Float::Fastnum(a.1)),
168            Self::F64(a) => (Float::F64(a.0), Float::F64(a.1)),
169            Self::F32(a) => (Float::F32(a.0), Float::F32(a.1)),
170        }
171    }
172    pub fn is_zero(&self) -> bool {
173        match self {
174            Self::Rug(a) => a.is_zero(),
175            Self::Fastnum(a) => a.0.is_zero() && a.1.is_zero(),
176            Self::F64(a) => a.0 == 0.0 && a.1 == 0.0,
177            Self::F32(a) => a.0 == 0.0 && a.1 == 0.0,
178        }
179    }
180    pub fn ftype(&self) -> Type {
181        match self {
182            Self::Rug(_) => Type::Rug,
183            Self::Fastnum(_) => Type::Fastnum,
184            Self::F64(_) => Type::F64,
185            Self::F32(_) => Type::F32,
186        }
187    }
188    pub fn sin_cos(self) -> (Self, Self) {
189        match self {
190            Self::Rug(a) => {
191                let p = a.prec();
192                let (s, c) = a.sin_cos(rug::Complex::new(p));
193                (Self::Rug(s), Self::Rug(c))
194            }
195            Self::Fastnum(a) => {
196                let (s, c) = a.sin_cos();
197                (Self::Fastnum(s), Self::Fastnum(c))
198            }
199            Self::F64(a) => {
200                let (s, c) = a.sin_cos();
201                (Self::F64(s), Self::F64(c))
202            }
203            Self::F32(a) => {
204                let (s, c) = a.sin_cos();
205                (Self::F32(s), Self::F32(c))
206            }
207        }
208    }
209}
210
211impl PartialEq<f64> for Complex {
212    fn eq(&self, other: &f64) -> bool {
213        match self {
214            Self::Rug(a) => a == other,
215            Self::Fastnum(a) => a.0 == *other,
216            Self::F64(a) => a.0 == *other,
217            Self::F32(a) => a.0 == *other as f32,
218        }
219    }
220}
221impl PartialEq<i32> for Complex {
222    fn eq(&self, other: &i32) -> bool {
223        match self {
224            Self::Rug(a) => a == other,
225            Self::Fastnum(a) => a.0 == *other,
226            Self::F64(a) => a.0 == *other as f64,
227            Self::F32(a) => a.0 == *other as f32,
228        }
229    }
230}
231impl Mul<Integer> for Complex {
232    type Output = Self;
233    fn mul(self, rhs: Integer) -> Self::Output {
234        match (self, rhs) {
235            (Complex::Rug(a), Integer::Rug(b)) => Complex::Rug(a * b),
236            (Complex::Fastnum(a), Integer::Fastnum(b)) => Complex::Fastnum(a * b),
237            (Complex::F64(a), Integer::F64(b)) => Complex::F64(a * b as f64),
238            (Complex::F32(a), Integer::F32(b)) => Complex::F32(a * b as f32),
239            _ => unreachable!(),
240        }
241    }
242}
243impl Div<Integer> for Complex {
244    type Output = Self;
245    fn div(self, rhs: Integer) -> Self::Output {
246        match (self, rhs) {
247            (Complex::Rug(a), Integer::Rug(b)) => Complex::Rug(a / b),
248            (Complex::Fastnum(a), Integer::Fastnum(b)) => Complex::Fastnum(a / b),
249            (Complex::F64(a), Integer::F64(b)) => Complex::F64(a / b as f64),
250            (Complex::F32(a), Integer::F32(b)) => Complex::F32(a / b as f32),
251            _ => unreachable!(),
252        }
253    }
254}
255impl Mul<Complex> for Integer {
256    type Output = Complex;
257    fn mul(self, rhs: Complex) -> Self::Output {
258        match (rhs, self) {
259            (Complex::Rug(a), Integer::Rug(b)) => Complex::Rug(a * b),
260            (Complex::Fastnum(a), Integer::Fastnum(b)) => Complex::Fastnum(a * b),
261            (Complex::F64(a), Integer::F64(b)) => Complex::F64(a * b as f64),
262            (Complex::F32(a), Integer::F32(b)) => Complex::F32(a * b as f32),
263            _ => unreachable!(),
264        }
265    }
266}
267impl Div<Complex> for Integer {
268    type Output = Complex;
269    fn div(self, rhs: Complex) -> Self::Output {
270        match (rhs, self) {
271            (Complex::Rug(a), Integer::Rug(b)) => Complex::Rug(a / b),
272            (Complex::Fastnum(a), Integer::Fastnum(b)) => Complex::Fastnum(a / b),
273            (Complex::F64(a), Integer::F64(b)) => Complex::F64(a / b as f64),
274            (Complex::F32(a), Integer::F32(b)) => Complex::F32(a / b as f32),
275            _ => unreachable!(),
276        }
277    }
278}
279
280impl WithVal<(Float, Float)> for Complex {
281    fn with_val(_: Type, prec: u32, val: (Float, Float)) -> Self {
282        match val {
283            (Float::Rug(a), Float::Rug(b)) => Complex::Rug(rug::Complex::with_val(prec, (a, b))),
284            (Float::Fastnum(a), Float::Fastnum(b)) => Complex::Fastnum(CDecimal(a, b)),
285            (Float::F64(a), Float::F64(b)) => Complex::F64(CF64(a, b)),
286            (Float::F32(a), Float::F32(b)) => Complex::F32(CF32(a, b)),
287            _ => unreachable!(),
288        }
289    }
290}
291impl_new_val!(
292    Complex,
293    (Rug, rug::Complex::with_val),
294    (Fastnum, CDecimal::with_val),
295    (F64, |_, x| CF64(x, 0.0)),
296    (F32, |_, x| CF32(x as f32, 0.0))
297);
298
299impl_from_complex_tuple!(f64, i32);
300impl_from_complex_tuple!(i32, f64);
301impl_from_complex_tuple!(i32, Special);
302impl_from_complex_tuple!(Special, Special);
303impl_from_complex_tuple!(Special, i32);
304impl_complex!(Complex, Rug, Fastnum, F64, F32);
305impl_neg!(Complex, Rug, Fastnum, F64, F32);
306impl_self_ops!(
307    Complex,
308    (Rug, |x| x),
309    (Fastnum, |x| x),
310    (F64, |x| x),
311    (F32, |x| x)
312);