1use pretty_dtoa::{dtoa, FmtFloatConfig};
2use std::{fmt, ops};
3
4use crate::util::DEFAULT_FLOAT_CONFIG;
5
6pub trait Integer:
7 num_traits::PrimInt + ops::AddAssign + ops::SubAssign + fmt::Display + fmt::Debug
8{
9}
10
11impl Integer for usize {}
12impl Integer for u8 {}
13impl Integer for u16 {}
14impl Integer for u32 {}
15impl Integer for u64 {}
16impl Integer for u128 {}
17
18impl Integer for isize {}
19impl Integer for i8 {}
20impl Integer for i16 {}
21impl Integer for i32 {}
22impl Integer for i64 {}
23impl Integer for i128 {}
24
25pub trait Float: Scalar {}
26
27impl Float for f64 {}
28impl Float for f32 {}
29
30pub trait Complex<F: Float>: Scalar {
31 fn new(re: F, im: F) -> Self;
32 fn conj(&self) -> Self;
33 fn real(&self) -> F;
34 fn imag(&self) -> F;
35}
36
37impl Complex<f64> for num_complex::Complex<f64> {
38 fn new(re: f64, im: f64) -> Self {
39 Self::new(re, im)
40 }
41
42 fn conj(&self) -> Self {
43 self.conj()
44 }
45
46 fn real(&self) -> f64 {
47 self.re
48 }
49
50 fn imag(&self) -> f64 {
51 self.im
52 }
53}
54
55impl Complex<f32> for num_complex::Complex<f32> {
56 fn new(re: f32, im: f32) -> Self {
57 Self::new(re, im)
58 }
59
60 fn conj(&self) -> Self {
61 self.conj()
62 }
63
64 fn real(&self) -> f32 {
65 self.re
66 }
67
68 fn imag(&self) -> f32 {
69 self.im
70 }
71}
72
73pub trait Scalar<Output = Self>:
74 PartialEq
75 + Copy
76 + Clone
77 + ops::Add<Output = Self>
78 + ops::Sub<Output = Self>
79 + ops::Mul<Output = Self>
80 + ops::Div<Output = Self>
81 + ops::AddAssign
82 + ops::SubAssign
83 + ops::MulAssign
84 + num_traits::Zero
85 + num_traits::One<Output = Self>
86 + fmt::Display
87 + Nonzero
88{
89 fn pretty_string(&self, _config: Option<FmtFloatConfig>) -> String {
90 format!("{}", self)
91 }
92}
93
94impl Scalar for f64 {
95 fn pretty_string(&self, config: Option<FmtFloatConfig>) -> String {
96 dtoa(*self, config.unwrap_or(DEFAULT_FLOAT_CONFIG))
97 }
98}
99impl Scalar for f32 {
100 fn pretty_string(&self, config: Option<FmtFloatConfig>) -> String {
101 dtoa(*self as f64, config.unwrap_or(DEFAULT_FLOAT_CONFIG))
102 }
103}
104
105impl Scalar for num_complex::Complex<f64> {
106 fn pretty_string(&self, config: Option<FmtFloatConfig>) -> String {
107 format!(
108 "{}{}j{}",
109 dtoa(self.re, config.unwrap_or(DEFAULT_FLOAT_CONFIG)),
110 if self.im.signum() < 0.0 { "-" } else { "+" },
111 dtoa(self.im, config.unwrap_or(DEFAULT_FLOAT_CONFIG))
112 )
113 .to_string()
114 }
115}
116impl Scalar for num_complex::Complex<f32> {
117 fn pretty_string(&self, config: Option<FmtFloatConfig>) -> String {
118 format!(
119 "{}{}j{}",
120 dtoa(self.re as f64, config.unwrap_or(DEFAULT_FLOAT_CONFIG)),
121 if self.im.signum() < 0.0 { "-" } else { "+" },
122 dtoa(self.im as f64, config.unwrap_or(DEFAULT_FLOAT_CONFIG))
123 )
124 .to_string()
125 }
126}
127
128impl Scalar for usize {}
129impl Scalar for u8 {}
130impl Scalar for u16 {}
131impl Scalar for u32 {}
132impl Scalar for u64 {}
133impl Scalar for u128 {}
134
135impl Scalar for isize {}
136impl Scalar for i8 {}
137impl Scalar for i16 {}
138impl Scalar for i32 {}
139impl Scalar for i64 {}
140impl Scalar for i128 {}
141
142pub trait Nonzero: PartialEq + Default {
143 fn nonzero(&self) -> bool {
144 *self != Default::default()
145 }
146}
147
148impl Nonzero for f64 {}
149impl Nonzero for f32 {}
150
151impl Nonzero for num_complex::Complex<f64> {}
152impl Nonzero for num_complex::Complex<f32> {}
153
154impl Nonzero for bool {}
155
156impl Nonzero for usize {}
157impl Nonzero for u8 {}
158impl Nonzero for u16 {}
159impl Nonzero for u32 {}
160impl Nonzero for u64 {}
161impl Nonzero for u128 {}
162
163impl Nonzero for isize {}
164impl Nonzero for i8 {}
165impl Nonzero for i16 {}
166impl Nonzero for i32 {}
167impl Nonzero for i64 {}
168impl Nonzero for i128 {}