use std::fmt;
use num_bigint::{BigInt, BigUint};
use num_traits::{Signed, Zero};
pub(super) fn format_binary_display(
f: &mut fmt::Formatter<'_>,
mantissa: &BigInt,
exponent: &BigInt,
) -> fmt::Result {
if mantissa.is_zero() {
return write!(f, "0.0");
}
let is_negative = mantissa.is_negative();
let abs_mantissa = mantissa.magnitude();
let (formatted_mantissa, adjusted_exponent) =
format_mantissa_with_point(abs_mantissa, exponent);
if is_negative {
write!(f, "-{} * 2^{}", formatted_mantissa, adjusted_exponent)
} else {
write!(f, "{} * 2^{}", formatted_mantissa, adjusted_exponent)
}
}
pub(super) fn format_ubinary_display(
f: &mut fmt::Formatter<'_>,
mantissa: &BigUint,
exponent: &BigInt,
) -> fmt::Result {
if mantissa.is_zero() {
return write!(f, "0.0");
}
let (formatted_mantissa, adjusted_exponent) = format_mantissa_with_point(mantissa, exponent);
write!(f, "{} * 2^{}", formatted_mantissa, adjusted_exponent)
}
fn format_mantissa_with_point(mantissa: &BigUint, exponent: &BigInt) -> (String, BigInt) {
let binary_str = format!("{:b}", mantissa);
let num_bits = binary_str.len();
let formatted_mantissa = if num_bits == 1 {
format!("{}.0", binary_str)
} else {
format!("{}.{}", &binary_str[0..1], &binary_str[1..])
};
let adjusted_exponent = exponent + BigInt::from(num_bits) - 1_i32;
(formatted_mantissa, adjusted_exponent)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn format_single_bit_mantissa() {
let mantissa = BigUint::from(1u32);
let exponent = BigInt::from(0);
let (formatted, adjusted_exp) = format_mantissa_with_point(&mantissa, &exponent);
assert_eq!(formatted, "1.0");
assert_eq!(adjusted_exp, BigInt::from(0));
}
#[test]
fn format_multi_bit_mantissa() {
let mantissa = BigUint::from(123u32);
let exponent = BigInt::from(5);
let (formatted, adjusted_exp) = format_mantissa_with_point(&mantissa, &exponent);
assert_eq!(formatted, "1.111011");
assert_eq!(adjusted_exp, BigInt::from(11)); }
#[test]
fn format_binary_display_zero() {
let mantissa = BigInt::from(0);
let exponent = BigInt::from(42);
let result = format!(
"{}",
FormatWrapper(&mantissa, &exponent, format_binary_display)
);
assert_eq!(result, "0.0");
}
#[test]
fn format_binary_display_negative() {
let mantissa = BigInt::from(-15); let exponent = BigInt::from(3);
let result = format!(
"{}",
FormatWrapper(&mantissa, &exponent, format_binary_display)
);
assert_eq!(result, "-1.111 * 2^6"); }
#[test]
fn demonstrate_new_format() {
let mantissa = BigUint::from(123u32);
let exponent = BigInt::from(5);
let (formatted, adjusted_exp) = format_mantissa_with_point(&mantissa, &exponent);
println!("Old format would be: 123 * 2^5");
println!("New format is: {} * 2^{}", formatted, adjusted_exp);
assert_eq!(formatted, "1.111011");
assert_eq!(adjusted_exp, BigInt::from(11));
}
struct FormatWrapper<'a, T>(
&'a T,
&'a BigInt,
fn(&mut fmt::Formatter<'_>, &T, &BigInt) -> fmt::Result,
);
impl<'a, T> fmt::Display for FormatWrapper<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(self.2)(f, self.0, self.1)
}
}
}