machina_softfloat/
types.rs1use core::fmt;
5
6pub trait BitOps:
11 Copy + Clone + PartialEq + Eq + core::hash::Hash + fmt::Debug + Sized + 'static
12{
13 const ZERO: Self;
14 const ONE: Self;
15 const MAX: Self;
16 const BITS: u32;
17 fn shl(self, n: u32) -> Self;
18 fn shr(self, n: u32) -> Self;
19 fn bitand(self, other: Self) -> Self;
20 fn bitor(self, other: Self) -> Self;
21 fn bitxor(self, other: Self) -> Self;
22 fn not(self) -> Self;
23 fn wrapping_sub(self, other: Self) -> Self;
24 fn wrapping_add(self, other: Self) -> Self;
25 fn to_u128(self) -> u128;
26 fn from_u128(v: u128) -> Self;
27 fn is_zero(self) -> bool;
28 fn leading_zeros(self) -> u32;
29}
30
31macro_rules! impl_bitops {
32 ($ty:ty) => {
33 impl BitOps for $ty {
34 const ZERO: Self = 0;
35 const ONE: Self = 1;
36 const MAX: Self = <$ty>::MAX;
37 const BITS: u32 = <$ty>::BITS;
38 #[inline]
39 fn shl(self, n: u32) -> Self {
40 self << n
41 }
42 #[inline]
43 fn shr(self, n: u32) -> Self {
44 self >> n
45 }
46 #[inline]
47 fn bitand(self, o: Self) -> Self {
48 self & o
49 }
50 #[inline]
51 fn bitor(self, o: Self) -> Self {
52 self | o
53 }
54 #[inline]
55 fn bitxor(self, o: Self) -> Self {
56 self ^ o
57 }
58 #[inline]
59 fn not(self) -> Self {
60 !self
61 }
62 #[inline]
63 fn wrapping_sub(self, o: Self) -> Self {
64 <$ty>::wrapping_sub(self, o)
65 }
66 #[inline]
67 fn wrapping_add(self, o: Self) -> Self {
68 <$ty>::wrapping_add(self, o)
69 }
70 #[inline]
71 fn to_u128(self) -> u128 {
72 self as u128
73 }
74 #[inline]
75 fn from_u128(v: u128) -> Self {
76 v as Self
77 }
78 #[inline]
79 fn is_zero(self) -> bool {
80 self == 0
81 }
82 #[inline]
83 fn leading_zeros(self) -> u32 {
84 <$ty>::leading_zeros(self)
85 }
86 }
87 };
88}
89
90impl_bitops!(u16);
91impl_bitops!(u32);
92impl_bitops!(u64);
93impl_bitops!(u128);
94
95pub trait FloatFormat: Copy + Clone + PartialEq + Eq {
100 type Bits: BitOps;
101 const EXP_BITS: u32;
102 const FRAC_BITS: u32;
103 const BIAS: i32;
104 const HAS_EXPLICIT_INT: bool;
105 fn to_bits(self) -> Self::Bits;
106 fn from_bits(bits: Self::Bits) -> Self;
107}
108
109#[repr(transparent)]
114#[derive(Clone, Copy, PartialEq, Eq, Hash)]
115pub struct Float16(pub(crate) u16);
116
117impl Float16 {
118 pub const fn from_bits(u: u16) -> Self {
119 Self(u)
120 }
121 pub const fn to_bits(self) -> u16 {
122 self.0
123 }
124
125 pub fn is_nan(self) -> bool {
126 let exp = (self.0 >> 10) & 0x1F;
127 let frac = self.0 & 0x3FF;
128 exp == 0x1F && frac != 0
129 }
130 pub fn is_inf(self) -> bool {
131 let exp = (self.0 >> 10) & 0x1F;
132 let frac = self.0 & 0x3FF;
133 exp == 0x1F && frac == 0
134 }
135 pub fn is_zero(self) -> bool {
136 self.0 & 0x7FFF == 0
137 }
138 pub fn is_neg(self) -> bool {
139 self.0 & 0x8000 != 0
140 }
141}
142
143impl fmt::Debug for Float16 {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(f, "Float16(0x{:04X})", self.0)
146 }
147}
148
149impl FloatFormat for Float16 {
150 type Bits = u16;
151 const EXP_BITS: u32 = 5;
152 const FRAC_BITS: u32 = 10;
153 const BIAS: i32 = 15;
154 const HAS_EXPLICIT_INT: bool = false;
155 fn to_bits(self) -> u16 {
156 self.0
157 }
158 fn from_bits(bits: u16) -> Self {
159 Self(bits)
160 }
161}
162
163#[repr(transparent)]
168#[derive(Clone, Copy, PartialEq, Eq, Hash)]
169pub struct BFloat16(pub(crate) u16);
170
171impl BFloat16 {
172 pub const fn from_bits(u: u16) -> Self {
173 Self(u)
174 }
175 pub const fn to_bits(self) -> u16 {
176 self.0
177 }
178
179 pub fn is_nan(self) -> bool {
180 let exp = (self.0 >> 7) & 0xFF;
181 let frac = self.0 & 0x7F;
182 exp == 0xFF && frac != 0
183 }
184 pub fn is_inf(self) -> bool {
185 let exp = (self.0 >> 7) & 0xFF;
186 let frac = self.0 & 0x7F;
187 exp == 0xFF && frac == 0
188 }
189 pub fn is_zero(self) -> bool {
190 self.0 & 0x7FFF == 0
191 }
192 pub fn is_neg(self) -> bool {
193 self.0 & 0x8000 != 0
194 }
195}
196
197impl fmt::Debug for BFloat16 {
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 write!(f, "BFloat16(0x{:04X})", self.0)
200 }
201}
202
203impl FloatFormat for BFloat16 {
204 type Bits = u16;
205 const EXP_BITS: u32 = 8;
206 const FRAC_BITS: u32 = 7;
207 const BIAS: i32 = 127;
208 const HAS_EXPLICIT_INT: bool = false;
209 fn to_bits(self) -> u16 {
210 self.0
211 }
212 fn from_bits(bits: u16) -> Self {
213 Self(bits)
214 }
215}
216
217#[repr(transparent)]
222#[derive(Clone, Copy, PartialEq, Eq, Hash)]
223pub struct Float32(pub(crate) u32);
224
225impl Float32 {
226 pub const fn from_bits(u: u32) -> Self {
227 Self(u)
228 }
229 pub const fn to_bits(self) -> u32 {
230 self.0
231 }
232
233 pub fn is_nan(self) -> bool {
234 let exp = (self.0 >> 23) & 0xFF;
235 let frac = self.0 & 0x7F_FFFF;
236 exp == 0xFF && frac != 0
237 }
238 pub fn is_inf(self) -> bool {
239 let exp = (self.0 >> 23) & 0xFF;
240 let frac = self.0 & 0x7F_FFFF;
241 exp == 0xFF && frac == 0
242 }
243 pub fn is_zero(self) -> bool {
244 self.0 & 0x7FFF_FFFF == 0
245 }
246 pub fn is_neg(self) -> bool {
247 self.0 & 0x8000_0000 != 0
248 }
249 pub fn from_f32(v: f32) -> Self {
251 Self(v.to_bits())
252 }
253 pub fn to_f32(self) -> f32 {
255 f32::from_bits(self.0)
256 }
257}
258
259impl fmt::Debug for Float32 {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 write!(f, "Float32(0x{:08X})", self.0)
262 }
263}
264
265impl FloatFormat for Float32 {
266 type Bits = u32;
267 const EXP_BITS: u32 = 8;
268 const FRAC_BITS: u32 = 23;
269 const BIAS: i32 = 127;
270 const HAS_EXPLICIT_INT: bool = false;
271 fn to_bits(self) -> u32 {
272 self.0
273 }
274 fn from_bits(bits: u32) -> Self {
275 Self(bits)
276 }
277}
278
279#[repr(transparent)]
284#[derive(Clone, Copy, PartialEq, Eq, Hash)]
285pub struct Float64(pub(crate) u64);
286
287impl Float64 {
288 pub const fn from_bits(u: u64) -> Self {
289 Self(u)
290 }
291 pub const fn to_bits(self) -> u64 {
292 self.0
293 }
294
295 pub fn is_nan(self) -> bool {
296 let exp = (self.0 >> 52) & 0x7FF;
297 let frac = self.0 & 0xF_FFFF_FFFF_FFFF;
298 exp == 0x7FF && frac != 0
299 }
300 pub fn is_inf(self) -> bool {
301 let exp = (self.0 >> 52) & 0x7FF;
302 let frac = self.0 & 0xF_FFFF_FFFF_FFFF;
303 exp == 0x7FF && frac == 0
304 }
305 pub fn is_zero(self) -> bool {
306 self.0 & 0x7FFF_FFFF_FFFF_FFFF == 0
307 }
308 pub fn is_neg(self) -> bool {
309 self.0 & 0x8000_0000_0000_0000 != 0
310 }
311 pub fn from_f64(v: f64) -> Self {
312 Self(v.to_bits())
313 }
314 pub fn to_f64(self) -> f64 {
315 f64::from_bits(self.0)
316 }
317}
318
319impl fmt::Debug for Float64 {
320 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321 write!(f, "Float64(0x{:016X})", self.0)
322 }
323}
324
325impl FloatFormat for Float64 {
326 type Bits = u64;
327 const EXP_BITS: u32 = 11;
328 const FRAC_BITS: u32 = 52;
329 const BIAS: i32 = 1023;
330 const HAS_EXPLICIT_INT: bool = false;
331 fn to_bits(self) -> u64 {
332 self.0
333 }
334 fn from_bits(bits: u64) -> Self {
335 Self(bits)
336 }
337}
338
339#[repr(transparent)]
344#[derive(Clone, Copy, PartialEq, Eq, Hash)]
345pub struct Float128(pub(crate) u128);
346
347impl Float128 {
348 pub const fn from_bits(u: u128) -> Self {
349 Self(u)
350 }
351 pub const fn to_bits(self) -> u128 {
352 self.0
353 }
354
355 pub fn is_nan(self) -> bool {
356 let exp = (self.0 >> 112) & 0x7FFF;
357 let frac = self.0 & 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF;
358 exp == 0x7FFF && frac != 0
359 }
360 pub fn is_inf(self) -> bool {
361 let exp = (self.0 >> 112) & 0x7FFF;
362 let frac = self.0 & 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF;
363 exp == 0x7FFF && frac == 0
364 }
365 pub fn is_zero(self) -> bool {
366 self.0 & ((1u128 << 127) - 1) == 0
367 }
368 pub fn is_neg(self) -> bool {
369 self.0 & (1u128 << 127) != 0
370 }
371}
372
373impl fmt::Debug for Float128 {
374 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375 write!(f, "Float128(0x{:032X})", self.0)
376 }
377}
378
379impl FloatFormat for Float128 {
380 type Bits = u128;
381 const EXP_BITS: u32 = 15;
382 const FRAC_BITS: u32 = 112;
383 const BIAS: i32 = 16383;
384 const HAS_EXPLICIT_INT: bool = false;
385 fn to_bits(self) -> u128 {
386 self.0
387 }
388 fn from_bits(bits: u128) -> Self {
389 Self(bits)
390 }
391}
392
393#[derive(Clone, Copy, PartialEq, Eq, Hash)]
398pub struct FloatX80 {
399 pub lo: u64,
400 pub hi: u16,
401}
402
403impl FloatX80 {
404 pub fn from_bits(u: u128) -> Self {
405 Self {
406 lo: u as u64,
407 hi: (u >> 64) as u16,
408 }
409 }
410 pub fn to_bits(self) -> u128 {
411 (self.lo as u128) | ((self.hi as u128) << 64)
412 }
413
414 pub fn is_nan(self) -> bool {
415 let exp = self.hi & 0x7FFF;
416 if exp != 0x7FFF {
418 return false;
419 }
420 let j = (self.lo >> 63) & 1;
424 let frac = self.lo & 0x7FFF_FFFF_FFFF_FFFF;
425 if j == 1 && frac != 0 {
426 return true;
427 }
428 if j == 0 {
430 return true;
431 }
432 false
433 }
434 pub fn is_inf(self) -> bool {
435 let exp = self.hi & 0x7FFF;
436 if exp != 0x7FFF {
437 return false;
438 }
439 self.lo == 0x8000_0000_0000_0000
441 }
442 pub fn is_zero(self) -> bool {
443 self.lo == 0 && (self.hi & 0x7FFF) == 0
444 }
445 pub fn is_neg(self) -> bool {
446 self.hi & 0x8000 != 0
447 }
448}
449
450impl fmt::Debug for FloatX80 {
451 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
452 write!(f, "FloatX80(hi=0x{:04X}, lo=0x{:016X})", self.hi, self.lo)
453 }
454}
455
456impl FloatFormat for FloatX80 {
457 type Bits = u128;
459 const EXP_BITS: u32 = 15;
460 const FRAC_BITS: u32 = 63;
464 const BIAS: i32 = 16383;
465 const HAS_EXPLICIT_INT: bool = true;
466
467 fn to_bits(self) -> u128 {
468 FloatX80::to_bits(self)
469 }
470 fn from_bits(bits: u128) -> Self {
471 FloatX80::from_bits(bits)
472 }
473}