use core::cmp::Ordering::{self, *};
use malachite_base::num::arithmetic::traits::{Acsc, AcscAssign, IsPowerOf2, PowerOf2, Reciprocal};
use malachite_base::num::basic::floats::PrimitiveFloat;
use malachite_base::num::basic::traits::{
Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Two, Zero,
};
use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs};
use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
use malachite_base::num::float::NiceFloat;
use malachite_base::num::logic::traits::SignificantBits;
use malachite_base::rounding_modes::RoundingMode::{self, *};
use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes;
use malachite_base::test_util::generators::{
primitive_float_gen, primitive_float_unsigned_pair_gen_var_1,
unsigned_rounding_mode_pair_gen_var_3,
};
use malachite_float::float::arithmetic::acsc::{
primitive_float_acsc, primitive_float_acsc_pi, primitive_float_acsc_pi_rational,
primitive_float_acsc_rational, primitive_float_acsc_with_period,
primitive_float_acsc_with_period_rational,
};
use malachite_float::test_util::common::{
assert_rounding_ordering_consistent, parse_hex_string, rug_round_try_from_rounding_mode,
to_hex_string,
};
use malachite_float::test_util::float::arithmetic::acsc::{
rug_acsc, rug_acsc_prec_round, rug_acsc_rational_prec_round, rug_acsc_with_period_prec_round,
rug_acsc_with_period_rational_prec_round,
};
use malachite_float::test_util::generators::{
float_gen, float_rounding_mode_pair_gen_var_51, float_unsigned_pair_gen_var_1,
float_unsigned_pair_gen_var_2, float_unsigned_rounding_mode_triple_gen_var_48,
float_unsigned_rounding_mode_triple_gen_var_49, float_unsigned_rounding_mode_triple_gen_var_50,
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_27,
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_28,
float_unsigned_unsigned_triple_gen_var_1, rational_unsigned_rounding_mode_triple_gen_var_13,
rational_unsigned_unsigned_rounding_mode_quadruple_gen_var_10,
};
use malachite_float::{ComparableFloat, ComparableFloatRef, Float};
use malachite_q::Rational;
use malachite_q::test_util::generators::{
rational_gen, rational_unsigned_pair_gen_var_1, rational_unsigned_pair_gen_var_3,
};
use std::panic::catch_unwind;
use std::str::FromStr;
fn asin_of_reciprocal(x: &Float, prec: u64, rm: RoundingMode) -> Option<(Float, Ordering)> {
if !x.is_finite() || *x == 0u32 || x.get_exponent().unwrap().unsigned_abs() > 1000 {
return None;
}
Some(Float::asin_rational_prec_round(
Rational::exact_from(x).reciprocal(),
prec,
rm,
))
}
#[test]
fn test_acsc_prec_round() {
let test = |s: &str,
s_hex: &str,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
o_out: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let (c, o) = x.clone().acsc_prec_round(prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = x.acsc_prec_round_ref(prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_prec_round_assign(prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if rm == Nearest {
let (c_alt, o_alt) = x.acsc_prec_ref(prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if let Some((c_alt, o_alt)) = asin_of_reciprocal(&x, prec, rm) {
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_c, rug_o) = rug_acsc_prec_round(&rug::Float::exact_from(&x), prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
};
test("NaN", "NaN", 10, Nearest, "NaN", "NaN", Equal);
test("Infinity", "Infinity", 10, Exact, "0.0", "0x0.0", Equal);
test("-Infinity", "-Infinity", 10, Exact, "-0.0", "-0x0.0", Equal);
test("0.0", "0x0.0", 10, Exact, "NaN", "NaN", Equal);
test("-0.0", "-0x0.0", 10, Exact, "NaN", "NaN", Equal);
test("0.50", "0x0.8#1", 10, Nearest, "NaN", "NaN", Equal);
test("1.0", "0x1.0#1", 10, Floor, "1.5703", "0x1.920#10", Less);
test(
"1.0",
"0x1.0#1",
10,
Ceiling,
"1.5723",
"0x1.928#10",
Greater,
);
test("1.0", "0x1.0#1", 10, Nearest, "1.5703", "0x1.920#10", Less);
test("1.0", "0x1.0#1", 1, Nearest, "2.0", "0x2.0#1", Greater);
test(
"-1.0",
"-0x1.0#1",
10,
Floor,
"-1.5723",
"-0x1.928#10",
Less,
);
test(
"-1.0",
"-0x1.0#1",
10,
Ceiling,
"-1.5703",
"-0x1.920#10",
Greater,
);
test(
"-1.0",
"-0x1.0#1",
10,
Nearest,
"-1.5703",
"-0x1.920#10",
Greater,
);
test("2.0", "0x2.0#1", 10, Floor, "0.52344", "0x0.860#10", Less);
test(
"2.0",
"0x2.0#1",
10,
Ceiling,
"0.52441",
"0x0.864#10",
Greater,
);
test("2.0", "0x2.0#1", 10, Down, "0.52344", "0x0.860#10", Less);
test("2.0", "0x2.0#1", 10, Up, "0.52441", "0x0.864#10", Greater);
test("2.0", "0x2.0#1", 10, Nearest, "0.52344", "0x0.860#10", Less);
test(
"2.0",
"0x2.0#1",
53,
Nearest,
"0.52359877559829893",
"0x0.860a91c16b9b30#53",
Greater,
);
test(
"-2.0",
"-0x2.0#1",
53,
Nearest,
"-0.52359877559829893",
"-0x0.860a91c16b9b30#53",
Less,
);
test(
"2.0",
"0x2.0#1",
100,
Nearest,
"0.52359877559829887307710723054682",
"0x0.860a91c16b9b2c232dd99707b#100",
Greater,
);
test(
"2.5",
"0x2.8#3",
10,
Nearest,
"0.41162",
"0x0.696#10",
Greater,
);
test(
"2.5",
"0x2.8#3",
53,
Nearest,
"0.41151684606748801",
"0x0.69592b039ce8cc#53",
Less,
);
test(
"1.5",
"0x1.8#2",
20,
Nearest,
"0.72972775",
"0x0.bacf7#20",
Greater,
);
test(
"-1.5",
"-0x1.8#2",
20,
Nearest,
"-0.72972775",
"-0x0.bacf7#20",
Less,
);
test(
"100.0",
"0x64.0#7",
20,
Nearest,
"0.010000169",
"0x0.028f5f0#20",
Greater,
);
test(
"-100.0",
"-0x64.0#7",
20,
Nearest,
"-0.010000169",
"-0x0.028f5f0#20",
Less,
);
test(
"1.0000000000000002",
"0x1.0000000000001#53",
53,
Nearest,
"1.5707963057214724",
"0x1.921fb4e9c057f#53",
Greater,
);
test(
"1.3e30",
"0x1.0E+25#1",
20,
Nearest,
"7.8886091e-31",
"0x1.00000E-25#20",
Less,
);
test(
"-1.3e30",
"-0x1.0E+25#1",
20,
Nearest,
"-7.8886091e-31",
"-0x1.00000E-25#20",
Greater,
);
}
#[test]
#[should_panic]
fn acsc_prec_round_fail_1() {
Float::TWO.acsc_prec_round(0, Floor);
}
#[test]
#[should_panic]
fn acsc_prec_round_fail_2() {
Float::TWO.acsc_prec_round(10, Exact);
}
#[test]
#[should_panic]
fn acsc_prec_round_fail_3() {
Float::ONE.acsc_prec_round(10, Exact);
}
#[test]
#[should_panic]
fn acsc_prec_round_ref_fail() {
Float::TWO.acsc_prec_round_ref(0, Floor);
}
#[test]
#[should_panic]
fn acsc_prec_fail() {
Float::TWO.acsc_prec(0);
}
#[test]
#[should_panic]
fn acsc_round_fail() {
Float::TWO.acsc_round(Exact);
}
fn acsc_exact(x: &Float) -> bool {
x.is_nan() || x.lt_abs(&1u32) || !x.is_finite()
}
#[allow(clippy::needless_pass_by_value)]
fn acsc_prec_round_properties_helper(x: Float, prec: u64, rm: RoundingMode) {
if rm == Exact && !acsc_exact(&x) {
assert_panic!(x.acsc_prec_round_ref(prec, Exact));
return;
}
let (c, o) = x.clone().acsc_prec_round(prec, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = x.acsc_prec_round_ref(prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_prec_round_assign(prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if let Some((c_alt, o_alt)) = asin_of_reciprocal(&x, prec, rm) {
assert_eq!(
ComparableFloatRef(&c_alt),
ComparableFloatRef(&c),
"x = {:#x} exp = {:?} prec_x = {:?} prec = {prec} rm = {rm:?}",
ComparableFloatRef(&x),
x.get_exponent(),
x.get_prec()
);
assert_eq!(o_alt, o, "x = {x} prec = {prec} rm = {rm:?}");
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_c, rug_o) = rug_acsc_prec_round(&rug::Float::exact_from(&x), prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o, "x = {x} prec = {prec} rm = {rm:?}");
}
assert_eq!(c.is_nan(), x.is_nan() || x.lt_abs(&1u32));
if !c.is_nan() {
assert!(c.is_finite());
assert!(c <= 2u32);
assert!(c >= -2i32);
if c.is_normal() {
assert_eq!(c.get_prec(), Some(prec));
}
}
let (c_neg, o_neg) = (-&x).acsc_prec_round(prec, -rm);
assert_eq!(ComparableFloat(-c_neg), ComparableFloat(c.clone()));
assert_eq!(o_neg.reverse(), o);
if o == Equal {
assert!(acsc_exact(&x));
for rm in exhaustive_rounding_modes() {
let (c2, oo) = x.acsc_prec_round_ref(prec, rm);
assert_eq!(ComparableFloatRef(&c2), ComparableFloatRef(&c));
assert_eq!(oo, Equal);
}
} else {
assert_panic!(x.acsc_prec_round_ref(prec, Exact));
}
}
#[test]
fn acsc_prec_round_properties() {
float_unsigned_rounding_mode_triple_gen_var_48().test_properties(|(x, prec, rm)| {
acsc_prec_round_properties_helper(x, prec, rm);
});
float_unsigned_rounding_mode_triple_gen_var_49().test_properties(|(x, prec, rm)| {
acsc_prec_round_properties_helper(x, prec, rm);
});
unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| {
for x in [Float::NAN, Float::ZERO, Float::NEGATIVE_ZERO, Float::ONE_HALF] {
let (c, o) = x.acsc_prec_round(prec, rm);
assert!(c.is_nan());
assert_eq!(o, Equal);
}
let (c, o) = Float::INFINITY.acsc_prec_round(prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (c, o) = Float::NEGATIVE_INFINITY.acsc_prec_round(prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Equal);
if rm == Exact {
assert_panic!(Float::ONE.acsc_prec_round(prec, Exact));
assert_panic!(Float::NEGATIVE_ONE.acsc_prec_round(prec, Exact));
} else {
let (p, o_p) = Float::pi_prec_round(prec, rm);
let (c, o) = Float::ONE.acsc_prec_round(prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(p >> 1u32));
assert_eq!(o, o_p);
let (p, o_p) = Float::pi_prec_round(prec, -rm);
let (c, o) = Float::NEGATIVE_ONE.acsc_prec_round(prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(-(p >> 1u32)));
assert_eq!(o, o_p.reverse());
}
});
}
#[test]
fn acsc_prec_properties() {
float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| {
let (c, o) = x.clone().acsc_prec(prec);
assert!(c.is_valid());
let (c_alt, o_alt) = x.acsc_prec_ref(prec);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_prec_assign(prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_prec_round_ref(prec, Nearest);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
}
#[test]
fn acsc_round_properties() {
float_rounding_mode_pair_gen_var_51().test_properties(|(x, rm)| {
let (c, o) = x.clone().acsc_round(rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = x.acsc_round_ref(rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_round_assign(rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_prec_round_ref(x.significant_bits(), rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
}
#[test]
fn acsc_properties() {
float_gen().test_properties(|x| {
let c = x.clone().acsc();
assert!(c.is_valid());
let c_alt = (&x).acsc();
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let mut c_alt = x.clone();
c_alt.acsc_assign();
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let (c_alt, _) = x.acsc_prec_ref(x.significant_bits());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
if x.is_finite() && x != 0u32 && x.get_exponent().unwrap().unsigned_abs() <= 1000 {
let c_alt = Float::from(&rug_acsc(&rug::Float::exact_from(&x)));
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
}
});
}
#[test]
fn test_acsc_rational_prec_round() {
let test = |s: &str, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, o_out: Ordering| {
let x = Rational::from_str(s).unwrap();
let (c, o) = Float::acsc_rational_prec_round(x.clone(), prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = Float::acsc_rational_prec_round_ref(&x, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if rm == Nearest {
let (c_alt, o_alt) = Float::acsc_rational_prec(x.clone(), prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = Float::acsc_rational_prec_ref(&x, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if x != 0u32 {
let (c_alt, o_alt) = Float::asin_rational_prec_round(x.clone().reciprocal(), prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_c, rug_o) = rug_acsc_rational_prec_round(&x, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
};
test("0", 10, Exact, "NaN", "NaN", Equal);
test("1/2", 10, Exact, "NaN", "NaN", Equal);
test("-1/2", 10, Nearest, "NaN", "NaN", Equal);
test("1", 10, Floor, "1.5703", "0x1.920#10", Less);
test("1", 10, Ceiling, "1.5723", "0x1.928#10", Greater);
test("1", 10, Nearest, "1.5703", "0x1.920#10", Less);
test("-1", 10, Nearest, "-1.5703", "-0x1.920#10", Greater);
test("2", 10, Floor, "0.52344", "0x0.860#10", Less);
test("2", 10, Ceiling, "0.52441", "0x0.864#10", Greater);
test(
"2",
53,
Nearest,
"0.52359877559829893",
"0x0.860a91c16b9b30#53",
Greater,
);
test(
"-2",
53,
Nearest,
"-0.52359877559829893",
"-0x0.860a91c16b9b30#53",
Less,
);
test("5/3", 10, Floor, "0.64258", "0x0.a48#10", Less);
test("5/3", 10, Ceiling, "0.64355", "0x0.a4c#10", Greater);
test(
"5/3",
53,
Nearest,
"0.64350110879328437",
"0x0.a4bc7d1934f708#53",
Less,
);
test(
"-5/3",
53,
Nearest,
"-0.64350110879328437",
"-0x0.a4bc7d1934f708#53",
Greater,
);
test("100/99", 20, Nearest, "1.4292564", "0x1.6de3c#20", Less);
test("100", 20, Nearest, "0.010000169", "0x0.028f5f0#20", Greater);
test("-100", 20, Nearest, "-0.010000169", "-0x0.028f5f0#20", Less);
test(
"100000000000000000000000000000000000000000",
20,
Nearest,
"1.0000005e-41",
"0xd.f01fE-35#20",
Greater,
);
}
#[test]
#[should_panic]
fn acsc_rational_prec_round_fail_1() {
Float::acsc_rational_prec_round(Rational::TWO, 0, Floor);
}
#[test]
#[should_panic]
fn acsc_rational_prec_round_fail_2() {
Float::acsc_rational_prec_round(Rational::TWO, 10, Exact);
}
#[test]
#[should_panic]
fn acsc_rational_prec_round_fail_3() {
Float::acsc_rational_prec_round(Rational::ONE, 10, Exact);
}
#[test]
#[should_panic]
fn acsc_rational_prec_fail() {
Float::acsc_rational_prec(Rational::TWO, 0);
}
#[test]
fn test_acsc_rational_underflow() {
let x = Rational::power_of_2((1i64 << 30) + 2);
let (c, o) = Float::acsc_rational_prec_round_ref(&x, 53, Nearest);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Less);
let (c, o) = Float::acsc_rational_prec_round_ref(&x, 53, Ceiling);
assert_eq!(
ComparableFloat(c),
ComparableFloat(Float::min_positive_value_prec(53))
);
assert_eq!(o, Greater);
let (c, o) = Float::acsc_rational_prec_round_ref(&x, 53, Floor);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Less);
let x = -x;
let (c, o) = Float::acsc_rational_prec_round_ref(&x, 53, Nearest);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Greater);
let (c, o) = Float::acsc_rational_prec_round_ref(&x, 53, Floor);
assert_eq!(
ComparableFloat(c),
ComparableFloat(-Float::min_positive_value_prec(53))
);
assert_eq!(o, Less);
}
#[allow(clippy::needless_pass_by_value)]
fn acsc_rational_prec_round_properties_helper(x: Rational, prec: u64, rm: RoundingMode) {
if rm == Exact && !x.lt_abs(&1u32) {
assert_panic!(Float::acsc_rational_prec_round_ref(&x, prec, Exact));
return;
}
let (c, o) = Float::acsc_rational_prec_round(x.clone(), prec, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = Float::acsc_rational_prec_round_ref(&x, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if x != 0u32 {
let (c_alt, o_alt) = Float::asin_rational_prec_round(x.clone().reciprocal(), prec, rm);
assert_eq!(
ComparableFloatRef(&c_alt),
ComparableFloatRef(&c),
"x = {x} exp = {} prec = {prec} rm = {rm:?}",
x.floor_log_base_2_abs() + 1
);
assert_eq!(o_alt, o, "x = {x} prec = {prec} rm = {rm:?}");
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_c, rug_o) = rug_acsc_rational_prec_round(&x, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o, "x = {x} prec = {prec} rm = {rm:?}");
}
assert_eq!(c.is_nan(), x.lt_abs(&1u32));
if !c.is_nan() {
assert!(c.is_finite());
assert!(c <= 2u32);
assert!(c >= -2i32);
}
if let Ok(f) = Float::try_from(&x) {
let (c_alt, o_alt) = f.acsc_prec_round(prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if o == Equal {
assert!(x.lt_abs(&1u32));
} else {
assert_panic!(Float::acsc_rational_prec_round_ref(&x, prec, Exact));
}
}
#[test]
fn acsc_rational_prec_round_properties() {
rational_unsigned_rounding_mode_triple_gen_var_13().test_properties(|(x, prec, rm)| {
acsc_rational_prec_round_properties_helper(x, prec, rm);
});
unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| {
for x in [Rational::ZERO, Rational::ONE_HALF, -Rational::ONE_HALF] {
let (c, o) = Float::acsc_rational_prec_round(x, prec, rm);
assert!(c.is_nan());
assert_eq!(o, Equal);
}
if rm == Exact {
assert_panic!(Float::acsc_rational_prec_round(Rational::ONE, prec, Exact));
assert_panic!(Float::acsc_rational_prec_round(
Rational::NEGATIVE_ONE,
prec,
Exact
));
} else {
let (p, o_p) = Float::pi_prec_round(prec, rm);
let (c, o) = Float::acsc_rational_prec_round(Rational::ONE, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(p >> 1u32));
assert_eq!(o, o_p);
let (p, o_p) = Float::pi_prec_round(prec, -rm);
let (c, o) = Float::acsc_rational_prec_round(Rational::NEGATIVE_ONE, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(-(p >> 1u32)));
assert_eq!(o, o_p.reverse());
}
});
}
#[test]
fn acsc_rational_prec_properties() {
rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| {
let (c, o) = Float::acsc_rational_prec(x.clone(), prec);
assert!(c.is_valid());
let (c_alt, o_alt) = Float::acsc_rational_prec_ref(&x, prec);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = Float::acsc_rational_prec_round_ref(&x, prec, Nearest);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
}
#[test]
#[allow(clippy::approx_constant, clippy::type_repetition_in_bounds)]
fn test_primitive_float_acsc() {
fn test<T: PrimitiveFloat>(x: T, out: T)
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
assert_eq!(NiceFloat(primitive_float_acsc(x)), NiceFloat(out));
}
test::<f32>(f32::NAN, f32::NAN);
test::<f32>(f32::INFINITY, 0.0);
test::<f32>(f32::NEGATIVE_INFINITY, -0.0);
test::<f32>(0.0, f32::NAN);
test::<f32>(-0.0, f32::NAN);
test::<f32>(0.5, f32::NAN);
test::<f32>(1.0, 1.5707964);
test::<f32>(-1.0, -1.5707964);
test::<f32>(2.0, 0.5235988);
test::<f32>(-2.0, -0.5235988);
test::<f32>(2.5, 0.41151685);
test::<f32>(1.5, 0.7297277);
test::<f32>(100.0, 0.0100001665);
test::<f32>(1.0e30, 1.0e-30);
test::<f64>(f64::NAN, f64::NAN);
test::<f64>(f64::INFINITY, 0.0);
test::<f64>(f64::NEGATIVE_INFINITY, -0.0);
test::<f64>(0.0, f64::NAN);
test::<f64>(-0.0, f64::NAN);
test::<f64>(0.5, f64::NAN);
test::<f64>(1.0, 1.5707963267948966);
test::<f64>(-1.0, -1.5707963267948966);
test::<f64>(2.0, 0.5235987755982989);
test::<f64>(-2.0, -0.5235987755982989);
test::<f64>(2.5, 0.411516846067488);
test::<f64>(1.5, 0.7297276562269663);
test::<f64>(100.0, 0.010000166674167112);
test::<f64>(1.0e300, 1.0e-300);
}
#[test]
#[allow(clippy::approx_constant, clippy::type_repetition_in_bounds)]
fn test_primitive_float_acsc_rational() {
fn test<T: PrimitiveFloat>(s: &str, out: T)
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
assert_eq!(
NiceFloat(primitive_float_acsc_rational::<T>(
&Rational::from_str(s).unwrap()
)),
NiceFloat(out)
);
}
test::<f32>("0", f32::NAN);
test::<f32>("1/2", f32::NAN);
test::<f32>("1", 1.5707964);
test::<f32>("-1", -1.5707964);
test::<f32>("2", 0.5235988);
test::<f32>("-2", -0.5235988);
test::<f32>("5/3", 0.6435011);
test::<f32>("-5/3", -0.6435011);
test::<f32>("100/99", 1.4292568);
test::<f32>("100", 0.0100001665);
test::<f64>("0", f64::NAN);
test::<f64>("1/2", f64::NAN);
test::<f64>("1", 1.5707963267948966);
test::<f64>("-1", -1.5707963267948966);
test::<f64>("2", 0.5235987755982989);
test::<f64>("-2", -0.5235987755982989);
test::<f64>("5/3", 0.6435011087932844);
test::<f64>("-5/3", -0.6435011087932844);
test::<f64>("100/99", 1.4292568534704695);
test::<f64>("100", 0.010000166674167112);
}
#[allow(clippy::type_repetition_in_bounds)]
fn primitive_float_acsc_properties_helper<T: PrimitiveFloat>()
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_gen::<T>().test_properties(|x| {
let c = primitive_float_acsc(x);
assert_eq!(c.is_nan(), x.is_nan() || x.abs() < T::ONE);
if !c.is_nan() {
assert!(c.is_finite());
if c.is_normal() {
let (c_float, _) = Float::acsc_prec(Float::from(x), T::MANTISSA_WIDTH + 64);
assert_eq!(
NiceFloat(T::rounding_from(&c_float, Nearest).0),
NiceFloat(c)
);
}
}
});
}
#[test]
fn primitive_float_acsc_properties() {
apply_fn_to_primitive_floats!(primitive_float_acsc_properties_helper);
}
#[allow(clippy::type_repetition_in_bounds)]
fn primitive_float_acsc_rational_properties_helper<T: PrimitiveFloat>()
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
rational_gen().test_properties(|x| {
let c = primitive_float_acsc_rational::<T>(&x);
assert_eq!(c.is_nan(), x.lt_abs(&1u32));
if !c.is_nan() {
assert!(c.is_finite());
if c.is_normal() {
let (c_float, _) = Float::acsc_rational_prec_ref(&x, T::MANTISSA_WIDTH + 64);
assert_eq!(
NiceFloat(T::rounding_from(&c_float, Nearest).0),
NiceFloat(c)
);
}
}
});
}
#[test]
fn primitive_float_acsc_rational_properties() {
apply_fn_to_primitive_floats!(primitive_float_acsc_rational_properties_helper);
}
fn asinu_of_reciprocal(
x: &Float,
u: u64,
prec: u64,
rm: RoundingMode,
) -> Option<(Float, Ordering)> {
if !x.is_finite() || *x == 0u32 || x.get_exponent().unwrap().unsigned_abs() > 1000 {
return None;
}
Some(Float::asin_with_period_rational_prec_round(
Rational::exact_from(x).reciprocal(),
u,
prec,
rm,
))
}
fn asin_of_reciprocal_huge(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
if x.significand_ref().unwrap().is_power_of_2() {
let (r, o_r) = x.reciprocal_prec_round_ref(64, Exact);
assert_eq!(o_r, Equal);
r.asin_prec_round(prec, rm)
} else {
Float::asin_rational_prec_round(Rational::exact_from(x).reciprocal(), prec, rm)
}
}
fn asinu_of_reciprocal_huge(x: &Float, u: u64, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
if x.significand_ref().unwrap().is_power_of_2() {
let (r, o_r) = x.reciprocal_prec_round_ref(64, Exact);
assert_eq!(o_r, Equal);
r.asin_with_period_prec_round(u, prec, rm)
} else {
Float::asin_with_period_rational_prec_round(
Rational::exact_from(x).reciprocal(),
u,
prec,
rm,
)
}
}
#[test]
fn test_acsc_huge() {
let test =
|s_hex: &str, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, o_out: Ordering| {
let x = parse_hex_string(s_hex);
let (c, o) = x.acsc_prec_round_ref(prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = asin_of_reciprocal_huge(&x, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
};
test(
"0x1.0E+134217727#1",
53,
Nearest,
"7.8098438886530598e-161614248",
"0x1.0000000000000E-134217727#53",
Less,
);
test(
"0x1.0E+134217728#1",
53,
Nearest,
"4.8811524304081624e-161614249",
"0x1.0000000000000E-134217728#53",
Less,
);
test(
"0x1.0E+134217728#1",
53,
Floor,
"4.8811524304081624e-161614249",
"0x1.0000000000000E-134217728#53",
Less,
);
test(
"0x1.0E+134217728#1",
53,
Ceiling,
"4.8811524304081635e-161614249",
"0x1.0000000000001E-134217728#53",
Greater,
);
test(
"0x4.0E+268435455#1",
20,
Nearest,
"9.5302596e-323228497",
"0x4.00000E-268435456#20",
Less,
);
test(
"0x3.0E+134217728#2",
53,
Nearest,
"1.6270508101360540e-161614249",
"0x5.5555555555554E-134217729#53",
Less,
);
test(
"-0x4.0E+268435455#1",
20,
Nearest,
"-9.5302596e-323228497",
"-0x4.00000E-268435456#20",
Greater,
);
test(
"-0x1.0E+134217728#1",
53,
Nearest,
"-4.8811524304081624e-161614249",
"-0x1.0000000000000E-134217728#53",
Greater,
);
}
#[test]
fn test_acsc_with_period_huge() {
let test = |s_hex: &str,
u: u64,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
o_out: Ordering| {
let x = parse_hex_string(s_hex);
let (c, o) = x.acsc_with_period_prec_round_ref(u, prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = asinu_of_reciprocal_huge(&x, u, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
};
test(
"0x1.0E+134217728#1",
360,
53,
Nearest,
"2.7966943342241198e-161614247",
"0x3.94bb834c783f0E-134217727#53",
Greater,
);
test(
"0x1.0E+134217728#1",
1,
53,
Nearest,
"7.7685953728447774e-161614250",
"0x2.8be60db939106E-134217729#53",
Greater,
);
test(
"0x1.0E+134217728#1",
1,
53,
Ceiling,
"7.7685953728447774e-161614250",
"0x2.8be60db939106E-134217729#53",
Greater,
);
test(
"0x1.0E+134217728#1",
1,
53,
Floor,
"7.7685953728447761e-161614250",
"0x2.8be60db939104E-134217729#53",
Less,
);
test(
"0x4.0E+268435455#1",
1,
20,
Nearest,
"2.3825649e-323228497",
"0x1.00000E-268435456#20",
Greater,
);
test(
"0x3.0E+134217728#2",
360,
53,
Nearest,
"9.3223144474137315e-161614248",
"0x1.3193d66ed2bfaE-134217727#53",
Less,
);
test(
"-0x4.0E+268435455#1",
1,
20,
Nearest,
"-2.3825649e-323228497",
"-0x1.00000E-268435456#20",
Less,
);
test(
"-0x1.0E+134217728#1",
360,
53,
Nearest,
"-2.7966943342241198e-161614247",
"-0x3.94bb834c783f0E-134217727#53",
Less,
);
}
#[test]
fn test_acsc_with_period_prec_round() {
let test = |s: &str,
s_hex: &str,
u: u64,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
o_out: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let (c, o) = x.clone().acsc_with_period_prec_round(u, prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(u, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_with_period_prec_round_assign(u, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if rm == Nearest {
let (c_alt, o_alt) = x.acsc_with_period_prec_ref(u, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if let Some((c_alt, o_alt)) = asinu_of_reciprocal(&x, u, prec, rm) {
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm)
&& u <= u64::from(u32::MAX)
{
let (rug_c, rug_o) =
rug_acsc_with_period_prec_round(&rug::Float::exact_from(&x), u, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
};
test("NaN", "NaN", 360, 10, Nearest, "NaN", "NaN", Equal);
test(
"Infinity", "Infinity", 360, 10, Exact, "0.0", "0x0.0", Equal,
);
test(
"-Infinity",
"-Infinity",
360,
10,
Exact,
"-0.0",
"-0x0.0",
Equal,
);
test("Infinity", "Infinity", 0, 10, Exact, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 360, 10, Exact, "NaN", "NaN", Equal);
test("-0.0", "-0x0.0", 360, 10, Exact, "NaN", "NaN", Equal);
test("0.50", "0x0.8#1", 360, 10, Nearest, "NaN", "NaN", Equal);
test("0.50", "0x0.8#1", 0, 10, Exact, "NaN", "NaN", Equal);
test("1.0", "0x1.0#1", 0, 10, Exact, "0.0", "0x0.0", Equal);
test("-1.0", "-0x1.0#1", 0, 10, Exact, "-0.0", "-0x0.0", Equal);
test("2.5", "0x2.8#3", 0, 10, Exact, "0.0", "0x0.0", Equal);
test(
"1.0",
"0x1.0#1",
360,
10,
Exact,
"90.000",
"0x5a.0#10",
Equal,
);
test(
"-1.0",
"-0x1.0#1",
360,
10,
Exact,
"-90.000",
"-0x5a.0#10",
Equal,
);
test(
"1.0",
"0x1.0#1",
12,
10,
Exact,
"3.0000",
"0x3.00#10",
Equal,
);
test(
"1.0",
"0x1.0#1",
7,
10,
Exact,
"1.7500",
"0x1.c00#10",
Equal,
);
test(
"-1.0",
"-0x1.0#1",
7,
10,
Exact,
"-1.7500",
"-0x1.c00#10",
Equal,
);
test("1.0", "0x1.0#1", 7, 1, Floor, "1.0", "0x1.0#1", Less);
test("1.0", "0x1.0#1", 7, 1, Ceiling, "2.0", "0x2.0#1", Greater);
test("1.0", "0x1.0#1", 7, 1, Nearest, "2.0", "0x2.0#1", Greater);
test("-1.0", "-0x1.0#1", 7, 1, Floor, "-2.0", "-0x2.0#1", Less);
test(
"-1.0", "-0x1.0#1", 7, 1, Ceiling, "-1.0", "-0x1.0#1", Greater,
);
test(
"2.0",
"0x2.0#1",
360,
10,
Exact,
"30.000",
"0x1e.00#10",
Equal,
);
test(
"-2.0",
"-0x2.0#1",
360,
10,
Exact,
"-30.000",
"-0x1e.00#10",
Equal,
);
test(
"2.0",
"0x2.0#1",
12,
10,
Exact,
"1.0000",
"0x1.000#10",
Equal,
);
test(
"-2.0",
"-0x2.0#1",
12,
10,
Exact,
"-1.0000",
"-0x1.000#10",
Equal,
);
test(
"2.0",
"0x2.0#1",
3,
10,
Exact,
"0.25000",
"0x0.400#10",
Equal,
);
test(
"2.0",
"0x2.0#1",
7,
10,
Nearest,
"0.58301",
"0x0.954#10",
Less,
);
test(
"-2.0",
"-0x2.0#1",
7,
10,
Nearest,
"-0.58301",
"-0x0.954#10",
Greater,
);
test(
"2.5",
"0x2.8#3",
360,
10,
Floor,
"23.562",
"0x17.90#10",
Less,
);
test(
"2.5",
"0x2.8#3",
360,
10,
Ceiling,
"23.594",
"0x17.98#10",
Greater,
);
test(
"2.5",
"0x2.8#3",
360,
10,
Down,
"23.562",
"0x17.90#10",
Less,
);
test(
"2.5",
"0x2.8#3",
360,
10,
Up,
"23.594",
"0x17.98#10",
Greater,
);
test(
"2.5",
"0x2.8#3",
360,
10,
Nearest,
"23.594",
"0x17.98#10",
Greater,
);
test(
"-2.5",
"-0x2.8#3",
360,
10,
Nearest,
"-23.594",
"-0x17.98#10",
Less,
);
test(
"2.5",
"0x2.8#3",
360,
100,
Nearest,
"23.578178478201831104022499419824",
"0x17.9403813720bef0116b2a86fe#100",
Less,
);
test(
"1.5",
"0x1.8#2",
360,
20,
Nearest,
"41.810303",
"0x29.cf70#20",
Less,
);
test(
"-1.5",
"-0x1.8#2",
360,
20,
Nearest,
"-41.810303",
"-0x29.cf70#20",
Greater,
);
test(
"100.0",
"0x64.0#7",
360,
20,
Nearest,
"0.57296753",
"0x0.92ae0#20",
Greater,
);
test(
"1.3e30",
"0x1.0E+25#1",
360,
20,
Nearest,
"4.5198398e-29",
"0x3.94bb8E-24#20",
Less,
);
test(
"-1.3e30",
"-0x1.0E+25#1",
360,
20,
Nearest,
"-4.5198398e-29",
"-0x3.94bb8E-24#20",
Greater,
);
test(
"1.3e30",
"0x1.0E+25#1",
1,
20,
Nearest,
"1.2555107e-31",
"0x2.8be60E-26#20",
Less,
);
test(
"1.3e30",
"0x1.0E+25#1",
18446744073709551615,
20,
Nearest,
"2.3160085e-12",
"0x2.8be60E-10#20",
Less,
);
test(
"1.0",
"0x1.0#1",
18446744073709551615,
64,
Exact,
"4611686018427387903.75",
"0x3fffffffffffffff.c#64",
Equal,
);
test(
"2.0",
"0x2.0#1",
18446744073709551615,
64,
Exact,
"1537228672809129301.25",
"0x1555555555555555.4#64",
Equal,
);
test(
"2.5",
"0x2.8#3",
18446744073709551615,
20,
Nearest,
"1.2081676e18",
"0x1.0c446E+15#20",
Less,
);
}
#[test]
#[should_panic]
fn acsc_with_period_prec_round_fail_1() {
Float::TWO.acsc_with_period_prec_round(7, 0, Floor);
}
#[test]
#[should_panic]
fn acsc_with_period_prec_round_fail_2() {
Float::from(2.5).acsc_with_period_prec_round(7, 10, Exact);
}
#[test]
#[should_panic]
fn acsc_with_period_prec_round_fail_3() {
Float::TWO.acsc_with_period_prec_round(7, 10, Exact);
}
#[test]
#[should_panic]
fn acsc_with_period_prec_round_fail_4() {
Float::ONE.acsc_with_period_prec_round(7, 2, Exact);
}
#[test]
#[should_panic]
fn acsc_with_period_prec_round_ref_fail() {
Float::TWO.acsc_with_period_prec_round_ref(7, 0, Floor);
}
#[test]
#[should_panic]
fn acsc_with_period_prec_fail() {
Float::TWO.acsc_with_period_prec(7, 0);
}
#[test]
#[should_panic]
fn acsc_with_period_round_fail() {
Float::from(2.5).acsc_with_period_round(7, Exact);
}
#[test]
fn test_acsc_with_period_underflow() {
let x = parse_hex_string("0x4.0E+268435455#1");
let min = Float::min_positive_value_prec(20);
let (c, o) = x.acsc_with_period_prec_round_ref(1, 20, Nearest);
assert_eq!(ComparableFloatRef(&c), ComparableFloatRef(&min));
assert_eq!(o, Greater);
let (c, o) = x.acsc_with_period_prec_round_ref(1, 20, Floor);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Less);
let (c, o) = x.acsc_with_period_prec_round_ref(1, 20, Ceiling);
assert_eq!(ComparableFloatRef(&c), ComparableFloatRef(&min));
assert_eq!(o, Greater);
let (c, o) = x.acsc_with_period_prec_round_ref(8, 20, Nearest);
assert!(c > min);
assert_ne!(o, Equal);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(16, 20, Nearest);
assert_eq!(ComparableFloat(c_alt), ComparableFloat(c << 1u32));
assert_eq!(o_alt, o);
let x = -x;
let (c, o) = x.acsc_with_period_prec_round_ref(1, 20, Nearest);
assert_eq!(ComparableFloat(c), ComparableFloat(-&min));
assert_eq!(o, Less);
let (c, o) = x.acsc_with_period_prec_round_ref(1, 20, Ceiling);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Greater);
let (c, o) = x.acsc_with_period_prec_round_ref(1, 20, Floor);
assert_eq!(ComparableFloat(c), ComparableFloat(-min));
assert_eq!(o, Less);
}
fn acsc_with_period_exact(x: &Float, u: u64, prec: u64) -> bool {
x.is_nan()
|| x.lt_abs(&1u32)
|| !x.is_finite()
|| u == 0
|| (x.eq_abs(&Float::ONE) && Float::from_unsigned_prec(u, prec).1 == Equal)
|| (x.eq_abs(&Float::TWO)
&& u.is_multiple_of(3)
&& Float::from_unsigned_prec(u / 3, prec).1 == Equal)
}
#[allow(clippy::needless_pass_by_value)]
fn acsc_with_period_prec_round_properties_helper(x: Float, u: u64, prec: u64, rm: RoundingMode) {
if rm == Exact && !acsc_with_period_exact(&x, u, prec) {
assert_panic!(x.acsc_with_period_prec_round_ref(u, prec, Exact));
return;
}
let (c, o) = x.clone().acsc_with_period_prec_round(u, prec, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(u, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_with_period_prec_round_assign(u, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if let Some((c_alt, o_alt)) = asinu_of_reciprocal(&x, u, prec, rm) {
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o, "x = {x} u = {u} prec = {prec} rm = {rm:?}");
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm)
&& u <= u64::from(u32::MAX)
{
let (rug_c, rug_o) =
rug_acsc_with_period_prec_round(&rug::Float::exact_from(&x), u, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o, "x = {x} u = {u} prec = {prec} rm = {rm:?}");
}
assert_eq!(c.is_nan(), x.is_nan() || x.lt_abs(&1u32));
if !c.is_nan() {
assert!(c.is_finite());
let bound = Float::from_unsigned_prec_round(u, prec, Ceiling).0 >> 2u32;
assert!(c <= bound);
assert!(c >= -bound);
if c.is_normal() {
assert_eq!(c.get_prec(), Some(prec));
}
}
let (c_neg, o_neg) = (-&x).acsc_with_period_prec_round(u, prec, -rm);
assert_eq!(ComparableFloat(-c_neg), ComparableFloat(c.clone()));
assert_eq!(o_neg.reverse(), o);
if o == Equal {
assert!(acsc_with_period_exact(&x, u, prec));
for rm in exhaustive_rounding_modes() {
let (c2, oo) = x.acsc_with_period_prec_round_ref(u, prec, rm);
assert_eq!(ComparableFloatRef(&c2), ComparableFloatRef(&c));
assert_eq!(oo, Equal);
}
} else {
assert_panic!(x.acsc_with_period_prec_round_ref(u, prec, Exact));
}
}
#[test]
fn acsc_with_period_prec_round_properties() {
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_27().test_properties(
|(x, u, prec, rm)| {
acsc_with_period_prec_round_properties_helper(x, u, prec, rm);
},
);
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_28().test_properties(
|(x, u, prec, rm)| {
acsc_with_period_prec_round_properties_helper(x, u, prec, rm);
},
);
unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| {
for x in [Float::NAN, Float::ZERO, Float::NEGATIVE_ZERO, Float::ONE_HALF] {
for u in [0, 4] {
let (c, o) = x.clone().acsc_with_period_prec_round(u, prec, rm);
assert!(c.is_nan());
assert_eq!(o, Equal);
}
}
for u in [0, 4] {
let (c, o) = Float::INFINITY.acsc_with_period_prec_round(u, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (c, o) = Float::NEGATIVE_INFINITY.acsc_with_period_prec_round(u, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Equal);
}
for x in [Float::ONE, Float::TWO, Float::from(2.5)] {
let (c, o) = x.acsc_with_period_prec_round_ref(0, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (c, o) = (-x).acsc_with_period_prec_round(0, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Equal);
}
let (q, o_q) = Float::from_unsigned_prec_round(8u32, prec, rm);
let (c, o) = Float::ONE.acsc_with_period_prec_round(8, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(q >> 2u32));
assert_eq!(o, o_q);
let (q, o_q) = Float::from_unsigned_prec_round(8u32, prec, -rm);
let (c, o) = Float::NEGATIVE_ONE.acsc_with_period_prec_round(8, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(-(q >> 2u32)));
assert_eq!(o, o_q.reverse());
let (q, o_q) = Float::from_unsigned_prec_round(4u32, prec, rm);
let (c, o) = Float::TWO.acsc_with_period_prec_round(12, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(q >> 2u32));
assert_eq!(o, o_q);
let (q, o_q) = Float::from_unsigned_prec_round(4u32, prec, -rm);
let (c, o) = (-Float::TWO).acsc_with_period_prec_round(12, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(-(q >> 2u32)));
assert_eq!(o, o_q.reverse());
});
}
#[test]
fn acsc_with_period_prec_properties() {
float_unsigned_unsigned_triple_gen_var_1::<u64, u64>().test_properties(|(x, u, prec)| {
let (c, o) = x.clone().acsc_with_period_prec(u, prec);
assert!(c.is_valid());
let (c_alt, o_alt) = x.acsc_with_period_prec_ref(u, prec);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_with_period_prec_assign(u, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(u, prec, Nearest);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
}
#[test]
fn acsc_with_period_round_properties() {
float_unsigned_rounding_mode_triple_gen_var_50().test_properties(|(x, u, rm)| {
let (c, o) = x.clone().acsc_with_period_round(u, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = x.acsc_with_period_round_ref(u, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_with_period_round_assign(u, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(u, x.significant_bits(), rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
}
#[test]
fn acsc_with_period_properties() {
float_unsigned_pair_gen_var_2::<u64>().test_properties(|(x, u)| {
let c = x.clone().acsc_with_period(u);
assert!(c.is_valid());
let c_alt = x.acsc_with_period_ref(u);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let mut c_alt = x.clone();
c_alt.acsc_with_period_assign(u);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let (c_alt, _) = x.acsc_with_period_prec_ref(u, x.significant_bits());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
});
}
#[test]
#[allow(clippy::approx_constant, clippy::type_repetition_in_bounds)]
fn test_primitive_float_acsc_with_period() {
fn test<T: PrimitiveFloat>(x: T, u: u64, out: T)
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
assert_eq!(
NiceFloat(primitive_float_acsc_with_period(x, u)),
NiceFloat(out)
);
}
test::<f32>(f32::NAN, 360, f32::NAN);
test::<f32>(f32::INFINITY, 360, 0.0);
test::<f32>(f32::NEGATIVE_INFINITY, 360, -0.0);
test::<f32>(0.0, 360, f32::NAN);
test::<f32>(0.5, 360, f32::NAN);
test::<f32>(0.5, 0, f32::NAN);
test::<f32>(1.0, 360, 90.0);
test::<f32>(1.0, 0, 0.0);
test::<f32>(-1.0, 0, -0.0);
test::<f32>(-1.0, 360, -90.0);
test::<f32>(2.0, 360, 30.0);
test::<f32>(-2.0, 360, -30.0);
test::<f32>(2.0, 12, 1.0);
test::<f32>(-2.0, 12, -1.0);
test::<f32>(2.0, 7, 0.5833333);
test::<f32>(2.5, 360, 23.578178);
test::<f32>(-2.5, 360, -23.578178);
test::<f32>(1.5, 360, 41.810314);
test::<f32>(100.0, 360, 0.57296735);
test::<f32>(1.0e30, 360, 5.729578e-29);
test::<f32>(1.0e30, 1, 1.5915494e-31);
test::<f32>(1.0, 18446744073709551615, 4.611686e18);
test::<f64>(f64::NAN, 360, f64::NAN);
test::<f64>(f64::INFINITY, 360, 0.0);
test::<f64>(f64::NEGATIVE_INFINITY, 360, -0.0);
test::<f64>(0.0, 360, f64::NAN);
test::<f64>(0.5, 360, f64::NAN);
test::<f64>(0.5, 0, f64::NAN);
test::<f64>(1.0, 360, 90.0);
test::<f64>(1.0, 0, 0.0);
test::<f64>(-1.0, 0, -0.0);
test::<f64>(-1.0, 360, -90.0);
test::<f64>(2.0, 360, 30.0);
test::<f64>(-2.0, 360, -30.0);
test::<f64>(2.0, 12, 1.0);
test::<f64>(-2.0, 12, -1.0);
test::<f64>(2.0, 7, 0.5833333333333334);
test::<f64>(2.5, 360, 23.57817847820183);
test::<f64>(-2.5, 360, -23.57817847820183);
test::<f64>(1.5, 360, 41.810314895778596);
test::<f64>(100.0, 360, 0.5729673448571526);
test::<f64>(1.0e300, 360, 5.729577951308232e-299);
test::<f64>(1.0e300, 1, 1.5915494309189532e-301);
test::<f64>(1.0, 18446744073709551615, 4.611686018427388e18);
}
#[allow(clippy::type_repetition_in_bounds)]
fn primitive_float_acsc_with_period_properties_helper<T: PrimitiveFloat>()
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_unsigned_pair_gen_var_1::<T, u64>().test_properties(|(x, u)| {
let c = primitive_float_acsc_with_period(x, u);
assert_eq!(c.is_nan(), x.is_nan() || x.abs() < T::ONE);
if !c.is_nan() {
assert!(c.is_finite());
if c.is_normal() {
let (c_float, _) =
Float::acsc_with_period_prec(Float::from(x), u, T::MANTISSA_WIDTH + 64);
assert_eq!(
NiceFloat(T::rounding_from(&c_float, Nearest).0),
NiceFloat(c)
);
}
}
});
}
#[test]
fn primitive_float_acsc_with_period_properties() {
apply_fn_to_primitive_floats!(primitive_float_acsc_with_period_properties_helper);
}
#[test]
fn test_acsc_with_period_rational_prec_round() {
let test = |s: &str,
u: u64,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
o_out: Ordering| {
let x = Rational::from_str(s).unwrap();
let (c, o) = Float::acsc_with_period_rational_prec_round(x.clone(), u, prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_round_ref(&x, u, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if rm == Nearest {
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec(x.clone(), u, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_ref(&x, u, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if x != 0u32 {
let (c_alt, o_alt) =
Float::asin_with_period_rational_prec_round(x.clone().reciprocal(), u, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if !c.is_nan()
&& let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm)
&& u <= u64::from(u32::MAX)
{
let (rug_c, rug_o) = rug_acsc_with_period_rational_prec_round(&x, u, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
};
test("0", 360, 10, Nearest, "NaN", "NaN", Equal);
test("1/2", 360, 10, Exact, "NaN", "NaN", Equal);
test("-1/2", 360, 10, Nearest, "NaN", "NaN", Equal);
test("0", 0, 10, Exact, "NaN", "NaN", Equal);
test("1/2", 0, 10, Exact, "NaN", "NaN", Equal);
test("1", 0, 10, Exact, "0.0", "0x0.0", Equal);
test("-1", 0, 10, Exact, "-0.0", "-0x0.0", Equal);
test("5/3", 0, 10, Exact, "0.0", "0x0.0", Equal);
test("1", 360, 10, Exact, "90.000", "0x5a.0#10", Equal);
test("-1", 360, 10, Exact, "-90.000", "-0x5a.0#10", Equal);
test("1", 12, 10, Exact, "3.0000", "0x3.00#10", Equal);
test("1", 7, 10, Exact, "1.7500", "0x1.c00#10", Equal);
test("-1", 7, 10, Exact, "-1.7500", "-0x1.c00#10", Equal);
test("1", 7, 1, Floor, "1.0", "0x1.0#1", Less);
test("1", 7, 1, Ceiling, "2.0", "0x2.0#1", Greater);
test("1", 7, 1, Nearest, "2.0", "0x2.0#1", Greater);
test("-1", 7, 1, Floor, "-2.0", "-0x2.0#1", Less);
test("-1", 7, 1, Ceiling, "-1.0", "-0x1.0#1", Greater);
test("2", 360, 10, Exact, "30.000", "0x1e.00#10", Equal);
test("-2", 360, 10, Exact, "-30.000", "-0x1e.00#10", Equal);
test("2", 12, 10, Exact, "1.0000", "0x1.000#10", Equal);
test("-2", 12, 10, Exact, "-1.0000", "-0x1.000#10", Equal);
test("2", 3, 10, Exact, "0.25000", "0x0.400#10", Equal);
test("2", 7, 10, Nearest, "0.58301", "0x0.954#10", Less);
test("-2", 7, 10, Nearest, "-0.58301", "-0x0.954#10", Greater);
test("5/3", 360, 10, Floor, "36.812", "0x24.d#10", Less);
test("5/3", 360, 10, Ceiling, "36.875", "0x24.e#10", Greater);
test("5/3", 360, 10, Down, "36.812", "0x24.d#10", Less);
test("5/3", 360, 10, Up, "36.875", "0x24.e#10", Greater);
test("5/3", 360, 10, Nearest, "36.875", "0x24.e#10", Greater);
test("-5/3", 360, 10, Nearest, "-36.875", "-0x24.e#10", Less);
test(
"5/3",
360,
100,
Nearest,
"36.869897645844021296855612559085",
"0x24.deb19cb3c478602c9ec9b860#100",
Less,
);
test("3/2", 360, 20, Nearest, "41.810303", "0x29.cf70#20", Less);
test(
"-3/2",
360,
20,
Nearest,
"-41.810303",
"-0x29.cf70#20",
Greater,
);
test(
"100/99",
360,
20,
Nearest,
"81.890381",
"0x51.e3f0#20",
Less,
);
test(
"-100/99",
360,
20,
Nearest,
"-81.890381",
"-0x51.e3f0#20",
Greater,
);
test(
"100",
360,
20,
Nearest,
"0.57296753",
"0x0.92ae0#20",
Greater,
);
test(
"-100",
360,
20,
Nearest,
"-0.57296753",
"-0x0.92ae0#20",
Less,
);
test(
"100000000000000000000000000000000000000000",
360,
20,
Nearest,
"5.7295801e-40",
"0x3.1e964E-33#20",
Greater,
);
test(
"-100000000000000000000000000000000000000000",
360,
20,
Nearest,
"-5.7295801e-40",
"-0x3.1e964E-33#20",
Less,
);
test(
"100000000000000000000000000000000000000000",
1,
20,
Nearest,
"1.5915494e-42",
"0x2.37e24E-35#20",
Less,
);
test(
"3/2",
1,
20,
Nearest,
"0.11613977",
"0x0.1dbb56#20",
Greater,
);
test(
"1",
18446744073709551615,
64,
Exact,
"4611686018427387903.75",
"0x3fffffffffffffff.c#64",
Equal,
);
test(
"2",
18446744073709551615,
64,
Exact,
"1537228672809129301.25",
"0x1555555555555555.4#64",
Equal,
);
test(
"5/3",
18446744073709551615,
20,
Nearest,
"1.8892490e18",
"0x1.a37f6E+15#20",
Greater,
);
}
#[test]
#[should_panic]
fn acsc_with_period_rational_prec_round_fail_1() {
Float::acsc_with_period_rational_prec_round(Rational::TWO, 7, 0, Floor);
}
#[test]
#[should_panic]
fn acsc_with_period_rational_prec_round_fail_2() {
Float::acsc_with_period_rational_prec_round(Rational::from_unsigneds(3u8, 2), 7, 10, Exact);
}
#[test]
#[should_panic]
fn acsc_with_period_rational_prec_round_fail_3() {
Float::acsc_with_period_rational_prec_round(Rational::TWO, 7, 10, Exact);
}
#[test]
#[should_panic]
fn acsc_with_period_rational_prec_round_fail_4() {
Float::acsc_with_period_rational_prec_round(Rational::ONE, 7, 2, Exact);
}
#[test]
#[should_panic]
fn acsc_with_period_rational_prec_round_ref_fail() {
Float::acsc_with_period_rational_prec_round_ref(&Rational::TWO, 7, 0, Floor);
}
#[test]
#[should_panic]
fn acsc_with_period_rational_prec_fail() {
Float::acsc_with_period_rational_prec(Rational::TWO, 7, 0);
}
#[test]
fn test_acsc_with_period_rational_underflow() {
let x = Rational::power_of_2((1i64 << 30) + 2);
let min = Float::min_positive_value_prec(53);
let (c, o) = Float::acsc_with_period_rational_prec_round_ref(&x, 1, 53, Nearest);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Less);
let (c, o) = Float::acsc_with_period_rational_prec_round_ref(&x, 1, 53, Ceiling);
assert_eq!(ComparableFloatRef(&c), ComparableFloatRef(&min));
assert_eq!(o, Greater);
let (c, o) = Float::acsc_with_period_rational_prec_round_ref(&x, 1 << 10, 53, Nearest);
assert!(c > min);
assert_ne!(o, Equal);
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_round_ref(&x, 1 << 11, 53, Nearest);
assert_eq!(ComparableFloat(c_alt), ComparableFloat(c << 1u32));
assert_eq!(o_alt, o);
let x = -x;
let (c, o) = Float::acsc_with_period_rational_prec_round_ref(&x, 1, 53, Nearest);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Greater);
let (c, o) = Float::acsc_with_period_rational_prec_round_ref(&x, 1, 53, Floor);
assert_eq!(ComparableFloat(c), ComparableFloat(-min));
assert_eq!(o, Less);
}
fn acsc_with_period_rational_exact(x: &Rational, u: u64, prec: u64) -> bool {
x.lt_abs(&1u32)
|| u == 0
|| (x.eq_abs(&Rational::ONE) && Float::from_unsigned_prec(u, prec).1 == Equal)
|| (x.eq_abs(&Rational::TWO)
&& u.is_multiple_of(3)
&& Float::from_unsigned_prec(u / 3, prec).1 == Equal)
}
#[allow(clippy::needless_pass_by_value)]
fn acsc_with_period_rational_prec_round_properties_helper(
x: Rational,
u: u64,
prec: u64,
rm: RoundingMode,
) {
if rm == Exact && !acsc_with_period_rational_exact(&x, u, prec) {
assert_panic!(Float::acsc_with_period_rational_prec_round_ref(
&x, u, prec, Exact
));
return;
}
let (c, o) = Float::acsc_with_period_rational_prec_round(x.clone(), u, prec, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_round_ref(&x, u, prec, rm);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if x != 0u32 {
let (c_alt, o_alt) =
Float::asin_with_period_rational_prec_round(x.clone().reciprocal(), u, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o, "x = {x} u = {u} prec = {prec} rm = {rm:?}");
}
if !c.is_nan()
&& let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm)
&& u <= u64::from(u32::MAX)
{
let (rug_c, rug_o) = rug_acsc_with_period_rational_prec_round(&x, u, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o, "x = {x} u = {u} prec = {prec} rm = {rm:?}");
}
assert_eq!(c.is_nan(), x.lt_abs(&1u32));
if !c.is_nan() {
assert!(c.is_finite());
let bound = Float::from_unsigned_prec_round(u, prec, Ceiling).0 >> 2u32;
assert!(c <= bound);
assert!(c >= -bound);
if c.is_normal() {
assert_eq!(c.get_prec(), Some(prec));
}
}
let (c_neg, o_neg) = Float::acsc_with_period_rational_prec_round(-&x, u, prec, -rm);
assert_eq!(ComparableFloat(-c_neg), ComparableFloat(c.clone()));
assert_eq!(o_neg.reverse(), o);
if let Ok(f) = Float::try_from(&x) {
let (c_alt, o_alt) = f.acsc_with_period_prec_round(u, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if o == Equal {
assert!(acsc_with_period_rational_exact(&x, u, prec));
for rm in exhaustive_rounding_modes() {
let (c2, oo) = Float::acsc_with_period_rational_prec_round_ref(&x, u, prec, rm);
assert_eq!(ComparableFloatRef(&c2), ComparableFloatRef(&c));
assert_eq!(oo, Equal);
}
} else {
assert_panic!(Float::acsc_with_period_rational_prec_round_ref(
&x, u, prec, Exact
));
}
}
#[test]
fn acsc_with_period_rational_prec_round_properties() {
rational_unsigned_unsigned_rounding_mode_quadruple_gen_var_10().test_properties(
|(x, u, prec, rm)| {
acsc_with_period_rational_prec_round_properties_helper(x, u, prec, rm);
},
);
unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| {
for x in [Rational::ZERO, Rational::ONE_HALF, -Rational::ONE_HALF] {
for u in [0, 4] {
let (c, o) = Float::acsc_with_period_rational_prec_round(x.clone(), u, prec, rm);
assert!(c.is_nan());
assert_eq!(o, Equal);
}
}
for x in [Rational::ONE, Rational::TWO, Rational::from_unsigneds(5u8, 3)] {
let (c, o) = Float::acsc_with_period_rational_prec_round_ref(&x, 0, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (c, o) = Float::acsc_with_period_rational_prec_round(-x, 0, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(Float::NEGATIVE_ZERO));
assert_eq!(o, Equal);
}
let (q, o_q) = Float::from_unsigned_prec_round(8u32, prec, rm);
let (c, o) = Float::acsc_with_period_rational_prec_round(Rational::ONE, 8, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(q >> 2u32));
assert_eq!(o, o_q);
let (q, o_q) = Float::from_unsigned_prec_round(8u32, prec, -rm);
let (c, o) =
Float::acsc_with_period_rational_prec_round(Rational::NEGATIVE_ONE, 8, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(-(q >> 2u32)));
assert_eq!(o, o_q.reverse());
let (q, o_q) = Float::from_unsigned_prec_round(4u32, prec, rm);
let (c, o) = Float::acsc_with_period_rational_prec_round(Rational::TWO, 12, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(q >> 2u32));
assert_eq!(o, o_q);
let (q, o_q) = Float::from_unsigned_prec_round(4u32, prec, -rm);
let (c, o) = Float::acsc_with_period_rational_prec_round(-Rational::TWO, 12, prec, rm);
assert_eq!(ComparableFloat(c), ComparableFloat(-(q >> 2u32)));
assert_eq!(o, o_q.reverse());
});
}
#[test]
fn acsc_with_period_rational_prec_properties() {
rational_unsigned_unsigned_rounding_mode_quadruple_gen_var_10().test_properties(
|(x, u, prec, _)| {
let (c, o) = Float::acsc_with_period_rational_prec(x.clone(), u, prec);
assert!(c.is_valid());
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_ref(&x, u, prec);
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) =
Float::acsc_with_period_rational_prec_round_ref(&x, u, prec, Nearest);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
},
);
}
#[test]
#[allow(clippy::approx_constant, clippy::type_repetition_in_bounds)]
fn test_primitive_float_acsc_with_period_rational() {
fn test<T: PrimitiveFloat>(s: &str, u: u64, out: T)
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
assert_eq!(
NiceFloat(primitive_float_acsc_with_period_rational::<T>(
&Rational::from_str(s).unwrap(),
u
)),
NiceFloat(out)
);
}
test::<f32>("0", 360, f32::NAN);
test::<f32>("1/2", 360, f32::NAN);
test::<f32>("1/2", 0, f32::NAN);
test::<f32>("1", 360, 90.0);
test::<f32>("1", 0, 0.0);
test::<f32>("-1", 0, -0.0);
test::<f32>("-1", 360, -90.0);
test::<f32>("2", 360, 30.0);
test::<f32>("-2", 360, -30.0);
test::<f32>("2", 12, 1.0);
test::<f32>("-2", 12, -1.0);
test::<f32>("2", 7, 0.5833333);
test::<f32>("5/3", 360, 36.869896);
test::<f32>("-5/3", 360, -36.869896);
test::<f32>("3/2", 360, 41.810314);
test::<f32>("100/99", 360, 81.89039);
test::<f32>("100", 360, 0.57296735);
test::<f32>("1", 18446744073709551615, 4.611686e18);
test::<f32>("-1", 18446744073709551615, -4.611686e18);
test::<f64>("0", 360, f64::NAN);
test::<f64>("1/2", 360, f64::NAN);
test::<f64>("1/2", 0, f64::NAN);
test::<f64>("1", 360, 90.0);
test::<f64>("1", 0, 0.0);
test::<f64>("-1", 0, -0.0);
test::<f64>("-1", 360, -90.0);
test::<f64>("2", 360, 30.0);
test::<f64>("-2", 360, -30.0);
test::<f64>("2", 12, 1.0);
test::<f64>("-2", 12, -1.0);
test::<f64>("2", 7, 0.5833333333333334);
test::<f64>("5/3", 360, 36.86989764584402);
test::<f64>("-5/3", 360, -36.86989764584402);
test::<f64>("3/2", 360, 41.810314895778596);
test::<f64>("100/99", 360, 81.89038554400582);
test::<f64>("100", 360, 0.5729673448571526);
test::<f64>("1", 18446744073709551615, 4.611686018427388e18);
test::<f64>("-1", 18446744073709551615, -4.611686018427388e18);
}
#[allow(clippy::type_repetition_in_bounds)]
fn primitive_float_acsc_with_period_rational_properties_helper<T: PrimitiveFloat>()
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
rational_unsigned_pair_gen_var_1::<u64>().test_properties(|(x, u)| {
let c = primitive_float_acsc_with_period_rational::<T>(&x, u);
assert_eq!(c.is_nan(), x.lt_abs(&1u32));
if !c.is_nan() {
assert!(c.is_finite());
if c.is_normal() {
let (c_float, _) =
Float::acsc_with_period_rational_prec_ref(&x, u, T::MANTISSA_WIDTH + 64);
assert_eq!(
NiceFloat(T::rounding_from(&c_float, Nearest).0),
NiceFloat(c)
);
}
}
});
}
#[test]
fn primitive_float_acsc_with_period_rational_properties() {
apply_fn_to_primitive_floats!(primitive_float_acsc_with_period_rational_properties_helper);
}
#[test]
fn test_acsc_pi_prec_round() {
let test = |s: &str,
s_hex: &str,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
o_out: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let (c, o) = x.clone().acsc_pi_prec_round(prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = x.acsc_pi_prec_round_ref(prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_pi_prec_round_assign(prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if rm == Nearest {
let (c_alt, o_alt) = x.acsc_pi_prec_ref(prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_c, rug_o) =
rug_acsc_with_period_prec_round(&rug::Float::exact_from(&x), 2, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
};
test("NaN", "NaN", 10, Nearest, "NaN", "NaN", Equal);
test("Infinity", "Infinity", 10, Exact, "0.0", "0x0.0", Equal);
test("-Infinity", "-Infinity", 10, Exact, "-0.0", "-0x0.0", Equal);
test("0.0", "0x0.0", 10, Exact, "NaN", "NaN", Equal);
test("-0.0", "-0x0.0", 10, Exact, "NaN", "NaN", Equal);
test("0.50", "0x0.8#1", 10, Nearest, "NaN", "NaN", Equal);
test("1.0", "0x1.0#1", 10, Exact, "0.50000", "0x0.800#10", Equal);
test("1.0", "0x1.0#1", 1, Exact, "0.50", "0x0.8#1", Equal);
test(
"-1.0",
"-0x1.0#1",
10,
Exact,
"-0.50000",
"-0x0.800#10",
Equal,
);
test("-1.0", "-0x1.0#1", 1, Exact, "-0.50", "-0x0.8#1", Equal);
test("2.0", "0x2.0#1", 10, Floor, "0.16650", "0x0.2aa#10", Less);
test(
"2.0",
"0x2.0#1",
10,
Ceiling,
"0.16675",
"0x0.2ab#10",
Greater,
);
test(
"2.0",
"0x2.0#1",
10,
Nearest,
"0.16675",
"0x0.2ab#10",
Greater,
);
test(
"2.0",
"0x2.0#1",
53,
Nearest,
"0.16666666666666666",
"0x0.2aaaaaaaaaaaaa#53",
Less,
);
test(
"-2.0",
"-0x2.0#1",
53,
Nearest,
"-0.16666666666666666",
"-0x0.2aaaaaaaaaaaaa#53",
Greater,
);
test("2.5", "0x2.8#3", 10, Floor, "0.13086", "0x0.218#10", Less);
test(
"2.5",
"0x2.8#3",
10,
Ceiling,
"0.13110",
"0x0.219#10",
Greater,
);
test(
"2.5",
"0x2.8#3",
10,
Nearest,
"0.13110",
"0x0.219#10",
Greater,
);
test(
"2.5",
"0x2.8#3",
53,
Nearest,
"0.13098988043445461",
"0x0.21888d8492abba#53",
Less,
);
test(
"1.5",
"0x1.8#2",
20,
Nearest,
"0.23227954",
"0x0.3b76ac#20",
Greater,
);
test(
"-1.5",
"-0x1.8#2",
20,
Nearest,
"-0.23227954",
"-0x0.3b76ac#20",
Less,
);
test(
"100.0",
"0x64.0#7",
20,
Nearest,
"0.0031831525",
"0x0.00d09c7#20",
Greater,
);
test(
"1.0000000000000002",
"0x1.0000000000001#53",
53,
Nearest,
"0.49999999329212075",
"0x0.7fffffe3309bd8#53",
Greater,
);
test(
"1.3e30",
"0x1.0E+25#1",
20,
Nearest,
"2.5110214e-31",
"0x5.17cc0E-26#20",
Less,
);
test(
"-1.3e30",
"-0x1.0E+25#1",
20,
Nearest,
"-2.5110214e-31",
"-0x5.17cc0E-26#20",
Greater,
);
}
#[test]
#[should_panic]
fn acsc_pi_prec_round_fail_1() {
Float::ONE.acsc_pi_prec_round(0, Floor);
}
#[test]
#[should_panic]
fn acsc_pi_prec_round_fail_2() {
Float::TWO.acsc_pi_prec_round(10, Exact);
}
#[test]
#[should_panic]
fn acsc_pi_rational_prec_round_fail() {
Float::acsc_pi_rational_prec_round(Rational::TWO, 10, Exact);
}
#[test]
fn test_acsc_pi_rational_prec_round() {
let test = |s: &str, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, o_out: Ordering| {
let x = Rational::from_str(s).unwrap();
let (c, o) = Float::acsc_pi_rational_prec_round(x.clone(), prec, rm);
assert!(c.is_valid());
assert_eq!(c.to_string(), out);
assert_eq!(to_hex_string(&c), out_hex);
assert_eq!(o, o_out);
let (c_alt, o_alt) = Float::acsc_pi_rational_prec_round_ref(&x, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if rm == Nearest {
let (c_alt, o_alt) = Float::acsc_pi_rational_prec(x.clone(), prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = Float::acsc_pi_rational_prec_ref(&x, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if x != 0u32 {
let (c_alt, o_alt) =
Float::asin_pi_rational_prec_round(x.clone().reciprocal(), prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
}
if !c.is_nan()
&& let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm)
{
let (rug_c, rug_o) = rug_acsc_with_period_rational_prec_round(&x, 2, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
};
test("0", 10, Nearest, "NaN", "NaN", Equal);
test("1/2", 10, Nearest, "NaN", "NaN", Equal);
test("-1/2", 10, Nearest, "NaN", "NaN", Equal);
test("1", 10, Exact, "0.50000", "0x0.800#10", Equal);
test("1", 1, Exact, "0.50", "0x0.8#1", Equal);
test("-1", 10, Exact, "-0.50000", "-0x0.800#10", Equal);
test("-1", 1, Exact, "-0.50", "-0x0.8#1", Equal);
test("2", 10, Floor, "0.16650", "0x0.2aa#10", Less);
test("2", 10, Ceiling, "0.16675", "0x0.2ab#10", Greater);
test(
"2",
53,
Nearest,
"0.16666666666666666",
"0x0.2aaaaaaaaaaaaa#53",
Less,
);
test(
"-2",
53,
Nearest,
"-0.16666666666666666",
"-0x0.2aaaaaaaaaaaaa#53",
Greater,
);
test("5/3", 10, Floor, "0.20459", "0x0.346#10", Less);
test("5/3", 10, Ceiling, "0.20483", "0x0.347#10", Greater);
test("5/3", 10, Nearest, "0.20483", "0x0.347#10", Greater);
test(
"5/3",
53,
Nearest,
"0.20483276469913345",
"0x0.346feb898833de#53",
Less,
);
test(
"-5/3",
53,
Nearest,
"-0.20483276469913345",
"-0x0.346feb898833de#53",
Greater,
);
test("100/99", 20, Nearest, "0.45494652", "0x0.747760#20", Less);
test(
"100",
20,
Nearest,
"0.0031831525",
"0x0.00d09c7#20",
Greater,
);
test(
"-100",
20,
Nearest,
"-0.0031831525",
"-0x0.00d09c7#20",
Less,
);
test(
"100000000000000000000000000000000000000000",
20,
Nearest,
"3.1830987e-42",
"0x4.6fc48E-35#20",
Less,
);
}
#[test]
fn acsc_pi_properties() {
let exact_ok = |x: &Float, prec: u64, rm: RoundingMode| {
rm != Exact || x.acsc_with_period_prec_round_ref(2, prec, Nearest).1 == Equal
};
float_unsigned_rounding_mode_triple_gen_var_48().test_properties(|(x, prec, rm)| {
if !exact_ok(&x, prec, rm) {
assert_panic!(x.acsc_pi_prec_round_ref(prec, Exact));
return;
}
let (c, o) = x.clone().acsc_pi_prec_round(prec, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(2, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_pi_prec_round_ref(prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_pi_prec_round_assign(prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if !c.is_nan() {
assert!(c.is_finite());
assert!(c <= Float::ONE_HALF);
assert!(c >= -Float::ONE_HALF);
}
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_c, rug_o) =
rug_acsc_with_period_prec_round(&rug::Float::exact_from(&x), 2, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
});
float_unsigned_rounding_mode_triple_gen_var_49().test_properties(|(x, prec, rm)| {
if !exact_ok(&x, prec, rm) {
return;
}
let (c, o) = x.acsc_pi_prec_round_ref(prec, rm);
let (c_alt, o_alt) = x.acsc_with_period_prec_round_ref(2, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| {
let (c, o) = x.clone().acsc_pi_prec(prec);
let (c_alt, o_alt) = x.acsc_with_period_prec_ref(2, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_pi_prec_ref(prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_pi_prec_assign(prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
float_rounding_mode_pair_gen_var_51().test_properties(|(x, rm)| {
if !exact_ok(&x, x.significant_bits(), rm) {
return;
}
let (c, o) = x.clone().acsc_pi_round(rm);
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = x.acsc_with_period_round_ref(2, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = x.acsc_pi_round_ref(rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let mut c_alt = x.clone();
let o_alt = c_alt.acsc_pi_round_assign(rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
rational_unsigned_rounding_mode_triple_gen_var_13().test_properties(|(x, prec, rm)| {
if rm == Exact && Float::acsc_with_period_rational_prec_ref(&x, 2, prec).1 != Equal {
assert_panic!(Float::acsc_pi_rational_prec_round_ref(&x, prec, Exact));
return;
}
let (c, o) = Float::acsc_pi_rational_prec_round(x.clone(), prec, rm);
assert!(c.is_valid());
assert_rounding_ordering_consistent(&c, rm, o);
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_round_ref(&x, 2, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = Float::acsc_pi_rational_prec_round_ref(&x, prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
if x != 0u32 {
let (c_alt, o_alt) =
Float::asin_pi_rational_prec_round(x.clone().reciprocal(), prec, rm);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o, "x = {x} prec = {prec} rm = {rm:?}");
}
if !c.is_nan()
&& let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm)
{
let (rug_c, rug_o) = rug_acsc_with_period_rational_prec_round(&x, 2, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_c)),
ComparableFloatRef(&c)
);
assert_eq!(rug_o, o);
}
});
rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| {
let (c, o) = Float::acsc_pi_rational_prec(x.clone(), prec);
let (c_alt, o_alt) = Float::acsc_with_period_rational_prec_ref(&x, 2, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
let (c_alt, o_alt) = Float::acsc_pi_rational_prec_ref(&x, prec);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
assert_eq!(o_alt, o);
});
float_gen().test_properties(|x| {
let c = x.clone().acsc_pi();
assert!(c.is_valid());
let c_alt = x.acsc_pi_ref();
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let mut c_alt = x.clone();
c_alt.acsc_pi_assign();
assert!(c_alt.is_valid());
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let c_alt = x.acsc_with_period_ref(2);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
let (c_alt, _) = x.acsc_pi_prec_round_ref(x.significant_bits(), Nearest);
assert_eq!(ComparableFloatRef(&c_alt), ComparableFloatRef(&c));
});
}
#[test]
#[allow(clippy::type_repetition_in_bounds)]
fn test_primitive_float_acsc_pi() {
fn test<T: PrimitiveFloat>(x: T, out: T)
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
assert_eq!(NiceFloat(primitive_float_acsc_pi(x)), NiceFloat(out));
}
test::<f32>(f32::NAN, f32::NAN);
test::<f32>(f32::INFINITY, 0.0);
test::<f32>(f32::NEGATIVE_INFINITY, -0.0);
test::<f32>(0.0, f32::NAN);
test::<f32>(0.5, f32::NAN);
test::<f32>(1.0, 0.5);
test::<f32>(-1.0, -0.5);
test::<f32>(2.0, 0.16666667);
test::<f32>(-2.0, -0.16666667);
test::<f32>(2.5, 0.13098988);
test::<f32>(1.5, 0.23227952);
test::<f32>(100.0, 0.0031831518);
test::<f32>(1.0e30, 3.1830988e-31);
test::<f64>(f64::NAN, f64::NAN);
test::<f64>(f64::INFINITY, 0.0);
test::<f64>(f64::NEGATIVE_INFINITY, -0.0);
test::<f64>(0.0, f64::NAN);
test::<f64>(0.5, f64::NAN);
test::<f64>(1.0, 0.5);
test::<f64>(-1.0, -0.5);
test::<f64>(2.0, 0.16666666666666666);
test::<f64>(-2.0, -0.16666666666666666);
test::<f64>(2.5, 0.13098988043445461);
test::<f64>(1.5, 0.23227952719876999);
test::<f64>(100.0, 0.0031831519158730705);
test::<f64>(1.0e300, 3.1830988618379065e-301);
}
#[test]
#[allow(clippy::type_repetition_in_bounds)]
fn test_primitive_float_acsc_pi_rational() {
fn test<T: PrimitiveFloat>(s: &str, out: T)
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float>,
{
assert_eq!(
NiceFloat(primitive_float_acsc_pi_rational::<T>(
&Rational::from_str(s).unwrap()
)),
NiceFloat(out)
);
}
test::<f32>("0", f32::NAN);
test::<f32>("1/2", f32::NAN);
test::<f32>("1", 0.5);
test::<f32>("-1", -0.5);
test::<f32>("2", 0.16666667);
test::<f32>("-2", -0.16666667);
test::<f32>("5/3", 0.20483276);
test::<f32>("-5/3", -0.20483276);
test::<f32>("100/99", 0.45494658);
test::<f32>("100", 0.0031831518);
test::<f64>("0", f64::NAN);
test::<f64>("1/2", f64::NAN);
test::<f64>("1", 0.5);
test::<f64>("-1", -0.5);
test::<f64>("2", 0.16666666666666666);
test::<f64>("-2", -0.16666666666666666);
test::<f64>("5/3", 0.20483276469913345);
test::<f64>("-5/3", -0.20483276469913345);
test::<f64>("100/99", 0.4549465863555879);
test::<f64>("100", 0.0031831519158730705);
}
#[allow(clippy::type_repetition_in_bounds)]
fn primitive_float_acsc_pi_properties_helper<T: PrimitiveFloat>()
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_gen::<T>().test_properties(|x| {
assert_eq!(
NiceFloat(primitive_float_acsc_pi(x)),
NiceFloat(primitive_float_acsc_with_period(x, 2))
);
});
rational_gen().test_properties(|x| {
assert_eq!(
NiceFloat(primitive_float_acsc_pi_rational::<T>(&x)),
NiceFloat(primitive_float_acsc_with_period_rational::<T>(&x, 2))
);
});
}
#[test]
fn primitive_float_acsc_pi_properties() {
apply_fn_to_primitive_floats!(primitive_float_acsc_pi_properties_helper);
}