use super::Class;
use super::Status;
use super::Rounding;
use context::*;
use libc::c_char;
#[cfg(feature = "ord_subset")]
use ord_subset;
#[cfg(feature = "rustc-serialize")]
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
#[cfg(feature = "serde")]
use serde;
use std::mem::MaybeUninit;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::default::Default;
use std::ffi::{CStr, CString};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::Sum;
use std::num::FpCategory;
use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Rem, RemAssign,
Neg, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl,
ShlAssign, Shr, ShrAssign};
use std::str::FromStr;
use std::str::from_utf8_unchecked;
thread_local!(static CTX: RefCell<Context> = RefCell::new(d128::default_context()));
#[repr(C)]
#[derive(Clone, Copy)]
pub struct d128 {
bytes: [u8; 16],
}
#[repr(C)]
#[derive(Clone, Copy)]
struct decNumber {
digits: i32,
exponent: i32,
bits: u8,
lsu: [u16; 12],
}
impl Default for d128 {
fn default() -> Self {
d128::zero()
}
}
#[cfg(feature = "ord_subset")]
impl ord_subset::OrdSubset for d128 {
fn is_outside_order(&self) -> bool {
self.is_nan()
}
}
#[cfg(feature = "ord_subset")]
impl Into<ord_subset::OrdVar<d128>> for d128 {
fn into(self) -> ord_subset::OrdVar<d128> {
ord_subset::OrdVar::new(self)
}
}
#[cfg(feature = "rustc-serialize")]
impl Decodable for d128 {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
let s = d.read_str()?;
Ok(Self::from_str(&s).expect("unreachable"))
}
}
#[cfg(feature = "rustc-serialize")]
impl Encodable for d128 {
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
e.emit_str(&format!("{}", self))
}
}
impl Hash for d128 {
fn hash<H: Hasher>(&self, state: &mut H) {
self.bytes.hash(state);
}
}
#[cfg(feature = "serde")]
impl serde::ser::Serialize for d128 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::ser::Serializer
{
serializer.serialize_str(&self.to_string())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::de::Deserialize<'de> for d128 {
fn deserialize<D>(deserializer: D) -> Result<d128, D::Error>
where D: serde::de::Deserializer<'de>
{
deserializer.deserialize_str(d128Visitor)
}
}
#[cfg(feature = "serde")]
#[allow(non_camel_case_types)]
struct d128Visitor;
#[cfg(feature = "serde")]
impl<'de> serde::de::Visitor<'de> for d128Visitor {
type Value = d128;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a d128 value")
}
fn visit_str<E>(self, s: &str) -> Result<d128, E>
where E: serde::de::Error
{
use serde::de::Unexpected;
d128::from_str(s).map_err(|_| E::invalid_value(Unexpected::Str(s), &self))
}
}
impl From<i32> for d128 {
fn from(val: i32) -> d128 {
unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadFromInt32(res.as_mut_ptr(), val)
}
}
}
impl From<u32> for d128 {
fn from(val: u32) -> d128 {
unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadFromUInt32(res.as_mut_ptr(), val)
}
}
}
impl From<u64> for d128 {
fn from(mut val: u64) -> d128 {
let mut bcd = [0u8; 34];
let mut i = 33;
while val > 0 {
bcd[i] = (val % 10) as u8;
val /= 10;
i -= 1;
}
unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadFromBCD(res.as_mut_ptr(), 0, bcd.as_ptr(), 0)
}
}
}
impl From<i64> for d128 {
fn from(val: i64) -> d128 {
if val < 0 {
-d128::from(!(val as u64) + 1)
} else {
d128::from(val as u64)
}
}
}
impl AsRef<d128> for d128 {
fn as_ref(&self) -> &d128 {
&self
}
}
impl FromStr for d128 {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
let cstr = match CString::new(s) {
Err(..) => CString::new("qNaN").unwrap(),
Ok(cstr) => cstr,
};
d128::with_context(|ctx| {
let out: d128 = unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
decQuadFromString(res.as_mut_ptr(), cstr.as_ptr(), ctx);
res.assume_init()
};
Ok(out)
})
}
}
impl Into<i32> for d128 {
fn into(self) -> i32 {
d128::with_context(|ctx| unsafe { decQuadToInt32(&self, ctx, ctx.rounding) })
}
}
impl Into<u32> for d128 {
fn into(self) -> u32 {
d128::with_context(|ctx| unsafe { decQuadToUInt32(&self, ctx, ctx.rounding) })
}
}
impl fmt::Display for d128 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut buf = [0; 43];
unsafe {
decQuadToString(self, buf.as_mut().as_mut_ptr());
let cstr = CStr::from_ptr(buf.as_ptr());
fmt.pad(from_utf8_unchecked(cstr.to_bytes()))
}
}
}
impl fmt::Debug for d128 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, fmt)
}
}
impl fmt::LowerExp for d128 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut buf = [0; 43];
unsafe {
decQuadToEngString(self, buf.as_mut().as_mut_ptr());
let cstr = CStr::from_ptr(buf.as_ptr());
fmt.pad(from_utf8_unchecked(cstr.to_bytes()))
}
}
}
impl fmt::LowerHex for d128 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
for b in self.bytes.iter().rev() {
write!(fmt, "{:02x}", b)?;
}
Ok(())
}
}
impl PartialEq<d128> for d128 {
fn eq(&self, other: &d128) -> bool {
self.compare(other).is_zero()
}
}
impl PartialOrd<d128> for d128 {
fn partial_cmp(&self, other: &d128) -> Option<::std::cmp::Ordering> {
use std::cmp::Ordering;
match self.compare(other) {
v if v.is_nan() => None,
v if v.is_zero() => Some(Ordering::Equal),
v if v.is_positive() => Some(Ordering::Greater),
v if v.is_negative() => Some(Ordering::Less),
_ => unreachable!(),
}
}
}
macro_rules! ffi_unary_op {
($(#[$attr:meta])* impl $op:ident, $method:ident, $ffi:ident for $t:ident) => {
$(#[$attr])*
impl $op for $t {
type Output = $t;
fn $method(mut self) -> $t {
$t::with_context(|ctx| {
unsafe { *$ffi(&mut self, &self, ctx)}
})
}
}
impl<'a> $op for &'a $t {
type Output = $t;
fn $method(self) -> $t {
$t::with_context(|ctx| {
unsafe {
let mut res: MaybeUninit<$t> = MaybeUninit::uninit();
*$ffi(res.as_mut_ptr(), self, ctx)
}
})
}
}
}
}
macro_rules! ffi_binary_op {
($(#[$attr:meta])* impl $op:ident, $method:ident, $ffi:ident for $t:ident) => {
$(#[$attr])*
impl $op<$t> for $t {
type Output = $t;
fn $method(mut self, other: $t) -> $t {
$t::with_context(|ctx| {
unsafe { *$ffi(&mut self, &self, &other, ctx)}
})
}
}
impl<'a> $op<$t> for &'a $t {
type Output = $t;
fn $method(self, mut other: $t) -> $t {
$t::with_context(|ctx| {
unsafe { *$ffi(&mut other, self, &other, ctx) }
})
}
}
impl<'a> $op<&'a$t> for $t {
type Output = $t;
fn $method(mut self, other: &'a $t) -> $t {
$t::with_context(|ctx| {
unsafe { *$ffi(&mut self, &self, other, ctx) }
})
}
}
impl<'a, 'b> $op<&'a $t> for &'b $t {
type Output = $t;
fn $method(self, other: &'a $t) -> $t {
$t::with_context(|ctx| {
unsafe {
let mut res: MaybeUninit<$t> = MaybeUninit::uninit();
*$ffi(res.as_mut_ptr(), self, other, ctx)
}
})
}
}
}
}
macro_rules! ffi_unary_assign_op {
($(#[$attr:meta])* impl $op:ident, $method:ident, $ffi:ident for $t:ident) => {
$(#[$attr])*
impl $op<$t> for $t {
fn $method(&mut self, other: $t) {
$t::with_context(|ctx| {
unsafe { $ffi(self, self, &other, ctx); }
})
}
}
}
}
ffi_binary_op!(impl Add, add, decQuadAdd for d128);
ffi_binary_op!(impl Sub, sub, decQuadSubtract for d128);
ffi_binary_op!(impl Mul, mul, decQuadMultiply for d128);
ffi_binary_op!(impl Div, div, decQuadDivide for d128);
ffi_binary_op!(
impl BitAnd, bitand, decQuadAnd for d128);
ffi_binary_op!(
impl BitOr, bitor, decQuadOr for d128);
ffi_binary_op!(
impl BitXor, bitxor, decQuadXor for d128);
ffi_binary_op!(impl Rem, rem, decQuadRemainder for d128);
ffi_unary_assign_op!(impl AddAssign, add_assign, decQuadAdd for d128);
ffi_unary_assign_op!(impl SubAssign, sub_assign, decQuadSubtract for d128);
ffi_unary_assign_op!(impl MulAssign, mul_assign, decQuadMultiply for d128);
ffi_unary_assign_op!(impl DivAssign, div_assign, decQuadDivide for d128);
ffi_unary_assign_op!(impl BitAndAssign, bitand_assign, decQuadAnd for d128);
ffi_unary_assign_op!(impl BitOrAssign, bitor_assign, decQuadOr for d128);
ffi_unary_assign_op!(impl BitXorAssign, bitxor_assign, decQuadXor for d128);
ffi_unary_assign_op!(impl RemAssign, rem_assign, decQuadRemainder for d128);
ffi_unary_op!(impl Neg, neg, decQuadMinus for d128);
ffi_unary_op!(
impl Not, not, decQuadInvert for d128);
impl Shl<usize> for d128 {
type Output = d128;
fn shl(mut self, amount: usize) -> d128 {
let shift = d128::from(amount as u32);
d128::with_context(|ctx| unsafe { *decQuadShift(&mut self, &self, &shift, ctx) })
}
}
impl<'a> Shl<usize> for &'a d128 {
type Output = d128;
fn shl(self, amount: usize) -> d128 {
let shift = d128::from(amount as u32);
d128::with_context(|ctx| {
unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadShift(res.as_mut_ptr(), self, &shift, ctx)
}
})
}
}
impl ShlAssign<usize> for d128 {
fn shl_assign(&mut self, amount: usize) {
let shift = d128::from(amount as u32);
d128::with_context(|ctx| {
unsafe {
decQuadShift(self, self, &shift, ctx);
}
})
}
}
impl Shr<usize> for d128 {
type Output = d128;
fn shr(mut self, amount: usize) -> d128 {
let shift = -d128::from(amount as u32);
d128::with_context(|ctx| unsafe { *decQuadShift(&mut self, &self, &shift, ctx) })
}
}
impl<'a> Shr<usize> for &'a d128 {
type Output = d128;
fn shr(self, amount: usize) -> d128 {
let shift = -d128::from(amount as u32);
d128::with_context(|ctx| {
unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadShift(res.as_mut_ptr(), self, &shift, ctx)
}
})
}
}
impl ShrAssign<usize> for d128 {
fn shr_assign(&mut self, amount: usize) {
let shift = -d128::from(amount as u32);
d128::with_context(|ctx| {
unsafe {
decQuadShift(self, self, &shift, ctx);
}
})
}
}
impl<T> Sum<T> for d128 where T: Borrow<d128> {
fn sum<I: IntoIterator<Item = T>>(iter: I) -> d128 {
iter.into_iter()
.fold(d128::zero(), |acc, val|
acc + val.borrow())
}
}
impl d128 {
fn default_context() -> Context {
unsafe {
let mut res: MaybeUninit<Context> = MaybeUninit::uninit();
let out = decContextDefault(res.as_mut_ptr(), 128);
*out
}
}
fn with_context<F, R>(f: F) -> R
where F: FnOnce(&mut Context) -> R
{
CTX.with(|ctx| f(&mut ctx.borrow_mut()))
}
pub unsafe fn from_raw_bytes(bytes: [u8; 16]) -> d128 {
d128 { bytes: bytes }
}
pub fn to_raw_bytes(&self) -> [u8; 16] {
self.bytes
}
pub fn get_status() -> Status {
d128::with_context(|ctx| Status::from_bits_truncate(ctx.status))
}
pub fn set_status(status: Status) {
d128::with_context(|ctx| ctx.status = status.bits());
}
pub fn from_hex(s: &str) -> d128 {
if s.len() != 32 {
Self::from_str("qNaN").unwrap()
} else {
unsafe {
let mut res: d128 = MaybeUninit::zeroed().assume_init();
for (i, octet) in s.as_bytes().chunks(2).rev().enumerate() {
res.bytes[i] = match u8::from_str_radix(from_utf8_unchecked(octet), 16) {
Ok(val) => val,
Err(..) => return Self::from_str("qNaN").unwrap(),
};
}
res
}
}
}
pub fn zero() -> d128 {
unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadZero(res.as_mut_ptr())
}
}
pub fn infinity() -> d128 {
d128!(Infinity)
}
pub fn neg_infinity() -> d128 {
d128!(-Infinity)
}
pub fn abs(mut self) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadAbs(&mut self, &self, ctx) })
}
pub fn mul_add<O: AsRef<d128>>(mut self, a: O, b: O) -> d128 {
d128::with_context(|ctx| unsafe {
*decQuadFMA(&mut self, &self, a.as_ref(), b.as_ref(), ctx)
})
}
pub fn logb(mut self) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadLogB(&mut self, &self, ctx) })
}
pub fn max<O: AsRef<d128>>(mut self, other: O) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadMax(&mut self, &self, other.as_ref(), ctx) })
}
pub fn min<O: AsRef<d128>>(mut self, other: O) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadMin(&mut self, &self, other.as_ref(), ctx) })
}
pub fn next(mut self) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadNextPlus(&mut self, &self, ctx) })
}
pub fn previous(mut self) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadNextMinus(&mut self, &self, ctx) })
}
pub fn pow<O: AsRef<d128>>(mut self, exp: O) -> d128 {
d128::with_context(|ctx| unsafe {
let mut num_self : MaybeUninit<decNumber> = MaybeUninit::uninit();
let mut num_exp : MaybeUninit<decNumber> = MaybeUninit::uninit();
decimal128ToNumber(&self, num_self.as_mut_ptr());
decimal128ToNumber(exp.as_ref(), num_exp.as_mut_ptr());
let mut num_self = num_self.assume_init();
let num_exp = num_exp.assume_init();
decNumberPower(&mut num_self, &num_self, &num_exp, ctx);
*decimal128FromNumber(&mut self, &num_self, ctx)
})
}
pub fn exp<O: AsRef<d128>>(mut self, exp: O) -> d128 {
d128::with_context(|ctx| unsafe {
let mut num_self : MaybeUninit<decNumber> = MaybeUninit::uninit();
let mut num_exp : MaybeUninit<decNumber> = MaybeUninit::uninit();
decimal128ToNumber(&self, num_self.as_mut_ptr());
decimal128ToNumber(exp.as_ref(), num_exp.as_mut_ptr());
let mut num_self = num_self.assume_init();
let num_exp = num_exp.assume_init();
decNumberExp(&mut num_self, &num_self, &num_exp, ctx);
*decimal128FromNumber(&mut self, &num_self, ctx)
})
}
pub fn ln(mut self) -> d128 {
d128::with_context(|ctx| unsafe {
let mut num_self : MaybeUninit<decNumber> = MaybeUninit::uninit();
decimal128ToNumber(&self, num_self.as_mut_ptr());
let mut num_self = num_self.assume_init();
decNumberLn(&mut num_self, &num_self, ctx);
*decimal128FromNumber(&mut self, &num_self, ctx)
})
}
pub fn log10(mut self) -> d128 {
d128::with_context(|ctx| unsafe {
let mut num_self: MaybeUninit<decNumber> = MaybeUninit::uninit();
decimal128ToNumber(&self, num_self.as_mut_ptr());
let mut num_self = num_self.assume_init();
decNumberLog10(&mut num_self, &num_self, ctx);
*decimal128FromNumber(&mut self, &num_self, ctx)
})
}
pub fn towards<O: AsRef<d128>>(mut self, other: O) -> d128 {
d128::with_context(|ctx| unsafe {
*decQuadNextToward(&mut self, &self, other.as_ref(), ctx)
})
}
pub fn quantize<O: AsRef<d128>>(mut self, other: O) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadQuantize(&mut self, &self, other.as_ref(), ctx) })
}
pub fn reduce(mut self) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadReduce(&mut self, &self, ctx) })
}
pub fn rotate<O: AsRef<d128>>(mut self, amount: O) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadRotate(&mut self, &self, amount.as_ref(), ctx) })
}
pub fn scaleb<O: AsRef<d128>>(mut self, other: O) -> d128 {
d128::with_context(|ctx| unsafe { *decQuadScaleB(&mut self, &self, other.as_ref(), ctx) })
}
pub fn compare<O: AsRef<d128>>(&self, other: O) -> d128 {
d128::with_context(|ctx| unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadCompare(res.as_mut_ptr(), self, other.as_ref(), ctx)
})
}
pub fn compare_total<O: AsRef<d128>>(&self, other: O) -> d128 {
d128::with_context(|ctx| unsafe {
let mut res: MaybeUninit<d128> = MaybeUninit::uninit();
*decQuadCompareTotal(res.as_mut_ptr(), self, other.as_ref(), ctx)
})
}
pub fn canonical(mut self) -> d128 {
unsafe { *decQuadCanonical(&mut self, &self) }
}
pub fn class(&self) -> Class {
unsafe { decQuadClass(self) }
}
pub fn classify(&self) -> FpCategory {
use std::num::FpCategory::*;
use super::Class::*;
match self.class() {
Qnan | Snan => Nan,
PosInf | NegInf => Infinite,
PosZero | NegZero => Zero,
PosNormal | NegNormal => Normal,
PosSubnormal | NegSubnormal => Subnormal,
}
}
pub fn digits(&self) -> u32 {
unsafe { decQuadDigits(self) }
}
pub fn is_canonical(&self) -> bool {
unsafe { decQuadIsCanonical(self) != 0 }
}
pub fn is_finite(&self) -> bool {
unsafe { decQuadIsFinite(self) != 0 }
}
pub fn is_integer(&self) -> bool {
unsafe { decQuadIsInteger(self) != 0 }
}
pub fn is_logical(&self) -> bool {
unsafe { decQuadIsLogical(self) != 0 }
}
pub fn is_infinite(&self) -> bool {
unsafe { decQuadIsInfinite(self) != 0 }
}
pub fn is_nan(&self) -> bool {
unsafe { decQuadIsNaN(self) != 0 }
}
pub fn is_negative(&self) -> bool {
unsafe { decQuadIsNegative(self) != 0 }
}
pub fn is_normal(&self) -> bool {
unsafe { decQuadIsNormal(self) != 0 }
}
pub fn is_positive(&self) -> bool {
unsafe { decQuadIsPositive(self) != 0 }
}
pub fn is_signaling(&self) -> bool {
unsafe { decQuadIsSignaling(self) != 0 }
}
pub fn is_signed(&self) -> bool {
unsafe { decQuadIsSigned(self) != 0 }
}
pub fn is_subnormal(&self) -> bool {
unsafe { decQuadIsSubnormal(self) != 0 }
}
pub fn is_zero(&self) -> bool {
unsafe { decQuadIsZero(self) != 0 }
}
}
extern "C" {
fn decContextDefault(ctx: *mut Context, kind: u32) -> *mut Context;
fn decQuadFromBCD(res: *mut d128, exp: i32, bcd: *const u8, sign: i32) -> *mut d128;
fn decQuadFromInt32(res: *mut d128, src: i32) -> *mut d128;
fn decQuadFromString(res: *mut d128, s: *const c_char, ctx: *mut Context) -> *mut d128;
fn decQuadFromUInt32(res: *mut d128, src: u32) -> *mut d128;
fn decQuadToString(src: *const d128, s: *mut c_char) -> *mut c_char;
fn decQuadToInt32(src: *const d128, ctx: *mut Context, round: Rounding) -> i32;
fn decQuadToUInt32(src: *const d128, ctx: *mut Context, round: Rounding) -> u32;
fn decQuadToEngString(res: *const d128, s: *mut c_char) -> *mut c_char;
fn decQuadZero(res: *mut d128) -> *mut d128;
fn decQuadAbs(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadAdd(res: *mut d128, a: *const d128, b: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadAnd(res: *mut d128, a: *const d128, b: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadDivide(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadFMA(res: *mut d128,
a: *const d128,
b: *const d128,
c: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadInvert(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadLogB(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadMax(res: *mut d128, a: *const d128, b: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadMin(res: *mut d128, a: *const d128, b: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadMinus(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadMultiply(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadNextMinus(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadNextPlus(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadNextToward(res: *mut d128,
src: *const d128,
other: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadOr(res: *mut d128, a: *const d128, b: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadQuantize(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadReduce(res: *mut d128, src: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadRemainder(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadRotate(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadScaleB(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadShift(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadSubtract(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadXor(res: *mut d128, a: *const d128, b: *const d128, ctx: *mut Context) -> *mut d128;
fn decQuadCompare(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadCompareTotal(res: *mut d128,
a: *const d128,
b: *const d128,
ctx: *mut Context)
-> *mut d128;
fn decQuadCanonical(res: *mut d128, src: *const d128) -> *mut d128;
fn decQuadClass(src: *const d128) -> Class;
fn decQuadDigits(src: *const d128) -> u32;
fn decQuadIsCanonical(src: *const d128) -> u32;
fn decQuadIsFinite(src: *const d128) -> u32;
fn decQuadIsInteger(src: *const d128) -> u32;
fn decQuadIsLogical(src: *const d128) -> u32;
fn decQuadIsInfinite(src: *const d128) -> u32;
fn decQuadIsNaN(src: *const d128) -> u32;
fn decQuadIsNegative(src: *const d128) -> u32;
fn decQuadIsNormal(src: *const d128) -> u32;
fn decQuadIsPositive(src: *const d128) -> u32;
fn decQuadIsSignaling(src: *const d128) -> u32;
fn decQuadIsSigned(src: *const d128) -> u32;
fn decQuadIsSubnormal(src: *const d128) -> u32;
fn decQuadIsZero(src: *const d128) -> u32;
fn decimal128FromNumber(res: *mut d128, src: *const decNumber, ctx: *mut Context) -> *mut d128;
fn decimal128ToNumber(src: *const d128, res: *mut decNumber) -> *mut decNumber;
fn decNumberPower(res: *mut decNumber,
lhs: *const decNumber,
rhs: *const decNumber,
ctx: *mut Context)
-> *mut decNumber;
fn decNumberExp(res: *mut decNumber,
lhs: *const decNumber,
rhs: *const decNumber,
ctx: *mut Context)
-> *mut decNumber;
fn decNumberLn(res: *mut decNumber,
rhs: *const decNumber,
ctx: *mut Context)
-> *mut decNumber;
fn decNumberLog10(res: *mut decNumber,
rhs: *const decNumber,
ctx: *mut Context)
-> *mut decNumber;
}
#[cfg(test)]
mod tests {
#[cfg(any(feature = "ord_subset", feature = "rustc-serialize"))]
use super::*;
#[cfg(any(feature = "ord_subset", feature = "serde"))]
use std::collections::BTreeMap;
#[cfg(feature = "ord_subset")]
use ord_subset;
#[cfg(feature = "rustc-serialize")]
use rustc_serialize::json;
#[cfg(feature = "serde")]
use serde_json::{from_str, to_string};
#[test]
fn default() {
assert_eq!(d128::zero(), d128::default());
assert_eq!(d128::zero(), Default::default());
}
#[test]
fn special() {
assert!(d128::infinity().is_infinite());
assert!(!d128::infinity().is_negative());
assert!(d128::neg_infinity().is_infinite());
assert!(d128::neg_infinity().is_negative());
assert_eq!(d128::infinity() + d128!(1), d128::infinity());
}
#[cfg(feature = "ord_subset")]
#[test]
#[should_panic]
fn test_ord_subset_nan() {
ord_subset::OrdVar::new(d128!(NaN));
}
#[cfg(feature = "ord_subset")]
#[test]
#[should_panic]
fn test_ord_subset_qnan() {
ord_subset::OrdVar::new(d128!(qNaN));
}
#[cfg(feature = "ord_subset")]
#[test]
fn test_ord_subset_zero() {
assert_eq!(*ord_subset::OrdVar::new(d128::zero()), d128::zero());
}
#[cfg(feature = "ord_subset")]
#[test]
fn test_into_for_btreemap() {
let mut m = BTreeMap::<ord_subset::OrdVar<d128>, i64>::new();
m.insert(d128!(1.1).into(), 1);
assert_eq!(m[&d128!(1.1).into()], 1);
}
#[cfg(feature = "rustc-serialize")]
#[test]
fn test_rustc_serialize() {
#[derive(RustcDecodable, RustcEncodable, PartialEq, Debug)]
struct Test {
price: d128,
}
let a = Test { price: d128!(12.3456) };
assert_eq!(json::encode(&a).unwrap(), "{\"price\":\"12.3456\"}");
let b = json::decode("{\"price\":\"12.3456\"}").unwrap();
assert_eq!(a, b);
}
#[cfg(feature = "serde")]
#[test]
fn test_serde() {
let mut a = BTreeMap::new();
a.insert("price".to_string(), d128!(432.232));
a.insert("amt".to_string(), d128!(9.9));
assert_eq!(&to_string(&a).unwrap(),
"{\"amt\":\"9.9\",\"price\":\"432.232\"}");
let b = from_str("{\"price\":\"432.232\",\"amt\":\"9.9\"}").unwrap();
assert_eq!(a, b);
}
#[test]
fn unary_op() {
assert_eq!(d128!(-1.1), -d128!(1.1));
assert_eq!(d128!(-1.1), -&d128!(1.1));
}
#[test]
fn binary_op() {
assert_eq!(d128!(3.33), d128!(1.11) + d128!(2.22));
assert_eq!(d128!(3.33), &d128!(1.11) + d128!(2.22));
assert_eq!(d128!(3.33), d128!(1.11) + &d128!(2.22));
assert_eq!(d128!(3.33), &d128!(1.11) + &d128!(2.22));
assert_eq!(d128!(5) << 2, d128!(500));
assert_eq!(d128!(500) >> 1, d128!(50));
}
#[test]
fn assign_op() {
let mut x = d128!(1);
x += d128!(2);
assert_eq!(x, d128!(3));
x *= d128!(3);
assert_eq!(x, d128!(9));
x -= d128!(1);
assert_eq!(x, d128!(8));
x /= d128!(16);
assert_eq!(x, d128!(0.5));
x <<= 2;
assert_eq!(x, d128!(50));
x >>= 1;
assert_eq!(x, d128!(5));
}
#[test]
fn as_ref_operand() {
assert_eq!(d128!(1.1), d128!(1.1).min(d128!(2.2)));
assert_eq!(d128!(1.1), d128!(1.1).min(&d128!(2.2)));
}
#[test]
fn from_i64() {
assert_eq!(d128::from_str(&::std::i64::MAX.to_string()).unwrap(),
d128::from(::std::i64::MAX));
assert_eq!(d128::from(0i32), d128::from(0i64));
assert_eq!(d128::from_str(&(::std::i64::MIN).to_string()).unwrap(),
d128::from(::std::i64::MIN));
}
#[test]
fn from_u64() {
assert_eq!(d128::from_str(&::std::u64::MAX.to_string()).unwrap(),
d128::from(::std::u64::MAX));
assert_eq!(d128::from(0i32), d128::from(0u64));
assert_eq!(d128::from_str(&(::std::u64::MIN).to_string()).unwrap(),
d128::from(::std::u64::MIN));
}
#[test]
fn test_sum() {
let decimals = vec![d128!(1), d128!(2), d128!(3), d128!(4)];
assert_eq!(d128!(10), decimals.iter().sum());
assert_eq!(d128!(10), decimals.into_iter().sum());
}
}