1#[cfg(all(feature = "serde", feature = "alloc"))]
2#[allow(unused_imports)]
3use alloc::string::ToString;
4#[cfg(feature = "bytemuck")]
5use bytemuck::{Pod, Zeroable};
6use core::{
7 cmp::Ordering,
8 iter::{Product, Sum},
9 num::FpCategory,
10 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
11};
12#[cfg(not(target_arch = "spirv"))]
13use core::{
14 fmt::{
15 Binary, Debug, Display, Error, Formatter, LowerExp, LowerHex, Octal, UpperExp, UpperHex,
16 },
17 num::ParseFloatError,
18 str::FromStr,
19};
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
23
24pub(crate) mod arch;
25
26#[allow(non_camel_case_types)]
34#[derive(Clone, Copy, Default)]
35#[repr(transparent)]
36#[cfg_attr(feature = "serde", derive(Serialize))]
37#[cfg_attr(
38 feature = "rkyv",
39 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
40)]
41#[cfg_attr(feature = "rkyv", rkyv(resolver = F16Resolver))]
42#[cfg_attr(feature = "bytemuck", derive(Zeroable, Pod))]
43#[cfg_attr(kani, derive(kani::Arbitrary))]
44#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
45#[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
46pub struct f16(u16);
47
48impl f16 {
49 #[inline]
51 #[must_use]
52 pub const fn from_bits(bits: u16) -> f16 {
53 f16(bits)
54 }
55
56 #[inline]
64 #[must_use]
65 pub fn from_f32(value: f32) -> f16 {
66 f16(arch::f32_to_f16(value))
67 }
68
69 #[inline]
81 #[must_use]
82 pub const fn from_f32_const(value: f32) -> f16 {
83 f16(arch::f32_to_f16_fallback(value))
84 }
85
86 #[inline]
94 #[must_use]
95 pub fn from_f64(value: f64) -> f16 {
96 f16(arch::f64_to_f16(value))
97 }
98
99 #[inline]
111 #[must_use]
112 pub const fn from_f64_const(value: f64) -> f16 {
113 f16(arch::f64_to_f16_fallback(value))
114 }
115
116 #[inline]
118 #[must_use]
119 pub const fn to_bits(self) -> u16 {
120 self.0
121 }
122
123 #[inline]
134 #[must_use]
135 pub const fn to_le_bytes(self) -> [u8; 2] {
136 self.0.to_le_bytes()
137 }
138
139 #[inline]
150 #[must_use]
151 pub const fn to_be_bytes(self) -> [u8; 2] {
152 self.0.to_be_bytes()
153 }
154
155 #[inline]
174 #[must_use]
175 pub const fn to_ne_bytes(self) -> [u8; 2] {
176 self.0.to_ne_bytes()
177 }
178
179 #[inline]
189 #[must_use]
190 pub const fn from_le_bytes(bytes: [u8; 2]) -> f16 {
191 f16::from_bits(u16::from_le_bytes(bytes))
192 }
193
194 #[inline]
204 #[must_use]
205 pub const fn from_be_bytes(bytes: [u8; 2]) -> f16 {
206 f16::from_bits(u16::from_be_bytes(bytes))
207 }
208
209 #[inline]
227 #[must_use]
228 pub const fn from_ne_bytes(bytes: [u8; 2]) -> f16 {
229 f16::from_bits(u16::from_ne_bytes(bytes))
230 }
231
232 #[inline]
237 #[must_use]
238 pub fn to_f32(self) -> f32 {
239 arch::f16_to_f32(self.0)
240 }
241
242 #[inline]
251 #[must_use]
252 pub const fn to_f32_const(self) -> f32 {
253 arch::f16_to_f32_fallback(self.0)
254 }
255
256 #[inline]
261 #[must_use]
262 pub fn to_f64(self) -> f64 {
263 arch::f16_to_f64(self.0)
264 }
265
266 #[inline]
275 #[must_use]
276 pub const fn to_f64_const(self) -> f64 {
277 arch::f16_to_f64_fallback(self.0)
278 }
279
280 #[inline]
294 #[must_use]
295 pub const fn is_nan(self) -> bool {
296 self.0 & 0x7FFFu16 > 0x7C00u16
297 }
298
299 #[inline]
319 #[must_use]
320 pub const fn is_infinite(self) -> bool {
321 self.0 & 0x7FFFu16 == 0x7C00u16
322 }
323
324 #[inline]
343 #[must_use]
344 pub const fn is_finite(self) -> bool {
345 self.0 & 0x7C00u16 != 0x7C00u16
346 }
347
348 #[inline]
370 #[must_use]
371 pub const fn is_normal(self) -> bool {
372 let exp = self.0 & 0x7C00u16;
373 exp != 0x7C00u16 && exp != 0
374 }
375
376 #[must_use]
394 pub const fn classify(self) -> FpCategory {
395 let exp = self.0 & 0x7C00u16;
396 let man = self.0 & 0x03FFu16;
397 match (exp, man) {
398 (0, 0) => FpCategory::Zero,
399 (0, _) => FpCategory::Subnormal,
400 (0x7C00u16, 0) => FpCategory::Infinite,
401 (0x7C00u16, _) => FpCategory::Nan,
402 _ => FpCategory::Normal,
403 }
404 }
405
406 #[must_use]
425 pub const fn signum(self) -> f16 {
426 if self.is_nan() {
427 self
428 } else if self.0 & 0x8000u16 != 0 {
429 Self::NEG_ONE
430 } else {
431 Self::ONE
432 }
433 }
434
435 #[inline]
453 #[must_use]
454 pub const fn is_sign_positive(self) -> bool {
455 self.0 & 0x8000u16 == 0
456 }
457
458 #[inline]
476 #[must_use]
477 pub const fn is_sign_negative(self) -> bool {
478 self.0 & 0x8000u16 != 0
479 }
480
481 #[inline]
500 #[must_use]
501 pub const fn copysign(self, sign: f16) -> f16 {
502 f16((sign.0 & 0x8000u16) | (self.0 & 0x7FFFu16))
503 }
504
505 #[inline]
519 #[must_use]
520 pub fn max(self, other: f16) -> f16 {
521 if self.is_nan() || other > self {
522 other
523 } else {
524 self
525 }
526 }
527
528 #[inline]
542 #[must_use]
543 pub fn min(self, other: f16) -> f16 {
544 if self.is_nan() || other < self {
545 other
546 } else {
547 self
548 }
549 }
550
551 #[inline]
571 #[must_use]
572 pub fn clamp(self, min: f16, max: f16) -> f16 {
573 assert!(min <= max);
574 let mut x = self;
575 if x < min {
576 x = min;
577 }
578 if x > max {
579 x = max;
580 }
581 x
582 }
583
584 #[inline]
651 #[must_use]
652 pub fn total_cmp(&self, other: &Self) -> Ordering {
653 let mut left = self.to_bits() as i16;
654 let mut right = other.to_bits() as i16;
655 left ^= (((left >> 15) as u16) >> 1) as i16;
656 right ^= (((right >> 15) as u16) >> 1) as i16;
657 left.cmp(&right)
658 }
659
660 #[cfg(feature = "serde")]
682 pub fn serialize_as_f32<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
683 serializer.serialize_f32(self.to_f32())
684 }
685
686 #[cfg(all(feature = "serde", feature = "alloc"))]
708 pub fn serialize_as_string<S: serde::Serializer>(
709 &self,
710 serializer: S,
711 ) -> Result<S::Ok, S::Error> {
712 serializer.serialize_str(&self.to_string())
713 }
714
715 pub const DIGITS: u32 = 3;
717 pub const EPSILON: f16 = f16(0x1400u16);
722 pub const INFINITY: f16 = f16(0x7C00u16);
724 pub const MANTISSA_DIGITS: u32 = 11;
726 pub const MAX: f16 = f16(0x7BFF);
728 pub const MAX_10_EXP: i32 = 4;
730 pub const MAX_EXP: i32 = 16;
732 pub const MIN: f16 = f16(0xFBFF);
734 pub const MIN_10_EXP: i32 = -4;
736 pub const MIN_EXP: i32 = -13;
738 pub const MIN_POSITIVE: f16 = f16(0x0400u16);
740 pub const NAN: f16 = f16(0x7E00u16);
742 pub const NEG_INFINITY: f16 = f16(0xFC00u16);
744 pub const RADIX: u32 = 2;
746
747 pub const MIN_POSITIVE_SUBNORMAL: f16 = f16(0x0001u16);
749 pub const MAX_SUBNORMAL: f16 = f16(0x03FFu16);
751
752 pub const ONE: f16 = f16(0x3C00u16);
754 pub const ZERO: f16 = f16(0x0000u16);
756 pub const NEG_ZERO: f16 = f16(0x8000u16);
758 pub const NEG_ONE: f16 = f16(0xBC00u16);
760
761 pub const E: f16 = f16(0x4170u16);
763 pub const PI: f16 = f16(0x4248u16);
765 pub const FRAC_1_PI: f16 = f16(0x3518u16);
767 pub const FRAC_1_SQRT_2: f16 = f16(0x39A8u16);
769 pub const FRAC_2_PI: f16 = f16(0x3918u16);
771 pub const FRAC_2_SQRT_PI: f16 = f16(0x3C83u16);
773 pub const FRAC_PI_2: f16 = f16(0x3E48u16);
775 pub const FRAC_PI_3: f16 = f16(0x3C30u16);
777 pub const FRAC_PI_4: f16 = f16(0x3A48u16);
779 pub const FRAC_PI_6: f16 = f16(0x3830u16);
781 pub const FRAC_PI_8: f16 = f16(0x3648u16);
783 pub const LN_10: f16 = f16(0x409Bu16);
785 pub const LN_2: f16 = f16(0x398Cu16);
787 pub const LOG10_E: f16 = f16(0x36F3u16);
789 pub const LOG10_2: f16 = f16(0x34D1u16);
791 pub const LOG2_E: f16 = f16(0x3DC5u16);
793 pub const LOG2_10: f16 = f16(0x42A5u16);
795 pub const SQRT_2: f16 = f16(0x3DA8u16);
797}
798
799impl From<f16> for f32 {
800 #[inline]
801 fn from(x: f16) -> f32 {
802 x.to_f32()
803 }
804}
805
806impl From<f16> for f64 {
807 #[inline]
808 fn from(x: f16) -> f64 {
809 x.to_f64()
810 }
811}
812
813impl From<i8> for f16 {
814 #[inline]
815 fn from(x: i8) -> f16 {
816 f16::from_f32(f32::from(x))
818 }
819}
820
821impl From<u8> for f16 {
822 #[inline]
823 fn from(x: u8) -> f16 {
824 f16::from_f32(f32::from(x))
826 }
827}
828
829impl PartialEq for f16 {
830 fn eq(&self, other: &f16) -> bool {
831 if self.is_nan() || other.is_nan() {
832 false
833 } else {
834 (self.0 == other.0) || ((self.0 | other.0) & 0x7FFFu16 == 0)
835 }
836 }
837}
838
839impl PartialOrd for f16 {
840 fn partial_cmp(&self, other: &f16) -> Option<Ordering> {
841 if self.is_nan() || other.is_nan() {
842 None
843 } else {
844 let neg = self.0 & 0x8000u16 != 0;
845 let other_neg = other.0 & 0x8000u16 != 0;
846 match (neg, other_neg) {
847 (false, false) => Some(self.0.cmp(&other.0)),
848 (false, true) => {
849 if (self.0 | other.0) & 0x7FFFu16 == 0 {
850 Some(Ordering::Equal)
851 } else {
852 Some(Ordering::Greater)
853 }
854 }
855 (true, false) => {
856 if (self.0 | other.0) & 0x7FFFu16 == 0 {
857 Some(Ordering::Equal)
858 } else {
859 Some(Ordering::Less)
860 }
861 }
862 (true, true) => Some(other.0.cmp(&self.0)),
863 }
864 }
865 }
866
867 fn lt(&self, other: &f16) -> bool {
868 if self.is_nan() || other.is_nan() {
869 false
870 } else {
871 let neg = self.0 & 0x8000u16 != 0;
872 let other_neg = other.0 & 0x8000u16 != 0;
873 match (neg, other_neg) {
874 (false, false) => self.0 < other.0,
875 (false, true) => false,
876 (true, false) => (self.0 | other.0) & 0x7FFFu16 != 0,
877 (true, true) => self.0 > other.0,
878 }
879 }
880 }
881
882 fn le(&self, other: &f16) -> bool {
883 if self.is_nan() || other.is_nan() {
884 false
885 } else {
886 let neg = self.0 & 0x8000u16 != 0;
887 let other_neg = other.0 & 0x8000u16 != 0;
888 match (neg, other_neg) {
889 (false, false) => self.0 <= other.0,
890 (false, true) => (self.0 | other.0) & 0x7FFFu16 == 0,
891 (true, false) => true,
892 (true, true) => self.0 >= other.0,
893 }
894 }
895 }
896
897 fn gt(&self, other: &f16) -> bool {
898 if self.is_nan() || other.is_nan() {
899 false
900 } else {
901 let neg = self.0 & 0x8000u16 != 0;
902 let other_neg = other.0 & 0x8000u16 != 0;
903 match (neg, other_neg) {
904 (false, false) => self.0 > other.0,
905 (false, true) => (self.0 | other.0) & 0x7FFFu16 != 0,
906 (true, false) => false,
907 (true, true) => self.0 < other.0,
908 }
909 }
910 }
911
912 fn ge(&self, other: &f16) -> bool {
913 if self.is_nan() || other.is_nan() {
914 false
915 } else {
916 let neg = self.0 & 0x8000u16 != 0;
917 let other_neg = other.0 & 0x8000u16 != 0;
918 match (neg, other_neg) {
919 (false, false) => self.0 >= other.0,
920 (false, true) => true,
921 (true, false) => (self.0 | other.0) & 0x7FFFu16 == 0,
922 (true, true) => self.0 <= other.0,
923 }
924 }
925 }
926}
927
928#[cfg(not(target_arch = "spirv"))]
929impl FromStr for f16 {
930 type Err = ParseFloatError;
931 fn from_str(src: &str) -> Result<f16, ParseFloatError> {
932 f32::from_str(src).map(f16::from_f32)
933 }
934}
935
936#[cfg(not(target_arch = "spirv"))]
937impl Debug for f16 {
938 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
939 Debug::fmt(&self.to_f32(), f)
940 }
941}
942
943#[cfg(not(target_arch = "spirv"))]
944impl Display for f16 {
945 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
946 Display::fmt(&self.to_f32(), f)
947 }
948}
949
950#[cfg(not(target_arch = "spirv"))]
951impl LowerExp for f16 {
952 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
953 write!(f, "{:e}", self.to_f32())
954 }
955}
956
957#[cfg(not(target_arch = "spirv"))]
958impl UpperExp for f16 {
959 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
960 write!(f, "{:E}", self.to_f32())
961 }
962}
963
964#[cfg(not(target_arch = "spirv"))]
965impl Binary for f16 {
966 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
967 write!(f, "{:b}", self.0)
968 }
969}
970
971#[cfg(not(target_arch = "spirv"))]
972impl Octal for f16 {
973 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
974 write!(f, "{:o}", self.0)
975 }
976}
977
978#[cfg(not(target_arch = "spirv"))]
979impl LowerHex for f16 {
980 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
981 write!(f, "{:x}", self.0)
982 }
983}
984
985#[cfg(not(target_arch = "spirv"))]
986impl UpperHex for f16 {
987 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
988 write!(f, "{:X}", self.0)
989 }
990}
991
992impl Neg for f16 {
993 type Output = Self;
994
995 #[inline]
996 fn neg(self) -> Self::Output {
997 Self(self.0 ^ 0x8000)
998 }
999}
1000
1001impl Neg for &f16 {
1002 type Output = <f16 as Neg>::Output;
1003
1004 #[inline]
1005 fn neg(self) -> Self::Output {
1006 Neg::neg(*self)
1007 }
1008}
1009
1010impl Add for f16 {
1011 type Output = Self;
1012
1013 #[inline]
1014 fn add(self, rhs: Self) -> Self::Output {
1015 f16(arch::add_f16(self.0, rhs.0))
1016 }
1017}
1018
1019impl Add<&f16> for f16 {
1020 type Output = <f16 as Add<f16>>::Output;
1021
1022 #[inline]
1023 fn add(self, rhs: &f16) -> Self::Output {
1024 self.add(*rhs)
1025 }
1026}
1027
1028impl Add<&f16> for &f16 {
1029 type Output = <f16 as Add<f16>>::Output;
1030
1031 #[inline]
1032 fn add(self, rhs: &f16) -> Self::Output {
1033 (*self).add(*rhs)
1034 }
1035}
1036
1037impl Add<f16> for &f16 {
1038 type Output = <f16 as Add<f16>>::Output;
1039
1040 #[inline]
1041 fn add(self, rhs: f16) -> Self::Output {
1042 (*self).add(rhs)
1043 }
1044}
1045
1046impl AddAssign for f16 {
1047 #[inline]
1048 fn add_assign(&mut self, rhs: Self) {
1049 *self = (*self).add(rhs);
1050 }
1051}
1052
1053impl AddAssign<&f16> for f16 {
1054 #[inline]
1055 fn add_assign(&mut self, rhs: &f16) {
1056 *self = (*self).add(rhs);
1057 }
1058}
1059
1060impl Sub for f16 {
1061 type Output = Self;
1062
1063 #[inline]
1064 fn sub(self, rhs: Self) -> Self::Output {
1065 f16(arch::subtract_f16(self.0, rhs.0))
1066 }
1067}
1068
1069impl Sub<&f16> for f16 {
1070 type Output = <f16 as Sub<f16>>::Output;
1071
1072 #[inline]
1073 fn sub(self, rhs: &f16) -> Self::Output {
1074 self.sub(*rhs)
1075 }
1076}
1077
1078impl Sub<&f16> for &f16 {
1079 type Output = <f16 as Sub<f16>>::Output;
1080
1081 #[inline]
1082 fn sub(self, rhs: &f16) -> Self::Output {
1083 (*self).sub(*rhs)
1084 }
1085}
1086
1087impl Sub<f16> for &f16 {
1088 type Output = <f16 as Sub<f16>>::Output;
1089
1090 #[inline]
1091 fn sub(self, rhs: f16) -> Self::Output {
1092 (*self).sub(rhs)
1093 }
1094}
1095
1096impl SubAssign for f16 {
1097 #[inline]
1098 fn sub_assign(&mut self, rhs: Self) {
1099 *self = (*self).sub(rhs);
1100 }
1101}
1102
1103impl SubAssign<&f16> for f16 {
1104 #[inline]
1105 fn sub_assign(&mut self, rhs: &f16) {
1106 *self = (*self).sub(rhs);
1107 }
1108}
1109
1110impl Mul for f16 {
1111 type Output = Self;
1112
1113 #[inline]
1114 fn mul(self, rhs: Self) -> Self::Output {
1115 f16(arch::multiply_f16(self.0, rhs.0))
1116 }
1117}
1118
1119impl Mul<&f16> for f16 {
1120 type Output = <f16 as Mul<f16>>::Output;
1121
1122 #[inline]
1123 fn mul(self, rhs: &f16) -> Self::Output {
1124 self.mul(*rhs)
1125 }
1126}
1127
1128impl Mul<&f16> for &f16 {
1129 type Output = <f16 as Mul<f16>>::Output;
1130
1131 #[inline]
1132 fn mul(self, rhs: &f16) -> Self::Output {
1133 (*self).mul(*rhs)
1134 }
1135}
1136
1137impl Mul<f16> for &f16 {
1138 type Output = <f16 as Mul<f16>>::Output;
1139
1140 #[inline]
1141 fn mul(self, rhs: f16) -> Self::Output {
1142 (*self).mul(rhs)
1143 }
1144}
1145
1146impl MulAssign for f16 {
1147 #[inline]
1148 fn mul_assign(&mut self, rhs: Self) {
1149 *self = (*self).mul(rhs);
1150 }
1151}
1152
1153impl MulAssign<&f16> for f16 {
1154 #[inline]
1155 fn mul_assign(&mut self, rhs: &f16) {
1156 *self = (*self).mul(rhs);
1157 }
1158}
1159
1160impl Div for f16 {
1161 type Output = Self;
1162
1163 #[inline]
1164 fn div(self, rhs: Self) -> Self::Output {
1165 f16(arch::divide_f16(self.0, rhs.0))
1166 }
1167}
1168
1169impl Div<&f16> for f16 {
1170 type Output = <f16 as Div<f16>>::Output;
1171
1172 #[inline]
1173 fn div(self, rhs: &f16) -> Self::Output {
1174 self.div(*rhs)
1175 }
1176}
1177
1178impl Div<&f16> for &f16 {
1179 type Output = <f16 as Div<f16>>::Output;
1180
1181 #[inline]
1182 fn div(self, rhs: &f16) -> Self::Output {
1183 (*self).div(*rhs)
1184 }
1185}
1186
1187impl Div<f16> for &f16 {
1188 type Output = <f16 as Div<f16>>::Output;
1189
1190 #[inline]
1191 fn div(self, rhs: f16) -> Self::Output {
1192 (*self).div(rhs)
1193 }
1194}
1195
1196impl DivAssign for f16 {
1197 #[inline]
1198 fn div_assign(&mut self, rhs: Self) {
1199 *self = (*self).div(rhs);
1200 }
1201}
1202
1203impl DivAssign<&f16> for f16 {
1204 #[inline]
1205 fn div_assign(&mut self, rhs: &f16) {
1206 *self = (*self).div(rhs);
1207 }
1208}
1209
1210impl Rem for f16 {
1211 type Output = Self;
1212
1213 #[inline]
1214 fn rem(self, rhs: Self) -> Self::Output {
1215 f16(arch::remainder_f16(self.0, rhs.0))
1216 }
1217}
1218
1219impl Rem<&f16> for f16 {
1220 type Output = <f16 as Rem<f16>>::Output;
1221
1222 #[inline]
1223 fn rem(self, rhs: &f16) -> Self::Output {
1224 self.rem(*rhs)
1225 }
1226}
1227
1228impl Rem<&f16> for &f16 {
1229 type Output = <f16 as Rem<f16>>::Output;
1230
1231 #[inline]
1232 fn rem(self, rhs: &f16) -> Self::Output {
1233 (*self).rem(*rhs)
1234 }
1235}
1236
1237impl Rem<f16> for &f16 {
1238 type Output = <f16 as Rem<f16>>::Output;
1239
1240 #[inline]
1241 fn rem(self, rhs: f16) -> Self::Output {
1242 (*self).rem(rhs)
1243 }
1244}
1245
1246impl RemAssign for f16 {
1247 #[inline]
1248 fn rem_assign(&mut self, rhs: Self) {
1249 *self = (*self).rem(rhs);
1250 }
1251}
1252
1253impl RemAssign<&f16> for f16 {
1254 #[inline]
1255 fn rem_assign(&mut self, rhs: &f16) {
1256 *self = (*self).rem(rhs);
1257 }
1258}
1259
1260impl Product for f16 {
1261 #[inline]
1262 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
1263 f16(arch::product_f16(iter.map(|f| f.to_bits())))
1264 }
1265}
1266
1267impl<'a> Product<&'a f16> for f16 {
1268 #[inline]
1269 fn product<I: Iterator<Item = &'a f16>>(iter: I) -> Self {
1270 f16(arch::product_f16(iter.map(|f| f.to_bits())))
1271 }
1272}
1273
1274impl Sum for f16 {
1275 #[inline]
1276 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1277 f16(arch::sum_f16(iter.map(|f| f.to_bits())))
1278 }
1279}
1280
1281impl<'a> Sum<&'a f16> for f16 {
1282 #[inline]
1283 fn sum<I: Iterator<Item = &'a f16>>(iter: I) -> Self {
1284 f16(arch::sum_f16(iter.map(|f| f.to_bits())))
1285 }
1286}
1287
1288#[cfg(feature = "serde")]
1289struct Visitor;
1290
1291#[cfg(feature = "serde")]
1292impl<'de> Deserialize<'de> for f16 {
1293 fn deserialize<D>(deserializer: D) -> Result<f16, D::Error>
1294 where
1295 D: serde::de::Deserializer<'de>,
1296 {
1297 deserializer.deserialize_newtype_struct("f16", Visitor)
1298 }
1299}
1300
1301#[cfg(feature = "serde")]
1302impl<'de> serde::de::Visitor<'de> for Visitor {
1303 type Value = f16;
1304
1305 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1306 write!(formatter, "tuple struct f16")
1307 }
1308
1309 fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1310 where
1311 D: serde::Deserializer<'de>,
1312 {
1313 Ok(f16(<u16 as Deserialize>::deserialize(deserializer)?))
1314 }
1315
1316 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1317 where
1318 E: serde::de::Error,
1319 {
1320 v.parse().map_err(|_| {
1321 serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &"a float string")
1322 })
1323 }
1324
1325 fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
1326 where
1327 E: serde::de::Error,
1328 {
1329 Ok(f16::from_f32(v))
1330 }
1331
1332 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
1333 where
1334 E: serde::de::Error,
1335 {
1336 Ok(f16::from_f64(v))
1337 }
1338}
1339
1340#[allow(
1341 clippy::cognitive_complexity,
1342 clippy::float_cmp,
1343 clippy::neg_cmp_op_on_partial_ord
1344)]
1345#[cfg(test)]
1346mod test {
1347 use super::*;
1348 #[allow(unused_imports)]
1349 use core::cmp::Ordering;
1350 #[cfg(feature = "num-traits")]
1351 use num_traits::{AsPrimitive, FromBytes, FromPrimitive, ToBytes, ToPrimitive};
1352 use quickcheck_macros::quickcheck;
1353
1354 #[cfg(feature = "num-traits")]
1355 #[test]
1356 fn as_primitive() {
1357 let two = f16::from_f32(2.0);
1358 assert_eq!(<i32 as AsPrimitive<f16>>::as_(2), two);
1359 assert_eq!(<f16 as AsPrimitive<i32>>::as_(two), 2);
1360
1361 assert_eq!(<f32 as AsPrimitive<f16>>::as_(2.0), two);
1362 assert_eq!(<f16 as AsPrimitive<f32>>::as_(two), 2.0);
1363
1364 assert_eq!(<f64 as AsPrimitive<f16>>::as_(2.0), two);
1365 assert_eq!(<f16 as AsPrimitive<f64>>::as_(two), 2.0);
1366 }
1367
1368 #[cfg(feature = "num-traits")]
1369 #[test]
1370 fn to_primitive() {
1371 let two = f16::from_f32(2.0);
1372 assert_eq!(ToPrimitive::to_i32(&two).unwrap(), 2i32);
1373 assert_eq!(ToPrimitive::to_f32(&two).unwrap(), 2.0f32);
1374 assert_eq!(ToPrimitive::to_f64(&two).unwrap(), 2.0f64);
1375 }
1376
1377 #[cfg(feature = "num-traits")]
1378 #[test]
1379 fn from_primitive() {
1380 let two = f16::from_f32(2.0);
1381 assert_eq!(<f16 as FromPrimitive>::from_i32(2).unwrap(), two);
1382 assert_eq!(<f16 as FromPrimitive>::from_f32(2.0).unwrap(), two);
1383 assert_eq!(<f16 as FromPrimitive>::from_f64(2.0).unwrap(), two);
1384 }
1385
1386 #[cfg(feature = "num-traits")]
1387 #[test]
1388 fn to_and_from_bytes() {
1389 let two = f16::from_f32(2.0);
1390 assert_eq!(<f16 as ToBytes>::to_le_bytes(&two), [0, 64]);
1391 assert_eq!(<f16 as FromBytes>::from_le_bytes(&[0, 64]), two);
1392 assert_eq!(<f16 as ToBytes>::to_be_bytes(&two), [64, 0]);
1393 assert_eq!(<f16 as FromBytes>::from_be_bytes(&[64, 0]), two);
1394 }
1395
1396 #[test]
1397 #[cfg_attr(miri, ignore)]
1398 fn test_f16_consts() {
1399 let digits = ((f16::MANTISSA_DIGITS as f32 - 1.0) * 2f32.log10()).floor() as u32;
1401 assert_eq!(f16::DIGITS, digits);
1402 let digits32 = ((core::f32::MANTISSA_DIGITS as f32 - 1.0) * 2f32.log10()).floor() as u32;
1404 assert_eq!(core::f32::DIGITS, digits32);
1405
1406 let one = f16::from_f32(1.0);
1408 let one_plus_epsilon = f16::from_bits(one.to_bits() + 1);
1409 let epsilon = f16::from_f32(one_plus_epsilon.to_f32() - 1.0);
1410 assert_eq!(f16::EPSILON, epsilon);
1411 let one_plus_epsilon32 = f32::from_bits(1.0f32.to_bits() + 1);
1413 let epsilon32 = one_plus_epsilon32 - 1f32;
1414 assert_eq!(core::f32::EPSILON, epsilon32);
1415
1416 let max = f16::from_bits(f16::INFINITY.to_bits() - 1);
1418 let min = f16::from_bits(f16::NEG_INFINITY.to_bits() - 1);
1419 let min_pos = f16::from_f32(2f32.powi(f16::MIN_EXP - 1));
1420 assert_eq!(f16::MAX, max);
1421 assert_eq!(f16::MIN, min);
1422 assert_eq!(f16::MIN_POSITIVE, min_pos);
1423 let max32 = f32::from_bits(core::f32::INFINITY.to_bits() - 1);
1425 let min32 = f32::from_bits(core::f32::NEG_INFINITY.to_bits() - 1);
1426 let min_pos32 = 2f32.powi(core::f32::MIN_EXP - 1);
1427 assert_eq!(core::f32::MAX, max32);
1428 assert_eq!(core::f32::MIN, min32);
1429 assert_eq!(core::f32::MIN_POSITIVE, min_pos32);
1430
1431 let ten_to_min = 10f32.powi(f16::MIN_10_EXP);
1433 assert!(ten_to_min / 10.0 < f16::MIN_POSITIVE.to_f32());
1434 assert!(ten_to_min > f16::MIN_POSITIVE.to_f32());
1435 let ten_to_max = 10f32.powi(f16::MAX_10_EXP);
1436 assert!(ten_to_max < f16::MAX.to_f32());
1437 assert!(ten_to_max * 10.0 > f16::MAX.to_f32());
1438 let ten_to_min32 = 10f64.powi(core::f32::MIN_10_EXP);
1440 assert!(ten_to_min32 / 10.0 < f64::from(core::f32::MIN_POSITIVE));
1441 assert!(ten_to_min32 > f64::from(core::f32::MIN_POSITIVE));
1442 let ten_to_max32 = 10f64.powi(core::f32::MAX_10_EXP);
1443 assert!(ten_to_max32 < f64::from(core::f32::MAX));
1444 assert!(ten_to_max32 * 10.0 > f64::from(core::f32::MAX));
1445 }
1446
1447 #[test]
1448 fn test_f16_consts_from_f32() {
1449 let one = f16::from_f32(1.0);
1450 let zero = f16::from_f32(0.0);
1451 let neg_zero = f16::from_f32(-0.0);
1452 let neg_one = f16::from_f32(-1.0);
1453 let inf = f16::from_f32(core::f32::INFINITY);
1454 let neg_inf = f16::from_f32(core::f32::NEG_INFINITY);
1455 let nan = f16::from_f32(core::f32::NAN);
1456
1457 assert_eq!(f16::ONE, one);
1458 assert_eq!(f16::ZERO, zero);
1459 assert!(zero.is_sign_positive());
1460 assert_eq!(f16::NEG_ZERO, neg_zero);
1461 assert!(neg_zero.is_sign_negative());
1462 assert_eq!(f16::NEG_ONE, neg_one);
1463 assert!(neg_one.is_sign_negative());
1464 assert_eq!(f16::INFINITY, inf);
1465 assert_eq!(f16::NEG_INFINITY, neg_inf);
1466 assert!(nan.is_nan());
1467 assert!(f16::NAN.is_nan());
1468
1469 let e = f16::from_f32(core::f32::consts::E);
1470 let pi = f16::from_f32(core::f32::consts::PI);
1471 let frac_1_pi = f16::from_f32(core::f32::consts::FRAC_1_PI);
1472 let frac_1_sqrt_2 = f16::from_f32(core::f32::consts::FRAC_1_SQRT_2);
1473 let frac_2_pi = f16::from_f32(core::f32::consts::FRAC_2_PI);
1474 let frac_2_sqrt_pi = f16::from_f32(core::f32::consts::FRAC_2_SQRT_PI);
1475 let frac_pi_2 = f16::from_f32(core::f32::consts::FRAC_PI_2);
1476 let frac_pi_3 = f16::from_f32(core::f32::consts::FRAC_PI_3);
1477 let frac_pi_4 = f16::from_f32(core::f32::consts::FRAC_PI_4);
1478 let frac_pi_6 = f16::from_f32(core::f32::consts::FRAC_PI_6);
1479 let frac_pi_8 = f16::from_f32(core::f32::consts::FRAC_PI_8);
1480 let ln_10 = f16::from_f32(core::f32::consts::LN_10);
1481 let ln_2 = f16::from_f32(core::f32::consts::LN_2);
1482 let log10_e = f16::from_f32(core::f32::consts::LOG10_E);
1483 let log10_2 = f16::from_f32(2f32.log10());
1485 let log2_e = f16::from_f32(core::f32::consts::LOG2_E);
1486 let log2_10 = f16::from_f32(10f32.log2());
1488 let sqrt_2 = f16::from_f32(core::f32::consts::SQRT_2);
1489
1490 assert_eq!(f16::E, e);
1491 assert_eq!(f16::PI, pi);
1492 assert_eq!(f16::FRAC_1_PI, frac_1_pi);
1493 assert_eq!(f16::FRAC_1_SQRT_2, frac_1_sqrt_2);
1494 assert_eq!(f16::FRAC_2_PI, frac_2_pi);
1495 assert_eq!(f16::FRAC_2_SQRT_PI, frac_2_sqrt_pi);
1496 assert_eq!(f16::FRAC_PI_2, frac_pi_2);
1497 assert_eq!(f16::FRAC_PI_3, frac_pi_3);
1498 assert_eq!(f16::FRAC_PI_4, frac_pi_4);
1499 assert_eq!(f16::FRAC_PI_6, frac_pi_6);
1500 assert_eq!(f16::FRAC_PI_8, frac_pi_8);
1501 assert_eq!(f16::LN_10, ln_10);
1502 assert_eq!(f16::LN_2, ln_2);
1503 assert_eq!(f16::LOG10_E, log10_e);
1504 assert_eq!(f16::LOG10_2, log10_2);
1505 assert_eq!(f16::LOG2_E, log2_e);
1506 assert_eq!(f16::LOG2_10, log2_10);
1507 assert_eq!(f16::SQRT_2, sqrt_2);
1508 }
1509
1510 #[test]
1511 fn test_f16_consts_from_f64() {
1512 let one = f16::from_f64(1.0);
1513 let zero = f16::from_f64(0.0);
1514 let neg_zero = f16::from_f64(-0.0);
1515 let inf = f16::from_f64(core::f64::INFINITY);
1516 let neg_inf = f16::from_f64(core::f64::NEG_INFINITY);
1517 let nan = f16::from_f64(core::f64::NAN);
1518
1519 assert_eq!(f16::ONE, one);
1520 assert_eq!(f16::ZERO, zero);
1521 assert!(zero.is_sign_positive());
1522 assert_eq!(f16::NEG_ZERO, neg_zero);
1523 assert!(neg_zero.is_sign_negative());
1524 assert_eq!(f16::INFINITY, inf);
1525 assert_eq!(f16::NEG_INFINITY, neg_inf);
1526 assert!(nan.is_nan());
1527 assert!(f16::NAN.is_nan());
1528
1529 let e = f16::from_f64(core::f64::consts::E);
1530 let pi = f16::from_f64(core::f64::consts::PI);
1531 let frac_1_pi = f16::from_f64(core::f64::consts::FRAC_1_PI);
1532 let frac_1_sqrt_2 = f16::from_f64(core::f64::consts::FRAC_1_SQRT_2);
1533 let frac_2_pi = f16::from_f64(core::f64::consts::FRAC_2_PI);
1534 let frac_2_sqrt_pi = f16::from_f64(core::f64::consts::FRAC_2_SQRT_PI);
1535 let frac_pi_2 = f16::from_f64(core::f64::consts::FRAC_PI_2);
1536 let frac_pi_3 = f16::from_f64(core::f64::consts::FRAC_PI_3);
1537 let frac_pi_4 = f16::from_f64(core::f64::consts::FRAC_PI_4);
1538 let frac_pi_6 = f16::from_f64(core::f64::consts::FRAC_PI_6);
1539 let frac_pi_8 = f16::from_f64(core::f64::consts::FRAC_PI_8);
1540 let ln_10 = f16::from_f64(core::f64::consts::LN_10);
1541 let ln_2 = f16::from_f64(core::f64::consts::LN_2);
1542 let log10_e = f16::from_f64(core::f64::consts::LOG10_E);
1543 let log10_2 = f16::from_f64(2f64.log10());
1545 let log2_e = f16::from_f64(core::f64::consts::LOG2_E);
1546 let log2_10 = f16::from_f64(10f64.log2());
1548 let sqrt_2 = f16::from_f64(core::f64::consts::SQRT_2);
1549
1550 assert_eq!(f16::E, e);
1551 assert_eq!(f16::PI, pi);
1552 assert_eq!(f16::FRAC_1_PI, frac_1_pi);
1553 assert_eq!(f16::FRAC_1_SQRT_2, frac_1_sqrt_2);
1554 assert_eq!(f16::FRAC_2_PI, frac_2_pi);
1555 assert_eq!(f16::FRAC_2_SQRT_PI, frac_2_sqrt_pi);
1556 assert_eq!(f16::FRAC_PI_2, frac_pi_2);
1557 assert_eq!(f16::FRAC_PI_3, frac_pi_3);
1558 assert_eq!(f16::FRAC_PI_4, frac_pi_4);
1559 assert_eq!(f16::FRAC_PI_6, frac_pi_6);
1560 assert_eq!(f16::FRAC_PI_8, frac_pi_8);
1561 assert_eq!(f16::LN_10, ln_10);
1562 assert_eq!(f16::LN_2, ln_2);
1563 assert_eq!(f16::LOG10_E, log10_e);
1564 assert_eq!(f16::LOG10_2, log10_2);
1565 assert_eq!(f16::LOG2_E, log2_e);
1566 assert_eq!(f16::LOG2_10, log2_10);
1567 assert_eq!(f16::SQRT_2, sqrt_2);
1568 }
1569
1570 #[test]
1571 fn test_nan_conversion_to_smaller() {
1572 let nan64 = f64::from_bits(0x7FF0_0000_0000_0001u64);
1573 let neg_nan64 = f64::from_bits(0xFFF0_0000_0000_0001u64);
1574 let nan32 = f32::from_bits(0x7F80_0001u32);
1575 let neg_nan32 = f32::from_bits(0xFF80_0001u32);
1576 let nan32_from_64 = nan64 as f32;
1577 let neg_nan32_from_64 = neg_nan64 as f32;
1578 let nan16_from_64 = f16::from_f64(nan64);
1579 let neg_nan16_from_64 = f16::from_f64(neg_nan64);
1580 let nan16_from_32 = f16::from_f32(nan32);
1581 let neg_nan16_from_32 = f16::from_f32(neg_nan32);
1582
1583 assert!(nan64.is_nan() && nan64.is_sign_positive());
1584 assert!(neg_nan64.is_nan() && neg_nan64.is_sign_negative());
1585 assert!(nan32.is_nan() && nan32.is_sign_positive());
1586 assert!(neg_nan32.is_nan() && neg_nan32.is_sign_negative());
1587
1588 assert!(nan32_from_64.is_nan());
1590 assert!(neg_nan32_from_64.is_nan());
1591 assert!(nan16_from_64.is_nan());
1592 assert!(neg_nan16_from_64.is_nan());
1593 assert!(nan16_from_32.is_nan());
1594 assert!(neg_nan16_from_32.is_nan());
1595 }
1596
1597 #[test]
1598 fn test_nan_conversion_to_larger() {
1599 let nan16 = f16::from_bits(0x7C01u16);
1600 let neg_nan16 = f16::from_bits(0xFC01u16);
1601 let nan32 = f32::from_bits(0x7F80_0001u32);
1602 let neg_nan32 = f32::from_bits(0xFF80_0001u32);
1603 let nan32_from_16 = f32::from(nan16);
1604 let neg_nan32_from_16 = f32::from(neg_nan16);
1605 let nan64_from_16 = f64::from(nan16);
1606 let neg_nan64_from_16 = f64::from(neg_nan16);
1607 let nan64_from_32 = f64::from(nan32);
1608 let neg_nan64_from_32 = f64::from(neg_nan32);
1609
1610 assert!(nan16.is_nan() && nan16.is_sign_positive());
1611 assert!(neg_nan16.is_nan() && neg_nan16.is_sign_negative());
1612 assert!(nan32.is_nan() && nan32.is_sign_positive());
1613 assert!(neg_nan32.is_nan() && neg_nan32.is_sign_negative());
1614
1615 assert!(nan32_from_16.is_nan());
1617 assert!(neg_nan32_from_16.is_nan());
1618 assert!(nan64_from_16.is_nan());
1619 assert!(neg_nan64_from_16.is_nan());
1620 assert!(nan64_from_32.is_nan());
1621 assert!(neg_nan64_from_32.is_nan());
1622 }
1623
1624 #[test]
1625 #[cfg_attr(miri, ignore)]
1626 fn test_f16_to_f32() {
1627 let f = f16::from_f32(7.0);
1628 assert_eq!(f.to_f32(), 7.0f32);
1629
1630 let f = f16::from_f32(7.1);
1632 let diff = (f.to_f32() - 7.1f32).abs();
1633 assert!(diff <= 4.0 * f16::EPSILON.to_f32());
1635
1636 assert_eq!(f16::from_bits(0x0000_0001).to_f32(), 2.0f32.powi(-24));
1637 assert_eq!(f16::from_bits(0x0000_0005).to_f32(), 5.0 * 2.0f32.powi(-24));
1638
1639 assert_eq!(f16::from_bits(0x0000_0001), f16::from_f32(2.0f32.powi(-24)));
1640 assert_eq!(
1641 f16::from_bits(0x0000_0005),
1642 f16::from_f32(5.0 * 2.0f32.powi(-24))
1643 );
1644 }
1645
1646 #[test]
1647 #[cfg_attr(miri, ignore)]
1648 fn test_f16_to_f64() {
1649 let f = f16::from_f64(7.0);
1650 assert_eq!(f.to_f64(), 7.0f64);
1651
1652 let f = f16::from_f64(7.1);
1654 let diff = (f.to_f64() - 7.1f64).abs();
1655 assert!(diff <= 4.0 * f16::EPSILON.to_f64());
1657
1658 assert_eq!(f16::from_bits(0x0000_0001).to_f64(), 2.0f64.powi(-24));
1659 assert_eq!(f16::from_bits(0x0000_0005).to_f64(), 5.0 * 2.0f64.powi(-24));
1660
1661 assert_eq!(f16::from_bits(0x0000_0001), f16::from_f64(2.0f64.powi(-24)));
1662 assert_eq!(
1663 f16::from_bits(0x0000_0005),
1664 f16::from_f64(5.0 * 2.0f64.powi(-24))
1665 );
1666 }
1667
1668 #[test]
1669 fn test_comparisons() {
1670 let zero = f16::from_f64(0.0);
1671 let one = f16::from_f64(1.0);
1672 let neg_zero = f16::from_f64(-0.0);
1673 let neg_one = f16::from_f64(-1.0);
1674
1675 assert_eq!(zero.partial_cmp(&neg_zero), Some(Ordering::Equal));
1676 assert_eq!(neg_zero.partial_cmp(&zero), Some(Ordering::Equal));
1677 assert!(zero == neg_zero);
1678 assert!(neg_zero == zero);
1679 assert!(!(zero != neg_zero));
1680 assert!(!(neg_zero != zero));
1681 assert!(!(zero < neg_zero));
1682 assert!(!(neg_zero < zero));
1683 assert!(zero <= neg_zero);
1684 assert!(neg_zero <= zero);
1685 assert!(!(zero > neg_zero));
1686 assert!(!(neg_zero > zero));
1687 assert!(zero >= neg_zero);
1688 assert!(neg_zero >= zero);
1689
1690 assert_eq!(one.partial_cmp(&neg_zero), Some(Ordering::Greater));
1691 assert_eq!(neg_zero.partial_cmp(&one), Some(Ordering::Less));
1692 assert!(!(one == neg_zero));
1693 assert!(!(neg_zero == one));
1694 assert!(one != neg_zero);
1695 assert!(neg_zero != one);
1696 assert!(!(one < neg_zero));
1697 assert!(neg_zero < one);
1698 assert!(!(one <= neg_zero));
1699 assert!(neg_zero <= one);
1700 assert!(one > neg_zero);
1701 assert!(!(neg_zero > one));
1702 assert!(one >= neg_zero);
1703 assert!(!(neg_zero >= one));
1704
1705 assert_eq!(one.partial_cmp(&neg_one), Some(Ordering::Greater));
1706 assert_eq!(neg_one.partial_cmp(&one), Some(Ordering::Less));
1707 assert!(!(one == neg_one));
1708 assert!(!(neg_one == one));
1709 assert!(one != neg_one);
1710 assert!(neg_one != one);
1711 assert!(!(one < neg_one));
1712 assert!(neg_one < one);
1713 assert!(!(one <= neg_one));
1714 assert!(neg_one <= one);
1715 assert!(one > neg_one);
1716 assert!(!(neg_one > one));
1717 assert!(one >= neg_one);
1718 assert!(!(neg_one >= one));
1719 }
1720
1721 #[test]
1722 #[allow(clippy::erasing_op, clippy::identity_op)]
1723 #[cfg_attr(miri, ignore)]
1724 fn round_to_even_f32() {
1725 let min_sub = f16::from_bits(1);
1727 let min_sub_f = (-24f32).exp2();
1728 assert_eq!(f16::from_f32(min_sub_f).to_bits(), min_sub.to_bits());
1729 assert_eq!(f32::from(min_sub).to_bits(), min_sub_f.to_bits());
1730
1731 assert_eq!(
1735 f16::from_f32(min_sub_f * 0.49).to_bits(),
1736 min_sub.to_bits() * 0
1737 );
1738 assert_eq!(
1739 f16::from_f32(min_sub_f * 0.50).to_bits(),
1740 min_sub.to_bits() * 0
1741 );
1742 assert_eq!(
1743 f16::from_f32(min_sub_f * 0.51).to_bits(),
1744 min_sub.to_bits() * 1
1745 );
1746
1747 assert_eq!(
1751 f16::from_f32(min_sub_f * 1.49).to_bits(),
1752 min_sub.to_bits() * 1
1753 );
1754 assert_eq!(
1755 f16::from_f32(min_sub_f * 1.50).to_bits(),
1756 min_sub.to_bits() * 2
1757 );
1758 assert_eq!(
1759 f16::from_f32(min_sub_f * 1.51).to_bits(),
1760 min_sub.to_bits() * 2
1761 );
1762
1763 assert_eq!(
1767 f16::from_f32(min_sub_f * 2.49).to_bits(),
1768 min_sub.to_bits() * 2
1769 );
1770 assert_eq!(
1771 f16::from_f32(min_sub_f * 2.50).to_bits(),
1772 min_sub.to_bits() * 2
1773 );
1774 assert_eq!(
1775 f16::from_f32(min_sub_f * 2.51).to_bits(),
1776 min_sub.to_bits() * 3
1777 );
1778
1779 assert_eq!(
1780 f16::from_f32(2000.49f32).to_bits(),
1781 f16::from_f32(2000.0).to_bits()
1782 );
1783 assert_eq!(
1784 f16::from_f32(2000.50f32).to_bits(),
1785 f16::from_f32(2000.0).to_bits()
1786 );
1787 assert_eq!(
1788 f16::from_f32(2000.51f32).to_bits(),
1789 f16::from_f32(2001.0).to_bits()
1790 );
1791 assert_eq!(
1792 f16::from_f32(2001.49f32).to_bits(),
1793 f16::from_f32(2001.0).to_bits()
1794 );
1795 assert_eq!(
1796 f16::from_f32(2001.50f32).to_bits(),
1797 f16::from_f32(2002.0).to_bits()
1798 );
1799 assert_eq!(
1800 f16::from_f32(2001.51f32).to_bits(),
1801 f16::from_f32(2002.0).to_bits()
1802 );
1803 assert_eq!(
1804 f16::from_f32(2002.49f32).to_bits(),
1805 f16::from_f32(2002.0).to_bits()
1806 );
1807 assert_eq!(
1808 f16::from_f32(2002.50f32).to_bits(),
1809 f16::from_f32(2002.0).to_bits()
1810 );
1811 assert_eq!(
1812 f16::from_f32(2002.51f32).to_bits(),
1813 f16::from_f32(2003.0).to_bits()
1814 );
1815 }
1816
1817 #[test]
1818 #[allow(clippy::erasing_op, clippy::identity_op)]
1819 #[cfg_attr(miri, ignore)]
1820 fn round_to_even_f64() {
1821 let min_sub = f16::from_bits(1);
1823 let min_sub_f = (-24f64).exp2();
1824 assert_eq!(f16::from_f64(min_sub_f).to_bits(), min_sub.to_bits());
1825 assert_eq!(f64::from(min_sub).to_bits(), min_sub_f.to_bits());
1826
1827 assert_eq!(
1831 f16::from_f64(min_sub_f * 0.49).to_bits(),
1832 min_sub.to_bits() * 0
1833 );
1834 assert_eq!(
1835 f16::from_f64(min_sub_f * 0.50).to_bits(),
1836 min_sub.to_bits() * 0
1837 );
1838 assert_eq!(
1839 f16::from_f64(min_sub_f * 0.51).to_bits(),
1840 min_sub.to_bits() * 1
1841 );
1842
1843 assert_eq!(
1847 f16::from_f64(min_sub_f * 1.49).to_bits(),
1848 min_sub.to_bits() * 1
1849 );
1850 assert_eq!(
1851 f16::from_f64(min_sub_f * 1.50).to_bits(),
1852 min_sub.to_bits() * 2
1853 );
1854 assert_eq!(
1855 f16::from_f64(min_sub_f * 1.51).to_bits(),
1856 min_sub.to_bits() * 2
1857 );
1858
1859 assert_eq!(
1863 f16::from_f64(min_sub_f * 2.49).to_bits(),
1864 min_sub.to_bits() * 2
1865 );
1866 assert_eq!(
1867 f16::from_f64(min_sub_f * 2.50).to_bits(),
1868 min_sub.to_bits() * 2
1869 );
1870 assert_eq!(
1871 f16::from_f64(min_sub_f * 2.51).to_bits(),
1872 min_sub.to_bits() * 3
1873 );
1874
1875 assert_eq!(
1876 f16::from_f64(2000.49f64).to_bits(),
1877 f16::from_f64(2000.0).to_bits()
1878 );
1879 assert_eq!(
1880 f16::from_f64(2000.50f64).to_bits(),
1881 f16::from_f64(2000.0).to_bits()
1882 );
1883 assert_eq!(
1884 f16::from_f64(2000.51f64).to_bits(),
1885 f16::from_f64(2001.0).to_bits()
1886 );
1887 assert_eq!(
1888 f16::from_f64(2001.49f64).to_bits(),
1889 f16::from_f64(2001.0).to_bits()
1890 );
1891 assert_eq!(
1892 f16::from_f64(2001.50f64).to_bits(),
1893 f16::from_f64(2002.0).to_bits()
1894 );
1895 assert_eq!(
1896 f16::from_f64(2001.51f64).to_bits(),
1897 f16::from_f64(2002.0).to_bits()
1898 );
1899 assert_eq!(
1900 f16::from_f64(2002.49f64).to_bits(),
1901 f16::from_f64(2002.0).to_bits()
1902 );
1903 assert_eq!(
1904 f16::from_f64(2002.50f64).to_bits(),
1905 f16::from_f64(2002.0).to_bits()
1906 );
1907 assert_eq!(
1908 f16::from_f64(2002.51f64).to_bits(),
1909 f16::from_f64(2003.0).to_bits()
1910 );
1911 }
1912
1913 #[test]
1914 fn arithmetic() {
1915 assert_eq!(f16::ONE + f16::ONE, f16::from_f32(2.));
1916 assert_eq!(f16::ONE - f16::ONE, f16::ZERO);
1917 assert_eq!(f16::ONE * f16::ONE, f16::ONE);
1918 assert_eq!(f16::from_f32(2.) * f16::from_f32(2.), f16::from_f32(4.));
1919 assert_eq!(f16::ONE / f16::ONE, f16::ONE);
1920 assert_eq!(f16::from_f32(4.) / f16::from_f32(2.), f16::from_f32(2.));
1921 assert_eq!(f16::from_f32(4.) % f16::from_f32(3.), f16::from_f32(1.));
1922 }
1923
1924 #[cfg(feature = "std")]
1925 #[test]
1926 fn formatting() {
1927 let f = f16::from_f32(0.1152344);
1928
1929 assert_eq!(format!("{:.3}", f), "0.115");
1930 assert_eq!(format!("{:.4}", f), "0.1152");
1931 assert_eq!(format!("{:+.4}", f), "+0.1152");
1932 assert_eq!(format!("{:>+10.4}", f), " +0.1152");
1933
1934 assert_eq!(format!("{:.3?}", f), "0.115");
1935 assert_eq!(format!("{:.4?}", f), "0.1152");
1936 assert_eq!(format!("{:+.4?}", f), "+0.1152");
1937 assert_eq!(format!("{:>+10.4?}", f), " +0.1152");
1938 }
1939
1940 impl quickcheck::Arbitrary for f16 {
1941 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
1942 f16(u16::arbitrary(g))
1943 }
1944 }
1945
1946 #[quickcheck]
1947 fn qc_roundtrip_f16_f32_is_identity(f: f16) -> bool {
1948 let roundtrip = f16::from_f32(f.to_f32());
1949 if f.is_nan() {
1950 roundtrip.is_nan() && f.is_sign_negative() == roundtrip.is_sign_negative()
1951 } else {
1952 f.0 == roundtrip.0
1953 }
1954 }
1955
1956 #[quickcheck]
1957 fn qc_roundtrip_f16_f64_is_identity(f: f16) -> bool {
1958 let roundtrip = f16::from_f64(f.to_f64());
1959 if f.is_nan() {
1960 roundtrip.is_nan() && f.is_sign_negative() == roundtrip.is_sign_negative()
1961 } else {
1962 f.0 == roundtrip.0
1963 }
1964 }
1965
1966 #[test]
1967 fn test_max() {
1968 let a = f16::from_f32(0.0);
1969 let b = f16::from_f32(42.0);
1970 assert_eq!(a.max(b), b);
1971
1972 let a = f16::from_f32(42.0);
1973 let b = f16::from_f32(0.0);
1974 assert_eq!(a.max(b), a);
1975
1976 let a = f16::NAN;
1977 let b = f16::from_f32(42.0);
1978 assert_eq!(a.max(b), b);
1979
1980 let a = f16::from_f32(42.0);
1981 let b = f16::NAN;
1982 assert_eq!(a.max(b), a);
1983
1984 let a = f16::NAN;
1985 let b = f16::NAN;
1986 assert!(a.max(b).is_nan());
1987 }
1988
1989 #[test]
1990 fn test_min() {
1991 let a = f16::from_f32(0.0);
1992 let b = f16::from_f32(42.0);
1993 assert_eq!(a.min(b), a);
1994
1995 let a = f16::from_f32(42.0);
1996 let b = f16::from_f32(0.0);
1997 assert_eq!(a.min(b), b);
1998
1999 let a = f16::NAN;
2000 let b = f16::from_f32(42.0);
2001 assert_eq!(a.min(b), b);
2002
2003 let a = f16::from_f32(42.0);
2004 let b = f16::NAN;
2005 assert_eq!(a.min(b), a);
2006
2007 let a = f16::NAN;
2008 let b = f16::NAN;
2009 assert!(a.min(b).is_nan());
2010 }
2011}