half/
num_traits.rs

1use crate::{bf16, f16};
2use core::cmp::Ordering;
3use core::{num::FpCategory, ops::Div};
4use num_traits::{
5    AsPrimitive, Bounded, FloatConst, FromPrimitive, Num, NumCast, One, ToPrimitive, Zero,
6};
7
8impl ToPrimitive for f16 {
9    #[inline]
10    fn to_i64(&self) -> Option<i64> {
11        Self::to_f32(*self).to_i64()
12    }
13    #[inline]
14    fn to_u64(&self) -> Option<u64> {
15        Self::to_f32(*self).to_u64()
16    }
17    #[inline]
18    fn to_i8(&self) -> Option<i8> {
19        Self::to_f32(*self).to_i8()
20    }
21    #[inline]
22    fn to_u8(&self) -> Option<u8> {
23        Self::to_f32(*self).to_u8()
24    }
25    #[inline]
26    fn to_i16(&self) -> Option<i16> {
27        Self::to_f32(*self).to_i16()
28    }
29    #[inline]
30    fn to_u16(&self) -> Option<u16> {
31        Self::to_f32(*self).to_u16()
32    }
33    #[inline]
34    fn to_i32(&self) -> Option<i32> {
35        Self::to_f32(*self).to_i32()
36    }
37    #[inline]
38    fn to_u32(&self) -> Option<u32> {
39        Self::to_f32(*self).to_u32()
40    }
41    #[inline]
42    fn to_f32(&self) -> Option<f32> {
43        Some(Self::to_f32(*self))
44    }
45    #[inline]
46    fn to_f64(&self) -> Option<f64> {
47        Some(Self::to_f64(*self))
48    }
49}
50
51impl FromPrimitive for f16 {
52    #[inline]
53    fn from_i64(n: i64) -> Option<Self> {
54        n.to_f32().map(Self::from_f32)
55    }
56    #[inline]
57    fn from_u64(n: u64) -> Option<Self> {
58        n.to_f32().map(Self::from_f32)
59    }
60    #[inline]
61    fn from_i8(n: i8) -> Option<Self> {
62        n.to_f32().map(Self::from_f32)
63    }
64    #[inline]
65    fn from_u8(n: u8) -> Option<Self> {
66        n.to_f32().map(Self::from_f32)
67    }
68    #[inline]
69    fn from_i16(n: i16) -> Option<Self> {
70        n.to_f32().map(Self::from_f32)
71    }
72    #[inline]
73    fn from_u16(n: u16) -> Option<Self> {
74        n.to_f32().map(Self::from_f32)
75    }
76    #[inline]
77    fn from_i32(n: i32) -> Option<Self> {
78        n.to_f32().map(Self::from_f32)
79    }
80    #[inline]
81    fn from_u32(n: u32) -> Option<Self> {
82        n.to_f32().map(Self::from_f32)
83    }
84    #[inline]
85    fn from_f32(n: f32) -> Option<Self> {
86        n.to_f32().map(Self::from_f32)
87    }
88    #[inline]
89    fn from_f64(n: f64) -> Option<Self> {
90        n.to_f64().map(Self::from_f64)
91    }
92}
93
94impl Num for f16 {
95    type FromStrRadixErr = <f32 as Num>::FromStrRadixErr;
96
97    #[inline]
98    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
99        Ok(Self::from_f32(f32::from_str_radix(str, radix)?))
100    }
101}
102
103impl One for f16 {
104    #[inline]
105    fn one() -> Self {
106        Self::ONE
107    }
108}
109
110impl Zero for f16 {
111    #[inline]
112    fn zero() -> Self {
113        Self::ZERO
114    }
115
116    #[inline]
117    fn is_zero(&self) -> bool {
118        *self == Self::ZERO
119    }
120}
121
122impl NumCast for f16 {
123    #[inline]
124    fn from<T: ToPrimitive>(n: T) -> Option<Self> {
125        n.to_f32().map(Self::from_f32)
126    }
127}
128
129impl num_traits::float::FloatCore for f16 {
130    #[inline]
131    fn infinity() -> Self {
132        Self::INFINITY
133    }
134
135    #[inline]
136    fn neg_infinity() -> Self {
137        Self::NEG_INFINITY
138    }
139
140    #[inline]
141    fn nan() -> Self {
142        Self::NAN
143    }
144
145    #[inline]
146    fn neg_zero() -> Self {
147        Self::NEG_ZERO
148    }
149
150    #[inline]
151    fn min_value() -> Self {
152        Self::MIN
153    }
154
155    #[inline]
156    fn min_positive_value() -> Self {
157        Self::MIN_POSITIVE
158    }
159
160    #[inline]
161    fn epsilon() -> Self {
162        Self::EPSILON
163    }
164
165    #[inline]
166    fn max_value() -> Self {
167        Self::MAX
168    }
169
170    #[inline]
171    fn is_nan(self) -> bool {
172        self.is_nan()
173    }
174
175    #[inline]
176    fn is_infinite(self) -> bool {
177        self.is_infinite()
178    }
179
180    #[inline]
181    fn is_finite(self) -> bool {
182        self.is_finite()
183    }
184
185    #[inline]
186    fn is_normal(self) -> bool {
187        self.is_normal()
188    }
189
190    #[inline]
191    fn classify(self) -> FpCategory {
192        self.classify()
193    }
194
195    #[inline]
196    fn floor(self) -> Self {
197        Self::from_f32(self.to_f32().floor())
198    }
199
200    #[inline]
201    fn ceil(self) -> Self {
202        Self::from_f32(self.to_f32().ceil())
203    }
204
205    #[inline]
206    fn round(self) -> Self {
207        Self::from_f32(self.to_f32().round())
208    }
209
210    #[inline]
211    fn trunc(self) -> Self {
212        Self::from_f32(self.to_f32().trunc())
213    }
214
215    #[inline]
216    fn fract(self) -> Self {
217        Self::from_f32(self.to_f32().fract())
218    }
219
220    #[inline]
221    fn abs(self) -> Self {
222        Self::from_bits(self.to_bits() & 0x7FFF)
223    }
224
225    #[inline]
226    fn signum(self) -> Self {
227        self.signum()
228    }
229
230    #[inline]
231    fn is_sign_positive(self) -> bool {
232        self.is_sign_positive()
233    }
234
235    #[inline]
236    fn is_sign_negative(self) -> bool {
237        self.is_sign_negative()
238    }
239
240    fn min(self, other: Self) -> Self {
241        match self.partial_cmp(&other) {
242            None => {
243                if self.is_nan() {
244                    other
245                } else {
246                    self
247                }
248            }
249            Some(Ordering::Greater) | Some(Ordering::Equal) => other,
250            Some(Ordering::Less) => self,
251        }
252    }
253
254    fn max(self, other: Self) -> Self {
255        match self.partial_cmp(&other) {
256            None => {
257                if self.is_nan() {
258                    other
259                } else {
260                    self
261                }
262            }
263            Some(Ordering::Greater) | Some(Ordering::Equal) => self,
264            Some(Ordering::Less) => other,
265        }
266    }
267
268    #[inline]
269    fn recip(self) -> Self {
270        Self::from_f32(self.to_f32().recip())
271    }
272
273    #[inline]
274    fn powi(self, exp: i32) -> Self {
275        Self::from_f32(self.to_f32().powi(exp))
276    }
277
278    #[inline]
279    fn to_degrees(self) -> Self {
280        Self::from_f32(self.to_f32().to_degrees())
281    }
282
283    #[inline]
284    fn to_radians(self) -> Self {
285        Self::from_f32(self.to_f32().to_radians())
286    }
287
288    #[inline]
289    fn integer_decode(self) -> (u64, i16, i8) {
290        num_traits::float::FloatCore::integer_decode(self.to_f32())
291    }
292}
293
294impl num_traits::float::Float for f16 {
295    #[inline]
296    fn nan() -> Self {
297        Self::NAN
298    }
299
300    #[inline]
301    fn infinity() -> Self {
302        Self::INFINITY
303    }
304
305    #[inline]
306    fn neg_infinity() -> Self {
307        Self::NEG_INFINITY
308    }
309
310    #[inline]
311    fn neg_zero() -> Self {
312        Self::NEG_ZERO
313    }
314
315    #[inline]
316    fn min_value() -> Self {
317        Self::MIN
318    }
319
320    #[inline]
321    fn min_positive_value() -> Self {
322        Self::MIN_POSITIVE
323    }
324
325    #[inline]
326    fn epsilon() -> Self {
327        Self::EPSILON
328    }
329
330    #[inline]
331    fn max_value() -> Self {
332        Self::MAX
333    }
334
335    #[inline]
336    fn is_nan(self) -> bool {
337        self.is_nan()
338    }
339
340    #[inline]
341    fn is_infinite(self) -> bool {
342        self.is_infinite()
343    }
344
345    #[inline]
346    fn is_finite(self) -> bool {
347        self.is_finite()
348    }
349
350    #[inline]
351    fn is_normal(self) -> bool {
352        self.is_normal()
353    }
354
355    #[inline]
356    fn classify(self) -> FpCategory {
357        self.classify()
358    }
359
360    #[inline]
361    fn floor(self) -> Self {
362        Self::from_f32(self.to_f32().floor())
363    }
364
365    #[inline]
366    fn ceil(self) -> Self {
367        Self::from_f32(self.to_f32().ceil())
368    }
369
370    #[inline]
371    fn round(self) -> Self {
372        Self::from_f32(self.to_f32().round())
373    }
374
375    #[inline]
376    fn trunc(self) -> Self {
377        Self::from_f32(self.to_f32().trunc())
378    }
379
380    #[inline]
381    fn fract(self) -> Self {
382        Self::from_f32(self.to_f32().fract())
383    }
384
385    #[inline]
386    fn abs(self) -> Self {
387        Self::from_f32(self.to_f32().abs())
388    }
389
390    #[inline]
391    fn signum(self) -> Self {
392        Self::from_f32(self.to_f32().signum())
393    }
394
395    #[inline]
396    fn is_sign_positive(self) -> bool {
397        self.is_sign_positive()
398    }
399
400    #[inline]
401    fn is_sign_negative(self) -> bool {
402        self.is_sign_negative()
403    }
404
405    #[inline]
406    fn mul_add(self, a: Self, b: Self) -> Self {
407        Self::from_f32(self.to_f32().mul_add(a.to_f32(), b.to_f32()))
408    }
409
410    #[inline]
411    fn recip(self) -> Self {
412        Self::from_f32(self.to_f32().recip())
413    }
414
415    #[inline]
416    fn powi(self, n: i32) -> Self {
417        Self::from_f32(self.to_f32().powi(n))
418    }
419
420    #[inline]
421    fn powf(self, n: Self) -> Self {
422        Self::from_f32(self.to_f32().powf(n.to_f32()))
423    }
424
425    #[inline]
426    fn sqrt(self) -> Self {
427        Self::from_f32(self.to_f32().sqrt())
428    }
429
430    #[inline]
431    fn exp(self) -> Self {
432        Self::from_f32(self.to_f32().exp())
433    }
434
435    #[inline]
436    fn exp2(self) -> Self {
437        Self::from_f32(self.to_f32().exp2())
438    }
439
440    #[inline]
441    fn ln(self) -> Self {
442        Self::from_f32(self.to_f32().ln())
443    }
444
445    #[inline]
446    fn log(self, base: Self) -> Self {
447        Self::from_f32(self.to_f32().log(base.to_f32()))
448    }
449
450    #[inline]
451    fn log2(self) -> Self {
452        Self::from_f32(self.to_f32().log2())
453    }
454
455    #[inline]
456    fn log10(self) -> Self {
457        Self::from_f32(self.to_f32().log10())
458    }
459
460    #[inline]
461    fn to_degrees(self) -> Self {
462        Self::from_f32(self.to_f32().to_degrees())
463    }
464
465    #[inline]
466    fn to_radians(self) -> Self {
467        Self::from_f32(self.to_f32().to_radians())
468    }
469
470    #[inline]
471    fn max(self, other: Self) -> Self {
472        self.max(other)
473    }
474
475    #[inline]
476    fn min(self, other: Self) -> Self {
477        self.min(other)
478    }
479
480    #[inline]
481    fn abs_sub(self, other: Self) -> Self {
482        Self::from_f32((self.to_f32() - other.to_f32()).max(0.0))
483    }
484
485    #[inline]
486    fn cbrt(self) -> Self {
487        Self::from_f32(self.to_f32().cbrt())
488    }
489
490    #[inline]
491    fn hypot(self, other: Self) -> Self {
492        Self::from_f32(self.to_f32().hypot(other.to_f32()))
493    }
494
495    #[inline]
496    fn sin(self) -> Self {
497        Self::from_f32(self.to_f32().sin())
498    }
499
500    #[inline]
501    fn cos(self) -> Self {
502        Self::from_f32(self.to_f32().cos())
503    }
504
505    #[inline]
506    fn tan(self) -> Self {
507        Self::from_f32(self.to_f32().tan())
508    }
509
510    #[inline]
511    fn asin(self) -> Self {
512        Self::from_f32(self.to_f32().asin())
513    }
514
515    #[inline]
516    fn acos(self) -> Self {
517        Self::from_f32(self.to_f32().acos())
518    }
519
520    #[inline]
521    fn atan(self) -> Self {
522        Self::from_f32(self.to_f32().atan())
523    }
524
525    #[inline]
526    fn atan2(self, other: Self) -> Self {
527        Self::from_f32(self.to_f32().atan2(other.to_f32()))
528    }
529
530    #[inline]
531    fn sin_cos(self) -> (Self, Self) {
532        let (sin, cos) = self.to_f32().sin_cos();
533        (Self::from_f32(sin), Self::from_f32(cos))
534    }
535
536    #[inline]
537    fn exp_m1(self) -> Self {
538        Self::from_f32(self.to_f32().exp_m1())
539    }
540
541    #[inline]
542    fn ln_1p(self) -> Self {
543        Self::from_f32(self.to_f32().ln_1p())
544    }
545
546    #[inline]
547    fn sinh(self) -> Self {
548        Self::from_f32(self.to_f32().sinh())
549    }
550
551    #[inline]
552    fn cosh(self) -> Self {
553        Self::from_f32(self.to_f32().cosh())
554    }
555
556    #[inline]
557    fn tanh(self) -> Self {
558        Self::from_f32(self.to_f32().tanh())
559    }
560
561    #[inline]
562    fn asinh(self) -> Self {
563        Self::from_f32(self.to_f32().asinh())
564    }
565
566    #[inline]
567    fn acosh(self) -> Self {
568        Self::from_f32(self.to_f32().acosh())
569    }
570
571    #[inline]
572    fn atanh(self) -> Self {
573        Self::from_f32(self.to_f32().atanh())
574    }
575
576    #[inline]
577    fn integer_decode(self) -> (u64, i16, i8) {
578        num_traits::float::Float::integer_decode(self.to_f32())
579    }
580}
581
582impl FloatConst for f16 {
583    #[inline]
584    fn E() -> Self {
585        Self::E
586    }
587
588    #[inline]
589    fn FRAC_1_PI() -> Self {
590        Self::FRAC_1_PI
591    }
592
593    #[inline]
594    fn FRAC_1_SQRT_2() -> Self {
595        Self::FRAC_1_SQRT_2
596    }
597
598    #[inline]
599    fn FRAC_2_PI() -> Self {
600        Self::FRAC_2_PI
601    }
602
603    #[inline]
604    fn FRAC_2_SQRT_PI() -> Self {
605        Self::FRAC_2_SQRT_PI
606    }
607
608    #[inline]
609    fn FRAC_PI_2() -> Self {
610        Self::FRAC_PI_2
611    }
612
613    #[inline]
614    fn FRAC_PI_3() -> Self {
615        Self::FRAC_PI_3
616    }
617
618    #[inline]
619    fn FRAC_PI_4() -> Self {
620        Self::FRAC_PI_4
621    }
622
623    #[inline]
624    fn FRAC_PI_6() -> Self {
625        Self::FRAC_PI_6
626    }
627
628    #[inline]
629    fn FRAC_PI_8() -> Self {
630        Self::FRAC_PI_8
631    }
632
633    #[inline]
634    fn LN_10() -> Self {
635        Self::LN_10
636    }
637
638    #[inline]
639    fn LN_2() -> Self {
640        Self::LN_2
641    }
642
643    #[inline]
644    fn LOG10_E() -> Self {
645        Self::LOG10_E
646    }
647
648    #[inline]
649    fn LOG2_E() -> Self {
650        Self::LOG2_E
651    }
652
653    #[inline]
654    fn PI() -> Self {
655        Self::PI
656    }
657
658    fn SQRT_2() -> Self {
659        Self::SQRT_2
660    }
661
662    #[inline]
663    fn LOG10_2() -> Self
664    where
665        Self: Sized + Div<Self, Output = Self>,
666    {
667        Self::LOG10_2
668    }
669
670    #[inline]
671    fn LOG2_10() -> Self
672    where
673        Self: Sized + Div<Self, Output = Self>,
674    {
675        Self::LOG2_10
676    }
677}
678
679impl Bounded for f16 {
680    #[inline]
681    fn min_value() -> Self {
682        f16::MIN
683    }
684
685    #[inline]
686    fn max_value() -> Self {
687        f16::MAX
688    }
689}
690
691macro_rules! impl_as_primitive_to_f16 {
692    ($ty:ty, $meth:ident) => {
693        impl AsPrimitive<$ty> for f16 {
694            #[inline]
695            fn as_(self) -> $ty {
696                self.$meth().as_()
697            }
698        }
699    };
700}
701
702impl AsPrimitive<f16> for f16 {
703    #[inline]
704    fn as_(self) -> f16 {
705        self
706    }
707}
708
709impl_as_primitive_to_f16!(i64, to_f32);
710impl_as_primitive_to_f16!(u64, to_f32);
711impl_as_primitive_to_f16!(i8, to_f32);
712impl_as_primitive_to_f16!(u8, to_f32);
713impl_as_primitive_to_f16!(i16, to_f32);
714impl_as_primitive_to_f16!(u16, to_f32);
715impl_as_primitive_to_f16!(i32, to_f32);
716impl_as_primitive_to_f16!(u32, to_f32);
717impl_as_primitive_to_f16!(isize, to_f32);
718impl_as_primitive_to_f16!(usize, to_f32);
719impl_as_primitive_to_f16!(f32, to_f32);
720impl_as_primitive_to_f16!(f64, to_f64);
721impl_as_primitive_to_f16!(bf16, to_f32);
722
723macro_rules! impl_as_primitive_f16_from {
724    ($ty:ty, $meth:ident) => {
725        impl AsPrimitive<f16> for $ty {
726            #[inline]
727            fn as_(self) -> f16 {
728                f16::$meth(self.as_())
729            }
730        }
731    };
732}
733
734impl_as_primitive_f16_from!(i64, from_f32);
735impl_as_primitive_f16_from!(u64, from_f32);
736impl_as_primitive_f16_from!(i8, from_f32);
737impl_as_primitive_f16_from!(u8, from_f32);
738impl_as_primitive_f16_from!(i16, from_f32);
739impl_as_primitive_f16_from!(u16, from_f32);
740impl_as_primitive_f16_from!(i32, from_f32);
741impl_as_primitive_f16_from!(u32, from_f32);
742impl_as_primitive_f16_from!(isize, from_f32);
743impl_as_primitive_f16_from!(usize, from_f32);
744impl_as_primitive_f16_from!(f32, from_f32);
745impl_as_primitive_f16_from!(f64, from_f64);
746
747impl ToPrimitive for bf16 {
748    #[inline]
749    fn to_i64(&self) -> Option<i64> {
750        Self::to_f32(*self).to_i64()
751    }
752    #[inline]
753    fn to_u64(&self) -> Option<u64> {
754        Self::to_f32(*self).to_u64()
755    }
756    #[inline]
757    fn to_i8(&self) -> Option<i8> {
758        Self::to_f32(*self).to_i8()
759    }
760    #[inline]
761    fn to_u8(&self) -> Option<u8> {
762        Self::to_f32(*self).to_u8()
763    }
764    #[inline]
765    fn to_i16(&self) -> Option<i16> {
766        Self::to_f32(*self).to_i16()
767    }
768    #[inline]
769    fn to_u16(&self) -> Option<u16> {
770        Self::to_f32(*self).to_u16()
771    }
772    #[inline]
773    fn to_i32(&self) -> Option<i32> {
774        Self::to_f32(*self).to_i32()
775    }
776    #[inline]
777    fn to_u32(&self) -> Option<u32> {
778        Self::to_f32(*self).to_u32()
779    }
780    #[inline]
781    fn to_f32(&self) -> Option<f32> {
782        Some(Self::to_f32(*self))
783    }
784    #[inline]
785    fn to_f64(&self) -> Option<f64> {
786        Some(Self::to_f64(*self))
787    }
788}
789
790impl FromPrimitive for bf16 {
791    #[inline]
792    fn from_i64(n: i64) -> Option<Self> {
793        n.to_f32().map(Self::from_f32)
794    }
795    #[inline]
796    fn from_u64(n: u64) -> Option<Self> {
797        n.to_f32().map(Self::from_f32)
798    }
799    #[inline]
800    fn from_i8(n: i8) -> Option<Self> {
801        n.to_f32().map(Self::from_f32)
802    }
803    #[inline]
804    fn from_u8(n: u8) -> Option<Self> {
805        n.to_f32().map(Self::from_f32)
806    }
807    #[inline]
808    fn from_i16(n: i16) -> Option<Self> {
809        n.to_f32().map(Self::from_f32)
810    }
811    #[inline]
812    fn from_u16(n: u16) -> Option<Self> {
813        n.to_f32().map(Self::from_f32)
814    }
815    #[inline]
816    fn from_i32(n: i32) -> Option<Self> {
817        n.to_f32().map(Self::from_f32)
818    }
819    #[inline]
820    fn from_u32(n: u32) -> Option<Self> {
821        n.to_f32().map(Self::from_f32)
822    }
823    #[inline]
824    fn from_f32(n: f32) -> Option<Self> {
825        n.to_f32().map(Self::from_f32)
826    }
827    #[inline]
828    fn from_f64(n: f64) -> Option<Self> {
829        n.to_f64().map(Self::from_f64)
830    }
831}
832
833impl Num for bf16 {
834    type FromStrRadixErr = <f32 as Num>::FromStrRadixErr;
835
836    #[inline]
837    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
838        Ok(Self::from_f32(f32::from_str_radix(str, radix)?))
839    }
840}
841
842impl One for bf16 {
843    #[inline]
844    fn one() -> Self {
845        Self::ONE
846    }
847}
848
849impl Zero for bf16 {
850    #[inline]
851    fn zero() -> Self {
852        Self::ZERO
853    }
854
855    #[inline]
856    fn is_zero(&self) -> bool {
857        *self == Self::ZERO
858    }
859}
860
861impl NumCast for bf16 {
862    #[inline]
863    fn from<T: ToPrimitive>(n: T) -> Option<Self> {
864        n.to_f32().map(Self::from_f32)
865    }
866}
867
868impl num_traits::float::FloatCore for bf16 {
869    #[inline]
870    fn infinity() -> Self {
871        Self::INFINITY
872    }
873
874    #[inline]
875    fn neg_infinity() -> Self {
876        Self::NEG_INFINITY
877    }
878
879    #[inline]
880    fn nan() -> Self {
881        Self::NAN
882    }
883
884    #[inline]
885    fn neg_zero() -> Self {
886        Self::NEG_ZERO
887    }
888
889    #[inline]
890    fn min_value() -> Self {
891        Self::MIN
892    }
893
894    #[inline]
895    fn min_positive_value() -> Self {
896        Self::MIN_POSITIVE
897    }
898
899    #[inline]
900    fn epsilon() -> Self {
901        Self::EPSILON
902    }
903
904    #[inline]
905    fn max_value() -> Self {
906        Self::MAX
907    }
908
909    #[inline]
910    fn is_nan(self) -> bool {
911        self.is_nan()
912    }
913
914    #[inline]
915    fn is_infinite(self) -> bool {
916        self.is_infinite()
917    }
918
919    #[inline]
920    fn is_finite(self) -> bool {
921        self.is_finite()
922    }
923
924    #[inline]
925    fn is_normal(self) -> bool {
926        self.is_normal()
927    }
928
929    #[inline]
930    fn classify(self) -> FpCategory {
931        self.classify()
932    }
933
934    #[inline]
935    fn floor(self) -> Self {
936        Self::from_f32(self.to_f32().floor())
937    }
938
939    #[inline]
940    fn ceil(self) -> Self {
941        Self::from_f32(self.to_f32().ceil())
942    }
943
944    #[inline]
945    fn round(self) -> Self {
946        Self::from_f32(self.to_f32().round())
947    }
948
949    #[inline]
950    fn trunc(self) -> Self {
951        Self::from_f32(self.to_f32().trunc())
952    }
953
954    #[inline]
955    fn fract(self) -> Self {
956        Self::from_f32(self.to_f32().fract())
957    }
958
959    #[inline]
960    fn abs(self) -> Self {
961        Self::from_bits(self.to_bits() & 0x7FFF)
962    }
963
964    #[inline]
965    fn signum(self) -> Self {
966        self.signum()
967    }
968
969    #[inline]
970    fn is_sign_positive(self) -> bool {
971        self.is_sign_positive()
972    }
973
974    #[inline]
975    fn is_sign_negative(self) -> bool {
976        self.is_sign_negative()
977    }
978
979    fn min(self, other: Self) -> Self {
980        match self.partial_cmp(&other) {
981            None => {
982                if self.is_nan() {
983                    other
984                } else {
985                    self
986                }
987            }
988            Some(Ordering::Greater) | Some(Ordering::Equal) => other,
989            Some(Ordering::Less) => self,
990        }
991    }
992
993    fn max(self, other: Self) -> Self {
994        match self.partial_cmp(&other) {
995            None => {
996                if self.is_nan() {
997                    other
998                } else {
999                    self
1000                }
1001            }
1002            Some(Ordering::Greater) | Some(Ordering::Equal) => self,
1003            Some(Ordering::Less) => other,
1004        }
1005    }
1006
1007    #[inline]
1008    fn recip(self) -> Self {
1009        Self::from_f32(self.to_f32().recip())
1010    }
1011
1012    #[inline]
1013    fn powi(self, exp: i32) -> Self {
1014        Self::from_f32(self.to_f32().powi(exp))
1015    }
1016
1017    #[inline]
1018    fn to_degrees(self) -> Self {
1019        Self::from_f32(self.to_f32().to_degrees())
1020    }
1021
1022    #[inline]
1023    fn to_radians(self) -> Self {
1024        Self::from_f32(self.to_f32().to_radians())
1025    }
1026
1027    #[inline]
1028    fn integer_decode(self) -> (u64, i16, i8) {
1029        num_traits::float::FloatCore::integer_decode(self.to_f32())
1030    }
1031}
1032
1033impl num_traits::float::Float for bf16 {
1034    #[inline]
1035    fn nan() -> Self {
1036        Self::NAN
1037    }
1038
1039    #[inline]
1040    fn infinity() -> Self {
1041        Self::INFINITY
1042    }
1043
1044    #[inline]
1045    fn neg_infinity() -> Self {
1046        Self::NEG_INFINITY
1047    }
1048
1049    #[inline]
1050    fn neg_zero() -> Self {
1051        Self::NEG_ZERO
1052    }
1053
1054    #[inline]
1055    fn min_value() -> Self {
1056        Self::MIN
1057    }
1058
1059    #[inline]
1060    fn min_positive_value() -> Self {
1061        Self::MIN_POSITIVE
1062    }
1063
1064    #[inline]
1065    fn epsilon() -> Self {
1066        Self::EPSILON
1067    }
1068
1069    #[inline]
1070    fn max_value() -> Self {
1071        Self::MAX
1072    }
1073
1074    #[inline]
1075    fn is_nan(self) -> bool {
1076        self.is_nan()
1077    }
1078
1079    #[inline]
1080    fn is_infinite(self) -> bool {
1081        self.is_infinite()
1082    }
1083
1084    #[inline]
1085    fn is_finite(self) -> bool {
1086        self.is_finite()
1087    }
1088
1089    #[inline]
1090    fn is_normal(self) -> bool {
1091        self.is_normal()
1092    }
1093
1094    #[inline]
1095    fn classify(self) -> FpCategory {
1096        self.classify()
1097    }
1098
1099    #[inline]
1100    fn floor(self) -> Self {
1101        Self::from_f32(self.to_f32().floor())
1102    }
1103
1104    #[inline]
1105    fn ceil(self) -> Self {
1106        Self::from_f32(self.to_f32().ceil())
1107    }
1108
1109    #[inline]
1110    fn round(self) -> Self {
1111        Self::from_f32(self.to_f32().round())
1112    }
1113
1114    #[inline]
1115    fn trunc(self) -> Self {
1116        Self::from_f32(self.to_f32().trunc())
1117    }
1118
1119    #[inline]
1120    fn fract(self) -> Self {
1121        Self::from_f32(self.to_f32().fract())
1122    }
1123
1124    #[inline]
1125    fn abs(self) -> Self {
1126        Self::from_f32(self.to_f32().abs())
1127    }
1128
1129    #[inline]
1130    fn signum(self) -> Self {
1131        Self::from_f32(self.to_f32().signum())
1132    }
1133
1134    #[inline]
1135    fn is_sign_positive(self) -> bool {
1136        self.is_sign_positive()
1137    }
1138
1139    #[inline]
1140    fn is_sign_negative(self) -> bool {
1141        self.is_sign_negative()
1142    }
1143
1144    #[inline]
1145    fn mul_add(self, a: Self, b: Self) -> Self {
1146        Self::from_f32(self.to_f32().mul_add(a.to_f32(), b.to_f32()))
1147    }
1148
1149    #[inline]
1150    fn recip(self) -> Self {
1151        Self::from_f32(self.to_f32().recip())
1152    }
1153
1154    #[inline]
1155    fn powi(self, n: i32) -> Self {
1156        Self::from_f32(self.to_f32().powi(n))
1157    }
1158
1159    #[inline]
1160    fn powf(self, n: Self) -> Self {
1161        Self::from_f32(self.to_f32().powf(n.to_f32()))
1162    }
1163
1164    #[inline]
1165    fn sqrt(self) -> Self {
1166        Self::from_f32(self.to_f32().sqrt())
1167    }
1168
1169    #[inline]
1170    fn exp(self) -> Self {
1171        Self::from_f32(self.to_f32().exp())
1172    }
1173
1174    #[inline]
1175    fn exp2(self) -> Self {
1176        Self::from_f32(self.to_f32().exp2())
1177    }
1178
1179    #[inline]
1180    fn ln(self) -> Self {
1181        Self::from_f32(self.to_f32().ln())
1182    }
1183
1184    #[inline]
1185    fn log(self, base: Self) -> Self {
1186        Self::from_f32(self.to_f32().log(base.to_f32()))
1187    }
1188
1189    #[inline]
1190    fn log2(self) -> Self {
1191        Self::from_f32(self.to_f32().log2())
1192    }
1193
1194    #[inline]
1195    fn log10(self) -> Self {
1196        Self::from_f32(self.to_f32().log10())
1197    }
1198
1199    #[inline]
1200    fn to_degrees(self) -> Self {
1201        Self::from_f32(self.to_f32().to_degrees())
1202    }
1203
1204    #[inline]
1205    fn to_radians(self) -> Self {
1206        Self::from_f32(self.to_f32().to_radians())
1207    }
1208
1209    #[inline]
1210    fn max(self, other: Self) -> Self {
1211        self.max(other)
1212    }
1213
1214    #[inline]
1215    fn min(self, other: Self) -> Self {
1216        self.min(other)
1217    }
1218
1219    #[inline]
1220    fn abs_sub(self, other: Self) -> Self {
1221        Self::from_f32((self.to_f32() - other.to_f32()).max(0.0))
1222    }
1223
1224    #[inline]
1225    fn cbrt(self) -> Self {
1226        Self::from_f32(self.to_f32().cbrt())
1227    }
1228
1229    #[inline]
1230    fn hypot(self, other: Self) -> Self {
1231        Self::from_f32(self.to_f32().hypot(other.to_f32()))
1232    }
1233
1234    #[inline]
1235    fn sin(self) -> Self {
1236        Self::from_f32(self.to_f32().sin())
1237    }
1238
1239    #[inline]
1240    fn cos(self) -> Self {
1241        Self::from_f32(self.to_f32().cos())
1242    }
1243
1244    #[inline]
1245    fn tan(self) -> Self {
1246        Self::from_f32(self.to_f32().tan())
1247    }
1248
1249    #[inline]
1250    fn asin(self) -> Self {
1251        Self::from_f32(self.to_f32().asin())
1252    }
1253
1254    #[inline]
1255    fn acos(self) -> Self {
1256        Self::from_f32(self.to_f32().acos())
1257    }
1258
1259    #[inline]
1260    fn atan(self) -> Self {
1261        Self::from_f32(self.to_f32().atan())
1262    }
1263
1264    #[inline]
1265    fn atan2(self, other: Self) -> Self {
1266        Self::from_f32(self.to_f32().atan2(other.to_f32()))
1267    }
1268
1269    #[inline]
1270    fn sin_cos(self) -> (Self, Self) {
1271        let (sin, cos) = self.to_f32().sin_cos();
1272        (Self::from_f32(sin), Self::from_f32(cos))
1273    }
1274
1275    #[inline]
1276    fn exp_m1(self) -> Self {
1277        Self::from_f32(self.to_f32().exp_m1())
1278    }
1279
1280    #[inline]
1281    fn ln_1p(self) -> Self {
1282        Self::from_f32(self.to_f32().ln_1p())
1283    }
1284
1285    #[inline]
1286    fn sinh(self) -> Self {
1287        Self::from_f32(self.to_f32().sinh())
1288    }
1289
1290    #[inline]
1291    fn cosh(self) -> Self {
1292        Self::from_f32(self.to_f32().cosh())
1293    }
1294
1295    #[inline]
1296    fn tanh(self) -> Self {
1297        Self::from_f32(self.to_f32().tanh())
1298    }
1299
1300    #[inline]
1301    fn asinh(self) -> Self {
1302        Self::from_f32(self.to_f32().asinh())
1303    }
1304
1305    #[inline]
1306    fn acosh(self) -> Self {
1307        Self::from_f32(self.to_f32().acosh())
1308    }
1309
1310    #[inline]
1311    fn atanh(self) -> Self {
1312        Self::from_f32(self.to_f32().atanh())
1313    }
1314
1315    #[inline]
1316    fn integer_decode(self) -> (u64, i16, i8) {
1317        num_traits::float::Float::integer_decode(self.to_f32())
1318    }
1319}
1320
1321impl FloatConst for bf16 {
1322    #[inline]
1323    fn E() -> Self {
1324        Self::E
1325    }
1326
1327    #[inline]
1328    fn FRAC_1_PI() -> Self {
1329        Self::FRAC_1_PI
1330    }
1331
1332    #[inline]
1333    fn FRAC_1_SQRT_2() -> Self {
1334        Self::FRAC_1_SQRT_2
1335    }
1336
1337    #[inline]
1338    fn FRAC_2_PI() -> Self {
1339        Self::FRAC_2_PI
1340    }
1341
1342    #[inline]
1343    fn FRAC_2_SQRT_PI() -> Self {
1344        Self::FRAC_2_SQRT_PI
1345    }
1346
1347    #[inline]
1348    fn FRAC_PI_2() -> Self {
1349        Self::FRAC_PI_2
1350    }
1351
1352    #[inline]
1353    fn FRAC_PI_3() -> Self {
1354        Self::FRAC_PI_3
1355    }
1356
1357    #[inline]
1358    fn FRAC_PI_4() -> Self {
1359        Self::FRAC_PI_4
1360    }
1361
1362    #[inline]
1363    fn FRAC_PI_6() -> Self {
1364        Self::FRAC_PI_6
1365    }
1366
1367    #[inline]
1368    fn FRAC_PI_8() -> Self {
1369        Self::FRAC_PI_8
1370    }
1371
1372    #[inline]
1373    fn LN_10() -> Self {
1374        Self::LN_10
1375    }
1376
1377    #[inline]
1378    fn LN_2() -> Self {
1379        Self::LN_2
1380    }
1381
1382    #[inline]
1383    fn LOG10_E() -> Self {
1384        Self::LOG10_E
1385    }
1386
1387    #[inline]
1388    fn LOG2_E() -> Self {
1389        Self::LOG2_E
1390    }
1391
1392    #[inline]
1393    fn PI() -> Self {
1394        Self::PI
1395    }
1396
1397    #[inline]
1398    fn SQRT_2() -> Self {
1399        Self::SQRT_2
1400    }
1401
1402    #[inline]
1403    fn LOG10_2() -> Self
1404    where
1405        Self: Sized + Div<Self, Output = Self>,
1406    {
1407        Self::LOG10_2
1408    }
1409
1410    #[inline]
1411    fn LOG2_10() -> Self
1412    where
1413        Self: Sized + Div<Self, Output = Self>,
1414    {
1415        Self::LOG2_10
1416    }
1417}
1418
1419impl Bounded for bf16 {
1420    #[inline]
1421    fn min_value() -> Self {
1422        bf16::MIN
1423    }
1424
1425    #[inline]
1426    fn max_value() -> Self {
1427        bf16::MAX
1428    }
1429}
1430
1431impl AsPrimitive<bf16> for bf16 {
1432    #[inline]
1433    fn as_(self) -> bf16 {
1434        self
1435    }
1436}
1437
1438macro_rules! impl_as_primitive_to_bf16 {
1439    ($ty:ty, $meth:ident) => {
1440        impl AsPrimitive<$ty> for bf16 {
1441            #[inline]
1442            fn as_(self) -> $ty {
1443                self.$meth().as_()
1444            }
1445        }
1446    };
1447}
1448
1449impl_as_primitive_to_bf16!(i64, to_f32);
1450impl_as_primitive_to_bf16!(u64, to_f32);
1451impl_as_primitive_to_bf16!(i8, to_f32);
1452impl_as_primitive_to_bf16!(u8, to_f32);
1453impl_as_primitive_to_bf16!(i16, to_f32);
1454impl_as_primitive_to_bf16!(u16, to_f32);
1455impl_as_primitive_to_bf16!(i32, to_f32);
1456impl_as_primitive_to_bf16!(u32, to_f32);
1457impl_as_primitive_to_bf16!(isize, to_f32);
1458impl_as_primitive_to_bf16!(usize, to_f32);
1459impl_as_primitive_to_bf16!(f32, to_f32);
1460impl_as_primitive_to_bf16!(f64, to_f64);
1461impl_as_primitive_to_bf16!(f16, to_f32);
1462
1463macro_rules! impl_as_primitive_bf16_from {
1464    ($ty:ty, $meth:ident) => {
1465        impl AsPrimitive<bf16> for $ty {
1466            #[inline]
1467            fn as_(self) -> bf16 {
1468                bf16::$meth(self.as_())
1469            }
1470        }
1471    };
1472}
1473
1474impl_as_primitive_bf16_from!(i64, from_f32);
1475impl_as_primitive_bf16_from!(u64, from_f32);
1476impl_as_primitive_bf16_from!(i8, from_f32);
1477impl_as_primitive_bf16_from!(u8, from_f32);
1478impl_as_primitive_bf16_from!(i16, from_f32);
1479impl_as_primitive_bf16_from!(u16, from_f32);
1480impl_as_primitive_bf16_from!(i32, from_f32);
1481impl_as_primitive_bf16_from!(u32, from_f32);
1482impl_as_primitive_bf16_from!(isize, from_f32);
1483impl_as_primitive_bf16_from!(usize, from_f32);
1484impl_as_primitive_bf16_from!(f32, from_f32);
1485impl_as_primitive_bf16_from!(f64, from_f64);