use std::cmp::Ordering;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::ffi::{CStr, CString};
use std::fmt;
use std::iter::{Product, Sum};
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};
use std::str::FromStr;
use libc::c_char;
#[cfg(feature = "num-traits")]
use num_traits::{MulAdd, MulAddAssign, One, Zero};
use crate::context::{Class, Context};
use crate::decimal::Decimal;
use crate::decimal32::Decimal32;
use crate::decimal64::Decimal64;
use crate::error::ParseDecimalError;
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct Decimal128 {
pub(crate) inner: decnumber_sys::decQuad,
}
impl Decimal128 {
pub const NAN: Decimal128 = Decimal128::from_ne_bytes(if cfg!(target_endian = "little") {
[
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7c,
]
} else {
[
0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
]
});
pub const ZERO: Decimal128 = Decimal128::from_ne_bytes(if cfg!(target_endian = "little") {
[
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x08, 0x22,
]
} else {
[
0x22, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
]
});
pub const ONE: Decimal128 = Decimal128::from_ne_bytes(if cfg!(target_endian = "little") {
[
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x08, 0x22,
]
} else {
[
0x22, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
]
});
const TWO_POW_32: Decimal128 = Decimal128::from_ne_bytes(if cfg!(target_endian = "little") {
[
0x7A, 0xB5, 0xAF, 0x15, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x08, 0x22,
]
} else {
[
0x22, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x15, 0xAF, 0xB5, 0x7A,
]
});
pub fn from_le_bytes(mut bytes: [u8; 16]) -> Decimal128 {
if cfg!(target_endian = "big") {
bytes.reverse();
}
Decimal128::from_ne_bytes(bytes)
}
pub fn from_be_bytes(mut bytes: [u8; 16]) -> Decimal128 {
if cfg!(target_endian = "little") {
bytes.reverse();
}
Decimal128::from_ne_bytes(bytes)
}
pub const fn from_ne_bytes(bytes: [u8; 16]) -> Decimal128 {
Decimal128 {
inner: decnumber_sys::decQuad { bytes },
}
}
pub fn to_le_bytes(&self) -> [u8; 16] {
let mut bytes = self.to_ne_bytes();
if cfg!(target_endian = "big") {
bytes.reverse();
}
bytes
}
pub fn to_be_bytes(&self) -> [u8; 16] {
let mut bytes = self.to_ne_bytes();
if cfg!(target_endian = "little") {
bytes.reverse();
}
bytes
}
pub fn to_ne_bytes(&self) -> [u8; 16] {
self.inner.bytes
}
pub fn class(&self) -> Class {
Class::from_c(unsafe { decnumber_sys::decQuadClass(&self.inner) })
}
pub fn digits(&self) -> u32 {
unsafe { decnumber_sys::decQuadDigits(&self.inner) }
}
pub fn coefficient(&self) -> i128 {
let mut dpd = if cfg!(target_endian = "big") {
u128::from_be_bytes(self.inner.bytes)
} else {
u128::from_le_bytes(self.inner.bytes)
};
let dpd_mask = 0b11_1111_1111;
let mut dpd2bin = |include_mill: bool| -> i128 {
let mut r: i128 = 0;
r += i128::from(unsafe { decnumber_sys::DPD2BIN[dpd as usize & dpd_mask] });
dpd >>= 10;
r += i128::from(unsafe { decnumber_sys::DPD2BINK[dpd as usize & dpd_mask] });
dpd >>= 10;
if include_mill {
r += i128::from(unsafe { decnumber_sys::DPD2BINM[dpd as usize & dpd_mask] });
dpd >>= 10;
}
r
};
let mut r = dpd2bin(true);
r += dpd2bin(true) * 1_000_000_000;
r += dpd2bin(true) * 1_000_000_000_000_000_000;
r += dpd2bin(false) * 1_000_000_000_000_000_000_000_000_000;
let h = i128::from(unsafe { decnumber_sys::DECCOMBMSD[(dpd >> 12) as usize] });
if h > 0 {
r += h * 1_000_000_000_000_000_000_000_000_000_000_000;
}
if self.is_negative() {
r *= -1;
}
r
}
pub fn coefficient_digits(&self) -> [u8; decnumber_sys::DECQUAD_Pmax] {
let mut buf = [0u8; decnumber_sys::DECQUAD_Pmax];
unsafe {
decnumber_sys::decQuadGetCoefficient(&self.inner, buf.as_mut_ptr() as *mut u8);
}
buf
}
pub fn exponent(&self) -> i32 {
unsafe { decnumber_sys::decQuadGetExponent(&self.inner) }
}
pub fn canonical(mut self) -> Decimal128 {
let inner = &mut self.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadCanonical(inner, inner);
}
self
}
pub fn is_canonical(&self) -> bool {
unsafe { decnumber_sys::decQuadIsCanonical(&self.inner) != 0 }
}
pub fn is_finite(&self) -> bool {
unsafe { decnumber_sys::decQuadIsFinite(&self.inner) != 0 }
}
pub fn is_infinite(&self) -> bool {
unsafe { decnumber_sys::decQuadIsInfinite(&self.inner) != 0 }
}
pub fn is_integer(&self) -> bool {
unsafe { decnumber_sys::decQuadIsInteger(&self.inner) != 0 }
}
pub fn is_logical(&self) -> bool {
unsafe { decnumber_sys::decQuadIsInteger(&self.inner) != 0 }
}
pub fn is_nan(&self) -> bool {
unsafe { decnumber_sys::decQuadIsNaN(&self.inner) != 0 }
}
pub fn is_negative(&self) -> bool {
unsafe { decnumber_sys::decQuadIsNegative(&self.inner) != 0 }
}
pub fn is_normal(&self) -> bool {
unsafe { decnumber_sys::decQuadIsNormal(&self.inner) != 0 }
}
pub fn is_positive(&self) -> bool {
unsafe { decnumber_sys::decQuadIsPositive(&self.inner) != 0 }
}
pub fn is_signaling_nan(&self) -> bool {
unsafe { decnumber_sys::decQuadIsSignaling(&self.inner) != 0 }
}
pub fn is_signed(&self) -> bool {
unsafe { decnumber_sys::decQuadIsSigned(&self.inner) != 0 }
}
pub fn is_subnormal(&self) -> bool {
unsafe { decnumber_sys::decQuadIsSubnormal(&self.inner) != 0 }
}
pub fn is_zero(&self) -> bool {
unsafe { decnumber_sys::decQuadIsZero(&self.inner) != 0 }
}
pub fn quantum_matches(&self, rhs: &Decimal128) -> bool {
unsafe { decnumber_sys::decQuadSameQuantum(&self.inner, &rhs.inner) != 0 }
}
pub fn total_cmp(&self, rhs: &Decimal128) -> Ordering {
let mut d = Decimal128::ZERO;
unsafe {
decnumber_sys::decQuadCompareTotal(&mut d.inner, &self.inner, &rhs.inner);
}
if d.is_positive() {
Ordering::Greater
} else if d.is_negative() {
Ordering::Less
} else {
debug_assert!(d.is_zero());
Ordering::Equal
}
}
pub fn to_standard_notation_string(&self) -> String {
if !self.is_finite() {
return self.to_string();
}
let mut digits = [b'0'; decnumber_sys::DECQUAD_Pmax];
let mut digits_idx = 0;
let (sourlo, sourml, sourmh, sourhi) = if cfg!(target_endian = "little") {
(
u32::from_ne_bytes(self.inner.bytes[0..4].try_into().unwrap()) as usize,
u32::from_ne_bytes(self.inner.bytes[4..8].try_into().unwrap()) as usize,
u32::from_ne_bytes(self.inner.bytes[8..12].try_into().unwrap()) as usize,
u32::from_ne_bytes(self.inner.bytes[12..16].try_into().unwrap()) as usize,
)
} else {
(
u32::from_ne_bytes(self.inner.bytes[12..16].try_into().unwrap()) as usize,
u32::from_ne_bytes(self.inner.bytes[8..12].try_into().unwrap()) as usize,
u32::from_ne_bytes(self.inner.bytes[4..8].try_into().unwrap()) as usize,
u32::from_ne_bytes(self.inner.bytes[0..4].try_into().unwrap()) as usize,
)
};
let comb = ((sourhi >> 26) & 0x1f) as usize;
let msd = unsafe { decnumber_sys::DECCOMBMSD[comb] };
if msd > 0 {
digits[digits_idx] = b'0' + msd as u8;
digits_idx += 1;
}
#[allow(unused_assignments)]
let mut dpd: usize = 0;
dpd = (sourhi >> 4) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = ((sourhi & 0xf) << 6) | (sourmh >> 26); dpd2char!(dpd, digits, digits_idx);
dpd = (sourmh >> 16) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = (sourmh >> 6) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = ((sourmh & 0x3f) << 4) | (sourml >> 28); dpd2char!(dpd, digits, digits_idx);
dpd = (sourml >> 18) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = (sourml >> 8) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = ((sourml & 0xff) << 2) | (sourlo >> 30); dpd2char!(dpd, digits, digits_idx);
dpd = (sourlo >> 20) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = (sourlo >> 10) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
dpd = (sourlo) & 0x3ff; dpd2char!(dpd, digits, digits_idx);
stringify_digits!(self, digits, digits_idx)
}
}
impl Default for Decimal128 {
fn default() -> Decimal128 {
Decimal128::ZERO
}
}
impl fmt::Debug for Decimal128 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl fmt::Display for Decimal128 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut buf = ['\0'; decnumber_sys::DECQUAD_String];
let c_str = unsafe {
if f.alternate() {
decnumber_sys::decQuadToEngString(&self.inner, buf.as_mut_ptr() as *mut c_char);
} else {
decnumber_sys::decQuadToString(&self.inner, buf.as_mut_ptr() as *mut c_char);
}
CStr::from_ptr(buf.as_ptr() as *const c_char)
};
f.write_str(c_str.to_str().expect("decQuadToString yields valid UTF-8"))
}
}
impl FromStr for Decimal128 {
type Err = ParseDecimalError;
fn from_str(s: &str) -> Result<Decimal128, ParseDecimalError> {
Context::<Decimal128>::default().parse(s)
}
}
impl From<i32> for Decimal128 {
fn from(n: i32) -> Decimal128 {
let mut d = Decimal128::ZERO;
unsafe {
decnumber_sys::decQuadFromInt32(&mut d.inner, n);
}
d
}
}
impl From<u32> for Decimal128 {
fn from(n: u32) -> Decimal128 {
let mut d = Decimal128::ZERO;
unsafe {
decnumber_sys::decQuadFromUInt32(&mut d.inner, n);
}
d
}
}
impl From<i64> for Decimal128 {
fn from(n: i64) -> Decimal128 {
let mut cx = Context::<Decimal128>::default();
let d = from_signed_int!(Decimal128, cx, n);
debug_assert!(!cx.status().any());
d
}
}
impl From<u64> for Decimal128 {
fn from(n: u64) -> Decimal128 {
let mut cx = Context::<Decimal128>::default();
let d = from_unsigned_int!(Decimal128, cx, n);
debug_assert!(!cx.status().any());
d
}
}
impl From<Decimal32> for Decimal128 {
fn from(d32: Decimal32) -> Decimal128 {
Decimal128::from(Decimal64::from(d32))
}
}
impl From<Decimal64> for Decimal128 {
fn from(d64: Decimal64) -> Decimal128 {
let mut d128 = Decimal128::ZERO;
unsafe {
decnumber_sys::decDoubleToWider(&d64.inner, &mut d128.inner);
}
d128
}
}
impl PartialOrd for Decimal128 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Context::<Decimal128>::default().partial_cmp(*self, *other)
}
}
impl PartialEq for Decimal128 {
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Equal)
}
}
impl Neg for Decimal128 {
type Output = Decimal128;
fn neg(self) -> Decimal128 {
Context::<Decimal128>::default().minus(self)
}
}
impl Add<Decimal128> for Decimal128 {
type Output = Decimal128;
fn add(self, rhs: Decimal128) -> Decimal128 {
Context::<Decimal128>::default().add(self, rhs)
}
}
impl AddAssign<Decimal128> for Decimal128 {
fn add_assign(&mut self, rhs: Decimal128) {
*self = Context::<Decimal128>::default().add(*self, rhs);
}
}
impl Div<Decimal128> for Decimal128 {
type Output = Decimal128;
fn div(self, rhs: Decimal128) -> Decimal128 {
Context::<Decimal128>::default().div(self, rhs)
}
}
impl DivAssign<Decimal128> for Decimal128 {
fn div_assign(&mut self, rhs: Decimal128) {
*self = Context::<Decimal128>::default().div(*self, rhs);
}
}
impl Mul<Decimal128> for Decimal128 {
type Output = Decimal128;
fn mul(self, rhs: Decimal128) -> Decimal128 {
Context::<Decimal128>::default().mul(self, rhs)
}
}
impl MulAssign<Decimal128> for Decimal128 {
fn mul_assign(&mut self, rhs: Decimal128) {
*self = Context::<Decimal128>::default().mul(*self, rhs);
}
}
impl Rem<Decimal128> for Decimal128 {
type Output = Decimal128;
fn rem(self, rhs: Decimal128) -> Decimal128 {
Context::<Decimal128>::default().rem(self, rhs)
}
}
impl RemAssign<Decimal128> for Decimal128 {
fn rem_assign(&mut self, rhs: Decimal128) {
*self = Context::<Decimal128>::default().rem(*self, rhs);
}
}
impl Sub<Decimal128> for Decimal128 {
type Output = Decimal128;
fn sub(self, rhs: Decimal128) -> Decimal128 {
Context::<Decimal128>::default().sub(self, rhs)
}
}
impl SubAssign<Decimal128> for Decimal128 {
fn sub_assign(&mut self, rhs: Decimal128) {
*self = Context::<Decimal128>::default().sub(*self, rhs);
}
}
impl Sum for Decimal128 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Decimal128>,
{
let mut cx = Context::<Decimal128>::default();
let mut sum = Decimal128::ZERO;
for d in iter {
sum = cx.add(sum, d);
}
sum
}
}
impl<'a> Sum<&'a Decimal128> for Decimal128 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Decimal128>,
{
iter.copied().sum()
}
}
impl Product for Decimal128 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Decimal128>,
{
let mut cx = Context::<Decimal128>::default();
let mut product = Decimal128::ONE;
for d in iter {
product = cx.mul(product, d);
}
product
}
}
impl<'a> Product<&'a Decimal128> for Decimal128 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Decimal128>,
{
iter.copied().product()
}
}
impl Default for Context<Decimal128> {
fn default() -> Context<Decimal128> {
let mut ctx = MaybeUninit::<decnumber_sys::decContext>::uninit();
let ctx = unsafe {
decnumber_sys::decContextDefault(ctx.as_mut_ptr(), decnumber_sys::DEC_INIT_DECQUAD);
ctx.assume_init()
};
Context {
inner: ctx,
_phantom: PhantomData,
}
}
}
impl Context<Decimal128> {
pub fn parse<S>(&mut self, s: S) -> Result<Decimal128, ParseDecimalError>
where
S: Into<Vec<u8>>,
{
let c_string = CString::new(s).map_err(|_| ParseDecimalError)?;
let mut d = Decimal128::ZERO;
unsafe {
decnumber_sys::decQuadFromString(&mut d.inner, c_string.as_ptr(), &mut self.inner);
}
if (self.inner.status & decnumber_sys::DEC_Conversion_syntax) != 0 {
Err(ParseDecimalError)
} else {
Ok(d)
}
}
pub fn from_decimal<const N: usize>(&mut self, d: &Decimal<N>) -> Decimal128 {
let mut d128 = Decimal128::ZERO;
unsafe {
decnumber_sys::decimal128FromNumber(&mut d128.inner, d.as_ptr(), &mut self.inner);
}
d128
}
pub fn from_i128(&mut self, n: i128) -> Decimal128 {
from_signed_int!(Decimal128, self, n)
}
pub fn from_u128(&mut self, n: u128) -> Decimal128 {
from_unsigned_int!(Decimal128, self, n)
}
pub fn abs(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadAbs(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn add(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadAdd(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn and(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadAnd(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn div(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadDivide(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn div_integer(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadDivideInteger(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn fma(&mut self, mut x: Decimal128, y: Decimal128, z: Decimal128) -> Decimal128 {
let x_inner = &mut x.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadFMA(x_inner, x_inner, &y.inner, &z.inner, &mut self.inner);
}
x
}
pub fn invert(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadInvert(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn logb(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadLogB(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn max(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadMax(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn max_abs(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadMaxMag(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn min(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadMin(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn min_abs(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadMinMag(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn minus(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadMinus(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn mul(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadMultiply(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn next_minus(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadNextMinus(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn next_plus(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadNextPlus(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn next_toward(&mut self, mut x: Decimal128, y: Decimal128) -> Decimal128 {
let x_inner = &mut x.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadNextToward(x_inner, x_inner, &y.inner, &mut self.inner);
}
x
}
pub fn partial_cmp(&mut self, lhs: Decimal128, rhs: Decimal128) -> Option<Ordering> {
let mut d = Decimal128::ZERO;
unsafe {
decnumber_sys::decQuadCompare(&mut d.inner, &lhs.inner, &rhs.inner, &mut self.inner);
}
if d.is_positive() {
Some(Ordering::Greater)
} else if d.is_negative() {
Some(Ordering::Less)
} else if d.is_zero() {
Some(Ordering::Equal)
} else {
debug_assert!(d.is_nan());
None
}
}
pub fn plus(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadPlus(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn quantize(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadQuantize(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn reduce(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadReduce(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn rem(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadRemainder(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn rem_near(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadRemainderNear(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn rotate(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadRotate(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn round(&mut self, mut n: Decimal128) -> Decimal128 {
let n_inner = &mut n.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadToIntegralExact(n_inner, n_inner, &mut self.inner);
}
n
}
pub fn scaleb(&mut self, mut x: Decimal128, y: Decimal128) -> Decimal128 {
let x_inner = &mut x.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadScaleB(x_inner, x_inner, &y.inner, &mut self.inner);
}
x
}
pub fn set_exponent(&mut self, d: &mut Decimal128, e: i32) {
unsafe {
decnumber_sys::decQuadSetExponent(&mut d.inner, &mut self.inner, e);
}
}
pub fn shift(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadShift(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn rescale(&mut self, x: &mut Decimal128, s: i32) {
let e = x.exponent();
*x = self.shift(*x, Decimal128::from(e - s));
self.set_exponent(x, s);
}
pub fn sub(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadSubtract(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn or(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadOr(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
pub fn xor(&mut self, mut lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
let lhs_inner = &mut lhs.inner as *mut decnumber_sys::decQuad;
unsafe {
decnumber_sys::decQuadXor(lhs_inner, lhs_inner, &rhs.inner, &mut self.inner);
}
lhs
}
}
#[cfg(feature = "num-traits")]
impl One for Decimal128 {
#[inline]
fn one() -> Self {
Self::ONE
}
}
#[cfg(feature = "num-traits")]
impl Zero for Decimal128 {
#[inline]
fn zero() -> Self {
Self::ZERO
}
#[inline]
fn is_zero(&self) -> bool {
self.is_zero()
}
}
#[cfg(feature = "num-traits")]
impl MulAdd for Decimal128 {
type Output = Self;
fn mul_add(self, a: Self, b: Self) -> Self::Output {
Context::<Self>::default().fma(self, a, b)
}
}
#[cfg(feature = "num-traits")]
impl MulAddAssign for Decimal128 {
#[inline]
fn mul_add_assign(&mut self, a: Self, b: Self) {
*self = self.mul_add(a, b)
}
}