Skip to main content

deepcl_common/float/
relaxed.rs

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