1use crate::lib::*;
2
3#[allow(non_camel_case_types)]
14#[repr(transparent)]
15#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
16#[cfg_attr(feature = "json_schema", schemars(transparent))]
17#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct f16(#[cfg_attr(feature = "json_schema", schemars(with = "f32"))] u16);
19
20impl f16 {
21 #[inline]
25 pub const fn from_f32(f: f32) -> Self {
26 let bits = f.to_bits();
27 Self((bits >> 16) as u16) }
29
30 #[inline]
32 pub const fn to_f32(self) -> f32 {
33 f32::from_bits((self.0 as u32) << 16)
34 }
35
36 #[inline]
38 pub const fn to_bits(self) -> u16 {
39 self.0
40 }
41
42 #[inline]
44 pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
45 Self(u16::from_le_bytes(bytes))
46 }
47
48 #[inline]
50 pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
51 Self(u16::from_be_bytes(bytes))
52 }
53
54 #[inline]
56 pub const fn to_le_bytes(self) -> [u8; 2] {
57 self.to_bits().to_le_bytes()
58 }
59
60 #[inline]
62 pub const fn to_be_bytes(self) -> [u8; 2] {
63 self.to_bits().to_be_bytes()
64 }
65}
66
67impl fmt::Display for f16 {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 write!(f, "{:.06}", self.to_f32())
70 }
71}
72
73impl fmt::Debug for f16 {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "{:.06}", self.to_f32())
76 }
77}
78
79#[cfg(feature = "serde")]
80const _: () = {
81 use super::f16;
82 use serde::{Deserialize, Deserializer, Serialize, Serializer};
83
84 impl Serialize for f16 {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: Serializer,
88 {
89 self.to_f32().serialize(serializer)
90 }
91 }
92
93 impl<'de> Deserialize<'de> for f16 {
94 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
95 where
96 D: Deserializer<'de>,
97 {
98 let f = f32::deserialize(deserializer)?;
99 Ok(Self::from_f32(f))
100 }
101 }
102};
103
104#[test]
105fn test_half() {
106 {
107 let half = f16::from_f32(1.0);
108 const HALF_LE: [u8; 2] = [0x80, 0x3f];
109 const HALF_BE: [u8; 2] = [0x3f, 0x80];
110
111 assert_eq!(half.to_le_bytes(), HALF_LE);
112 assert_eq!(half.to_be_bytes(), HALF_BE);
113 assert_eq!(f16::from_le_bytes(HALF_LE), half);
114 assert_eq!(f16::from_be_bytes(HALF_BE), half);
115 assert_eq!(half.to_f32().to_bits(), (1.0_f32).to_bits()); assert_eq!(half.to_string(), "1.000000");
117 }
118
119 {
120 let half = f16::from_f32(0.049805);
121 const HALF_LE: [u8; 2] = [0x4c, 0x3d];
122 const HALF_BE: [u8; 2] = [0x3d, 0x4c];
123 assert_eq!(half.to_le_bytes(), HALF_LE);
124 assert_eq!(half.to_be_bytes(), HALF_BE);
125 assert_eq!(f16::from_le_bytes(HALF_LE), half);
126 assert_eq!(f16::from_be_bytes(HALF_BE), half);
127 assert_eq!(half.to_f32().to_bits(), (0.049804688_f32).to_bits()); assert_eq!(half.to_string(), "0.049805");
129 }
130}