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);