mod context;
mod extra_precision;
mod flags;
mod signals;
use core::cmp::Ordering;
use crate::{
bint::intrinsics::ExpType,
decimal::{dec::ExtraPrecision, signals::Signals, Context, Sign},
utils::assert_eq_size,
};
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub(crate) struct ControlBlock(u64);
impl ControlBlock {
const MIN_SCALE: u64 = 0x0000_0000_0000_8000;
const SCALE_MASK: u64 = 0x0000_0000_0000_FFFF;
#[allow(dead_code)]
#[inline(always)]
pub const fn default() -> Self {
Self::new(
0,
Sign::Plus,
Signals::empty(),
Context::default(),
ExtraPrecision::new(),
)
}
#[inline(always)]
pub const fn basic(scale: i16, sign: Sign) -> Self {
Self::new(
scale,
sign,
Signals::empty(),
Context::default(),
ExtraPrecision::new(),
)
}
#[inline(always)]
pub const fn new(
scale: i16,
sign: Sign,
signals: Signals,
ctx: Context,
extra_precision: ExtraPrecision,
) -> Self {
let mut this = Self((scale as u64) & Self::SCALE_MASK);
this.set_sign(sign);
this.raise_signals(signals);
this.set_context(ctx);
this.set_extra_precision(extra_precision);
this
}
#[inline(always)]
pub const fn get_scale(&self) -> i16 {
(self.0 & Self::SCALE_MASK) as i16
}
#[inline(always)]
pub const fn set_scale(&mut self, scale: i16) {
self.0 = (self.0 & !Self::SCALE_MASK) | (scale as u64) & Self::SCALE_MASK;
}
#[inline(always)]
pub const fn inc_scale(&mut self, inc: ExpType) {
let scale = self.get_scale() as i32 + inc as i32;
self.set_scale(scale as i16);
}
#[inline(always)]
pub const fn dec_scale(&mut self, dec: ExpType) {
let scale = self.get_scale() as i32 - dec as i32;
self.set_scale(scale as i16);
}
#[inline(always)]
pub const fn scale_cmp(&self, other: &Self) -> Ordering {
let self_scale = self.get_scale();
let other_scale = other.get_scale();
if self_scale == other_scale {
Ordering::Equal
} else if self_scale > other_scale {
Ordering::Greater
} else {
Ordering::Less
}
}
#[inline(always)]
pub const fn get_exponent(&self) -> i32 {
(self.get_scale() as i32).overflowing_neg().0
}
#[inline(always)]
pub const fn compound(&mut self, other: &Self) {
self.combine_signals(other);
self.combine_ctx(other);
}
}
assert_eq_size!(ControlBlock, u64);