irox_tools/primitives/
f32.rs1use crate::{FloatIsh, FromF64, PrimitiveMath, ToF64, ToSigned};
10
11impl crate::f64::FloatExt for f32 {
12 type Type = f32;
13 type Size = u32;
14
15 fn trunc(self) -> f32 {
16 (self as u64) as f32
17 }
18
19 fn fract(self) -> f32 {
20 self - self.trunc()
21 }
22
23 fn abs(self) -> f32 {
24 f32::from_bits(self.to_bits() & 0x7FFF_FFFF)
25 }
26 fn round(self) -> f32 {
27 (self + 0.5 * self.signum()).trunc()
28 }
29
30 fn floor(self) -> f32 {
31 if self.is_sign_negative() {
32 return (self - 1.0).trunc();
33 }
34 self.trunc()
35 }
36
37 fn ceil(self) -> f32 {
38 if self.is_sign_positive() {
39 return (self + 1.0).trunc();
40 }
41 self.trunc()
42 }
43
44 fn signum(self) -> f32 {
45 if self.is_nan() {
46 return f32::NAN;
47 }
48 if self.is_sign_negative() {
49 return -1.0;
50 }
51 1.0
52 }
53
54 fn clamp(self, min: Self, max: Self) -> Self::Type {
55 if self < min {
56 return min;
57 } else if self > max {
58 return max;
59 }
60 self
61 }
62
63 fn exp(self) -> Self::Type {
66 let mut out = 1.0;
67 let i = self;
68 let mut z = self;
69 let mut exp = 1.0;
70 let mut idx = 1;
71 let mut next = self;
72
73 while next.abs() > f32::EPSILON {
74 out += next;
75 idx += 1;
76 z *= i;
77 if z.is_infinite() {
78 break;
79 }
80 exp *= idx as Self::Type;
81 if exp.is_infinite() {
82 break;
83 }
84 next = z / exp;
85 if next.is_infinite() {
86 break;
87 }
88 }
89
90 out
91 }
92
93 fn ln(self) -> Self::Type {
96 let z = self as f64;
97 let iter = (z - 1.) / (z + 1.);
98 let mut out = 0.0f64;
99 let mut next = iter;
100 let mut base = iter;
101 let mut idx = 1u64;
102 while next.abs() > f64::EPSILON {
103 out += next;
104 idx += 2;
105 base *= iter * iter;
106 next = base / idx as f64;
107 }
108 (out * 2.0) as f32
109 }
110
111 fn log10(self) -> Self::Type {
112 self.ln() / core::f32::consts::LN_10
113 }
114
115 fn powi(self, val: i32) -> Self::Type {
117 let mut out = self;
118 let i = self;
119 for _ in 0..val.abs() {
120 out *= i;
121 }
122 out
123 }
124
125 fn powf(self, a: Self::Type) -> Self::Type {
128 let z = self;
129
130 (a * z.ln()).exp()
131 }
132
133 fn sqrt(self) -> Self::Type {
134 self.powf(0.5)
135 }
136
137 fn to_bits(self) -> Self::Size {
138 f32::to_bits(self)
139 }
140
141 fn exponent(self) -> u16 {
142 ((self.to_bits() >> 23) & 0x0F) as u16
143 }
144
145 fn significand(self) -> Self::Size {
146 self.to_bits() & 0x7FFFFF
147 }
148
149 fn sin(self) -> Self::Type {
150 if cfg!(feature = "std") {
151 f32::sin(self)
152 } else {
153 todo!()
154 }
155 }
156
157 fn cos(self) -> Self::Type {
158 if cfg!(feature = "std") {
159 f32::cos(self)
160 } else {
161 todo!()
162 }
163 }
164 fn tan(self) -> Self::Type {
165 if cfg!(feature = "std") {
166 f32::tan(self)
167 } else {
168 self.sin() / self.cos()
169 }
170 }
171
172 fn atan(self) -> Self::Type {
173 if cfg!(feature = "std") {
174 f32::atan(self)
175 } else {
176 todo!()
177 }
178 }
179
180 fn atan2(self, o: Self) -> Self::Type {
181 if cfg!(feature = "std") {
182 f32::atan2(self, o)
183 } else {
184 let _o = o;
185 todo!()
186 }
187 }
188}
189
190impl ToF64 for f32 {
191 fn to_f64(&self) -> f64 {
192 *self as f64
193 }
194}
195impl FromF64 for f32 {
196 fn from_f64(value: f64) -> Self {
197 value as f32
198 }
199}
200
201impl ToSigned for f32 {
202 type Output = f32;
203
204 fn to_signed(self) -> Self::Output {
205 self
206 }
207
208 fn negative_one() -> Self::Output {
209 -1.
210 }
211}
212
213impl PrimitiveMath for f32 {}
214impl FloatIsh for f32 {}
215
216#[cfg(all(test, not(feature = "std")))]
217mod tests {
218 #[test]
219 pub fn test_ln() {
220 assert_eq!(0.0, crate::f64::FloatExt::ln(1.0_f32));
221 assert_eq_eps!(1.0, crate::f64::FloatExt::ln(core::f32::consts::E), 1e-6);
222 assert_eq_eps!(4.6051702, crate::f64::FloatExt::ln(100f32), 1e-6);
223 assert_eq_eps!(
224 11.09033963004403,
225 crate::f64::FloatExt::ln(u16::MAX as f32),
226 1e-6
227 );
228 }
229
230 #[test]
231 pub fn test_exp() {
232 assert_eq_eps!(1.0, crate::f64::FloatExt::exp(0.0f32), 1e-6);
233 assert_eq_eps!(
234 core::f32::consts::E,
235 crate::f64::FloatExt::exp(1.0f32),
236 1e-6
237 );
238 assert_eq_eps!(7.389056098930649, crate::f64::FloatExt::exp(2.0f32), 1e-6);
239 assert_eq_eps!(
240 15.154261,
241 crate::f64::FloatExt::exp(core::f32::consts::E),
242 1e-6
243 );
244 }
245}