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);