#[macro_use]
extern crate amplify_apfloat;
extern crate amplify_num;
use amplify_apfloat::ieee::{Double, Half, Oct, Quad, Single, X87DoubleExtended};
use amplify_apfloat::{
Category, ExpInt, Float, FloatConvert, ParseError, Round, Status, IEK_INF, IEK_NAN, IEK_ZERO,
};
use amplify_num::{i256, u256};
trait SingleExt {
fn from_f32(input: f32) -> Self;
fn to_f32(self) -> f32;
}
impl SingleExt for Single {
fn from_f32(input: f32) -> Self { Self::from_bits(u256::from(input.to_bits())) }
fn to_f32(self) -> f32 { f32::from_bits(self.to_bits().low_u32()) }
}
trait DoubleExt {
fn from_f64(input: f64) -> Self;
fn to_f64(self) -> f64;
}
impl DoubleExt for Double {
fn from_f64(input: f64) -> Self { Self::from_bits(u256::from(input.to_bits())) }
fn to_f64(self) -> f64 { f64::from_bits(self.to_bits().low_u64()) }
}
#[test]
fn is_signaling() {
let payload = u256::from(4u8);
assert!(!Single::qnan(None).is_signaling());
assert!(!(-Single::qnan(None)).is_signaling());
assert!(!Single::qnan(Some(payload)).is_signaling());
assert!(!(-Single::qnan(Some(payload))).is_signaling());
assert!(Single::snan(None).is_signaling());
assert!((-Single::snan(None)).is_signaling());
assert!(Single::snan(Some(payload)).is_signaling());
assert!((-Single::snan(Some(payload))).is_signaling());
}
#[test]
fn next() {
let mut status;
let test = unpack!(status=, Oct::INFINITY.next_up());
let expected = Oct::INFINITY;
assert_eq!(status, Status::OK);
assert!(test.is_infinite());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::INFINITY.next_down());
let expected = Oct::largest();
assert_eq!(status, Status::OK);
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, (-Oct::INFINITY).next_up());
let expected = -Oct::largest();
assert_eq!(status, Status::OK);
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, (-Oct::INFINITY).next_down());
let expected = -Oct::INFINITY;
assert_eq!(status, Status::OK);
assert!(test.is_infinite() && test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::largest().next_up());
let expected = Oct::INFINITY;
assert_eq!(status, Status::OK);
assert!(test.is_infinite() && !test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::largest().next_down());
let expected = "0x1.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffep+262143"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_infinite() && !test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, (-Oct::largest()).next_up());
let expected = "-0x1.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffep+262143"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, (-Oct::largest()).next_down());
let expected = -Oct::INFINITY;
assert_eq!(status, Status::OK);
assert!(test.is_infinite() && test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1p-262378"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x2p-262378".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1p-262378"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = Oct::ZERO;
assert_eq!(status, Status::OK);
assert!(test.is_pos_zero());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1p-262378"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = -Oct::ZERO;
assert_eq!(status, Status::OK);
assert!(test.is_neg_zero());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1p-262378"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x2p-262378".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::qnan(None).next_up());
let expected = Oct::qnan(None);
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::qnan(None).next_down());
let expected = Oct::qnan(None);
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::snan(None).next_up());
let expected = Oct::qnan(None);
assert_eq!(status, Status::INVALID_OP);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::snan(None).next_down());
let expected = Oct::qnan(None);
assert_eq!(status, Status::INVALID_OP);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::ZERO.next_up());
let expected = Oct::SMALLEST;
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, Oct::ZERO.next_down());
let expected = -Oct::SMALLEST;
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, (-Oct::ZERO).next_up());
let expected = Oct::SMALLEST;
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, (-Oct::ZERO).next_down());
let expected = -Oct::SMALLEST;
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x1p-262142".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x1p-262142".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1p-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1p-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1p+1".parse::<Oct>().unwrap().next_up());
let expected = "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp+0"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1p+1".parse::<Oct>().unwrap().next_down());
let expected = "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp+0"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp+0"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x1p+1".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp+0"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x1p+1".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "-0x0.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffep-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "0x0.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffep-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1p-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x1.00000000000000000000000000000000000000000000000000000000001p-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1.00000000000000000000000000000000000000000000000000000000000p-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x1.00000000000000000000000000000000000000000000000000000000001p-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1p-262141".parse::<Oct>().unwrap().next_up());
let expected = "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x1p-262141".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x1p-262141".parse::<Oct>().unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1p-262141".parse::<Oct>().unwrap().next_down());
let expected = "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000dp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000bp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-262142"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000bp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-262142"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x0.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000dp-262142"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(test.is_denormal());
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-260000"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000dp-260000"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-260000"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000bp-260000"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(!test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-260000"
.parse::<Oct>()
.unwrap()
.next_up());
let expected = "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000bp-260000"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
let test = unpack!(status=, "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000cp-260000"
.parse::<Oct>()
.unwrap()
.next_down());
let expected = "-0x1.fffffffffffffffffffffffffffffffffffffffffffffffffffffff000dp-260000"
.parse::<Oct>()
.unwrap();
assert_eq!(status, Status::OK);
assert!(!test.is_denormal());
assert!(test.is_negative());
assert!(test.bitwise_eq(expected));
}
#[test]
#[allow(clippy::excessive_precision)]
fn fma() {
{
let mut f1 = Single::from_f32(14.5);
let f2 = Single::from_f32(-14.5);
let f3 = Single::from_f32(225.0);
f1 = f1.mul_add(f2, f3).value;
assert_eq!(14.75, f1.to_f32());
}
{
let val2 = Single::from_f32(2.0);
let mut f1 = Single::from_f32(1.17549435e-38);
let mut f2 = Single::from_f32(1.17549435e-38);
f1 /= val2;
f2 /= val2;
let f3 = Single::from_f32(12.0);
f1 = f1.mul_add(f2, f3).value;
assert_eq!(12.0, f1.to_f32());
}
{
let mut f1 = Double::from_f64(1.0);
let f2 = Double::from_f64(-1.0);
let f3 = Double::from_f64(1.0);
f1 = f1.mul_add(f2, f3).value;
assert!(!f1.is_negative() && f1.is_zero());
}
{
let mut f1 = Double::from_f64(1.0);
let f2 = Double::from_f64(-1.0);
let f3 = Double::from_f64(1.0);
f1 = f1.mul_add_r(f2, f3, Round::TowardNegative).value;
assert!(f1.is_negative() && f1.is_zero());
}
{
let mut f1 = Double::from_f64(0.0);
let f2 = Double::from_f64(-0.0);
let f3 = Double::from_f64(-0.0);
f1 = f1.mul_add(f2, f3).value;
assert!(f1.is_negative() && f1.is_zero());
}
{
let mut f1 = "-0x1p-1074".parse::<Double>().unwrap();
let f2 = "+0x1p-1074".parse::<Double>().unwrap();
let f3 = Double::from_f64(0.0);
f1 = f1.mul_add(f2, f3).value;
assert!(f1.is_negative() && f1.is_zero());
}
{
let mut m1 = X87DoubleExtended::from_u256(1u8.into()).value;
let m2 = X87DoubleExtended::from_u256(1u8.into()).value;
let a = X87DoubleExtended::from_u256(3u8.into()).value;
let mut loses_info = false;
m1 = m1.mul_add(m2, a).value;
let r: Single = m1.convert(&mut loses_info).value;
assert!(!loses_info);
assert_eq!(4.0, r.to_f32());
}
}
#[test]
fn min_num() {
let f1 = Double::from_f64(1.0);
let f2 = Double::from_f64(2.0);
let nan = Double::NAN;
assert_eq!(1.0, f1.min(f2).to_f64());
assert_eq!(1.0, f2.min(f1).to_f64());
assert_eq!(1.0, f1.min(nan).to_f64());
assert_eq!(1.0, nan.min(f1).to_f64());
}
#[test]
fn max_num() {
let f1 = Double::from_f64(1.0);
let f2 = Double::from_f64(2.0);
let nan = Double::NAN;
assert_eq!(2.0, f1.max(f2).to_f64());
assert_eq!(2.0, f2.max(f1).to_f64());
assert_eq!(1.0, f1.max(nan).to_f64());
assert_eq!(1.0, nan.max(f1).to_f64());
}
#[test]
fn denormal() {
{
assert!(!Single::from_f32(0.0).is_denormal());
let mut t = "1.17549435082228750797e-38".parse::<Single>().unwrap();
assert!(!t.is_denormal());
let val2 = Single::from_f32(2.0e0);
t /= val2;
assert!(t.is_denormal());
}
{
assert!(!Double::from_f64(0.0).is_denormal());
let mut t = "2.22507385850720138309e-308".parse::<Double>().unwrap();
assert!(!t.is_denormal());
let val2 = Double::from_f64(2.0e0);
t /= val2;
assert!(t.is_denormal());
}
{
assert!(!X87DoubleExtended::from_u256(0u8.into()).value.is_denormal());
let mut t = "3.36210314311209350626e-4932"
.parse::<X87DoubleExtended>()
.unwrap();
assert!(!t.is_denormal());
t /= X87DoubleExtended::from_u256(2u8.into()).value;
assert!(t.is_denormal());
}
{
assert!(!Quad::from_u256(0u8.into()).value.is_denormal());
let mut t = "3.36210314311209350626267781732175260e-4932"
.parse::<Quad>()
.unwrap();
assert!(!t.is_denormal());
t /= Quad::from_u256(2u8.into()).value;
assert!(t.is_denormal());
}
}
#[test]
fn decimal_strings_without_null_terminators() {
let val = "0.00"[..3].parse::<Double>().unwrap();
assert_eq!(val.to_f64(), 0.0);
let val = "0.01"[..3].parse::<Double>().unwrap();
assert_eq!(val.to_f64(), 0.0);
let val = "0.09"[..3].parse::<Double>().unwrap();
assert_eq!(val.to_f64(), 0.0);
let val = "0.095"[..4].parse::<Double>().unwrap();
assert_eq!(val.to_f64(), 0.09);
let val = "0.00e+3"[..7].parse::<Double>().unwrap();
assert_eq!(val.to_f64(), 0.00);
let val = "0e+3"[..4].parse::<Double>().unwrap();
assert_eq!(val.to_f64(), 0.00);
}
#[test]
fn oct_decimal_string() {
assert!("0".parse::<Oct>().unwrap().is_zero());
assert_eq!("0.5", "0.5".parse::<Oct>().unwrap().to_string());
}
#[test]
fn from_zero_decimal_string() {
assert_eq!(0.0, "0".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, ".0".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+.0".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-.0".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.0".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.0".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.0".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "00000.".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+00000.".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-00000.".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, ".00000".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+.00000".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-.00000".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0000.00000".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0000.00000".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0000.00000".parse::<Double>().unwrap().to_f64());
}
#[test]
fn from_zero_decimal_single_exponent_string() {
assert_eq!(0.0, "0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.e1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, ".0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+.0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-.0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, ".0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+.0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-.0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, ".0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+.0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-.0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.0e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.0e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0.0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0.0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0.0e-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "000.0000e1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+000.0000e+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-000.0000e+1".parse::<Double>().unwrap().to_f64());
}
#[test]
fn from_zero_decimal_large_exponent_string() {
assert_eq!(0.0, "0e1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0e1234".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0e1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0e+1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0e+1234".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0e+1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0e-1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0e-1234".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0e-1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "000.0000e1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "000.0000e-1234".parse::<Double>().unwrap().to_f64());
}
#[test]
fn from_zero_hexadecimal_string() {
assert_eq!(0.0, "0x0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0.p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0.p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0.p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0.p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0.p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0.p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x.0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x.0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x.0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x.0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x.0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x.0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x.0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x.0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x.0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0.0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0.0p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0.0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0.0p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "+0x0.0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0.0p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x00000.p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0000.00000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x.00000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.p1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0p1234".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.0, "-0x0p1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x00000.p1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0000.00000p1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x.00000p1234".parse::<Double>().unwrap().to_f64());
assert_eq!(0.0, "0x0.p1234".parse::<Double>().unwrap().to_f64());
}
#[test]
#[allow(clippy::approx_constant)]
fn from_decimal_string() {
assert_eq!(1.0, "1".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0, "2.".parse::<Double>().unwrap().to_f64());
assert_eq!(0.5, ".5".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "1.0".parse::<Double>().unwrap().to_f64());
assert_eq!(-2.0, "-2".parse::<Double>().unwrap().to_f64());
assert_eq!(-4.0, "-4.".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.5, "-.5".parse::<Double>().unwrap().to_f64());
assert_eq!(-1.5, "-1.5".parse::<Double>().unwrap().to_f64());
assert_eq!(1.25e12, "1.25e12".parse::<Double>().unwrap().to_f64());
assert_eq!(1.25e+12, "1.25e+12".parse::<Double>().unwrap().to_f64());
assert_eq!(1.25e-12, "1.25e-12".parse::<Double>().unwrap().to_f64());
assert_eq!(1024.0, "1024.".parse::<Double>().unwrap().to_f64());
assert_eq!(1024.05, "1024.05000".parse::<Double>().unwrap().to_f64());
assert_eq!(0.05, ".05000".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0, "2.".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0e2, "2.e2".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0e+2, "2.e+2".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0e-2, "2.e-2".parse::<Double>().unwrap().to_f64());
assert_eq!(2.05e2, "002.05000e2".parse::<Double>().unwrap().to_f64());
assert_eq!(2.05e+2, "002.05000e+2".parse::<Double>().unwrap().to_f64());
assert_eq!(2.05e-2, "002.05000e-2".parse::<Double>().unwrap().to_f64());
assert_eq!(2.05e12, "002.05000e12".parse::<Double>().unwrap().to_f64());
assert_eq!(2.05e+12, "002.05000e+12".parse::<Double>().unwrap().to_f64());
assert_eq!(2.05e-12, "002.05000e-12".parse::<Double>().unwrap().to_f64());
assert!("99e99999".parse::<Double>().unwrap().is_infinite());
assert!("-99e99999".parse::<Double>().unwrap().is_infinite());
assert!("1e-99999".parse::<Double>().unwrap().is_pos_zero());
assert!("-1e-99999".parse::<Double>().unwrap().is_neg_zero());
assert_eq!(2.71828, "2.71828".parse::<Double>().unwrap().to_f64());
}
#[test]
fn from_hexadecimal_string() {
assert_eq!(1.0, "0x1p0".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "+0x1p0".parse::<Double>().unwrap().to_f64());
assert_eq!(-1.0, "-0x1p0".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "0x1p+0".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "+0x1p+0".parse::<Double>().unwrap().to_f64());
assert_eq!(-1.0, "-0x1p+0".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "0x1p-0".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "+0x1p-0".parse::<Double>().unwrap().to_f64());
assert_eq!(-1.0, "-0x1p-0".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0, "0x1p1".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0, "+0x1p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-2.0, "-0x1p1".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0, "0x1p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(2.0, "+0x1p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-2.0, "-0x1p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.5, "0x1p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.5, "+0x1p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.5, "-0x1p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(3.0, "0x1.8p1".parse::<Double>().unwrap().to_f64());
assert_eq!(3.0, "+0x1.8p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-3.0, "-0x1.8p1".parse::<Double>().unwrap().to_f64());
assert_eq!(3.0, "0x1.8p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(3.0, "+0x1.8p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-3.0, "-0x1.8p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.75, "0x1.8p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(0.75, "+0x1.8p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.75, "-0x1.8p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "0x1000.000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "+0x1000.000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-8192.0, "-0x1000.000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "0x1000.000p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "+0x1000.000p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-8192.0, "-0x1000.000p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(2048.0, "0x1000.000p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(2048.0, "+0x1000.000p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-2048.0, "-0x1000.000p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "0x1000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "+0x1000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(-8192.0, "-0x1000p1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "0x1000p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(8192.0, "+0x1000p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(-8192.0, "-0x1000p+1".parse::<Double>().unwrap().to_f64());
assert_eq!(2048.0, "0x1000p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(2048.0, "+0x1000p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(-2048.0, "-0x1000p-1".parse::<Double>().unwrap().to_f64());
assert_eq!(16384.0, "0x10p10".parse::<Double>().unwrap().to_f64());
assert_eq!(16384.0, "+0x10p10".parse::<Double>().unwrap().to_f64());
assert_eq!(-16384.0, "-0x10p10".parse::<Double>().unwrap().to_f64());
assert_eq!(16384.0, "0x10p+10".parse::<Double>().unwrap().to_f64());
assert_eq!(16384.0, "+0x10p+10".parse::<Double>().unwrap().to_f64());
assert_eq!(-16384.0, "-0x10p+10".parse::<Double>().unwrap().to_f64());
assert_eq!(0.015625, "0x10p-10".parse::<Double>().unwrap().to_f64());
assert_eq!(0.015625, "+0x10p-10".parse::<Double>().unwrap().to_f64());
assert_eq!(-0.015625, "-0x10p-10".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0625, "0x1.1p0".parse::<Double>().unwrap().to_f64());
assert_eq!(1.0, "0x1p0".parse::<Double>().unwrap().to_f64());
assert_eq!(
"0x1p-150".parse::<Double>().unwrap().to_f64(),
"+0x800000000000000001.p-221"
.parse::<Double>()
.unwrap()
.to_f64()
);
assert_eq!(
2251799813685248.5,
"0x80000000000004000000.010p-28"
.parse::<Double>()
.unwrap()
.to_f64()
);
}
#[test]
#[allow(clippy::excessive_precision)]
fn to_string() {
let to_string = |d: f64, precision: usize, width: usize| {
let x = Double::from_f64(d);
if precision == 0 {
format!("{:1$}", x, width)
} else {
format!("{:2$.1$}", x, precision, width)
}
};
assert_eq!("10", to_string(10.0, 6, 3));
assert_eq!("1.0E+1", to_string(10.0, 6, 0));
assert_eq!("10100", to_string(1.01E+4, 5, 2));
assert_eq!("1.01E+4", to_string(1.01E+4, 4, 2));
assert_eq!("1.01E+4", to_string(1.01E+4, 5, 1));
assert_eq!("0.0101", to_string(1.01E-2, 5, 2));
assert_eq!("0.0101", to_string(1.01E-2, 4, 2));
assert_eq!("1.01E-2", to_string(1.01E-2, 5, 1));
assert_eq!("0.78539816339744828", to_string(0.78539816339744830961, 0, 3));
assert_eq!("4.9406564584124654E-324", to_string(4.9406564584124654e-324, 0, 3));
assert_eq!("873.18340000000001", to_string(873.1834, 0, 1));
assert_eq!("8.7318340000000001E+2", to_string(873.1834, 0, 0));
assert_eq!("1.7976931348623157E+308", to_string(1.7976931348623157E+308, 0, 0));
let to_string = |d: f64, precision: usize, width: usize| {
let x = Double::from_f64(d);
if precision == 0 {
format!("{:#1$}", x, width)
} else {
format!("{:#2$.1$}", x, precision, width)
}
};
assert_eq!("10", to_string(10.0, 6, 3));
assert_eq!("1.000000e+01", to_string(10.0, 6, 0));
assert_eq!("10100", to_string(1.01E+4, 5, 2));
assert_eq!("1.0100e+04", to_string(1.01E+4, 4, 2));
assert_eq!("1.01000e+04", to_string(1.01E+4, 5, 1));
assert_eq!("0.0101", to_string(1.01E-2, 5, 2));
assert_eq!("0.0101", to_string(1.01E-2, 4, 2));
assert_eq!("1.01000e-02", to_string(1.01E-2, 5, 1));
assert_eq!("0.78539816339744828", to_string(0.78539816339744830961, 0, 3));
assert_eq!("4.94065645841246540e-324", to_string(4.9406564584124654e-324, 0, 3));
assert_eq!("873.18340000000001", to_string(873.1834, 0, 1));
assert_eq!("8.73183400000000010e+02", to_string(873.1834, 0, 0));
assert_eq!("1.79769313486231570e+308", to_string(1.7976931348623157E+308, 0, 0));
}
#[test]
fn to_integer() {
let mut is_exact = false;
assert_eq!(
Status::OK.and(10u8.into()),
"10".parse::<Double>()
.unwrap()
.to_u256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(is_exact);
assert_eq!(
Status::INVALID_OP.and(0u8.into()),
"-10"
.parse::<Double>()
.unwrap()
.to_u256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(!is_exact);
assert_eq!(
Status::INVALID_OP.and(31u8.into()),
"32".parse::<Double>()
.unwrap()
.to_u256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(!is_exact);
assert_eq!(
Status::INEXACT.and(7u8.into()),
"7.9"
.parse::<Double>()
.unwrap()
.to_u256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(!is_exact);
assert_eq!(
Status::OK.and(i256::from(-10)),
"-10"
.parse::<Double>()
.unwrap()
.to_i256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(is_exact);
assert_eq!(
Status::INVALID_OP.and(i256::from(-16)),
"-17"
.parse::<Double>()
.unwrap()
.to_i256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(!is_exact);
assert_eq!(
Status::INVALID_OP.and(i256::from(15)),
"16".parse::<Double>()
.unwrap()
.to_i256_r(5, Round::TowardZero, &mut is_exact,)
);
assert!(!is_exact);
}
#[test]
fn nan() {
fn nanbits<T: Float>(signaling: bool, negative: bool, fill: u256) -> u256 {
let x = if signaling {
T::snan(Some(fill))
} else {
T::qnan(Some(fill))
};
if negative {
(-x).to_bits()
} else {
x.to_bits()
}
}
assert_eq!(u256::from(0x7fc00000u128), nanbits::<Single>(false, false, 0u128.into()));
assert_eq!(u256::from(0xffc00000u128), nanbits::<Single>(false, true, 0u128.into()));
assert_eq!(u256::from(0x7fc0ae72u128), nanbits::<Single>(false, false, 0xae72u128.into()));
assert_eq!(u256::from(0x7fffae72u128), nanbits::<Single>(false, false, 0xffffae72u128.into()));
assert_eq!(u256::from(0x7fa00000u128), nanbits::<Single>(true, false, 0u128.into()));
assert_eq!(u256::from(0xffa00000u128), nanbits::<Single>(true, true, 0u128.into()));
assert_eq!(u256::from(0x7f80ae72u128), nanbits::<Single>(true, false, 0xae72u128.into()));
assert_eq!(u256::from(0x7fbfae72u128), nanbits::<Single>(true, false, 0xffffae72u128.into()));
assert_eq!(u256::from(0x7ff8000000000000u128), nanbits::<Double>(false, false, 0u8.into()));
assert_eq!(u256::from(0xfff8000000000000u128), nanbits::<Double>(false, true, 0u8.into()));
assert_eq!(
u256::from(0x7ff800000000ae72u128),
nanbits::<Double>(false, false, 0xae72u128.into())
);
assert_eq!(
u256::from(0x7fffffffffffae72u128),
nanbits::<Double>(false, false, 0xffffffffffffae72u128.into())
);
assert_eq!(u256::from(0x7ff4000000000000u128), nanbits::<Double>(true, false, 0u8.into()));
assert_eq!(u256::from(0xfff4000000000000u128), nanbits::<Double>(true, true, 0u8.into()));
assert_eq!(
u256::from(0x7ff000000000ae72u128),
nanbits::<Double>(true, false, 0xae72u128.into())
);
assert_eq!(
u256::from(0x7ff7ffffffffae72u128),
nanbits::<Double>(true, false, 0xffffffffffffae72u128.into())
);
}
#[test]
fn string_decimal_death() {
assert_eq!("".parse::<Double>(), Err(ParseError("Invalid string length")));
assert_eq!("+".parse::<Double>(), Err(ParseError("String has no digits")));
assert_eq!("-".parse::<Double>(), Err(ParseError("String has no digits")));
assert_eq!("\0".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("1\0".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("1\x002".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("1\x002e1".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("1e\0".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("1e1\0".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("1e1\x002".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("1.0f".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("..".parse::<Double>(), Err(ParseError("String contains multiple dots")));
assert_eq!("..0".parse::<Double>(), Err(ParseError("String contains multiple dots")));
assert_eq!("1.0.0".parse::<Double>(), Err(ParseError("String contains multiple dots")));
}
#[test]
fn string_decimal_significand_death() {
assert_eq!(".".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+.".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-.".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("e".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+e".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-e".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("e1".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+e1".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-e1".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!(".e1".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+.e1".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-.e1".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!(".e".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+.e".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-.e".parse::<Double>(), Err(ParseError("Significand has no digits")));
}
#[test]
fn string_decimal_exponent_death() {
assert_eq!("1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1.e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+1.e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-1.e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!(".1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+.1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-.1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1.1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+1.1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-1.1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1e+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1e-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!(".1e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!(".1e+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!(".1e-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1.0e".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1.0e+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("1.0e-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
}
#[test]
fn string_hexadecimal_death() {
assert_eq!("0x".parse::<Double>(), Err(ParseError("Invalid string")));
assert_eq!("+0x".parse::<Double>(), Err(ParseError("Invalid string")));
assert_eq!("-0x".parse::<Double>(), Err(ParseError("Invalid string")));
assert_eq!("0x0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("+0x0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("-0x0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("0x0.".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("+0x0.".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("-0x0.".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("0x.0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("+0x.0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("-0x.0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("0x0.0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("+0x0.0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("-0x0.0".parse::<Double>(), Err(ParseError("Hex strings require an exponent")));
assert_eq!("0x\0".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("0x1\0".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("0x1\x002".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("0x1\x002p1".parse::<Double>(), Err(ParseError("Invalid character in significand")));
assert_eq!("0x1p\0".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("0x1p1\0".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("0x1p1\x002".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("0x1p0f".parse::<Double>(), Err(ParseError("Invalid character in exponent")));
assert_eq!("0x..p1".parse::<Double>(), Err(ParseError("String contains multiple dots")));
assert_eq!("0x..0p1".parse::<Double>(), Err(ParseError("String contains multiple dots")));
assert_eq!("0x1.0.0p1".parse::<Double>(), Err(ParseError("String contains multiple dots")));
}
#[test]
fn string_hexadecimal_significand_death() {
assert_eq!("0x.".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0x.".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0x.".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("0xp".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0xp".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0xp".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("0xp+".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0xp+".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0xp+".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("0xp-".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0xp-".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0xp-".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("0x.p".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0x.p".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0x.p".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("0x.p+".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0x.p+".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0x.p+".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("0x.p-".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("+0x.p-".parse::<Double>(), Err(ParseError("Significand has no digits")));
assert_eq!("-0x.p-".parse::<Double>(), Err(ParseError("Significand has no digits")));
}
#[test]
fn string_hexadecimal_exponent_death() {
assert_eq!("0x1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1.p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1.p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1.p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1.p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1.p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1.p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1.p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1.p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1.p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x.1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x.1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x.1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x.1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x.1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x.1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x.1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x.1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x.1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1.1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1.1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1.1p".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1.1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1.1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1.1p+".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("0x1.1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("+0x1.1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
assert_eq!("-0x1.1p-".parse::<Double>(), Err(ParseError("Exponent has no digits")));
}
#[test]
#[allow(clippy::excessive_precision)]
fn exact_inverse() {
assert!(
Double::from_f64(2.0)
.get_exact_inverse()
.unwrap()
.bitwise_eq(Double::from_f64(0.5))
);
assert!(
Single::from_f32(2.0)
.get_exact_inverse()
.unwrap()
.bitwise_eq(Single::from_f32(0.5))
);
assert!(
"2.0"
.parse::<Quad>()
.unwrap()
.get_exact_inverse()
.unwrap()
.bitwise_eq("0.5".parse::<Quad>().unwrap())
);
assert!(
"2.0"
.parse::<X87DoubleExtended>()
.unwrap()
.get_exact_inverse()
.unwrap()
.bitwise_eq("0.5".parse::<X87DoubleExtended>().unwrap())
);
assert!(
Single::from_f32(1.17549435e-38)
.get_exact_inverse()
.unwrap()
.bitwise_eq(Single::from_f32(8.5070592e+37))
);
assert!(Single::from_f32(1.7014118e38).get_exact_inverse().is_none());
assert!(Double::from_f64(0.0).get_exact_inverse().is_none());
assert!(
Single::from_f32(1.40129846e-45)
.get_exact_inverse()
.is_none()
);
}
#[test]
#[allow(clippy::approx_constant)]
fn round_to_integral() {
let t = Double::from_f64(-0.5);
assert_eq!(-0.0, t.round_to_integral(Round::TowardZero).value.to_f64());
assert_eq!(-1.0, t.round_to_integral(Round::TowardNegative).value.to_f64());
assert_eq!(-0.0, t.round_to_integral(Round::TowardPositive).value.to_f64());
assert_eq!(-0.0, t.round_to_integral(Round::NearestTiesToEven).value.to_f64());
let s = Double::from_f64(3.14);
assert_eq!(3.0, s.round_to_integral(Round::TowardZero).value.to_f64());
assert_eq!(3.0, s.round_to_integral(Round::TowardNegative).value.to_f64());
assert_eq!(4.0, s.round_to_integral(Round::TowardPositive).value.to_f64());
assert_eq!(3.0, s.round_to_integral(Round::NearestTiesToEven).value.to_f64());
let r = Double::largest();
assert_eq!(r.to_f64(), r.round_to_integral(Round::TowardZero).value.to_f64());
assert_eq!(r.to_f64(), r.round_to_integral(Round::TowardNegative).value.to_f64());
assert_eq!(r.to_f64(), r.round_to_integral(Round::TowardPositive).value.to_f64());
assert_eq!(r.to_f64(), r.round_to_integral(Round::NearestTiesToEven).value.to_f64());
let p = Double::ZERO.round_to_integral(Round::TowardZero).value;
assert_eq!(0.0, p.to_f64());
let p = (-Double::ZERO).round_to_integral(Round::TowardZero).value;
assert_eq!(-0.0, p.to_f64());
let p = Double::NAN.round_to_integral(Round::TowardZero).value;
assert!(p.to_f64().is_nan());
let p = Double::INFINITY.round_to_integral(Round::TowardZero).value;
assert!(p.to_f64().is_infinite() && p.to_f64() > 0.0);
let p = (-Double::INFINITY)
.round_to_integral(Round::TowardZero)
.value;
assert!(p.to_f64().is_infinite() && p.to_f64() < 0.0);
}
#[test]
#[allow(clippy::approx_constant)]
fn is_integer() {
let t = Double::from_f64(-0.0);
assert!(t.is_integer());
let t = Double::from_f64(3.14159);
assert!(!t.is_integer());
let t = Double::NAN;
assert!(!t.is_integer());
let t = Double::INFINITY;
assert!(!t.is_integer());
let t = -Double::INFINITY;
assert!(!t.is_integer());
let t = Double::largest();
assert!(t.is_integer());
}
#[test]
#[allow(clippy::excessive_precision)]
fn largest() {
assert_eq!(3.402823466e+38, Single::largest().to_f32());
assert_eq!(1.7976931348623158e+308, Double::largest().to_f64());
}
#[test]
fn smallest() {
let test = Single::SMALLEST;
let expected = "0x0.000002p-126".parse::<Single>().unwrap();
assert!(!test.is_negative());
assert!(test.is_finite_non_zero());
assert!(test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = -Single::SMALLEST;
let expected = "-0x0.000002p-126".parse::<Single>().unwrap();
assert!(test.is_negative());
assert!(test.is_finite_non_zero());
assert!(test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = Quad::SMALLEST;
let expected = "0x0.0000000000000000000000000001p-16382"
.parse::<Quad>()
.unwrap();
assert!(!test.is_negative());
assert!(test.is_finite_non_zero());
assert!(test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = -Quad::SMALLEST;
let expected = "-0x0.0000000000000000000000000001p-16382"
.parse::<Quad>()
.unwrap();
assert!(test.is_negative());
assert!(test.is_finite_non_zero());
assert!(test.is_denormal());
assert!(test.bitwise_eq(expected));
}
#[test]
fn smallest_normalized() {
let test = Single::smallest_normalized();
let expected = "0x1p-126".parse::<Single>().unwrap();
assert!(!test.is_negative());
assert!(test.is_finite_non_zero());
assert!(!test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = -Single::smallest_normalized();
let expected = "-0x1p-126".parse::<Single>().unwrap();
assert!(test.is_negative());
assert!(test.is_finite_non_zero());
assert!(!test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = Quad::smallest_normalized();
let expected = "0x1p-16382".parse::<Quad>().unwrap();
assert!(!test.is_negative());
assert!(test.is_finite_non_zero());
assert!(!test.is_denormal());
assert!(test.bitwise_eq(expected));
let test = -Quad::smallest_normalized();
let expected = "-0x1p-16382".parse::<Quad>().unwrap();
assert!(test.is_negative());
assert!(test.is_finite_non_zero());
assert!(!test.is_denormal());
assert!(test.bitwise_eq(expected));
}
#[test]
fn zero() {
assert_eq!(0.0, Single::from_f32(0.0).to_f32());
assert_eq!(-0.0, Single::from_f32(-0.0).to_f32());
assert!(Single::from_f32(-0.0).is_negative());
assert_eq!(0.0, Double::from_f64(0.0).to_f64());
assert_eq!(-0.0, Double::from_f64(-0.0).to_f64());
assert!(Double::from_f64(-0.0).is_negative());
fn test<T: Float>(sign: bool, bits: u256) {
let test = if sign { -T::ZERO } else { T::ZERO };
let pattern = if sign { "-0x0p+0" } else { "0x0p+0" };
let expected = pattern.parse::<T>().unwrap();
assert!(test.is_zero());
assert_eq!(sign, test.is_negative());
assert!(test.bitwise_eq(expected));
assert_eq!(bits, test.to_bits());
}
test::<Half>(false, u256::ZERO);
test::<Half>(true, u256::from(0x8000u128));
test::<Single>(false, u256::ZERO);
test::<Single>(true, u256::from(0x80000000u128));
test::<Double>(false, u256::ZERO);
test::<Double>(true, u256::from(0x8000000000000000u128));
test::<Quad>(false, u256::ZERO);
test::<Quad>(true, u256::from(0x8000000000000000_0000000000000000u128));
test::<X87DoubleExtended>(false, u256::ZERO);
test::<X87DoubleExtended>(true, u256::from(0x8000_0000000000000000u128));
}
#[test]
fn copy_sign() {
assert!(
Double::from_f64(-42.0)
.bitwise_eq(Double::from_f64(42.0).copy_sign(Double::from_f64(-1.0),),)
);
assert!(
Double::from_f64(42.0)
.bitwise_eq(Double::from_f64(-42.0).copy_sign(Double::from_f64(1.0),),)
);
assert!(
Double::from_f64(-42.0)
.bitwise_eq(Double::from_f64(-42.0).copy_sign(Double::from_f64(-1.0),),)
);
assert!(
Double::from_f64(42.0)
.bitwise_eq(Double::from_f64(42.0).copy_sign(Double::from_f64(1.0),),)
);
}
#[test]
fn convert() {
let mut loses_info = false;
let test = "1.0".parse::<Double>().unwrap();
let test: Single = test.convert(&mut loses_info).value;
assert_eq!(1.0, test.to_f32());
assert!(!loses_info);
let mut test = "0x1p-53".parse::<X87DoubleExtended>().unwrap();
let one = "1.0".parse::<X87DoubleExtended>().unwrap();
test += one;
let test: Double = test.convert(&mut loses_info).value;
assert_eq!(1.0, test.to_f64());
assert!(loses_info);
let mut test = "0x1p-53".parse::<Quad>().unwrap();
let one = "1.0".parse::<Quad>().unwrap();
test += one;
let test: Double = test.convert(&mut loses_info).value;
assert_eq!(1.0, test.to_f64());
assert!(loses_info);
let test = "0xf.fffffffp+28".parse::<X87DoubleExtended>().unwrap();
let test: Double = test.convert(&mut loses_info).value;
assert_eq!(4294967295.0, test.to_f64());
assert!(!loses_info);
let test = Single::snan(None);
let x87_snan = X87DoubleExtended::snan(None);
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
assert!(test.bitwise_eq(x87_snan));
assert!(!loses_info);
let test = Single::qnan(None);
let x87_qnan = X87DoubleExtended::qnan(None);
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
assert!(test.bitwise_eq(x87_qnan));
assert!(!loses_info);
let test = X87DoubleExtended::snan(None);
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
assert!(test.bitwise_eq(x87_snan));
assert!(!loses_info);
let test = X87DoubleExtended::qnan(None);
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
assert!(test.bitwise_eq(x87_qnan));
assert!(!loses_info);
}
#[test]
fn is_negative() {
let t = "0x1p+0".parse::<Single>().unwrap();
assert!(!t.is_negative());
let t = "-0x1p+0".parse::<Single>().unwrap();
assert!(t.is_negative());
assert!(!Single::INFINITY.is_negative());
assert!((-Single::INFINITY).is_negative());
assert!(!Single::ZERO.is_negative());
assert!((-Single::ZERO).is_negative());
assert!(!Single::NAN.is_negative());
assert!((-Single::NAN).is_negative());
assert!(!Single::snan(None).is_negative());
assert!((-Single::snan(None)).is_negative());
}
#[test]
fn is_normal() {
let t = "0x1p+0".parse::<Single>().unwrap();
assert!(t.is_normal());
assert!(!Single::INFINITY.is_normal());
assert!(!Single::ZERO.is_normal());
assert!(!Single::NAN.is_normal());
assert!(!Single::snan(None).is_normal());
assert!(!"0x1p-149".parse::<Single>().unwrap().is_normal());
}
#[test]
fn is_finite() {
let t = "0x1p+0".parse::<Single>().unwrap();
assert!(t.is_finite());
assert!(!Single::INFINITY.is_finite());
assert!(Single::ZERO.is_finite());
assert!(!Single::NAN.is_finite());
assert!(!Single::snan(None).is_finite());
assert!("0x1p-149".parse::<Single>().unwrap().is_finite());
}
#[test]
fn is_infinite() {
let t = "0x1p+0".parse::<Single>().unwrap();
assert!(!t.is_infinite());
assert!(Single::INFINITY.is_infinite());
assert!(!Single::ZERO.is_infinite());
assert!(!Single::NAN.is_infinite());
assert!(!Single::snan(None).is_infinite());
assert!(!"0x1p-149".parse::<Single>().unwrap().is_infinite());
}
#[test]
fn is_nan() {
let t = "0x1p+0".parse::<Single>().unwrap();
assert!(!t.is_nan());
assert!(!Single::INFINITY.is_nan());
assert!(!Single::ZERO.is_nan());
assert!(Single::NAN.is_nan());
assert!(Single::snan(None).is_nan());
assert!(!"0x1p-149".parse::<Single>().unwrap().is_nan());
}
#[test]
fn is_finite_non_zero() {
assert!("0x1p+0".parse::<Single>().unwrap().is_finite_non_zero());
assert!("-0x1p+0".parse::<Single>().unwrap().is_finite_non_zero());
assert!("0x1p-149".parse::<Single>().unwrap().is_finite_non_zero());
assert!("-0x1p-149".parse::<Single>().unwrap().is_finite_non_zero());
assert!(!Single::INFINITY.is_finite_non_zero());
assert!(!(-Single::INFINITY).is_finite_non_zero());
assert!(!Single::ZERO.is_finite_non_zero());
assert!(!(-Single::ZERO).is_finite_non_zero());
assert!(!Single::NAN.is_finite_non_zero());
assert!(!(-Single::NAN).is_finite_non_zero());
assert!(!Single::snan(None).is_finite_non_zero());
assert!(!(-Single::snan(None)).is_finite_non_zero());
}
#[test]
fn add() {
let p_inf = Single::INFINITY;
let m_inf = -Single::INFINITY;
let p_zero = Single::ZERO;
let m_zero = -Single::ZERO;
let qnan = Single::NAN;
let p_normal_value = "0x1p+0".parse::<Single>().unwrap();
let m_normal_value = "-0x1p+0".parse::<Single>().unwrap();
let p_largest_value = Single::largest();
let m_largest_value = -Single::largest();
let p_smallest_value = Single::SMALLEST;
let m_smallest_value = -Single::SMALLEST;
let p_smallest_normalized = Single::smallest_normalized();
let m_smallest_normalized = -Single::smallest_normalized();
let overflow_status = Status::OVERFLOW | Status::INEXACT;
let special_cases = [
(p_inf, p_inf, "inf", Status::OK, Category::Infinity),
(p_inf, m_inf, "nan", Status::INVALID_OP, Category::NaN),
(p_inf, p_zero, "inf", Status::OK, Category::Infinity),
(p_inf, m_zero, "inf", Status::OK, Category::Infinity),
(p_inf, qnan, "nan", Status::OK, Category::NaN),
(p_inf, p_normal_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_normal_value, "inf", Status::OK, Category::Infinity),
(p_inf, p_largest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_largest_value, "inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_value, "inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_normalized, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_normalized, "inf", Status::OK, Category::Infinity),
(m_inf, p_inf, "nan", Status::INVALID_OP, Category::NaN),
(m_inf, m_inf, "-inf", Status::OK, Category::Infinity),
(m_inf, p_zero, "-inf", Status::OK, Category::Infinity),
(m_inf, m_zero, "-inf", Status::OK, Category::Infinity),
(m_inf, qnan, "nan", Status::OK, Category::NaN),
(m_inf, p_normal_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_normal_value, "-inf", Status::OK, Category::Infinity),
(m_inf, p_largest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_largest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(p_zero, p_inf, "inf", Status::OK, Category::Infinity),
(p_zero, m_inf, "-inf", Status::OK, Category::Infinity),
(p_zero, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_zero, "0x0p+0", Status::OK, Category::Zero),
(p_zero, qnan, "nan", Status::OK, Category::NaN),
(p_zero, p_normal_value, "0x1p+0", Status::OK, Category::Normal),
(p_zero, m_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(p_zero, p_largest_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_zero, m_largest_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(p_zero, p_smallest_value, "0x1p-149", Status::OK, Category::Normal),
(p_zero, m_smallest_value, "-0x1p-149", Status::OK, Category::Normal),
(p_zero, p_smallest_normalized, "0x1p-126", Status::OK, Category::Normal),
(p_zero, m_smallest_normalized, "-0x1p-126", Status::OK, Category::Normal),
(m_zero, p_inf, "inf", Status::OK, Category::Infinity),
(m_zero, m_inf, "-inf", Status::OK, Category::Infinity),
(m_zero, p_zero, "0x0p+0", Status::OK, Category::Zero),
(m_zero, m_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, qnan, "nan", Status::OK, Category::NaN),
(m_zero, p_normal_value, "0x1p+0", Status::OK, Category::Normal),
(m_zero, m_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(m_zero, p_largest_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(m_zero, m_largest_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_zero, p_smallest_value, "0x1p-149", Status::OK, Category::Normal),
(m_zero, m_smallest_value, "-0x1p-149", Status::OK, Category::Normal),
(m_zero, p_smallest_normalized, "0x1p-126", Status::OK, Category::Normal),
(m_zero, m_smallest_normalized, "-0x1p-126", Status::OK, Category::Normal),
(qnan, p_inf, "nan", Status::OK, Category::NaN),
(qnan, m_inf, "nan", Status::OK, Category::NaN),
(qnan, p_zero, "nan", Status::OK, Category::NaN),
(qnan, m_zero, "nan", Status::OK, Category::NaN),
(qnan, qnan, "nan", Status::OK, Category::NaN),
(qnan, p_normal_value, "nan", Status::OK, Category::NaN),
(qnan, m_normal_value, "nan", Status::OK, Category::NaN),
(qnan, p_largest_value, "nan", Status::OK, Category::NaN),
(qnan, m_largest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_normalized, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_normalized, "nan", Status::OK, Category::NaN),
(p_normal_value, p_inf, "inf", Status::OK, Category::Infinity),
(p_normal_value, m_inf, "-inf", Status::OK, Category::Infinity),
(p_normal_value, p_zero, "0x1p+0", Status::OK, Category::Normal),
(p_normal_value, m_zero, "0x1p+0", Status::OK, Category::Normal),
(p_normal_value, qnan, "nan", Status::OK, Category::NaN),
(p_normal_value, p_normal_value, "0x1p+1", Status::OK, Category::Normal),
(p_normal_value, m_normal_value, "0x0p+0", Status::OK, Category::Zero),
(p_normal_value, p_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_normal_value, m_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_normal_value, p_smallest_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_normal_value, m_smallest_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_normal_value, p_smallest_normalized, "0x1p+0", Status::INEXACT, Category::Normal),
(p_normal_value, m_smallest_normalized, "0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, p_inf, "inf", Status::OK, Category::Infinity),
(m_normal_value, m_inf, "-inf", Status::OK, Category::Infinity),
(m_normal_value, p_zero, "-0x1p+0", Status::OK, Category::Normal),
(m_normal_value, m_zero, "-0x1p+0", Status::OK, Category::Normal),
(m_normal_value, qnan, "nan", Status::OK, Category::NaN),
(m_normal_value, p_normal_value, "0x0p+0", Status::OK, Category::Zero),
(m_normal_value, m_normal_value, "-0x1p+1", Status::OK, Category::Normal),
(m_normal_value, p_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_normal_value, m_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_normal_value, p_smallest_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, m_smallest_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, p_smallest_normalized, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, m_smallest_normalized, "-0x1p+0", Status::INEXACT, Category::Normal),
(p_largest_value, p_inf, "inf", Status::OK, Category::Infinity),
(p_largest_value, m_inf, "-inf", Status::OK, Category::Infinity),
(p_largest_value, p_zero, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, m_zero, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, qnan, "nan", Status::OK, Category::NaN),
(p_largest_value, p_normal_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_largest_value, m_normal_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_largest_value, p_largest_value, "inf", overflow_status, Category::Infinity),
(p_largest_value, m_largest_value, "0x0p+0", Status::OK, Category::Zero),
(p_largest_value, p_smallest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_largest_value, m_smallest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(
p_largest_value,
p_smallest_normalized,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
p_largest_value,
m_smallest_normalized,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(m_largest_value, p_inf, "inf", Status::OK, Category::Infinity),
(m_largest_value, m_inf, "-inf", Status::OK, Category::Infinity),
(m_largest_value, p_zero, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, m_zero, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, qnan, "nan", Status::OK, Category::NaN),
(m_largest_value, p_normal_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_largest_value, m_normal_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_largest_value, p_largest_value, "0x0p+0", Status::OK, Category::Zero),
(m_largest_value, m_largest_value, "-inf", overflow_status, Category::Infinity),
(m_largest_value, p_smallest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_largest_value, m_smallest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(
m_largest_value,
p_smallest_normalized,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
m_largest_value,
m_smallest_normalized,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(p_smallest_value, p_inf, "inf", Status::OK, Category::Infinity),
(p_smallest_value, m_inf, "-inf", Status::OK, Category::Infinity),
(p_smallest_value, p_zero, "0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, m_zero, "0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, qnan, "nan", Status::OK, Category::NaN),
(p_smallest_value, p_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_smallest_value, m_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(p_smallest_value, p_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_smallest_value, m_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_smallest_value, p_smallest_value, "0x1p-148", Status::OK, Category::Normal),
(p_smallest_value, m_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_value, p_smallest_normalized, "0x1.000002p-126", Status::OK, Category::Normal),
(p_smallest_value, m_smallest_normalized, "-0x1.fffffcp-127", Status::OK, Category::Normal),
(m_smallest_value, p_inf, "inf", Status::OK, Category::Infinity),
(m_smallest_value, m_inf, "-inf", Status::OK, Category::Infinity),
(m_smallest_value, p_zero, "-0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, m_zero, "-0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, qnan, "nan", Status::OK, Category::NaN),
(m_smallest_value, p_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(m_smallest_value, m_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_smallest_value, p_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_smallest_value, m_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_smallest_value, p_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_value, m_smallest_value, "-0x1p-148", Status::OK, Category::Normal),
(m_smallest_value, p_smallest_normalized, "0x1.fffffcp-127", Status::OK, Category::Normal),
(m_smallest_value, m_smallest_normalized, "-0x1.000002p-126", Status::OK, Category::Normal),
(p_smallest_normalized, p_inf, "inf", Status::OK, Category::Infinity),
(p_smallest_normalized, m_inf, "-inf", Status::OK, Category::Infinity),
(p_smallest_normalized, p_zero, "0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, m_zero, "0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, qnan, "nan", Status::OK, Category::NaN),
(p_smallest_normalized, p_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_smallest_normalized, m_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(
p_smallest_normalized,
p_largest_value,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
p_smallest_normalized,
m_largest_value,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(p_smallest_normalized, p_smallest_value, "0x1.000002p-126", Status::OK, Category::Normal),
(p_smallest_normalized, m_smallest_value, "0x1.fffffcp-127", Status::OK, Category::Normal),
(p_smallest_normalized, p_smallest_normalized, "0x1p-125", Status::OK, Category::Normal),
(p_smallest_normalized, m_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_normalized, p_inf, "inf", Status::OK, Category::Infinity),
(m_smallest_normalized, m_inf, "-inf", Status::OK, Category::Infinity),
(m_smallest_normalized, p_zero, "-0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, m_zero, "-0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, qnan, "nan", Status::OK, Category::NaN),
(m_smallest_normalized, p_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(m_smallest_normalized, m_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(
m_smallest_normalized,
p_largest_value,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
m_smallest_normalized,
m_largest_value,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(m_smallest_normalized, p_smallest_value, "-0x1.fffffcp-127", Status::OK, Category::Normal),
(m_smallest_normalized, m_smallest_value, "-0x1.000002p-126", Status::OK, Category::Normal),
(m_smallest_normalized, p_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_normalized, m_smallest_normalized, "-0x1p-125", Status::OK, Category::Normal),
];
for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
let status;
let result = unpack!(status=, x + y);
assert_eq!(status, e_status);
assert_eq!(result.category(), e_category);
assert!(result.bitwise_eq(e_result.parse::<Single>().unwrap()));
}
}
#[test]
fn subtract() {
let p_inf = Single::INFINITY;
let m_inf = -Single::INFINITY;
let p_zero = Single::ZERO;
let m_zero = -Single::ZERO;
let qnan = Single::NAN;
let p_normal_value = "0x1p+0".parse::<Single>().unwrap();
let m_normal_value = "-0x1p+0".parse::<Single>().unwrap();
let p_largest_value = Single::largest();
let m_largest_value = -Single::largest();
let p_smallest_value = Single::SMALLEST;
let m_smallest_value = -Single::SMALLEST;
let p_smallest_normalized = Single::smallest_normalized();
let m_smallest_normalized = -Single::smallest_normalized();
let overflow_status = Status::OVERFLOW | Status::INEXACT;
let special_cases = [
(p_inf, p_inf, "nan", Status::INVALID_OP, Category::NaN),
(p_inf, m_inf, "inf", Status::OK, Category::Infinity),
(p_inf, p_zero, "inf", Status::OK, Category::Infinity),
(p_inf, m_zero, "inf", Status::OK, Category::Infinity),
(p_inf, qnan, "-nan", Status::OK, Category::NaN),
(p_inf, p_normal_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_normal_value, "inf", Status::OK, Category::Infinity),
(p_inf, p_largest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_largest_value, "inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_value, "inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_normalized, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_normalized, "inf", Status::OK, Category::Infinity),
(m_inf, p_inf, "-inf", Status::OK, Category::Infinity),
(m_inf, m_inf, "nan", Status::INVALID_OP, Category::NaN),
(m_inf, p_zero, "-inf", Status::OK, Category::Infinity),
(m_inf, m_zero, "-inf", Status::OK, Category::Infinity),
(m_inf, qnan, "-nan", Status::OK, Category::NaN),
(m_inf, p_normal_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_normal_value, "-inf", Status::OK, Category::Infinity),
(m_inf, p_largest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_largest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(p_zero, p_inf, "-inf", Status::OK, Category::Infinity),
(p_zero, m_inf, "inf", Status::OK, Category::Infinity),
(p_zero, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_zero, "0x0p+0", Status::OK, Category::Zero),
(p_zero, qnan, "-nan", Status::OK, Category::NaN),
(p_zero, p_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(p_zero, m_normal_value, "0x1p+0", Status::OK, Category::Normal),
(p_zero, p_largest_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(p_zero, m_largest_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_zero, p_smallest_value, "-0x1p-149", Status::OK, Category::Normal),
(p_zero, m_smallest_value, "0x1p-149", Status::OK, Category::Normal),
(p_zero, p_smallest_normalized, "-0x1p-126", Status::OK, Category::Normal),
(p_zero, m_smallest_normalized, "0x1p-126", Status::OK, Category::Normal),
(m_zero, p_inf, "-inf", Status::OK, Category::Infinity),
(m_zero, m_inf, "inf", Status::OK, Category::Infinity),
(m_zero, p_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_zero, "0x0p+0", Status::OK, Category::Zero),
(m_zero, qnan, "-nan", Status::OK, Category::NaN),
(m_zero, p_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(m_zero, m_normal_value, "0x1p+0", Status::OK, Category::Normal),
(m_zero, p_largest_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_zero, m_largest_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(m_zero, p_smallest_value, "-0x1p-149", Status::OK, Category::Normal),
(m_zero, m_smallest_value, "0x1p-149", Status::OK, Category::Normal),
(m_zero, p_smallest_normalized, "-0x1p-126", Status::OK, Category::Normal),
(m_zero, m_smallest_normalized, "0x1p-126", Status::OK, Category::Normal),
(qnan, p_inf, "nan", Status::OK, Category::NaN),
(qnan, m_inf, "nan", Status::OK, Category::NaN),
(qnan, p_zero, "nan", Status::OK, Category::NaN),
(qnan, m_zero, "nan", Status::OK, Category::NaN),
(qnan, qnan, "nan", Status::OK, Category::NaN),
(qnan, p_normal_value, "nan", Status::OK, Category::NaN),
(qnan, m_normal_value, "nan", Status::OK, Category::NaN),
(qnan, p_largest_value, "nan", Status::OK, Category::NaN),
(qnan, m_largest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_normalized, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_normalized, "nan", Status::OK, Category::NaN),
(p_normal_value, p_inf, "-inf", Status::OK, Category::Infinity),
(p_normal_value, m_inf, "inf", Status::OK, Category::Infinity),
(p_normal_value, p_zero, "0x1p+0", Status::OK, Category::Normal),
(p_normal_value, m_zero, "0x1p+0", Status::OK, Category::Normal),
(p_normal_value, qnan, "-nan", Status::OK, Category::NaN),
(p_normal_value, p_normal_value, "0x0p+0", Status::OK, Category::Zero),
(p_normal_value, m_normal_value, "0x1p+1", Status::OK, Category::Normal),
(p_normal_value, p_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_normal_value, m_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_normal_value, p_smallest_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_normal_value, m_smallest_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_normal_value, p_smallest_normalized, "0x1p+0", Status::INEXACT, Category::Normal),
(p_normal_value, m_smallest_normalized, "0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, p_inf, "-inf", Status::OK, Category::Infinity),
(m_normal_value, m_inf, "inf", Status::OK, Category::Infinity),
(m_normal_value, p_zero, "-0x1p+0", Status::OK, Category::Normal),
(m_normal_value, m_zero, "-0x1p+0", Status::OK, Category::Normal),
(m_normal_value, qnan, "-nan", Status::OK, Category::NaN),
(m_normal_value, p_normal_value, "-0x1p+1", Status::OK, Category::Normal),
(m_normal_value, m_normal_value, "0x0p+0", Status::OK, Category::Zero),
(m_normal_value, p_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_normal_value, m_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_normal_value, p_smallest_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, m_smallest_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, p_smallest_normalized, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_normal_value, m_smallest_normalized, "-0x1p+0", Status::INEXACT, Category::Normal),
(p_largest_value, p_inf, "-inf", Status::OK, Category::Infinity),
(p_largest_value, m_inf, "inf", Status::OK, Category::Infinity),
(p_largest_value, p_zero, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, m_zero, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, qnan, "-nan", Status::OK, Category::NaN),
(p_largest_value, p_normal_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_largest_value, m_normal_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_largest_value, p_largest_value, "0x0p+0", Status::OK, Category::Zero),
(p_largest_value, m_largest_value, "inf", overflow_status, Category::Infinity),
(p_largest_value, p_smallest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_largest_value, m_smallest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(
p_largest_value,
p_smallest_normalized,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
p_largest_value,
m_smallest_normalized,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(m_largest_value, p_inf, "-inf", Status::OK, Category::Infinity),
(m_largest_value, m_inf, "inf", Status::OK, Category::Infinity),
(m_largest_value, p_zero, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, m_zero, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, qnan, "-nan", Status::OK, Category::NaN),
(m_largest_value, p_normal_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_largest_value, m_normal_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_largest_value, p_largest_value, "-inf", overflow_status, Category::Infinity),
(m_largest_value, m_largest_value, "0x0p+0", Status::OK, Category::Zero),
(m_largest_value, p_smallest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_largest_value, m_smallest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(
m_largest_value,
p_smallest_normalized,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
m_largest_value,
m_smallest_normalized,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(p_smallest_value, p_inf, "-inf", Status::OK, Category::Infinity),
(p_smallest_value, m_inf, "inf", Status::OK, Category::Infinity),
(p_smallest_value, p_zero, "0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, m_zero, "0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, qnan, "-nan", Status::OK, Category::NaN),
(p_smallest_value, p_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(p_smallest_value, m_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(p_smallest_value, p_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_smallest_value, m_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(p_smallest_value, p_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_value, m_smallest_value, "0x1p-148", Status::OK, Category::Normal),
(p_smallest_value, p_smallest_normalized, "-0x1.fffffcp-127", Status::OK, Category::Normal),
(p_smallest_value, m_smallest_normalized, "0x1.000002p-126", Status::OK, Category::Normal),
(m_smallest_value, p_inf, "-inf", Status::OK, Category::Infinity),
(m_smallest_value, m_inf, "inf", Status::OK, Category::Infinity),
(m_smallest_value, p_zero, "-0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, m_zero, "-0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, qnan, "-nan", Status::OK, Category::NaN),
(m_smallest_value, p_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_smallest_value, m_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(m_smallest_value, p_largest_value, "-0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_smallest_value, m_largest_value, "0x1.fffffep+127", Status::INEXACT, Category::Normal),
(m_smallest_value, p_smallest_value, "-0x1p-148", Status::OK, Category::Normal),
(m_smallest_value, m_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_value, p_smallest_normalized, "-0x1.000002p-126", Status::OK, Category::Normal),
(m_smallest_value, m_smallest_normalized, "0x1.fffffcp-127", Status::OK, Category::Normal),
(p_smallest_normalized, p_inf, "-inf", Status::OK, Category::Infinity),
(p_smallest_normalized, m_inf, "inf", Status::OK, Category::Infinity),
(p_smallest_normalized, p_zero, "0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, m_zero, "0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, qnan, "-nan", Status::OK, Category::NaN),
(p_smallest_normalized, p_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(p_smallest_normalized, m_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(
p_smallest_normalized,
p_largest_value,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
p_smallest_normalized,
m_largest_value,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(p_smallest_normalized, p_smallest_value, "0x1.fffffcp-127", Status::OK, Category::Normal),
(p_smallest_normalized, m_smallest_value, "0x1.000002p-126", Status::OK, Category::Normal),
(p_smallest_normalized, p_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_normalized, m_smallest_normalized, "0x1p-125", Status::OK, Category::Normal),
(m_smallest_normalized, p_inf, "-inf", Status::OK, Category::Infinity),
(m_smallest_normalized, m_inf, "inf", Status::OK, Category::Infinity),
(m_smallest_normalized, p_zero, "-0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, m_zero, "-0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, qnan, "-nan", Status::OK, Category::NaN),
(m_smallest_normalized, p_normal_value, "-0x1p+0", Status::INEXACT, Category::Normal),
(m_smallest_normalized, m_normal_value, "0x1p+0", Status::INEXACT, Category::Normal),
(
m_smallest_normalized,
p_largest_value,
"-0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(
m_smallest_normalized,
m_largest_value,
"0x1.fffffep+127",
Status::INEXACT,
Category::Normal,
),
(m_smallest_normalized, p_smallest_value, "-0x1.000002p-126", Status::OK, Category::Normal),
(m_smallest_normalized, m_smallest_value, "-0x1.fffffcp-127", Status::OK, Category::Normal),
(m_smallest_normalized, p_smallest_normalized, "-0x1p-125", Status::OK, Category::Normal),
(m_smallest_normalized, m_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
];
for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
let status;
let result = unpack!(status=, x - y);
assert_eq!(status, e_status);
assert_eq!(result.category(), e_category);
assert!(result.bitwise_eq(e_result.parse::<Single>().unwrap()));
}
}
#[test]
fn multiply() {
let p_inf = Single::INFINITY;
let m_inf = -Single::INFINITY;
let p_zero = Single::ZERO;
let m_zero = -Single::ZERO;
let qnan = Single::NAN;
let p_normal_value = "0x1p+0".parse::<Single>().unwrap();
let m_normal_value = "-0x1p+0".parse::<Single>().unwrap();
let p_largest_value = Single::largest();
let m_largest_value = -Single::largest();
let p_smallest_value = Single::SMALLEST;
let m_smallest_value = -Single::SMALLEST;
let p_smallest_normalized = Single::smallest_normalized();
let m_smallest_normalized = -Single::smallest_normalized();
let overflow_status = Status::OVERFLOW | Status::INEXACT;
let underflow_status = Status::UNDERFLOW | Status::INEXACT;
let special_cases = [
(p_inf, p_inf, "inf", Status::OK, Category::Infinity),
(p_inf, m_inf, "-inf", Status::OK, Category::Infinity),
(p_inf, p_zero, "nan", Status::INVALID_OP, Category::NaN),
(p_inf, m_zero, "nan", Status::INVALID_OP, Category::NaN),
(p_inf, qnan, "nan", Status::OK, Category::NaN),
(p_inf, p_normal_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_normal_value, "-inf", Status::OK, Category::Infinity),
(p_inf, p_largest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_largest_value, "-inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_value, "-inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_normalized, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(m_inf, p_inf, "-inf", Status::OK, Category::Infinity),
(m_inf, m_inf, "inf", Status::OK, Category::Infinity),
(m_inf, p_zero, "nan", Status::INVALID_OP, Category::NaN),
(m_inf, m_zero, "nan", Status::INVALID_OP, Category::NaN),
(m_inf, qnan, "nan", Status::OK, Category::NaN),
(m_inf, p_normal_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_normal_value, "inf", Status::OK, Category::Infinity),
(m_inf, p_largest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_largest_value, "inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_value, "inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_normalized, "inf", Status::OK, Category::Infinity),
(p_zero, p_inf, "nan", Status::INVALID_OP, Category::NaN),
(p_zero, m_inf, "nan", Status::INVALID_OP, Category::NaN),
(p_zero, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_zero, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, qnan, "nan", Status::OK, Category::NaN),
(p_zero, p_normal_value, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_normal_value, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_largest_value, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_largest_value, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_smallest_value, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_smallest_normalized, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, p_inf, "nan", Status::INVALID_OP, Category::NaN),
(m_zero, m_inf, "nan", Status::INVALID_OP, Category::NaN),
(m_zero, p_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_zero, "0x0p+0", Status::OK, Category::Zero),
(m_zero, qnan, "nan", Status::OK, Category::NaN),
(m_zero, p_normal_value, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_normal_value, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_largest_value, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_largest_value, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_smallest_value, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_smallest_normalized, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(qnan, p_inf, "nan", Status::OK, Category::NaN),
(qnan, m_inf, "nan", Status::OK, Category::NaN),
(qnan, p_zero, "nan", Status::OK, Category::NaN),
(qnan, m_zero, "nan", Status::OK, Category::NaN),
(qnan, qnan, "nan", Status::OK, Category::NaN),
(qnan, p_normal_value, "nan", Status::OK, Category::NaN),
(qnan, m_normal_value, "nan", Status::OK, Category::NaN),
(qnan, p_largest_value, "nan", Status::OK, Category::NaN),
(qnan, m_largest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_normalized, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_normalized, "nan", Status::OK, Category::NaN),
(p_normal_value, p_inf, "inf", Status::OK, Category::Infinity),
(p_normal_value, m_inf, "-inf", Status::OK, Category::Infinity),
(p_normal_value, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_normal_value, m_zero, "-0x0p+0", Status::OK, Category::Zero),
(p_normal_value, qnan, "nan", Status::OK, Category::NaN),
(p_normal_value, p_normal_value, "0x1p+0", Status::OK, Category::Normal),
(p_normal_value, m_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(p_normal_value, p_largest_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_normal_value, m_largest_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(p_normal_value, p_smallest_value, "0x1p-149", Status::OK, Category::Normal),
(p_normal_value, m_smallest_value, "-0x1p-149", Status::OK, Category::Normal),
(p_normal_value, p_smallest_normalized, "0x1p-126", Status::OK, Category::Normal),
(p_normal_value, m_smallest_normalized, "-0x1p-126", Status::OK, Category::Normal),
(m_normal_value, p_inf, "-inf", Status::OK, Category::Infinity),
(m_normal_value, m_inf, "inf", Status::OK, Category::Infinity),
(m_normal_value, p_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_normal_value, m_zero, "0x0p+0", Status::OK, Category::Zero),
(m_normal_value, qnan, "nan", Status::OK, Category::NaN),
(m_normal_value, p_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(m_normal_value, m_normal_value, "0x1p+0", Status::OK, Category::Normal),
(m_normal_value, p_largest_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_normal_value, m_largest_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(m_normal_value, p_smallest_value, "-0x1p-149", Status::OK, Category::Normal),
(m_normal_value, m_smallest_value, "0x1p-149", Status::OK, Category::Normal),
(m_normal_value, p_smallest_normalized, "-0x1p-126", Status::OK, Category::Normal),
(m_normal_value, m_smallest_normalized, "0x1p-126", Status::OK, Category::Normal),
(p_largest_value, p_inf, "inf", Status::OK, Category::Infinity),
(p_largest_value, m_inf, "-inf", Status::OK, Category::Infinity),
(p_largest_value, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_largest_value, m_zero, "-0x0p+0", Status::OK, Category::Zero),
(p_largest_value, qnan, "nan", Status::OK, Category::NaN),
(p_largest_value, p_normal_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, m_normal_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, p_largest_value, "inf", overflow_status, Category::Infinity),
(p_largest_value, m_largest_value, "-inf", overflow_status, Category::Infinity),
(p_largest_value, p_smallest_value, "0x1.fffffep-22", Status::OK, Category::Normal),
(p_largest_value, m_smallest_value, "-0x1.fffffep-22", Status::OK, Category::Normal),
(p_largest_value, p_smallest_normalized, "0x1.fffffep+1", Status::OK, Category::Normal),
(p_largest_value, m_smallest_normalized, "-0x1.fffffep+1", Status::OK, Category::Normal),
(m_largest_value, p_inf, "-inf", Status::OK, Category::Infinity),
(m_largest_value, m_inf, "inf", Status::OK, Category::Infinity),
(m_largest_value, p_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_largest_value, m_zero, "0x0p+0", Status::OK, Category::Zero),
(m_largest_value, qnan, "nan", Status::OK, Category::NaN),
(m_largest_value, p_normal_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, m_normal_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, p_largest_value, "-inf", overflow_status, Category::Infinity),
(m_largest_value, m_largest_value, "inf", overflow_status, Category::Infinity),
(m_largest_value, p_smallest_value, "-0x1.fffffep-22", Status::OK, Category::Normal),
(m_largest_value, m_smallest_value, "0x1.fffffep-22", Status::OK, Category::Normal),
(m_largest_value, p_smallest_normalized, "-0x1.fffffep+1", Status::OK, Category::Normal),
(m_largest_value, m_smallest_normalized, "0x1.fffffep+1", Status::OK, Category::Normal),
(p_smallest_value, p_inf, "inf", Status::OK, Category::Infinity),
(p_smallest_value, m_inf, "-inf", Status::OK, Category::Infinity),
(p_smallest_value, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_value, m_zero, "-0x0p+0", Status::OK, Category::Zero),
(p_smallest_value, qnan, "nan", Status::OK, Category::NaN),
(p_smallest_value, p_normal_value, "0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, m_normal_value, "-0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, p_largest_value, "0x1.fffffep-22", Status::OK, Category::Normal),
(p_smallest_value, m_largest_value, "-0x1.fffffep-22", Status::OK, Category::Normal),
(p_smallest_value, p_smallest_value, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_value, m_smallest_value, "-0x0p+0", underflow_status, Category::Zero),
(p_smallest_value, p_smallest_normalized, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_value, m_smallest_normalized, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_value, p_inf, "-inf", Status::OK, Category::Infinity),
(m_smallest_value, m_inf, "inf", Status::OK, Category::Infinity),
(m_smallest_value, p_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_smallest_value, m_zero, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_value, qnan, "nan", Status::OK, Category::NaN),
(m_smallest_value, p_normal_value, "-0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, m_normal_value, "0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, p_largest_value, "-0x1.fffffep-22", Status::OK, Category::Normal),
(m_smallest_value, m_largest_value, "0x1.fffffep-22", Status::OK, Category::Normal),
(m_smallest_value, p_smallest_value, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_value, m_smallest_value, "0x0p+0", underflow_status, Category::Zero),
(m_smallest_value, p_smallest_normalized, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_value, m_smallest_normalized, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_normalized, p_inf, "inf", Status::OK, Category::Infinity),
(p_smallest_normalized, m_inf, "-inf", Status::OK, Category::Infinity),
(p_smallest_normalized, p_zero, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_normalized, m_zero, "-0x0p+0", Status::OK, Category::Zero),
(p_smallest_normalized, qnan, "nan", Status::OK, Category::NaN),
(p_smallest_normalized, p_normal_value, "0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, m_normal_value, "-0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, p_largest_value, "0x1.fffffep+1", Status::OK, Category::Normal),
(p_smallest_normalized, m_largest_value, "-0x1.fffffep+1", Status::OK, Category::Normal),
(p_smallest_normalized, p_smallest_value, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_normalized, m_smallest_value, "-0x0p+0", underflow_status, Category::Zero),
(p_smallest_normalized, p_smallest_normalized, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_normalized, m_smallest_normalized, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_normalized, p_inf, "-inf", Status::OK, Category::Infinity),
(m_smallest_normalized, m_inf, "inf", Status::OK, Category::Infinity),
(m_smallest_normalized, p_zero, "-0x0p+0", Status::OK, Category::Zero),
(m_smallest_normalized, m_zero, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_normalized, qnan, "nan", Status::OK, Category::NaN),
(m_smallest_normalized, p_normal_value, "-0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, m_normal_value, "0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, p_largest_value, "-0x1.fffffep+1", Status::OK, Category::Normal),
(m_smallest_normalized, m_largest_value, "0x1.fffffep+1", Status::OK, Category::Normal),
(m_smallest_normalized, p_smallest_value, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_normalized, m_smallest_value, "0x0p+0", underflow_status, Category::Zero),
(m_smallest_normalized, p_smallest_normalized, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_normalized, m_smallest_normalized, "0x0p+0", underflow_status, Category::Zero),
];
for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
let status;
let result = unpack!(status=, x * y);
assert_eq!(status, e_status);
assert_eq!(result.category(), e_category);
assert!(result.bitwise_eq(e_result.parse::<Single>().unwrap()));
}
}
#[test]
fn divide() {
let p_inf = Single::INFINITY;
let m_inf = -Single::INFINITY;
let p_zero = Single::ZERO;
let m_zero = -Single::ZERO;
let qnan = Single::NAN;
let p_normal_value = "0x1p+0".parse::<Single>().unwrap();
let m_normal_value = "-0x1p+0".parse::<Single>().unwrap();
let p_largest_value = Single::largest();
let m_largest_value = -Single::largest();
let p_smallest_value = Single::SMALLEST;
let m_smallest_value = -Single::SMALLEST;
let p_smallest_normalized = Single::smallest_normalized();
let m_smallest_normalized = -Single::smallest_normalized();
let overflow_status = Status::OVERFLOW | Status::INEXACT;
let underflow_status = Status::UNDERFLOW | Status::INEXACT;
let special_cases = [
(p_inf, p_inf, "nan", Status::INVALID_OP, Category::NaN),
(p_inf, m_inf, "nan", Status::INVALID_OP, Category::NaN),
(p_inf, p_zero, "inf", Status::OK, Category::Infinity),
(p_inf, m_zero, "-inf", Status::OK, Category::Infinity),
(p_inf, qnan, "nan", Status::OK, Category::NaN),
(p_inf, p_normal_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_normal_value, "-inf", Status::OK, Category::Infinity),
(p_inf, p_largest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_largest_value, "-inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_value, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_value, "-inf", Status::OK, Category::Infinity),
(p_inf, p_smallest_normalized, "inf", Status::OK, Category::Infinity),
(p_inf, m_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(m_inf, p_inf, "nan", Status::INVALID_OP, Category::NaN),
(m_inf, m_inf, "nan", Status::INVALID_OP, Category::NaN),
(m_inf, p_zero, "-inf", Status::OK, Category::Infinity),
(m_inf, m_zero, "inf", Status::OK, Category::Infinity),
(m_inf, qnan, "nan", Status::OK, Category::NaN),
(m_inf, p_normal_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_normal_value, "inf", Status::OK, Category::Infinity),
(m_inf, p_largest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_largest_value, "inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_value, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_value, "inf", Status::OK, Category::Infinity),
(m_inf, p_smallest_normalized, "-inf", Status::OK, Category::Infinity),
(m_inf, m_smallest_normalized, "inf", Status::OK, Category::Infinity),
(p_zero, p_inf, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_inf, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_zero, "nan", Status::INVALID_OP, Category::NaN),
(p_zero, m_zero, "nan", Status::INVALID_OP, Category::NaN),
(p_zero, qnan, "nan", Status::OK, Category::NaN),
(p_zero, p_normal_value, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_normal_value, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_largest_value, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_largest_value, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_smallest_value, "-0x0p+0", Status::OK, Category::Zero),
(p_zero, p_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(p_zero, m_smallest_normalized, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, p_inf, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_inf, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_zero, "nan", Status::INVALID_OP, Category::NaN),
(m_zero, m_zero, "nan", Status::INVALID_OP, Category::NaN),
(m_zero, qnan, "nan", Status::OK, Category::NaN),
(m_zero, p_normal_value, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_normal_value, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_largest_value, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_largest_value, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_smallest_value, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_smallest_value, "0x0p+0", Status::OK, Category::Zero),
(m_zero, p_smallest_normalized, "-0x0p+0", Status::OK, Category::Zero),
(m_zero, m_smallest_normalized, "0x0p+0", Status::OK, Category::Zero),
(qnan, p_inf, "nan", Status::OK, Category::NaN),
(qnan, m_inf, "nan", Status::OK, Category::NaN),
(qnan, p_zero, "nan", Status::OK, Category::NaN),
(qnan, m_zero, "nan", Status::OK, Category::NaN),
(qnan, qnan, "nan", Status::OK, Category::NaN),
(qnan, p_normal_value, "nan", Status::OK, Category::NaN),
(qnan, m_normal_value, "nan", Status::OK, Category::NaN),
(qnan, p_largest_value, "nan", Status::OK, Category::NaN),
(qnan, m_largest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_value, "nan", Status::OK, Category::NaN),
(qnan, p_smallest_normalized, "nan", Status::OK, Category::NaN),
(qnan, m_smallest_normalized, "nan", Status::OK, Category::NaN),
(p_normal_value, p_inf, "0x0p+0", Status::OK, Category::Zero),
(p_normal_value, m_inf, "-0x0p+0", Status::OK, Category::Zero),
(p_normal_value, p_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_normal_value, m_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_normal_value, qnan, "nan", Status::OK, Category::NaN),
(p_normal_value, p_normal_value, "0x1p+0", Status::OK, Category::Normal),
(p_normal_value, m_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(p_normal_value, p_largest_value, "0x1p-128", underflow_status, Category::Normal),
(p_normal_value, m_largest_value, "-0x1p-128", underflow_status, Category::Normal),
(p_normal_value, p_smallest_value, "inf", overflow_status, Category::Infinity),
(p_normal_value, m_smallest_value, "-inf", overflow_status, Category::Infinity),
(p_normal_value, p_smallest_normalized, "0x1p+126", Status::OK, Category::Normal),
(p_normal_value, m_smallest_normalized, "-0x1p+126", Status::OK, Category::Normal),
(m_normal_value, p_inf, "-0x0p+0", Status::OK, Category::Zero),
(m_normal_value, m_inf, "0x0p+0", Status::OK, Category::Zero),
(m_normal_value, p_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_normal_value, m_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_normal_value, qnan, "nan", Status::OK, Category::NaN),
(m_normal_value, p_normal_value, "-0x1p+0", Status::OK, Category::Normal),
(m_normal_value, m_normal_value, "0x1p+0", Status::OK, Category::Normal),
(m_normal_value, p_largest_value, "-0x1p-128", underflow_status, Category::Normal),
(m_normal_value, m_largest_value, "0x1p-128", underflow_status, Category::Normal),
(m_normal_value, p_smallest_value, "-inf", overflow_status, Category::Infinity),
(m_normal_value, m_smallest_value, "inf", overflow_status, Category::Infinity),
(m_normal_value, p_smallest_normalized, "-0x1p+126", Status::OK, Category::Normal),
(m_normal_value, m_smallest_normalized, "0x1p+126", Status::OK, Category::Normal),
(p_largest_value, p_inf, "0x0p+0", Status::OK, Category::Zero),
(p_largest_value, m_inf, "-0x0p+0", Status::OK, Category::Zero),
(p_largest_value, p_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_largest_value, m_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_largest_value, qnan, "nan", Status::OK, Category::NaN),
(p_largest_value, p_normal_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, m_normal_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(p_largest_value, p_largest_value, "0x1p+0", Status::OK, Category::Normal),
(p_largest_value, m_largest_value, "-0x1p+0", Status::OK, Category::Normal),
(p_largest_value, p_smallest_value, "inf", overflow_status, Category::Infinity),
(p_largest_value, m_smallest_value, "-inf", overflow_status, Category::Infinity),
(p_largest_value, p_smallest_normalized, "inf", overflow_status, Category::Infinity),
(p_largest_value, m_smallest_normalized, "-inf", overflow_status, Category::Infinity),
(m_largest_value, p_inf, "-0x0p+0", Status::OK, Category::Zero),
(m_largest_value, m_inf, "0x0p+0", Status::OK, Category::Zero),
(m_largest_value, p_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_largest_value, m_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_largest_value, qnan, "nan", Status::OK, Category::NaN),
(m_largest_value, p_normal_value, "-0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, m_normal_value, "0x1.fffffep+127", Status::OK, Category::Normal),
(m_largest_value, p_largest_value, "-0x1p+0", Status::OK, Category::Normal),
(m_largest_value, m_largest_value, "0x1p+0", Status::OK, Category::Normal),
(m_largest_value, p_smallest_value, "-inf", overflow_status, Category::Infinity),
(m_largest_value, m_smallest_value, "inf", overflow_status, Category::Infinity),
(m_largest_value, p_smallest_normalized, "-inf", overflow_status, Category::Infinity),
(m_largest_value, m_smallest_normalized, "inf", overflow_status, Category::Infinity),
(p_smallest_value, p_inf, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_value, m_inf, "-0x0p+0", Status::OK, Category::Zero),
(p_smallest_value, p_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_smallest_value, m_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_smallest_value, qnan, "nan", Status::OK, Category::NaN),
(p_smallest_value, p_normal_value, "0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, m_normal_value, "-0x1p-149", Status::OK, Category::Normal),
(p_smallest_value, p_largest_value, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_value, m_largest_value, "-0x0p+0", underflow_status, Category::Zero),
(p_smallest_value, p_smallest_value, "0x1p+0", Status::OK, Category::Normal),
(p_smallest_value, m_smallest_value, "-0x1p+0", Status::OK, Category::Normal),
(p_smallest_value, p_smallest_normalized, "0x1p-23", Status::OK, Category::Normal),
(p_smallest_value, m_smallest_normalized, "-0x1p-23", Status::OK, Category::Normal),
(m_smallest_value, p_inf, "-0x0p+0", Status::OK, Category::Zero),
(m_smallest_value, m_inf, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_value, p_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_smallest_value, m_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_smallest_value, qnan, "nan", Status::OK, Category::NaN),
(m_smallest_value, p_normal_value, "-0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, m_normal_value, "0x1p-149", Status::OK, Category::Normal),
(m_smallest_value, p_largest_value, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_value, m_largest_value, "0x0p+0", underflow_status, Category::Zero),
(m_smallest_value, p_smallest_value, "-0x1p+0", Status::OK, Category::Normal),
(m_smallest_value, m_smallest_value, "0x1p+0", Status::OK, Category::Normal),
(m_smallest_value, p_smallest_normalized, "-0x1p-23", Status::OK, Category::Normal),
(m_smallest_value, m_smallest_normalized, "0x1p-23", Status::OK, Category::Normal),
(p_smallest_normalized, p_inf, "0x0p+0", Status::OK, Category::Zero),
(p_smallest_normalized, m_inf, "-0x0p+0", Status::OK, Category::Zero),
(p_smallest_normalized, p_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_smallest_normalized, m_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(p_smallest_normalized, qnan, "nan", Status::OK, Category::NaN),
(p_smallest_normalized, p_normal_value, "0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, m_normal_value, "-0x1p-126", Status::OK, Category::Normal),
(p_smallest_normalized, p_largest_value, "0x0p+0", underflow_status, Category::Zero),
(p_smallest_normalized, m_largest_value, "-0x0p+0", underflow_status, Category::Zero),
(p_smallest_normalized, p_smallest_value, "0x1p+23", Status::OK, Category::Normal),
(p_smallest_normalized, m_smallest_value, "-0x1p+23", Status::OK, Category::Normal),
(p_smallest_normalized, p_smallest_normalized, "0x1p+0", Status::OK, Category::Normal),
(p_smallest_normalized, m_smallest_normalized, "-0x1p+0", Status::OK, Category::Normal),
(m_smallest_normalized, p_inf, "-0x0p+0", Status::OK, Category::Zero),
(m_smallest_normalized, m_inf, "0x0p+0", Status::OK, Category::Zero),
(m_smallest_normalized, p_zero, "-inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_smallest_normalized, m_zero, "inf", Status::DIV_BY_ZERO, Category::Infinity),
(m_smallest_normalized, qnan, "nan", Status::OK, Category::NaN),
(m_smallest_normalized, p_normal_value, "-0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, m_normal_value, "0x1p-126", Status::OK, Category::Normal),
(m_smallest_normalized, p_largest_value, "-0x0p+0", underflow_status, Category::Zero),
(m_smallest_normalized, m_largest_value, "0x0p+0", underflow_status, Category::Zero),
(m_smallest_normalized, p_smallest_value, "-0x1p+23", Status::OK, Category::Normal),
(m_smallest_normalized, m_smallest_value, "0x1p+23", Status::OK, Category::Normal),
(m_smallest_normalized, p_smallest_normalized, "-0x1p+0", Status::OK, Category::Normal),
(m_smallest_normalized, m_smallest_normalized, "0x1p+0", Status::OK, Category::Normal),
];
for &(x, y, e_result, e_status, e_category) in &special_cases[..] {
let status;
let result = unpack!(status=, x / y);
assert_eq!(status, e_status);
assert_eq!(result.category(), e_category);
assert!(result.bitwise_eq(e_result.parse::<Single>().unwrap()));
}
}
#[test]
fn operator_overloads() {
let one = "0x1p+0".parse::<Single>().unwrap();
let two = "0x2p+0".parse::<Single>().unwrap();
assert!(two.bitwise_eq((one + one).value));
assert!(one.bitwise_eq((two - one).value));
assert!(two.bitwise_eq((one * two).value));
assert!(one.bitwise_eq((two / two).value));
}
#[test]
fn abs() {
let p_inf = Single::INFINITY;
let m_inf = -Single::INFINITY;
let p_zero = Single::ZERO;
let m_zero = -Single::ZERO;
let p_qnan = Single::NAN;
let m_qnan = -Single::NAN;
let p_snan = Single::snan(None);
let m_snan = -Single::snan(None);
let p_normal_value = "0x1p+0".parse::<Single>().unwrap();
let m_normal_value = "-0x1p+0".parse::<Single>().unwrap();
let p_largest_value = Single::largest();
let m_largest_value = -Single::largest();
let p_smallest_value = Single::SMALLEST;
let m_smallest_value = -Single::SMALLEST;
let p_smallest_normalized = Single::smallest_normalized();
let m_smallest_normalized = -Single::smallest_normalized();
assert!(p_inf.bitwise_eq(p_inf.abs()));
assert!(p_inf.bitwise_eq(m_inf.abs()));
assert!(p_zero.bitwise_eq(p_zero.abs()));
assert!(p_zero.bitwise_eq(m_zero.abs()));
assert!(p_qnan.bitwise_eq(p_qnan.abs()));
assert!(p_qnan.bitwise_eq(m_qnan.abs()));
assert!(p_snan.bitwise_eq(p_snan.abs()));
assert!(p_snan.bitwise_eq(m_snan.abs()));
assert!(p_normal_value.bitwise_eq(p_normal_value.abs()));
assert!(p_normal_value.bitwise_eq(m_normal_value.abs()));
assert!(p_largest_value.bitwise_eq(p_largest_value.abs()));
assert!(p_largest_value.bitwise_eq(m_largest_value.abs()));
assert!(p_smallest_value.bitwise_eq(p_smallest_value.abs()));
assert!(p_smallest_value.bitwise_eq(m_smallest_value.abs()));
assert!(p_smallest_normalized.bitwise_eq(p_smallest_normalized.abs(),));
assert!(p_smallest_normalized.bitwise_eq(m_smallest_normalized.abs(),));
}
#[test]
fn neg() {
let one = "1.0".parse::<Single>().unwrap();
let neg_one = "-1.0".parse::<Single>().unwrap();
let zero = Single::ZERO;
let neg_zero = -Single::ZERO;
let inf = Single::INFINITY;
let neg_inf = -Single::INFINITY;
let qnan = Single::NAN;
let neg_qnan = -Single::NAN;
assert!(neg_one.bitwise_eq(-one));
assert!(one.bitwise_eq(-neg_one));
assert!(neg_zero.bitwise_eq(-zero));
assert!(zero.bitwise_eq(-neg_zero));
assert!(neg_inf.bitwise_eq(-inf));
assert!(inf.bitwise_eq(-neg_inf));
assert!(neg_inf.bitwise_eq(-inf));
assert!(inf.bitwise_eq(-neg_inf));
assert!(neg_qnan.bitwise_eq(-qnan));
assert!(qnan.bitwise_eq(-neg_qnan));
}
#[test]
fn ilogb() {
assert_eq!(-1074, Double::SMALLEST.ilogb());
assert_eq!(-1074, (-Double::SMALLEST).ilogb());
assert_eq!(-1023, "0x1.ffffffffffffep-1024".parse::<Double>().unwrap().ilogb());
assert_eq!(-1023, "0x1.ffffffffffffep-1023".parse::<Double>().unwrap().ilogb());
assert_eq!(
-1023,
"-0x1.ffffffffffffep-1023"
.parse::<Double>()
.unwrap()
.ilogb()
);
assert_eq!(-51, "0x1p-51".parse::<Double>().unwrap().ilogb());
assert_eq!(-1023, "0x1.c60f120d9f87cp-1023".parse::<Double>().unwrap().ilogb());
assert_eq!(-2, "0x0.ffffp-1".parse::<Double>().unwrap().ilogb());
assert_eq!(-1023, "0x1.fffep-1023".parse::<Double>().unwrap().ilogb());
assert_eq!(1023, Double::largest().ilogb());
assert_eq!(1023, (-Double::largest()).ilogb());
assert_eq!(0, "0x1p+0".parse::<Single>().unwrap().ilogb());
assert_eq!(0, "-0x1p+0".parse::<Single>().unwrap().ilogb());
assert_eq!(42, "0x1p+42".parse::<Single>().unwrap().ilogb());
assert_eq!(-42, "0x1p-42".parse::<Single>().unwrap().ilogb());
assert_eq!(IEK_INF, Single::INFINITY.ilogb());
assert_eq!(IEK_INF, (-Single::INFINITY).ilogb());
assert_eq!(IEK_ZERO, Single::ZERO.ilogb());
assert_eq!(IEK_ZERO, (-Single::ZERO).ilogb());
assert_eq!(IEK_NAN, Single::NAN.ilogb());
assert_eq!(IEK_NAN, Single::snan(None).ilogb());
assert_eq!(127, Single::largest().ilogb());
assert_eq!(127, (-Single::largest()).ilogb());
assert_eq!(-149, Single::SMALLEST.ilogb());
assert_eq!(-149, (-Single::SMALLEST).ilogb());
assert_eq!(-126, Single::smallest_normalized().ilogb());
assert_eq!(-126, (-Single::smallest_normalized()).ilogb());
}
#[test]
fn scalbn() {
assert!(
"0x1p+0"
.parse::<Single>()
.unwrap()
.bitwise_eq("0x1p+0".parse::<Single>().unwrap().scalbn(0),)
);
assert!(
"0x1p+42"
.parse::<Single>()
.unwrap()
.bitwise_eq("0x1p+0".parse::<Single>().unwrap().scalbn(42),)
);
assert!(
"0x1p-42"
.parse::<Single>()
.unwrap()
.bitwise_eq("0x1p+0".parse::<Single>().unwrap().scalbn(-42),)
);
let p_inf = Single::INFINITY;
let m_inf = -Single::INFINITY;
let p_zero = Single::ZERO;
let m_zero = -Single::ZERO;
let p_qnan = Single::NAN;
let m_qnan = -Single::NAN;
let snan = Single::snan(None);
assert!(p_inf.bitwise_eq(p_inf.scalbn(0)));
assert!(m_inf.bitwise_eq(m_inf.scalbn(0)));
assert!(p_zero.bitwise_eq(p_zero.scalbn(0)));
assert!(m_zero.bitwise_eq(m_zero.scalbn(0)));
assert!(p_qnan.bitwise_eq(p_qnan.scalbn(0)));
assert!(m_qnan.bitwise_eq(m_qnan.scalbn(0)));
assert!(!snan.scalbn(0).is_signaling());
let scalbn_snan = snan.scalbn(1);
assert!(scalbn_snan.is_nan() && !scalbn_snan.is_signaling());
let payload = (u256::ONE << 50) | (u256::ONE << 49) | (u256::from(1234u32) << 32) | u256::ONE;
let snan_with_payload = Double::snan(Some(payload));
let quiet_payload = snan_with_payload.scalbn(1);
assert!(quiet_payload.is_nan() && !quiet_payload.is_signaling());
assert_eq!(payload, quiet_payload.to_bits() & ((u256::ONE << 51) - u256::ONE));
assert!(p_inf.bitwise_eq("0x1p+0".parse::<Single>().unwrap().scalbn(128),));
assert!(m_inf.bitwise_eq("-0x1p+0".parse::<Single>().unwrap().scalbn(128),));
assert!(p_inf.bitwise_eq("0x1p+127".parse::<Single>().unwrap().scalbn(1),));
assert!(p_zero.bitwise_eq("0x1p-127".parse::<Single>().unwrap().scalbn(-127),));
assert!(m_zero.bitwise_eq("-0x1p-127".parse::<Single>().unwrap().scalbn(-127),));
assert!(
"-0x1p-149"
.parse::<Single>()
.unwrap()
.bitwise_eq("-0x1p-127".parse::<Single>().unwrap().scalbn(-22),)
);
assert!(p_zero.bitwise_eq("0x1p-126".parse::<Single>().unwrap().scalbn(-24),));
let smallest_f64 = Double::SMALLEST;
let neg_smallest_f64 = -Double::SMALLEST;
let largest_f64 = Double::largest();
let neg_largest_f64 = -Double::largest();
let largest_denormal_f64 = "0x1.ffffffffffffep-1023".parse::<Double>().unwrap();
let neg_largest_denormal_f64 = "-0x1.ffffffffffffep-1023".parse::<Double>().unwrap();
assert!(smallest_f64.bitwise_eq("0x1p-1074".parse::<Double>().unwrap().scalbn(0),));
assert!(neg_smallest_f64.bitwise_eq("-0x1p-1074".parse::<Double>().unwrap().scalbn(0),));
assert!(
"0x1p+1023"
.parse::<Double>()
.unwrap()
.bitwise_eq(smallest_f64.scalbn(2097,),)
);
assert!(smallest_f64.scalbn(-2097).is_pos_zero());
assert!(smallest_f64.scalbn(-2098).is_pos_zero());
assert!(smallest_f64.scalbn(-2099).is_pos_zero());
assert!(
"0x1p+1022"
.parse::<Double>()
.unwrap()
.bitwise_eq(smallest_f64.scalbn(2096,),)
);
assert!(
"0x1p+1023"
.parse::<Double>()
.unwrap()
.bitwise_eq(smallest_f64.scalbn(2097,),)
);
assert!(smallest_f64.scalbn(2098).is_infinite());
assert!(smallest_f64.scalbn(2099).is_infinite());
assert!(smallest_f64.scalbn(-ExpInt::MAX).is_pos_zero());
assert!(largest_f64.scalbn(ExpInt::MAX).is_infinite());
assert!(largest_denormal_f64.bitwise_eq(largest_denormal_f64.scalbn(0),));
assert!(neg_largest_denormal_f64.bitwise_eq(neg_largest_denormal_f64.scalbn(0),));
assert!(
"0x1.ffffffffffffep-1022"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_denormal_f64.scalbn(1))
);
assert!(
"-0x1.ffffffffffffep-1021"
.parse::<Double>()
.unwrap()
.bitwise_eq(neg_largest_denormal_f64.scalbn(2))
);
assert!(
"0x1.ffffffffffffep+1"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_denormal_f64.scalbn(1024))
);
assert!(largest_denormal_f64.scalbn(-1023).is_pos_zero());
assert!(largest_denormal_f64.scalbn(-1024).is_pos_zero());
assert!(largest_denormal_f64.scalbn(-2048).is_pos_zero());
assert!(largest_denormal_f64.scalbn(2047).is_infinite());
assert!(largest_denormal_f64.scalbn(2098).is_infinite());
assert!(largest_denormal_f64.scalbn(2099).is_infinite());
assert!(
"0x1.ffffffffffffep-2"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_denormal_f64.scalbn(1021))
);
assert!(
"0x1.ffffffffffffep-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_denormal_f64.scalbn(1022))
);
assert!(
"0x1.ffffffffffffep+0"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_denormal_f64.scalbn(1023))
);
assert!(
"0x1.ffffffffffffep+1023"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_denormal_f64.scalbn(2046))
);
assert!(
"0x1p+974"
.parse::<Double>()
.unwrap()
.bitwise_eq(smallest_f64.scalbn(2048,),)
);
let random_denormal_f64 = "0x1.c60f120d9f87cp+51".parse::<Double>().unwrap();
assert!(
"0x1.c60f120d9f87cp-972"
.parse::<Double>()
.unwrap()
.bitwise_eq(random_denormal_f64.scalbn(-1023))
);
assert!(
"0x1.c60f120d9f87cp-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(random_denormal_f64.scalbn(-52))
);
assert!(
"0x1.c60f120d9f87cp-2"
.parse::<Double>()
.unwrap()
.bitwise_eq(random_denormal_f64.scalbn(-53))
);
assert!(
"0x1.c60f120d9f87cp+0"
.parse::<Double>()
.unwrap()
.bitwise_eq(random_denormal_f64.scalbn(-51))
);
assert!(random_denormal_f64.scalbn(-2097).is_pos_zero());
assert!(random_denormal_f64.scalbn(-2090).is_pos_zero());
assert!(
"-0x1p-1073"
.parse::<Double>()
.unwrap()
.bitwise_eq(neg_largest_f64.scalbn(-2097),)
);
assert!(
"-0x1p-1024"
.parse::<Double>()
.unwrap()
.bitwise_eq(neg_largest_f64.scalbn(-2048),)
);
assert!(
"0x1p-1073"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_f64.scalbn(-2097,),)
);
assert!(
"0x1p-1074"
.parse::<Double>()
.unwrap()
.bitwise_eq(largest_f64.scalbn(-2098,),)
);
assert!(
"-0x1p-1074"
.parse::<Double>()
.unwrap()
.bitwise_eq(neg_largest_f64.scalbn(-2098),)
);
assert!(neg_largest_f64.scalbn(-2099).is_neg_zero());
assert!(largest_f64.scalbn(1).is_infinite());
assert!(
"0x1p+0"
.parse::<Double>()
.unwrap()
.bitwise_eq("0x1p+52".parse::<Double>().unwrap().scalbn(-52),)
);
assert!(
"0x1p-103"
.parse::<Double>()
.unwrap()
.bitwise_eq("0x1p-51".parse::<Double>().unwrap().scalbn(-52),)
);
}
#[test]
fn frexp() {
let p_zero = Double::ZERO;
let m_zero = -Double::ZERO;
let one = Double::from_f64(1.0);
let m_one = Double::from_f64(-1.0);
let largest_denormal = "0x1.ffffffffffffep-1023".parse::<Double>().unwrap();
let neg_largest_denormal = "-0x1.ffffffffffffep-1023".parse::<Double>().unwrap();
let smallest = Double::SMALLEST;
let neg_smallest = -Double::SMALLEST;
let largest = Double::largest();
let neg_largest = -Double::largest();
let p_inf = Double::INFINITY;
let m_inf = -Double::INFINITY;
let p_qnan = Double::NAN;
let m_qnan = -Double::NAN;
let snan = Double::snan(None);
let payload = (u256::ONE << 50) | (u256::ONE << 49) | (u256::from(1234u32) << 32) | u256::ONE;
let snan_with_payload = Double::snan(Some(payload));
let mut exp = 0;
let frac = p_zero.frexp(&mut exp);
assert_eq!(0, exp);
assert!(frac.is_pos_zero());
let frac = m_zero.frexp(&mut exp);
assert_eq!(0, exp);
assert!(frac.is_neg_zero());
let frac = one.frexp(&mut exp);
assert_eq!(1, exp);
assert!("0x1p-1".parse::<Double>().unwrap().bitwise_eq(frac));
let frac = m_one.frexp(&mut exp);
assert_eq!(1, exp);
assert!("-0x1p-1".parse::<Double>().unwrap().bitwise_eq(frac));
let frac = largest_denormal.frexp(&mut exp);
assert_eq!(-1022, exp);
assert!(
"0x1.ffffffffffffep-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(frac)
);
let frac = neg_largest_denormal.frexp(&mut exp);
assert_eq!(-1022, exp);
assert!(
"-0x1.ffffffffffffep-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(frac)
);
let frac = smallest.frexp(&mut exp);
assert_eq!(-1073, exp);
assert!("0x1p-1".parse::<Double>().unwrap().bitwise_eq(frac));
let frac = neg_smallest.frexp(&mut exp);
assert_eq!(-1073, exp);
assert!("-0x1p-1".parse::<Double>().unwrap().bitwise_eq(frac));
let frac = largest.frexp(&mut exp);
assert_eq!(1024, exp);
assert!(
"0x1.fffffffffffffp-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(frac)
);
let frac = neg_largest.frexp(&mut exp);
assert_eq!(1024, exp);
assert!(
"-0x1.fffffffffffffp-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(frac)
);
let frac = p_inf.frexp(&mut exp);
assert_eq!(IEK_INF, exp);
assert!(frac.is_infinite() && !frac.is_negative());
let frac = m_inf.frexp(&mut exp);
assert_eq!(IEK_INF, exp);
assert!(frac.is_infinite() && frac.is_negative());
let frac = p_qnan.frexp(&mut exp);
assert_eq!(IEK_NAN, exp);
assert!(frac.is_nan());
let frac = m_qnan.frexp(&mut exp);
assert_eq!(IEK_NAN, exp);
assert!(frac.is_nan());
let frac = snan.frexp(&mut exp);
assert_eq!(IEK_NAN, exp);
assert!(frac.is_nan() && !frac.is_signaling());
let frac = snan_with_payload.frexp(&mut exp);
assert_eq!(IEK_NAN, exp);
assert!(frac.is_nan() && !frac.is_signaling());
assert_eq!(payload, frac.to_bits() & ((u256::ONE << 51) - u256::ONE));
let frac = "0x0.ffffp-1".parse::<Double>().unwrap().frexp(&mut exp);
assert_eq!(-1, exp);
assert!("0x1.fffep-1".parse::<Double>().unwrap().bitwise_eq(frac));
let frac = "0x1p-51".parse::<Double>().unwrap().frexp(&mut exp);
assert_eq!(-50, exp);
assert!("0x1p-1".parse::<Double>().unwrap().bitwise_eq(frac));
let frac = "0x1.c60f120d9f87cp+51"
.parse::<Double>()
.unwrap()
.frexp(&mut exp);
assert_eq!(52, exp);
assert!(
"0x1.c60f120d9f87cp-1"
.parse::<Double>()
.unwrap()
.bitwise_eq(frac)
);
}
#[test]
fn modulo() {
let mut status;
{
let f1 = "1.5".parse::<Double>().unwrap();
let f2 = "1.0".parse::<Double>().unwrap();
let expected = "0.5".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).bitwise_eq(expected));
assert_eq!(status, Status::OK);
}
{
let f1 = "0.5".parse::<Double>().unwrap();
let f2 = "1.0".parse::<Double>().unwrap();
let expected = "0.5".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).bitwise_eq(expected));
assert_eq!(status, Status::OK);
}
{
let f1 = "0x1.3333333333333p-2".parse::<Double>().unwrap(); let f2 = "0x1.47ae147ae147bp-7".parse::<Double>().unwrap(); let expected = "0x1.47ae147ae1471p-7".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).bitwise_eq(expected));
assert_eq!(status, Status::OK);
}
{
let f1 = "0x1p64".parse::<Double>().unwrap(); let f2 = "1.5".parse::<Double>().unwrap();
let expected = "1.0".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).bitwise_eq(expected));
assert_eq!(status, Status::OK);
}
{
let f1 = "0x1p1000".parse::<Double>().unwrap();
let f2 = "0x1p-1000".parse::<Double>().unwrap();
let expected = "0.0".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).bitwise_eq(expected));
assert_eq!(status, Status::OK);
}
{
let f1 = "0.0".parse::<Double>().unwrap();
let f2 = "1.0".parse::<Double>().unwrap();
let expected = "0.0".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).bitwise_eq(expected));
assert_eq!(status, Status::OK);
}
{
let f1 = "1.0".parse::<Double>().unwrap();
let f2 = "0.0".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).is_nan());
assert_eq!(status, Status::INVALID_OP);
}
{
let f1 = "0.0".parse::<Double>().unwrap();
let f2 = "0.0".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).is_nan());
assert_eq!(status, Status::INVALID_OP);
}
{
let f1 = Double::INFINITY;
let f2 = "1.0".parse::<Double>().unwrap();
assert!(unpack!(status=, f1 % f2).is_nan());
assert_eq!(status, Status::INVALID_OP);
}
}