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#[allow(missing_docs)]
15pub trait RealField:
16 ComplexField<RealField = Self>
17 + RelativeEq<Epsilon = Self>
18 + UlpsEq<Epsilon = Self>
19 + Signed
20 + PartialOrd
21{
22 fn is_sign_positive(&self) -> bool;
24 fn is_sign_negative(&self) -> bool;
26 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 fn min_value() -> Option<Self>;
39 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 #[inline]
107 fn min_value() -> Option<Self> {
108 Some($M::MIN)
109 }
110
111 #[inline]
113 fn max_value() -> Option<Self> {
114 Some($M::MAX)
115 }
116
117 #[inline]
119 fn pi() -> Self {
120 $M::consts::PI
121 }
122
123 #[inline]
125 fn two_pi() -> Self {
126 $M::consts::PI + $M::consts::PI
127 }
128
129 #[inline]
131 fn frac_pi_2() -> Self {
132 $M::consts::FRAC_PI_2
133 }
134
135 #[inline]
137 fn frac_pi_3() -> Self {
138 $M::consts::FRAC_PI_3
139 }
140
141 #[inline]
143 fn frac_pi_4() -> Self {
144 $M::consts::FRAC_PI_4
145 }
146
147 #[inline]
149 fn frac_pi_6() -> Self {
150 $M::consts::FRAC_PI_6
151 }
152
153 #[inline]
155 fn frac_pi_8() -> Self {
156 $M::consts::FRAC_PI_8
157 }
158
159 #[inline]
161 fn frac_1_pi() -> Self {
162 $M::consts::FRAC_1_PI
163 }
164
165 #[inline]
167 fn frac_2_pi() -> Self {
168 $M::consts::FRAC_2_PI
169 }
170
171 #[inline]
173 fn frac_2_sqrt_pi() -> Self {
174 $M::consts::FRAC_2_SQRT_PI
175 }
176
177
178 #[inline]
180 fn e() -> Self {
181 $M::consts::E
182 }
183
184 #[inline]
186 fn log2_e() -> Self {
187 $M::consts::LOG2_E
188 }
189
190 #[inline]
192 fn log10_e() -> Self {
193 $M::consts::LOG10_E
194 }
195
196 #[inline]
198 fn ln_2() -> Self {
199 $M::consts::LN_2
200 }
201
202 #[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#[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