use crate::*;
use crate::arithmetic::*;
#[derive(Clone, Copy, Default)]
pub(crate) struct WithScale<T> {
pub value: T,
pub scale: i64,
}
impl<T> WithScale<T> {
pub fn as_ref(&self) -> WithScale<&T> {
let &WithScale { ref value, scale } = self;
WithScale { value, scale }
}
}
macro_rules! impl_is_zero_for {
($t:ty) => {
impl WithScale<$t> {
pub fn is_zero(&self) -> bool {
self.value.is_zero()
}
}
}
}
impl_is_zero_for!(&BigUint);
impl<T: fmt::Debug> fmt::Debug for WithScale<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(scale={} {:?})", self.scale, self.value)
}
}
impl<T> From<(T, i64)> for WithScale<T> {
fn from(pair: (T, i64)) -> Self {
Self { value: pair.0, scale: pair.1 }
}
}
impl<'a> From<WithScale<&'a BigInt>> for BigDecimalRef<'a> {
fn from(obj: WithScale<&'a BigInt>) -> Self {
Self {
scale: obj.scale,
sign: obj.value.sign(),
digits: obj.value.magnitude(),
}
}
}
impl<'a> From<WithScale<&'a BigUint>> for BigDecimalRef<'a> {
fn from(obj: WithScale<&'a BigUint>) -> Self {
Self {
scale: obj.scale,
sign: Sign::Plus,
digits: obj.value,
}
}
}
impl From<WithScale<BigUint>> for BigDecimal {
fn from(obj: WithScale<BigUint>) -> Self {
let WithScale { value, scale } = obj;
Self {
scale: scale,
int_val: value.into(),
}
}
}
impl<'a> From<BigDecimalRef<'a>> for WithScale<&'a BigUint> {
fn from(obj: BigDecimalRef<'a>) -> Self {
Self {
value: obj.digits,
scale: obj.scale,
}
}
}
impl<'a, T> From<&'a WithScale<T>> for WithScale<&'a T> {
fn from(obj: &'a WithScale<T>) -> Self {
let &WithScale { ref value, scale } = obj;
Self { scale, value }
}
}
impl WithScale<BigUint> {
pub fn addassign_scaled_biguint<'a, Rhs>(&mut self, rhs: Rhs)
where Rhs: Into<WithScale<&'a BigUint>>
{
addition::addassign_scaled_biguint(self, rhs.into());
}
pub fn mulassign_scaled_biguint<'a, Rhs>(&mut self, rhs: Rhs)
where Rhs: Into<WithScale<&'a BigUint>>
{
let rhs = rhs.into();
self.scale += rhs.scale;
self.value *= rhs.value;
}
pub fn count_int_digits(&self) -> i64 {
let total_digits = decimal::count_digits_biguint(&self.value);
total_digits as i64 - self.scale
}
pub fn bits(&self) -> u64 {
self.value.bits()
}
}