lilliput_float/floats.rs
1/// A bit-level representation of a 8-bit floating-point number.
2///
3/// The bits are laid out as follows:
4/// - Sign bit: 1 bit
5/// - Exponent width: 4 bits
6/// - Significand precision: 4 bits (3 explicitly stored)
7///
8/// ```plain
9/// MSB ... LSB
10/// ┌─┬─┬─┬─┬─┬─┬─┬─┐
11/// └─┴─┴─┴─┴─┴─┴─┴─┘
12/// │ ├─────┘ ├───┘
13/// │ │ └ Significand (3 bits)
14/// │ └ Exponent (4 bits)
15/// └ Sign (1 bit)
16/// ```
17#[derive(Default, Copy, Clone)]
18#[repr(transparent)]
19pub struct F8(pub(crate) u8);
20
21impl std::fmt::Debug for F8 {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 write!(f, "{:08b}", self.0)
24 }
25}
26
27/// A bit-level representation of a 16-bit floating-point number.
28///
29/// The bits are laid out as follows:
30/// - Sign bit: 1 bit
31/// - Exponent width: 5 bits
32/// - Significand precision: 11 bits (10 explicitly stored)
33///
34/// ```plain
35/// MSB ... LSB
36/// ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
37/// └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
38/// │ ├───────┘ ├─────────────────┘
39/// │ │ └ Significand (10 bits)
40/// │ └ Exponent (5 bits)
41/// └ Sign (1 bit)
42/// ```
43#[derive(Default, Copy, Clone)]
44#[repr(transparent)]
45pub struct F16(pub(crate) u16);
46
47impl std::fmt::Debug for F16 {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 write!(f, "{:016b}", self.0)
50 }
51}
52
53/// A bit-level representation of a 24-bit floating-point number.
54///
55/// The bits are laid out as follows:
56/// - Sign bit: 1 bit
57/// - Exponent width: 7 bits
58/// - Significand precision: 17 bits (16 explicitly stored)
59///
60/// ```plain
61/// MSB ... LSB
62/// ┌─┬╴╴┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
63/// └─┴╴╴┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
64/// ├╴╴┘ │ ├───────────┘ ├─────────────────────────────┘
65/// │ │ │ └ Significand (16 bits)
66/// │ │ └ Exponent (7 bits)
67/// │ └ Sign (1 bit)
68/// └ Padding (8 bits)
69/// ```
70#[derive(Default, Copy, Clone)]
71#[repr(transparent)]
72pub struct F24(pub(crate) u32);
73
74impl std::fmt::Debug for F24 {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 write!(f, "{:024b}", self.0)
77 }
78}
79
80/// A bit-level representation of a 32-bit floating-point number.
81///
82/// The bits are laid out as follows:
83/// - Sign bit: 1 bit
84/// - Exponent width: 8 bits
85/// - Significand precision: 24 bits (23 explicitly stored)
86///
87/// ```plain
88/// MSB ... LSB
89/// ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
90/// └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
91/// │ ├─────────────┘ ├───────────────────────────────────────────┘
92/// │ │ └ Significand (23 bits)
93/// │ └ Exponent (8 bits)
94/// └ Sign (1 bit)
95/// ```
96#[derive(Default, Copy, Clone)]
97#[repr(transparent)]
98pub struct F32(pub(crate) u32);
99
100impl std::fmt::Debug for F32 {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{:032b}", self.0)
103 }
104}
105
106/// A bit-level representation of a 40-bit floating-point number.
107///
108/// The bits are laid out as follows:
109/// - Sign bit: 1 bit
110/// - Exponent width: 8 bits
111/// - Significand precision: 32 bits (31 explicitly stored)
112///
113/// ```plain
114/// MSB ... LSB
115/// ┌─┬╴╴┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬╴╴╴┬─┐
116/// └─┴╴╴┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴╴╴╴┴─┘
117/// ├╴╴┘ │ ├─────────────┘ ├───────────────────────────────────────╴╴╴─┘
118/// │ │ │ └ Significand (31 bits)
119/// │ │ └ Exponent (8 bits)
120/// │ └ Sign (1 bit)
121/// └ Padding (24 bits)
122/// ```
123#[derive(Default, Copy, Clone)]
124#[repr(transparent)]
125pub struct F40(pub(crate) u64);
126
127impl std::fmt::Debug for F40 {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 write!(f, "{:040b}", self.0)
130 }
131}
132
133/// A bit-level representation of a 48-bit floating-point number.
134///
135/// The bits are laid out as follows:
136/// - Sign bit: 1 bit
137/// - Exponent width: 9 bits
138/// - Significand precision: 39 bits (38 explicitly stored)
139///
140/// ```plain
141/// MSB ... LSB
142/// ┌─┬╴╴┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬╴╴╴┬─┐
143/// └─┴╴╴┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴╴╴╴┴─┘
144/// ├╴╴┘ │ ├───────────────┘ ├─────────────────────────────────────╴╴╴─┘
145/// │ │ │ └ Significand (38 bits)
146/// │ │ └ Exponent (9 bits)
147/// │ └ Sign (1 bit)
148/// └ Padding (16 bits)
149/// ```
150#[derive(Default, Copy, Clone)]
151#[repr(transparent)]
152pub struct F48(pub(crate) u64);
153
154impl std::fmt::Debug for F48 {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 write!(f, "{:048b}", self.0)
157 }
158}
159
160/// A bit-level representation of a 56-bit floating-point number.
161///
162/// The bits are laid out as follows:
163/// - Sign bit: 1 bit
164/// - Exponent width: 10 bits
165/// - Significand precision: 46 bits (45 explicitly stored)
166///
167/// ```plain
168/// MSB ... LSB
169/// ┌─┬╴╴┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬╴╴╴┬─┐
170/// └─┴╴╴┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴╴╴╴┴─┘
171/// ├╴╴┘ │ ├─────────────────┘ ├───────────────────────────────────╴╴╴─┘
172/// │ │ │ └ Significand (45 bits)
173/// │ │ └ Exponent (10 bits)
174/// │ └ Sign (1 bit)
175/// └ Padding (8 bits)
176/// ```
177#[derive(Default, Copy, Clone)]
178#[repr(transparent)]
179pub struct F56(pub(crate) u64);
180
181impl std::fmt::Debug for F56 {
182 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183 write!(f, "{:056b}", self.0)
184 }
185}
186
187/// A bit-level representation of a 64-bit floating-point number.
188///
189/// The bits are laid out as follows:
190/// - Sign bit: 1 bit
191/// - Exponent width: 11 bits
192/// - Significand precision: 53 bits (52 explicitly stored)
193///
194/// ```plain
195/// MSB ... LSB
196/// ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬╴╴╴┬─┐
197/// └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴╴╴╴┴─┘
198/// │ ├─────────────────┘ ├───────────────────────────────────╴╴╴─┘
199/// │ │ └ Significand (53 bits)
200/// │ └ Exponent (11 bits)
201/// └ Sign (1 bit)
202/// ```
203#[derive(Default, Copy, Clone)]
204#[repr(transparent)]
205pub struct F64(pub(crate) u64);
206
207impl std::fmt::Debug for F64 {
208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 write!(f, "{:064b}", self.0)
210 }
211}