irox_tools/primitives/
f32.rs1use crate::{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 fn exp(self) -> Self::Type {
56 let mut out = 1.0;
57 let i = self;
58 let mut z = self;
59 let mut exp = 1.0;
60 let mut idx = 1;
61 let mut next = self;
62
63 while next.abs() > f32::EPSILON {
64 out += next;
65 idx += 1;
66 z *= i;
67 if z.is_infinite() {
68 break;
69 }
70 exp *= idx as Self::Type;
71 if exp.is_infinite() {
72 break;
73 }
74 next = z / exp;
75 if next.is_infinite() {
76 break;
77 }
78 }
79
80 out
81 }
82
83 fn ln(self) -> Self::Type {
86 let z = self as f64;
87 let iter = (z - 1.) / (z + 1.);
88 let mut out = 0.0f64;
89 let mut next = iter;
90 let mut base = iter;
91 let mut idx = 1u64;
92 while next.abs() > f64::EPSILON {
93 out += next;
94 idx += 2;
95 base *= iter * iter;
96 next = base / idx as f64;
97 }
98 (out * 2.0) as f32
99 }
100
101 fn powf(self, a: Self::Type) -> Self::Type {
104 let z = self;
105
106 (a * z.ln()).exp()
107 }
108
109 fn powi(self, val: i32) -> Self::Type {
111 let mut out = self;
112 let i = self;
113 for _ in 0..val.abs() {
114 out *= i;
115 }
116 out
117 }
118
119 fn sqrt(self) -> Self::Type {
120 self.powf(0.5)
121 }
122
123 fn to_bits(self) -> Self::Size {
124 f32::to_bits(self)
125 }
126
127 fn exponent(self) -> u16 {
128 ((self.to_bits() >> 23) & 0x0F) as u16
129 }
130
131 fn significand(self) -> Self::Size {
132 self.to_bits() & 0x7FFFFF
133 }
134}
135
136impl ToF64 for f32 {
137 fn to_f64(&self) -> f64 {
138 *self as f64
139 }
140}
141
142impl ToSigned for f32 {
143 type Output = f32;
144
145 fn to_signed(self) -> Self::Output {
146 self
147 }
148
149 fn negative_one() -> Self::Output {
150 -1.
151 }
152}
153
154#[cfg(all(test, not(feature = "std")))]
155mod tests {
156 #[test]
157 pub fn test_ln() {
158 assert_eq!(0.0, crate::f64::FloatExt::ln(1.0_f32));
159 assert_eq_eps!(1.0, crate::f64::FloatExt::ln(core::f32::consts::E), 1e-6);
160 assert_eq_eps!(4.6051702, crate::f64::FloatExt::ln(100f32), 1e-6);
161 assert_eq_eps!(
162 11.09033963004403,
163 crate::f64::FloatExt::ln(u16::MAX as f32),
164 1e-6
165 );
166 }
167
168 #[test]
169 pub fn test_exp() {
170 assert_eq_eps!(1.0, crate::f64::FloatExt::exp(0.0f32), 1e-6);
171 assert_eq_eps!(
172 core::f32::consts::E,
173 crate::f64::FloatExt::exp(1.0f32),
174 1e-6
175 );
176 assert_eq_eps!(7.389056098930649, crate::f64::FloatExt::exp(2.0f32), 1e-6);
177 assert_eq_eps!(
178 15.154261,
179 crate::f64::FloatExt::exp(core::f32::consts::E),
180 1e-6
181 );
182 }
183}