1use f128::f128;
4use num::{traits::Float, Complex, FromPrimitive, Num, ToPrimitive};
5use std::{
6 fmt::Display,
7 ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign},
8};
9
10pub trait Rational: std::ops::Div<Output = Self> + num::One + ToPrimitive + FromPrimitive {
12 fn recip(self) -> Self {
13 Self::one() / self
14 }
15
16 fn upper_bound() -> Self;
17}
18
19impl Rational for f32 {
20 fn recip(self) -> Self {
21 f32::recip(self)
22 }
23
24 fn upper_bound() -> Self {
25 <f32 as Float>::max_value()
26 }
27}
28
29impl Rational for f64 {
30 fn recip(self) -> Self {
31 f64::recip(self)
32 }
33
34 fn upper_bound() -> Self {
35 <f64 as Float>::max_value()
36 }
37}
38
39impl Rational for f128 {
40 fn recip(self) -> Self {
41 Float::recip(self)
42 }
43
44 fn upper_bound() -> Self {
45 <f128 as Float>::max_value()
46 }
47}
48
49#[allow(clippy::module_name_repetitions)]
62pub trait RealScalar:
63 Clone
64 + PartialEq
65 + std::fmt::Debug
66 + Num
67 + FromPrimitive
68 + ToPrimitive
69 + SafeConstants
70 + std::ops::Neg<Output = Self>
71 + 'static
72 + AddAssign
73 + SubAssign
74 + MulAssign
75 + DivAssign
76 + RemAssign
77 + Display
80 + PartialEq
81 + PartialOrd
82 + Rational
84{
85}
86impl<
87 T: Clone
88 + PartialEq
89 + PartialOrd
90 + std::fmt::Debug
91 + Num
92 + FromPrimitive
93 + ToPrimitive
94 + SafeConstants
95 + std::ops::Neg<Output = Self>
96 + AddAssign
97 + SubAssign
98 + MulAssign
99 + DivAssign
100 + RemAssign
101 + 'static
104 + PartialEq
105 + PartialOrd
106 + Rational
108 + Display,
109 > RealScalar for T
110{
111}
112
113pub trait SafeConstants {
131 fn tiny_safe() -> Self;
133
134 fn small_safe() -> Self;
136
137 fn large_safe() -> Self;
139
140 fn is_small(&self) -> bool;
142
143 fn is_tiny(&self) -> bool;
145
146 fn is_large(&self) -> bool;
148}
149
150macro_rules! safe_constants_float_impl {
151 ($t:ty) => {
152 impl SafeConstants for $t {
153 fn tiny_safe() -> Self {
154 Self::MIN_POSITIVE
155 }
156
157 fn small_safe() -> Self {
158 Self::MIN_POSITIVE.sqrt() / Self::EPSILON
159 }
160
161 fn large_safe() -> Self {
162 Self::MAX * Self::small_safe()
163 }
164
165 fn is_tiny(&self) -> bool {
166 self.abs() < Self::tiny_safe()
167 }
168
169 fn is_small(&self) -> bool {
170 self.abs() < Self::small_safe()
171 }
172
173 fn is_large(&self) -> bool {
174 self.abs() > Self::large_safe()
175 }
176 }
177 };
178}
179
180safe_constants_float_impl!(f32);
181safe_constants_float_impl!(f64);
182safe_constants_float_impl!(f128);
183
184impl<T: SafeConstants> SafeConstants for Complex<T> {
185 fn tiny_safe() -> Self {
186 Self {
187 re: T::tiny_safe(),
188 im: T::tiny_safe(),
189 }
190 }
191
192 fn small_safe() -> Self {
193 Self {
194 re: T::small_safe(),
195 im: T::small_safe(),
196 }
197 }
198
199 fn large_safe() -> Self {
200 Self {
201 re: T::large_safe(),
202 im: T::large_safe(),
203 }
204 }
205
206 fn is_small(&self) -> bool {
207 self.re.is_small() && self.im.is_small()
208 }
209
210 fn is_tiny(&self) -> bool {
211 self.re.is_tiny() && self.im.is_tiny()
212 }
213
214 fn is_large(&self) -> bool {
215 self.re.is_large() || self.im.is_large()
216 }
217}