mod rounding_mode;
mod signal_traps;
pub use rounding_mode::RoundingMode;
pub use signal_traps::SignalsTraps;
use core::fmt::{Debug, Display, Formatter};
use crate::utils::{assert_eq_size, err_msg};
use crate::config::*;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum Notation {
Unspecified = 0b00,
Scientific = 0b01,
FullScale = 0b10,
Plain = 0b11, }
impl Notation {
pub const DEFAULT: Self = Self::Unspecified;
pub const fn default() -> Self {
Self::DEFAULT
}
pub const fn from_u8(val: u8) -> Option<Self> {
match val {
0b00 => Some(Self::Unspecified),
0b01 => Some(Self::Scientific),
0b10 => Some(Self::FullScale),
0b11 => Some(Self::Plain),
_ => None
}
}
pub const fn to_u8(self) -> u8 {
self as u8
}
}
impl Default for Notation {
fn default() -> Self {
Self::DEFAULT
}
}
impl Display for Notation {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
Self::Unspecified => "Unspecified Notation",
Self::Scientific => "Scientific Notation",
Self::FullScale => "Full Scale Notation",
Self::Plain => "Plain Notation",
})
}
}
impl Debug for Notation {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
Display::fmt(self, f)
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct FormatStyle {
pub notation: Notation,
leading_zero_threshold: u32,
trailing_zero_threshold: u32,
}
impl Default for FormatStyle {
fn default() -> Self {
Self::DEFAULT
}
}
impl FormatStyle {
pub const DEFAULT: Self = Self {
notation: Notation::DEFAULT,
leading_zero_threshold: EXPONENTIAL_FORMAT_LEADING_ZERO_THRESHOLD,
trailing_zero_threshold: EXPONENTIAL_FORMAT_TRAILING_ZERO_THRESHOLD,
};
pub const fn default() -> Self {
Self::DEFAULT
}
pub const fn leading_zero_threshold(&self) -> u32 {
self.leading_zero_threshold
}
pub const fn trailing_zero_threshold(&self) -> u32 {
self.trailing_zero_threshold
}
pub const fn set_leading_zero_threshold(&mut self, val: u32) -> &mut Self {
if val == 0 {
panic!(err_msg!("leading_zero_threshold should be great than zero!"));
}
self.leading_zero_threshold = val;
self
}
pub const fn set_trailing_zero_threshold(&mut self, val: u32) -> &mut Self {
self.trailing_zero_threshold = val;
self
}
}
impl Display for FormatStyle {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "FS={:?}", self.notation)?;
if self.notation == Notation::default() {
write!(f,
"(LeadingZeros:{},TrailingZeros:{})",
self.leading_zero_threshold,
self.trailing_zero_threshold
)?;
}
Ok(())
}
}
impl Debug for FormatStyle {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
Display::fmt(self, f)
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Context {
rounding_mode: RoundingMode,
signal_traps: SignalsTraps,
format_style: FormatStyle,
}
impl Context {
pub const DEFAULT: Self = Self {
rounding_mode: RoundingMode::DEFAULT,
signal_traps: SignalsTraps::DEFAULT,
format_style: FormatStyle::DEFAULT,
};
#[inline(always)]
#[must_use]
pub const fn default() -> Self {
Self::DEFAULT
}
#[inline(always)]
pub const fn set_rounding_mode(&mut self, rm: RoundingMode) -> &mut Self {
self.rounding_mode = rm;
self
}
#[must_use]
#[inline(always)]
pub const fn with_rounding_mode(mut self, rm: RoundingMode) -> Self {
self.set_rounding_mode(rm);
self
}
#[inline(always)]
pub const fn clear_traps(&mut self) -> &mut Self {
self.signal_traps = SignalsTraps::empty();
self
}
#[inline(always)]
#[must_use]
pub const fn without_traps(mut self) -> Self {
self.clear_traps();
self
}
#[inline(always)]
pub const fn set_signal_traps(&mut self, traps: SignalsTraps) -> &mut Self {
self.signal_traps = traps;
self
}
#[must_use]
#[inline(always)]
pub const fn with_signal_traps(mut self, traps: SignalsTraps) -> Self {
self.set_signal_traps(traps);
self
}
#[must_use]
#[inline(always)]
pub const fn rounding_mode(&self) -> RoundingMode {
self.rounding_mode
}
#[must_use]
#[inline(always)]
pub const fn signal_traps(&self) -> SignalsTraps {
self.signal_traps
}
#[must_use]
#[inline(always)]
pub const fn format_style<'a>(&'a self) -> &'a FormatStyle {
&self.format_style
}
#[must_use]
#[inline(always)]
pub const fn notation(&self) -> Notation {
self.format_style.notation
}
#[inline(always)]
pub const fn set_notation(&mut self, val: Notation) -> &mut Self {
self.format_style.notation = val;
self
}
#[must_use]
#[inline(always)]
pub const fn leading_zero_threshold(&self) -> u32 {
self.format_style.leading_zero_threshold
}
#[must_use]
#[inline(always)]
pub const fn trailing_zero_threshold(&self) -> u32 {
self.format_style.trailing_zero_threshold
}
#[inline(always)]
pub const fn set_leading_zero_threshold(&mut self, val: u32) -> &mut Self {
self.format_style.set_leading_zero_threshold(val);
self
}
#[inline(always)]
pub const fn set_trailing_zero_threshold(&mut self, val: u32) -> &mut Self {
self.format_style.set_trailing_zero_threshold(val);
self
}
#[inline(always)]
pub(crate) const fn new(
rounding_mode: RoundingMode,
signal_traps: SignalsTraps,
format_style: FormatStyle
) -> Self {
Self {
rounding_mode,
signal_traps,
format_style,
}
}
#[inline(always)]
pub(crate) const fn merge(mut self, other: Self) -> Self {
self.signal_traps = self.signal_traps.merge(other.signal_traps);
if !other.rounding_mode.is_default() {
self.rounding_mode = other.rounding_mode;
}
self.format_style = other.format_style;
self
}
}
impl Display for Context {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "R={}, S={}, {}", self.rounding_mode, self.signal_traps, &self.format_style)
}
}
impl Debug for Context {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
Display::fmt(self, f)
}
}
assert_eq_size!(Context, u128);