Skip to content

Commit ca62ab2

Browse files
author
lif
committed
human-readable fmt::Display for fixed-point
1 parent a2a5f97 commit ca62ab2

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

src/fixed.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,15 @@ macro_rules! impl_signed_fixed_ops {
345345
}
346346
}
347347
impl_trait_op_unit!($t, Neg, neg);
348+
349+
impl<const B: u32> core::fmt::Display for Fixed<$t, B> {
350+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
351+
if self.to_bits() < 0 {
352+
f.write_str("-")?;
353+
}
354+
fixed_fmt_abs::<B>(f, self.to_bits().abs() as u32)
355+
}
356+
}
348357
};
349358
}
350359
impl_signed_fixed_ops!(i8, u8);
@@ -389,8 +398,29 @@ macro_rules! impl_unsigned_fixed_ops {
389398
Self(self.0 & (<$t>::MAX << B))
390399
}
391400
}
401+
402+
impl<const B: u32> core::fmt::Display for Fixed<$t, B> {
403+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
404+
fixed_fmt_abs::<B>(f, self.to_bits() as u32)
405+
}
406+
}
392407
};
393408
}
394409
impl_unsigned_fixed_ops!(u8);
395410
impl_unsigned_fixed_ops!(u16);
396411
impl_unsigned_fixed_ops!(u32);
412+
413+
fn fixed_fmt_abs<const B: u32>(
414+
f: &mut core::fmt::Formatter, abs: u32,
415+
) -> core::fmt::Result {
416+
let width = f.width().unwrap_or(0);
417+
let precision = f.precision().unwrap_or(const { ((B as usize) + 1) / 3 });
418+
let fract = abs & ((1 << B) - 1);
419+
let fract_dec = fract
420+
.checked_mul(10u32.pow(precision as u32))
421+
.map(|x| x >> B)
422+
.unwrap_or_else(|| {
423+
(fract as u64 * 10u64.pow(precision as u32) >> B) as u32
424+
});
425+
write!(f, "{:width$}.{:0precision$}", abs >> B, fract_dec)
426+
}

0 commit comments

Comments
 (0)