1 use num::{Bounded, Signed};
2 use std::{f32, f64};
3 
4 use approx::{RelativeEq, UlpsEq};
5 
6 use crate::general::{ComplexField, Lattice};
7 
8 #[cfg(not(feature = "std"))]
9 use num::Float;
10 //#[cfg(feature = "decimal")]
11 //use decimal::d128;
12 
13 #[allow(missing_docs)]
14 
15 /// Trait shared by all reals.
16 ///
17 /// Reals are equipped with functions that are commonly used on reals. The results of those
18 /// functions only have to be approximately equal to the actual theoretical values.
19 // FIXME: SubsetOf should be removed when specialization will be supported by rustc. This will
20 // allow a blanket impl: impl<T: Clone> SubsetOf<T> for T { ... }
21 // NOTE: make all types debuggable/'static/Any ? This seems essential for any kind of generic programming.
22 pub trait RealField:
23     ComplexField<RealField = Self>
24     + RelativeEq<Epsilon = Self>
25     + UlpsEq<Epsilon = Self>
26     + Lattice
27     + Signed
28     + Bounded
29 {
30     // NOTE: a real must be bounded because, no matter the chosen representation, being `Copy` implies that it occupies a statically-known size, meaning that it must have min/max values.
31 
is_sign_positive(self) -> bool32     fn is_sign_positive(self) -> bool;
is_sign_negative(self) -> bool33     fn is_sign_negative(self) -> bool;
max(self, other: Self) -> Self34     fn max(self, other: Self) -> Self;
min(self, other: Self) -> Self35     fn min(self, other: Self) -> Self;
atan2(self, other: Self) -> Self36     fn atan2(self, other: Self) -> Self;
37 
pi() -> Self38     fn pi() -> Self;
two_pi() -> Self39     fn two_pi() -> Self;
frac_pi_2() -> Self40     fn frac_pi_2() -> Self;
frac_pi_3() -> Self41     fn frac_pi_3() -> Self;
frac_pi_4() -> Self42     fn frac_pi_4() -> Self;
frac_pi_6() -> Self43     fn frac_pi_6() -> Self;
frac_pi_8() -> Self44     fn frac_pi_8() -> Self;
frac_1_pi() -> Self45     fn frac_1_pi() -> Self;
frac_2_pi() -> Self46     fn frac_2_pi() -> Self;
frac_2_sqrt_pi() -> Self47     fn frac_2_sqrt_pi() -> Self;
48 
e() -> Self49     fn e() -> Self;
log2_e() -> Self50     fn log2_e() -> Self;
log10_e() -> Self51     fn log10_e() -> Self;
ln_2() -> Self52     fn ln_2() -> Self;
ln_10() -> Self53     fn ln_10() -> Self;
54 }
55 
56 macro_rules! impl_real(
57     ($($T:ty, $M:ident, $libm: ident);*) => ($(
58         impl RealField for $T {
59             #[inline]
60             fn is_sign_positive(self) -> bool {
61                 $M::is_sign_positive(self)
62             }
63 
64             #[inline]
65             fn is_sign_negative(self) -> bool {
66                 $M::is_sign_negative(self)
67             }
68 
69             #[inline]
70             fn max(self, other: Self) -> Self {
71                 $M::max(self, other)
72             }
73 
74             #[inline]
75             fn min(self, other: Self) -> Self {
76                 $M::min(self, other)
77             }
78 
79             #[inline]
80             fn atan2(self, other: Self) -> Self {
81                 $libm::atan2(self, other)
82             }
83 
84             /// Archimedes' constant.
85             #[inline]
86             fn pi() -> Self {
87                 $M::consts::PI
88             }
89 
90             /// 2.0 * pi.
91             #[inline]
92             fn two_pi() -> Self {
93                 $M::consts::PI + $M::consts::PI
94             }
95 
96             /// pi / 2.0.
97             #[inline]
98             fn frac_pi_2() -> Self {
99                 $M::consts::FRAC_PI_2
100             }
101 
102             /// pi / 3.0.
103             #[inline]
104             fn frac_pi_3() -> Self {
105                 $M::consts::FRAC_PI_3
106             }
107 
108             /// pi / 4.0.
109             #[inline]
110             fn frac_pi_4() -> Self {
111                 $M::consts::FRAC_PI_4
112             }
113 
114             /// pi / 6.0.
115             #[inline]
116             fn frac_pi_6() -> Self {
117                 $M::consts::FRAC_PI_6
118             }
119 
120             /// pi / 8.0.
121             #[inline]
122             fn frac_pi_8() -> Self {
123                 $M::consts::FRAC_PI_8
124             }
125 
126             /// 1.0 / pi.
127             #[inline]
128             fn frac_1_pi() -> Self {
129                 $M::consts::FRAC_1_PI
130             }
131 
132             /// 2.0 / pi.
133             #[inline]
134             fn frac_2_pi() -> Self {
135                 $M::consts::FRAC_2_PI
136             }
137 
138             /// 2.0 / sqrt(pi).
139             #[inline]
140             fn frac_2_sqrt_pi() -> Self {
141                 $M::consts::FRAC_2_SQRT_PI
142             }
143 
144 
145             /// Euler's number.
146             #[inline]
147             fn e() -> Self {
148                 $M::consts::E
149             }
150 
151             /// log2(e).
152             #[inline]
153             fn log2_e() -> Self {
154                 $M::consts::LOG2_E
155             }
156 
157             /// log10(e).
158             #[inline]
159             fn log10_e() -> Self {
160                 $M::consts::LOG10_E
161             }
162 
163             /// ln(2.0).
164             #[inline]
165             fn ln_2() -> Self {
166                 $M::consts::LN_2
167             }
168 
169             /// ln(10.0).
170             #[inline]
171             fn ln_10() -> Self {
172                 $M::consts::LN_10
173             }
174         }
175     )*)
176 );
177 
178 #[cfg(not(feature = "std"))]
179 impl_real!(f32,f32,Float; f64,f64,Float);
180 #[cfg(feature = "std")]
181 impl_real!(f32,f32,f32; f64,f64,f64);
182 //#[cfg(feature = "decimal")]
183 //impl_real!(d128, d128, d128);
184