Skip to content

Commit d6f30bf

Browse files
author
lif
committed
human-readable fmt::Display for fixed-point
1 parent 4c49644 commit d6f30bf

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
@@ -353,6 +353,15 @@ macro_rules! impl_signed_fixed_ops {
353353
}
354354
}
355355
impl_trait_op_unit!($t, Neg, neg);
356+
357+
impl<const B: u32> core::fmt::Display for Fixed<$t, B> {
358+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
359+
if self.to_bits() < 0 {
360+
f.write_str("-")?;
361+
}
362+
fixed_fmt_abs::<B>(f, self.to_bits().abs() as u32)
363+
}
364+
}
356365
};
357366
}
358367
impl_signed_fixed_ops!(i8, u8);
@@ -397,8 +406,29 @@ macro_rules! impl_unsigned_fixed_ops {
397406
Self(self.0 & (<$t>::MAX << B))
398407
}
399408
}
409+
410+
impl<const B: u32> core::fmt::Display for Fixed<$t, B> {
411+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
412+
fixed_fmt_abs::<B>(f, self.to_bits() as u32)
413+
}
414+
}
400415
};
401416
}
402417
impl_unsigned_fixed_ops!(u8);
403418
impl_unsigned_fixed_ops!(u16);
404419
impl_unsigned_fixed_ops!(u32);
420+
421+
fn fixed_fmt_abs<const B: u32>(
422+
f: &mut core::fmt::Formatter, abs: u32,
423+
) -> core::fmt::Result {
424+
let width = f.width().unwrap_or(0);
425+
let precision = f.precision().unwrap_or(const { ((B as usize) + 1) / 3 });
426+
let fract = abs & ((1 << B) - 1);
427+
let fract_dec = fract
428+
.checked_mul(10u32.pow(precision as u32))
429+
.map(|x| x >> B)
430+
.unwrap_or_else(|| {
431+
(fract as u64 * 10u64.pow(precision as u32) >> B) as u32
432+
});
433+
write!(f, "{:width$}.{:0precision$}", abs >> B, fract_dec)
434+
}

0 commit comments

Comments
 (0)