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(
9 any(target_arch = "nvptx", target_arch = "nvptx64"),
10 not(feature = "std"),
11 not(feature = "libm_force"),
12 feature = "cuda"
13))]
14use cuda_std::GpuFloat;
15#[cfg(all(not(feature = "std"), not(feature = "libm_force"), feature = "libm"))]
16use num::Float;
17#[allow(missing_docs)]
22pub trait RealField:
23 ComplexField<RealField = Self>
24 + RelativeEq<Epsilon = Self>
25 + UlpsEq<Epsilon = Self>
26 + Signed
27 + PartialOrd
28{
29 fn is_sign_positive(&self) -> bool;
31 fn is_sign_negative(&self) -> bool;
33 fn copysign(self, sign: Self) -> Self;
38
39 fn max(self, other: Self) -> Self;
40 fn min(self, other: Self) -> Self;
41 fn clamp(self, min: Self, max: Self) -> Self;
42 fn atan2(self, other: Self) -> Self;
43
44 fn min_value() -> Option<Self>;
46 fn max_value() -> Option<Self>;
48
49 fn pi() -> Self;
50 fn two_pi() -> Self;
51 fn frac_pi_2() -> Self;
52 fn frac_pi_3() -> Self;
53 fn frac_pi_4() -> Self;
54 fn frac_pi_6() -> Self;
55 fn frac_pi_8() -> Self;
56 fn frac_1_pi() -> Self;
57 fn frac_2_pi() -> Self;
58 fn frac_2_sqrt_pi() -> Self;
59
60 fn e() -> Self;
61 fn log2_e() -> Self;
62 fn log10_e() -> Self;
63 fn ln_2() -> Self;
64 fn ln_10() -> Self;
65}
66
67macro_rules! impl_real(
68 ($($T:ty, $M:ident, $cpysgn_mod: ident, $atan_mod: ident);*) => ($(
69 impl RealField for $T {
70 #[inline]
71 fn is_sign_positive(&self) -> bool {
72 $M::is_sign_positive(*self)
73 }
74
75 #[inline]
76 fn is_sign_negative(&self) -> bool {
77 $M::is_sign_negative(*self)
78 }
79
80 #[inline(always)]
81 fn copysign(self, sign: Self) -> Self {
82 $cpysgn_mod::copysign(self, sign)
83 }
84
85 #[inline]
86 fn max(self, other: Self) -> Self {
87 $M::max(self, other)
88 }
89
90 #[inline]
91 fn min(self, other: Self) -> Self {
92 $M::min(self, other)
93 }
94
95 #[inline]
96 fn clamp(self, min: Self, max: Self) -> Self {
97 if self < min {
98 min
99 } else if self > max {
100 max
101 } else {
102 self
103 }
104 }
105
106 #[inline]
107 fn atan2(self, other: Self) -> Self {
108 $atan_mod::atan2(self, other)
109 }
110
111
112 #[inline]
114 fn min_value() -> Option<Self> {
115 Some($M::MIN)
116 }
117
118 #[inline]
120 fn max_value() -> Option<Self> {
121 Some($M::MAX)
122 }
123
124 #[inline]
126 fn pi() -> Self {
127 $M::consts::PI
128 }
129
130 #[inline]
132 fn two_pi() -> Self {
133 $M::consts::PI + $M::consts::PI
134 }
135
136 #[inline]
138 fn frac_pi_2() -> Self {
139 $M::consts::FRAC_PI_2
140 }
141
142 #[inline]
144 fn frac_pi_3() -> Self {
145 $M::consts::FRAC_PI_3
146 }
147
148 #[inline]
150 fn frac_pi_4() -> Self {
151 $M::consts::FRAC_PI_4
152 }
153
154 #[inline]
156 fn frac_pi_6() -> Self {
157 $M::consts::FRAC_PI_6
158 }
159
160 #[inline]
162 fn frac_pi_8() -> Self {
163 $M::consts::FRAC_PI_8
164 }
165
166 #[inline]
168 fn frac_1_pi() -> Self {
169 $M::consts::FRAC_1_PI
170 }
171
172 #[inline]
174 fn frac_2_pi() -> Self {
175 $M::consts::FRAC_2_PI
176 }
177
178 #[inline]
180 fn frac_2_sqrt_pi() -> Self {
181 $M::consts::FRAC_2_SQRT_PI
182 }
183
184
185 #[inline]
187 fn e() -> Self {
188 $M::consts::E
189 }
190
191 #[inline]
193 fn log2_e() -> Self {
194 $M::consts::LOG2_E
195 }
196
197 #[inline]
199 fn log10_e() -> Self {
200 $M::consts::LOG10_E
201 }
202
203 #[inline]
205 fn ln_2() -> Self {
206 $M::consts::LN_2
207 }
208
209 #[inline]
211 fn ln_10() -> Self {
212 $M::consts::LN_10
213 }
214 }
215 )*)
216);
217
218#[cfg(all(
219 not(target_arch = "nvptx"),
220 not(target_arch = "nvptx64"),
221 not(feature = "std"),
222 not(feature = "libm_force"),
223 feature = "libm"
224))]
225impl_real!(f32, f32, Float, Float; f64, f64, Float, Float);
226#[cfg(all(feature = "std", not(feature = "libm_force")))]
227impl_real!(f32, f32, f32, f32; f64, f64, f64, f64);
228#[cfg(all(
229 any(target_arch = "nvptx", target_arch = "nvptx64"),
230 not(feature = "std"),
231 not(feature = "libm_force"),
232 feature = "cuda"
233))]
234impl_real!(
235 f32, f32, GpuFloat, GpuFloat;
236 f64, f64, GpuFloat, GpuFloat
237);
238#[cfg(feature = "libm_force")]
239impl_real!(f32, f32, libm_force_f32, libm_force_f32; f64, f64, libm_force, libm_force);
240
241#[cfg(feature = "libm_force")]
245mod libm_force_f32 {
246 #[inline(always)]
247 pub fn atan2(y: f32, x: f32) -> f32 {
248 libm_force::atan2f(y, x)
249 }
250
251 #[inline(always)]
252 pub fn copysign(x: f32, y: f32) -> f32 {
253 libm_force::copysignf(x, y)
254 }
255}
256
257