cubecl_common/float/
relaxed.rs1use core::f32;
2use core::{
3 cmp::Ordering,
4 ops::{Div, DivAssign, Mul, MulAssign, Rem, RemAssign},
5};
6
7use bytemuck::{Pod, Zeroable};
8use derive_more::derive::{
9 Add, AddAssign, Display, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
10};
11use num_traits::{Num, NumCast, One, ToPrimitive, Zero};
12
13#[allow(non_camel_case_types)]
16#[repr(transparent)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[derive(
19 Clone,
20 Copy,
21 Default,
22 Zeroable,
23 Pod,
24 PartialEq,
25 PartialOrd,
26 Neg,
27 Add,
28 Sub,
29 Mul,
30 Div,
31 Rem,
32 AddAssign,
33 SubAssign,
34 MulAssign,
35 DivAssign,
36 RemAssign,
37 Debug,
38 Display,
39)]
40pub struct flex32(f32);
41
42impl flex32 {
43 pub const MIN_POSITIVE: Self = Self(half::f16::MIN_POSITIVE.to_f32_const());
45
46 pub const fn from_f32(val: f32) -> Self {
48 flex32(val)
49 }
50
51 pub const fn from_f64(val: f64) -> Self {
53 flex32(val as f32)
54 }
55
56 pub const fn to_f32(self) -> f32 {
58 self.0
59 }
60
61 pub const fn to_f64(self) -> f64 {
63 self.0 as f64
64 }
65
66 pub fn total_cmp(&self, other: &flex32) -> Ordering {
68 self.0.total_cmp(&other.0)
69 }
70
71 pub fn is_nan(&self) -> bool {
73 self.0.is_nan()
74 }
75
76 pub fn from_bits(bits: u32) -> Self {
78 Self(f32::from_bits(bits))
79 }
80
81 pub fn to_bits(&self) -> u32 {
83 self.0.to_bits()
84 }
85}
86
87impl Mul for flex32 {
88 type Output = flex32;
89
90 fn mul(self, rhs: Self) -> Self::Output {
91 flex32(self.0 * rhs.0)
92 }
93}
94
95impl Div for flex32 {
96 type Output = flex32;
97
98 fn div(self, rhs: Self) -> Self::Output {
99 flex32(self.0 / rhs.0)
100 }
101}
102
103impl Rem for flex32 {
104 type Output = flex32;
105
106 fn rem(self, rhs: Self) -> Self::Output {
107 flex32(self.0 % rhs.0)
108 }
109}
110
111impl MulAssign for flex32 {
112 fn mul_assign(&mut self, rhs: Self) {
113 self.0 *= rhs.0;
114 }
115}
116
117impl DivAssign for flex32 {
118 fn div_assign(&mut self, rhs: Self) {
119 self.0 /= rhs.0;
120 }
121}
122
123impl RemAssign for flex32 {
124 fn rem_assign(&mut self, rhs: Self) {
125 self.0 %= rhs.0;
126 }
127}
128
129impl From<f32> for flex32 {
130 fn from(value: f32) -> Self {
131 Self::from_f32(value)
132 }
133}
134
135impl From<flex32> for f32 {
136 fn from(val: flex32) -> Self {
137 val.to_f32()
138 }
139}
140
141impl ToPrimitive for flex32 {
142 fn to_i64(&self) -> Option<i64> {
143 Some((*self).to_f32() as i64)
144 }
145
146 fn to_u64(&self) -> Option<u64> {
147 Some((*self).to_f32() as u64)
148 }
149
150 fn to_f32(&self) -> Option<f32> {
151 Some((*self).to_f32())
152 }
153
154 fn to_f64(&self) -> Option<f64> {
155 Some((*self).to_f32() as f64)
156 }
157}
158
159impl NumCast for flex32 {
160 fn from<T: num_traits::ToPrimitive>(n: T) -> Option<Self> {
161 Some(flex32::from_f32(n.to_f32()?))
162 }
163}
164
165impl num_traits::Float for flex32 {
166 fn nan() -> Self {
167 flex32(f32::nan())
168 }
169
170 fn infinity() -> Self {
171 flex32(f32::infinity())
172 }
173
174 fn neg_infinity() -> Self {
175 flex32(f32::neg_infinity())
176 }
177
178 fn neg_zero() -> Self {
179 flex32(f32::neg_zero())
180 }
181
182 fn min_value() -> Self {
183 flex32(<f32 as num_traits::Float>::min_value())
184 }
185
186 fn min_positive_value() -> Self {
187 flex32(f32::min_positive_value())
188 }
189
190 fn max_value() -> Self {
191 flex32(<f32 as num_traits::Float>::max_value())
192 }
193
194 fn is_nan(self) -> bool {
195 self.0.is_nan()
196 }
197
198 fn is_infinite(self) -> bool {
199 self.0.is_infinite()
200 }
201
202 fn is_finite(self) -> bool {
203 self.0.is_finite()
204 }
205
206 fn is_normal(self) -> bool {
207 self.0.is_normal()
208 }
209
210 fn classify(self) -> core::num::FpCategory {
211 self.0.classify()
212 }
213
214 fn floor(self) -> Self {
215 flex32(self.0.floor())
216 }
217
218 fn ceil(self) -> Self {
219 flex32(self.0.ceil())
220 }
221
222 fn round(self) -> Self {
223 flex32(self.0.round())
224 }
225
226 fn trunc(self) -> Self {
227 flex32(self.0.trunc())
228 }
229
230 fn fract(self) -> Self {
231 flex32(self.0.fract())
232 }
233
234 fn abs(self) -> Self {
235 flex32(self.0.abs())
236 }
237
238 fn signum(self) -> Self {
239 flex32(self.0.signum())
240 }
241
242 fn is_sign_positive(self) -> bool {
243 self.0.is_sign_positive()
244 }
245
246 fn is_sign_negative(self) -> bool {
247 self.0.is_sign_negative()
248 }
249
250 fn mul_add(self, a: Self, b: Self) -> Self {
251 flex32(self.0.mul_add(a.0, b.0))
252 }
253
254 fn recip(self) -> Self {
255 flex32(self.0.recip())
256 }
257
258 fn powi(self, n: i32) -> Self {
259 flex32(self.0.powi(n))
260 }
261
262 fn powf(self, n: Self) -> Self {
263 flex32(self.0.powf(n.0))
264 }
265
266 fn sqrt(self) -> Self {
267 flex32(self.0.sqrt())
268 }
269
270 fn exp(self) -> Self {
271 flex32(self.0.exp())
272 }
273
274 fn exp2(self) -> Self {
275 flex32(self.0.exp2())
276 }
277
278 fn ln(self) -> Self {
279 flex32(self.0.ln())
280 }
281
282 fn log(self, base: Self) -> Self {
283 flex32(self.0.log(base.0))
284 }
285
286 fn log2(self) -> Self {
287 flex32(self.0.log2())
288 }
289
290 fn log10(self) -> Self {
291 flex32(self.0.log10())
292 }
293
294 fn max(self, other: Self) -> Self {
295 flex32(self.0.max(other.0))
296 }
297
298 fn min(self, other: Self) -> Self {
299 flex32(self.0.min(other.0))
300 }
301
302 fn abs_sub(self, other: Self) -> Self {
303 flex32((self.0 - other.0).abs())
304 }
305
306 fn cbrt(self) -> Self {
307 flex32(self.0.cbrt())
308 }
309
310 fn hypot(self, other: Self) -> Self {
311 flex32(self.0.hypot(other.0))
312 }
313
314 fn sin(self) -> Self {
315 flex32(self.0.sin())
316 }
317
318 fn cos(self) -> Self {
319 flex32(self.0.cos())
320 }
321
322 fn tan(self) -> Self {
323 flex32(self.0.tan())
324 }
325
326 fn asin(self) -> Self {
327 flex32(self.0.asin())
328 }
329
330 fn acos(self) -> Self {
331 flex32(self.0.acos())
332 }
333
334 fn atan(self) -> Self {
335 flex32(self.0.atan())
336 }
337
338 fn atan2(self, other: Self) -> Self {
339 flex32(self.0.atan2(other.0))
340 }
341
342 fn sin_cos(self) -> (Self, Self) {
343 let (a, b) = self.0.sin_cos();
344 (flex32(a), flex32(b))
345 }
346
347 fn exp_m1(self) -> Self {
348 flex32(self.0.exp_m1())
349 }
350
351 fn ln_1p(self) -> Self {
352 flex32(self.0.ln_1p())
353 }
354
355 fn sinh(self) -> Self {
356 flex32(self.0.sinh())
357 }
358
359 fn cosh(self) -> Self {
360 flex32(self.0.cosh())
361 }
362
363 fn tanh(self) -> Self {
364 flex32(self.0.tanh())
365 }
366
367 fn asinh(self) -> Self {
368 flex32(self.0.asinh())
369 }
370
371 fn acosh(self) -> Self {
372 flex32(self.0.acosh())
373 }
374
375 fn atanh(self) -> Self {
376 flex32(self.0.atanh())
377 }
378
379 fn integer_decode(self) -> (u64, i16, i8) {
380 self.0.integer_decode()
381 }
382
383 fn epsilon() -> Self {
384 Self::from_f32(half::f16::EPSILON.to_f32())
385 }
386}
387
388impl Num for flex32 {
389 type FromStrRadixErr = <f32 as Num>::FromStrRadixErr;
390
391 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
392 Ok(flex32(f32::from_str_radix(str, radix)?))
393 }
394}
395
396impl One for flex32 {
397 fn one() -> Self {
398 flex32(1.0)
399 }
400}
401
402impl Zero for flex32 {
403 fn zero() -> Self {
404 flex32(0.0)
405 }
406
407 fn is_zero(&self) -> bool {
408 self.0 == 0.0
409 }
410}