use core::fmt;
use crate::int::{Int, Sign};
use crate::nat::Nat;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum RoundingMode {
#[default]
Nearest,
TowardZero,
TowardPositive,
TowardNegative,
AwayFromZero,
}
#[derive(Clone, PartialEq, Eq)]
pub struct Float {
sign: Sign,
significand: Nat,
exponent: i64,
precision: u64,
}
impl Float {
pub fn zero(precision: u64) -> Self {
Float {
sign: Sign::Zero,
significand: Nat::zero(),
exponent: 0,
precision: precision.max(1),
}
}
pub fn from_int_exact(n: &Int) -> Self {
let significand = n.magnitude().clone();
let precision = significand.bit_len().max(1);
Float {
sign: n.sign(),
significand,
exponent: 0,
precision,
}
}
#[inline]
pub fn sign(&self) -> Sign {
self.sign
}
#[inline]
pub fn precision(&self) -> u64 {
self.precision
}
#[inline]
pub fn exponent(&self) -> i64 {
self.exponent
}
#[inline]
pub fn significand(&self) -> &Nat {
&self.significand
}
#[inline]
pub fn is_zero(&self) -> bool {
self.sign == Sign::Zero
}
}
impl fmt::Display for Float {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_zero() {
return f.write_str("0");
}
if self.sign == Sign::Negative {
f.write_str("-")?;
}
write!(f, "{}·2^{}", self.significand, self.exponent)
}
}
impl fmt::Debug for Float {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Float({self} @ {}bit)", self.precision)
}
}