simba/scalar/
real.rs

1use num::Signed;
2use std::{f32, f64};
3
4use approx::{RelativeEq, UlpsEq};
5
6use crate::scalar::ComplexField;
7
8#[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))]
9use num::Float;
10//#[cfg(feature = "decimal")]
11//use decimal::d128;
12
13/// Trait shared by all reals.
14#[allow(missing_docs)]
15pub trait RealField:
16    ComplexField<RealField = Self>
17    + RelativeEq<Epsilon = Self>
18    + UlpsEq<Epsilon = Self>
19    + Signed
20    + PartialOrd
21{
22    /// Is the sign of this real number positive?
23    fn is_sign_positive(&self) -> bool;
24    /// Is the sign of this real number negative?
25    fn is_sign_negative(&self) -> bool;
26    /// Copies the sign of `sign` to `self`.
27    ///
28    /// - Returns `self.simd_abs()` if `sign` is positive or positive-zero.
29    /// - Returns `-self.simd_abs()` if `sign` is negative or negative-zero.
30    fn copysign(self, sign: Self) -> Self;
31
32    fn max(self, other: Self) -> Self;
33    fn min(self, other: Self) -> Self;
34    fn clamp(self, min: Self, max: Self) -> Self;
35    fn atan2(self, other: Self) -> Self;
36
37    /// The smallest finite positive value representable using this type.
38    fn min_value() -> Option<Self>;
39    /// The largest finite positive value representable using this type.
40    fn max_value() -> Option<Self>;
41
42    fn pi() -> Self;
43    fn two_pi() -> Self;
44    fn frac_pi_2() -> Self;
45    fn frac_pi_3() -> Self;
46    fn frac_pi_4() -> Self;
47    fn frac_pi_6() -> Self;
48    fn frac_pi_8() -> Self;
49    fn frac_1_pi() -> Self;
50    fn frac_2_pi() -> Self;
51    fn frac_2_sqrt_pi() -> Self;
52
53    fn e() -> Self;
54    fn log2_e() -> Self;
55    fn log10_e() -> Self;
56    fn ln_2() -> Self;
57    fn ln_10() -> Self;
58}
59
60macro_rules! impl_real (
61    ($($T:ty, $M:ident, $cpysgn_mod: ident, $atan_mod: ident);*) => ($(
62        impl RealField for $T {
63            #[inline]
64            fn is_sign_positive(&self) -> bool {
65                $M::is_sign_positive(*self)
66            }
67
68            #[inline]
69            fn is_sign_negative(&self) -> bool {
70                $M::is_sign_negative(*self)
71            }
72
73            #[inline(always)]
74            fn copysign(self, sign: Self) -> Self {
75                $cpysgn_mod::copysign(self, sign)
76            }
77
78            #[inline]
79            fn max(self, other: Self) -> Self {
80                $M::max(self, other)
81            }
82
83            #[inline]
84            fn min(self, other: Self) -> Self {
85                $M::min(self, other)
86            }
87
88            #[inline]
89            fn clamp(self, min: Self, max: Self) -> Self {
90                if self < min {
91                    min
92                } else if self > max {
93                    max
94                } else {
95                    self
96                }
97            }
98
99            #[inline]
100            fn atan2(self, other: Self) -> Self {
101                $atan_mod::atan2(self, other)
102            }
103
104
105            /// The smallest finite positive value representable using this type.
106            #[inline]
107            fn min_value() -> Option<Self> {
108                Some($M::MIN)
109            }
110
111            /// The largest finite positive value representable using this type.
112            #[inline]
113            fn max_value() -> Option<Self> {
114                Some($M::MAX)
115            }
116
117            /// Archimedes' constant.
118            #[inline]
119            fn pi() -> Self {
120                $M::consts::PI
121            }
122
123            /// 2.0 * pi.
124            #[inline]
125            fn two_pi() -> Self {
126                $M::consts::PI + $M::consts::PI
127            }
128
129            /// pi / 2.0.
130            #[inline]
131            fn frac_pi_2() -> Self {
132                $M::consts::FRAC_PI_2
133            }
134
135            /// pi / 3.0.
136            #[inline]
137            fn frac_pi_3() -> Self {
138                $M::consts::FRAC_PI_3
139            }
140
141            /// pi / 4.0.
142            #[inline]
143            fn frac_pi_4() -> Self {
144                $M::consts::FRAC_PI_4
145            }
146
147            /// pi / 6.0.
148            #[inline]
149            fn frac_pi_6() -> Self {
150                $M::consts::FRAC_PI_6
151            }
152
153            /// pi / 8.0.
154            #[inline]
155            fn frac_pi_8() -> Self {
156                $M::consts::FRAC_PI_8
157            }
158
159            /// 1.0 / pi.
160            #[inline]
161            fn frac_1_pi() -> Self {
162                $M::consts::FRAC_1_PI
163            }
164
165            /// 2.0 / pi.
166            #[inline]
167            fn frac_2_pi() -> Self {
168                $M::consts::FRAC_2_PI
169            }
170
171            /// 2.0 / sqrt(pi).
172            #[inline]
173            fn frac_2_sqrt_pi() -> Self {
174                $M::consts::FRAC_2_SQRT_PI
175            }
176
177
178            /// Euler's number.
179            #[inline]
180            fn e() -> Self {
181                $M::consts::E
182            }
183
184            /// log2(e).
185            #[inline]
186            fn log2_e() -> Self {
187                $M::consts::LOG2_E
188            }
189
190            /// log10(e).
191            #[inline]
192            fn log10_e() -> Self {
193                $M::consts::LOG10_E
194            }
195
196            /// ln(2.0).
197            #[inline]
198            fn ln_2() -> Self {
199                $M::consts::LN_2
200            }
201
202            /// ln(10.0).
203            #[inline]
204            fn ln_10() -> Self {
205                $M::consts::LN_10
206            }
207        }
208    )*)
209);
210
211#[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))]
212impl_real!(f32, f32, Float, Float; f64, f64, Float, Float);
213#[cfg(all(feature = "std", not(feature = "libm_force")))]
214impl_real!(f32, f32, f32, f32; f64, f64, f64, f64);
215#[cfg(feature = "libm_force")]
216impl_real!(f32, f32, libm_force_f32, libm_force_f32; f64, f64, libm_force, libm_force);
217
218// We use this dummy module to remove the 'f' suffix at the end of
219// each libm functions to make our generic Real/ComplexField impl
220// macros work.
221#[cfg(feature = "libm_force")]
222mod libm_force_f32 {
223    #[inline(always)]
224    pub fn atan2(y: f32, x: f32) -> f32 {
225        libm_force::atan2f(y, x)
226    }
227
228    #[inline(always)]
229    pub fn copysign(x: f32, y: f32) -> f32 {
230        libm_force::copysignf(x, y)
231    }
232}
233
234//#[cfg(feature = "decimal")]
235//impl_real!(d128, d128, d128);