use malachite_base::num::arithmetic::traits::{
IsPowerOf2, PowerOf2, ShlRound, ShlRoundAssign, ShrRound, UnsignedAbs,
};
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_base::num::basic::traits::{
Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
};
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::num::comparison::traits::PartialOrdAbs;
use malachite_base::num::conversion::traits::ExactFrom;
use malachite_base::rounding_modes::RoundingMode::{self, *};
use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes;
use malachite_base::test_util::generators::{
signed_rounding_mode_pair_gen, signed_rounding_mode_pair_gen_var_5,
signed_unsigned_pair_gen_var_19, signed_unsigned_pair_gen_var_20,
signed_unsigned_rounding_mode_triple_gen_var_7, signed_unsigned_rounding_mode_triple_gen_var_8,
unsigned_pair_gen_var_18, unsigned_rounding_mode_pair_gen,
unsigned_rounding_mode_pair_gen_var_5, unsigned_unsigned_rounding_mode_triple_gen_var_7,
};
use malachite_float::test_util::arithmetic::shl_round::{
rug_shl_prec_round_signed, rug_shl_prec_round_unsigned, rug_shl_prec_signed,
rug_shl_prec_unsigned, rug_shl_round_signed, rug_shl_round_unsigned, shl_prec_naive,
shl_prec_round_naive, shl_round_naive,
};
use malachite_float::test_util::common::{
parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string,
};
use malachite_float::test_util::generators::{
float_rounding_mode_pair_gen, float_signed_rounding_mode_triple_gen_var_1,
float_signed_rounding_mode_triple_gen_var_2,
float_signed_unsigned_rounding_mode_quadruple_gen_var_1,
float_signed_unsigned_rounding_mode_quadruple_gen_var_2,
float_signed_unsigned_triple_gen_var_1, float_signed_unsigned_triple_gen_var_2,
float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1,
float_unsigned_rounding_mode_triple_gen_var_5, float_unsigned_rounding_mode_triple_gen_var_6,
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1,
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2,
float_unsigned_unsigned_triple_gen_var_1, float_unsigned_unsigned_triple_gen_var_2,
};
use malachite_float::{ComparableFloat, ComparableFloatRef, Float};
use malachite_nz::integer::Integer;
use malachite_nz::test_util::generators::integer_unsigned_rounding_mode_triple_gen_var_5;
use malachite_q::Rational;
use std::cmp::Ordering::{self, *};
use std::ops::Shl;
use std::panic::catch_unwind;
fn test_shl_prec_round_unsigned_helper<
T: PrimitiveUnsigned,
F: Fn(Float, T, u64, RoundingMode, Float, Ordering),
>(
f: F,
) where
Float: ShlRoundAssign<T> + ShlRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>,
{
let test_r = |s,
s_hex,
v: u64,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
out_o: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_prec_round_assign(v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.clone().shl_prec_round(v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.shl_prec_round_ref(v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = shl_prec_round_naive(x.clone(), v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, out_o);
f(x, v, prec, rm, n, out_o);
};
let test = |s, s_hex, v: u64, prec: u64, out: &str, out_hex: &str| {
for rm in exhaustive_rounding_modes() {
test_r(s, s_hex, v, prec, rm, out, out_hex, Equal);
}
};
test("NaN", "NaN", 0, 1, "NaN", "NaN");
test("NaN", "NaN", 0, 10, "NaN", "NaN");
test("NaN", "NaN", 10, 1, "NaN", "NaN");
test("NaN", "NaN", 10, 10, "NaN", "NaN");
test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity");
test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity");
test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity");
test("Infinity", "Infinity", 10, 10, "Infinity", "Infinity");
test("-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity");
test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0");
test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0");
test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0");
test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0");
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Floor,
"6.0e1",
"0x4.0E+1#1",
Less,
);
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Ceiling,
"1.0e2",
"0x8.0E+1#1",
Greater,
);
test_r("123.0", "0x7b.0#7", 0, 1, Down, "6.0e1", "0x4.0E+1#1", Less);
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Up,
"1.0e2",
"0x8.0E+1#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Nearest,
"1.0e2",
"0x8.0E+1#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Floor,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Ceiling,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Down,
"123.0",
"0x7b.0#10",
Equal,
);
test_r("123.0", "0x7b.0#7", 0, 10, Up, "123.0", "0x7b.0#10", Equal);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Nearest,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Exact,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Floor,
"7.0e4",
"0x1.0E+4#1",
Less,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Ceiling,
"1.0e5",
"0x2.0E+4#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Down,
"7.0e4",
"0x1.0E+4#1",
Less,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Up,
"1.0e5",
"0x2.0E+4#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Nearest,
"1.0e5",
"0x2.0E+4#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Floor,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Ceiling,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Down,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Up,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Nearest,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Exact,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Floor,
"-1.0e2",
"-0x8.0E+1#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Ceiling,
"-6.0e1",
"-0x4.0E+1#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Down,
"-6.0e1",
"-0x4.0E+1#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Up,
"-1.0e2",
"-0x8.0E+1#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Nearest,
"-1.0e2",
"-0x8.0E+1#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Floor,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Ceiling,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Down,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Up,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Nearest,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Exact,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Floor,
"-1.0e5",
"-0x2.0E+4#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Ceiling,
"-7.0e4",
"-0x1.0E+4#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Down,
"-7.0e4",
"-0x1.0E+4#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Up,
"-1.0e5",
"-0x2.0E+4#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Nearest,
"-1.0e5",
"-0x2.0E+4#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Floor,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Ceiling,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Down,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Up,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Nearest,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Exact,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Floor,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Ceiling,
"Infinity",
"Infinity",
Greater,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Down,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Up,
"Infinity",
"Infinity",
Greater,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Nearest,
"Infinity",
"Infinity",
Greater,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Floor,
"-Infinity",
"-Infinity",
Less,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Ceiling,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Down,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Up,
"-Infinity",
"-Infinity",
Less,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Nearest,
"-Infinity",
"-Infinity",
Less,
);
}
#[test]
fn test_shl_prec_round_unsigned() {
test_shl_prec_round_unsigned_helper::<u8, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_unsigned_helper::<u16, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_unsigned_helper::<u32, _>(|x, v, prec, rm, shifted, o_out| {
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (n, o) = rug_shl_prec_round_unsigned(&rug::Float::exact_from(&x), v, prec, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&n)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, o_out);
}
});
test_shl_prec_round_unsigned_helper::<u64, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_unsigned_helper::<u128, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_unsigned_helper::<usize, _>(|_, _, _, _, _, _| {});
}
fn test_shl_prec_round_signed_helper<
T: PrimitiveSigned,
F: Fn(Float, T, u64, RoundingMode, Float, Ordering),
>(
f: F,
) where
Float: ShlRoundAssign<T> + ShlRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>,
{
let test_r = |s,
s_hex,
v: i64,
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
out_o: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_prec_round_assign(v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.clone().shl_prec_round(v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.shl_prec_round_ref(v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = shl_prec_round_naive(x.clone(), v, prec, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, out_o);
f(x, v, prec, rm, n, out_o);
};
let test = |s, s_hex, v: i64, prec: u64, out: &str, out_hex: &str| {
for rm in exhaustive_rounding_modes() {
test_r(s, s_hex, v, prec, rm, out, out_hex, Equal);
}
};
test("NaN", "NaN", 0, 1, "NaN", "NaN");
test("NaN", "NaN", 0, 10, "NaN", "NaN");
test("NaN", "NaN", 10, 1, "NaN", "NaN");
test("NaN", "NaN", 10, 10, "NaN", "NaN");
test("NaN", "NaN", -10, 1, "NaN", "NaN");
test("NaN", "NaN", -10, 10, "NaN", "NaN");
test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity");
test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity");
test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity");
test("Infinity", "Infinity", 10, 10, "Infinity", "Infinity");
test("Infinity", "Infinity", -10, 1, "Infinity", "Infinity");
test("Infinity", "Infinity", -10, 10, "Infinity", "Infinity");
test("-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", -10, 1, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", -10, 10, "-Infinity", "-Infinity");
test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0");
test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0");
test("0.0", "0x0.0", -10, 1, "0.0", "0x0.0");
test("0.0", "0x0.0", -10, 10, "0.0", "0x0.0");
test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0");
test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0");
test("-0.0", "-0x0.0", -10, 1, "-0.0", "-0x0.0");
test("-0.0", "-0x0.0", -10, 10, "-0.0", "-0x0.0");
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Floor,
"6.0e1",
"0x4.0E+1#1",
Less,
);
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Ceiling,
"1.0e2",
"0x8.0E+1#1",
Greater,
);
test_r("123.0", "0x7b.0#7", 0, 1, Down, "6.0e1", "0x4.0E+1#1", Less);
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Up,
"1.0e2",
"0x8.0E+1#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
0,
1,
Nearest,
"1.0e2",
"0x8.0E+1#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Floor,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Ceiling,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Down,
"123.0",
"0x7b.0#10",
Equal,
);
test_r("123.0", "0x7b.0#7", 0, 10, Up, "123.0", "0x7b.0#10", Equal);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Nearest,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
0,
10,
Exact,
"123.0",
"0x7b.0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Floor,
"7.0e4",
"0x1.0E+4#1",
Less,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Ceiling,
"1.0e5",
"0x2.0E+4#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Down,
"7.0e4",
"0x1.0E+4#1",
Less,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Up,
"1.0e5",
"0x2.0E+4#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
10,
1,
Nearest,
"1.0e5",
"0x2.0E+4#1",
Greater,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Floor,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Ceiling,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Down,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Up,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Nearest,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
10,
10,
Exact,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test_r("123.0", "0x7b.0#7", -10, 1, Floor, "0.06", "0x0.1#1", Less);
test_r(
"123.0", "0x7b.0#7", -10, 1, Ceiling, "0.1", "0x0.2#1", Greater,
);
test_r("123.0", "0x7b.0#7", -10, 1, Down, "0.06", "0x0.1#1", Less);
test_r("123.0", "0x7b.0#7", -10, 1, Up, "0.1", "0x0.2#1", Greater);
test_r(
"123.0", "0x7b.0#7", -10, 1, Nearest, "0.1", "0x0.2#1", Greater,
);
test_r(
"123.0",
"0x7b.0#7",
-10,
10,
Floor,
"0.1201",
"0x0.1ec0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
-10,
10,
Ceiling,
"0.1201",
"0x0.1ec0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
-10,
10,
Down,
"0.1201",
"0x0.1ec0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
-10,
10,
Up,
"0.1201",
"0x0.1ec0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
-10,
10,
Nearest,
"0.1201",
"0x0.1ec0#10",
Equal,
);
test_r(
"123.0",
"0x7b.0#7",
-10,
10,
Exact,
"0.1201",
"0x0.1ec0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Floor,
"-1.0e2",
"-0x8.0E+1#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Ceiling,
"-6.0e1",
"-0x4.0E+1#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Down,
"-6.0e1",
"-0x4.0E+1#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Up,
"-1.0e2",
"-0x8.0E+1#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
1,
Nearest,
"-1.0e2",
"-0x8.0E+1#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Floor,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Ceiling,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Down,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Up,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Nearest,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
0,
10,
Exact,
"-123.0",
"-0x7b.0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Floor,
"-1.0e5",
"-0x2.0E+4#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Ceiling,
"-7.0e4",
"-0x1.0E+4#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Down,
"-7.0e4",
"-0x1.0E+4#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Up,
"-1.0e5",
"-0x2.0E+4#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
1,
Nearest,
"-1.0e5",
"-0x2.0E+4#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Floor,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Ceiling,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Down,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Up,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Nearest,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
10,
10,
Exact,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
1,
Floor,
"-0.1",
"-0x0.2#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
1,
Ceiling,
"-0.06",
"-0x0.1#1",
Greater,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
1,
Down,
"-0.06",
"-0x0.1#1",
Greater,
);
test_r("-123.0", "-0x7b.0#7", -10, 1, Up, "-0.1", "-0x0.2#1", Less);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
1,
Nearest,
"-0.1",
"-0x0.2#1",
Less,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
10,
Floor,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
10,
Ceiling,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
10,
Down,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
10,
Up,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
10,
Nearest,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test_r(
"-123.0",
"-0x7b.0#7",
-10,
10,
Exact,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Floor,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Ceiling,
"Infinity",
"Infinity",
Greater,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Down,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Up,
"Infinity",
"Infinity",
Greater,
);
test_r(
"too_big",
"0x4.0E+268435455#1",
1,
1,
Nearest,
"Infinity",
"Infinity",
Greater,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Floor,
"-Infinity",
"-Infinity",
Less,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Ceiling,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Down,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Up,
"-Infinity",
"-Infinity",
Less,
);
test_r(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
Nearest,
"-Infinity",
"-Infinity",
Less,
);
test_r(
"too_small",
"0x1.0E-268435456#1",
-1,
1,
Floor,
"0.0",
"0x0.0",
Less,
);
test_r(
"too_small",
"0x1.0E-268435456#1",
-1,
1,
Ceiling,
"too_small",
"0x1.0E-268435456#1",
Greater,
);
test_r(
"too_small",
"0x1.0E-268435456#1",
-1,
1,
Down,
"0.0",
"0x0.0",
Less,
);
test_r(
"too_small",
"0x1.0E-268435456#1",
-1,
1,
Up,
"too_small",
"0x1.0E-268435456#1",
Greater,
);
test_r(
"too_small",
"0x1.0E-268435456#1",
-1,
1,
Nearest,
"0.0",
"0x0.0",
Less,
);
test_r(
"-too_small",
"-0x1.0E-268435456#1",
-1,
1,
Floor,
"-too_small",
"-0x1.0E-268435456#1",
Less,
);
test_r(
"-too_small",
"-0x1.0E-268435456#1",
-1,
1,
Ceiling,
"-0.0",
"-0x0.0",
Greater,
);
test_r(
"-too_small",
"-0x1.0E-268435456#1",
-1,
1,
Down,
"-0.0",
"-0x0.0",
Greater,
);
test_r(
"-too_small",
"-0x1.0E-268435456#1",
-1,
1,
Up,
"-too_small",
"-0x1.0E-268435456#1",
Less,
);
test_r(
"-too_small",
"-0x1.0E-268435456#1",
-1,
1,
Nearest,
"-0.0",
"-0x0.0",
Greater,
);
test_r(
"too_small",
"0x4.df81e47e11c9aa6dE-268435455#67",
-7,
66,
Nearest,
"too_small",
"0x1.00000000000000000E-268435456#66",
Greater,
);
test_r(
"-too_small",
"-0x4.df81e47e11c9aa6dE-268435455#67",
-7,
66,
Nearest,
"-too_small",
"-0x1.00000000000000000E-268435456#66",
Less,
);
}
#[test]
fn test_shl_prec_round_signed() {
test_shl_prec_round_signed_helper::<i8, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_signed_helper::<i16, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_signed_helper::<i32, _>(|x, v, prec, rm, shifted, o_out| {
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (n, o) = rug_shl_prec_round_signed(&rug::Float::exact_from(&x), v, prec, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&n)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, o_out);
}
});
test_shl_prec_round_signed_helper::<i64, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_signed_helper::<i128, _>(|_, _, _, _, _, _| {});
test_shl_prec_round_signed_helper::<isize, _>(|_, _, _, _, _, _| {});
}
#[test]
fn shl_prec_round_fail() {
assert_panic!(Float::ONE.shl_prec_round(Float::MAX_EXPONENT, 1, Exact));
assert_panic!(Float::ONE.shl_prec_round(Float::MIN_EXPONENT - 2, 1, Exact));
assert_panic!(Float::NEGATIVE_ONE.shl_prec_round(Float::MAX_EXPONENT, 1, Exact));
assert_panic!(Float::NEGATIVE_ONE.shl_prec_round(Float::MIN_EXPONENT - 2, 1, Exact));
}
fn test_shl_prec_unsigned_helper<T: PrimitiveUnsigned, F: Fn(Float, T, u64, Float, Ordering)>(f: F)
where
Rational: Shl<T, Output = Rational>,
{
let test = |s, s_hex, v: u64, prec: u64, out: &str, out_hex: &str, out_o: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_prec_assign(v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.clone().shl_prec(v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.shl_prec_ref(v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = shl_prec_naive(x.clone(), v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, out_o);
f(x, v, prec, n, out_o);
};
test("NaN", "NaN", 0, 1, "NaN", "NaN", Equal);
test("NaN", "NaN", 0, 10, "NaN", "NaN", Equal);
test("NaN", "NaN", 10, 1, "NaN", "NaN", Equal);
test("NaN", "NaN", 10, 10, "NaN", "NaN", Equal);
test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity", Equal);
test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity", Equal);
test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity", Equal);
test(
"Infinity", "Infinity", 10, 10, "Infinity", "Infinity", Equal,
);
test(
"-Infinity",
"-Infinity",
0,
1,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
0,
10,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
10,
1,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
10,
10,
"-Infinity",
"-Infinity",
Equal,
);
test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0", Equal);
test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0", Equal);
test("123.0", "0x7b.0#7", 0, 1, "1.0e2", "0x8.0E+1#1", Greater);
test("123.0", "0x7b.0#7", 0, 10, "123.0", "0x7b.0#10", Equal);
test("123.0", "0x7b.0#7", 10, 1, "1.0e5", "0x2.0E+4#1", Greater);
test(
"123.0",
"0x7b.0#7",
10,
10,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test("-123.0", "-0x7b.0#7", 0, 1, "-1.0e2", "-0x8.0E+1#1", Less);
test("-123.0", "-0x7b.0#7", 0, 10, "-123.0", "-0x7b.0#10", Equal);
test("-123.0", "-0x7b.0#7", 10, 1, "-1.0e5", "-0x2.0E+4#1", Less);
test(
"-123.0",
"-0x7b.0#7",
10,
10,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test(
"too_big",
"0x4.0E+268435455#1",
1,
1,
"Infinity",
"Infinity",
Greater,
);
test(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
"-Infinity",
"-Infinity",
Less,
);
}
#[test]
fn test_shl_prec_unsigned() {
test_shl_prec_unsigned_helper::<u8, _>(|_, _, _, _, _| {});
test_shl_prec_unsigned_helper::<u16, _>(|_, _, _, _, _| {});
test_shl_prec_unsigned_helper::<u32, _>(|x, v, prec, shifted, o_out| {
let (n, o) = rug_shl_prec_unsigned(&rug::Float::exact_from(&x), v, prec);
assert_eq!(
ComparableFloatRef(&Float::from(&n)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, o_out);
});
test_shl_prec_unsigned_helper::<u64, _>(|_, _, _, _, _| {});
test_shl_prec_unsigned_helper::<u128, _>(|_, _, _, _, _| {});
test_shl_prec_unsigned_helper::<usize, _>(|_, _, _, _, _| {});
}
fn test_shl_prec_signed_helper<T: PrimitiveSigned, F: Fn(Float, T, u64, Float, Ordering)>(f: F)
where
Rational: Shl<T, Output = Rational>,
{
let test = |s, s_hex, v: i64, prec: u64, out: &str, out_hex: &str, out_o: Ordering| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_prec_assign(v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.clone().shl_prec(v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.shl_prec_ref(v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = shl_prec_naive(x.clone(), v, prec);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, out_o);
f(x, v, prec, n, out_o);
};
test("NaN", "NaN", 0, 1, "NaN", "NaN", Equal);
test("NaN", "NaN", 0, 10, "NaN", "NaN", Equal);
test("NaN", "NaN", 10, 1, "NaN", "NaN", Equal);
test("NaN", "NaN", 10, 10, "NaN", "NaN", Equal);
test("NaN", "NaN", -10, 1, "NaN", "NaN", Equal);
test("NaN", "NaN", -10, 10, "NaN", "NaN", Equal);
test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity", Equal);
test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity", Equal);
test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity", Equal);
test(
"Infinity", "Infinity", 10, 10, "Infinity", "Infinity", Equal,
);
test(
"Infinity", "Infinity", -10, 1, "Infinity", "Infinity", Equal,
);
test(
"Infinity", "Infinity", -10, 10, "Infinity", "Infinity", Equal,
);
test(
"-Infinity",
"-Infinity",
0,
1,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
0,
10,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
10,
1,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
10,
10,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
-10,
1,
"-Infinity",
"-Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
-10,
10,
"-Infinity",
"-Infinity",
Equal,
);
test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", -10, 1, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", -10, 10, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0", Equal);
test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0", Equal);
test("-0.0", "-0x0.0", -10, 1, "-0.0", "-0x0.0", Equal);
test("-0.0", "-0x0.0", -10, 10, "-0.0", "-0x0.0", Equal);
test("123.0", "0x7b.0#7", 0, 1, "1.0e2", "0x8.0E+1#1", Greater);
test("123.0", "0x7b.0#7", 0, 10, "123.0", "0x7b.0#10", Equal);
test("123.0", "0x7b.0#7", 10, 1, "1.0e5", "0x2.0E+4#1", Greater);
test(
"123.0",
"0x7b.0#7",
10,
10,
"1.26e5",
"0x1.ec0E+4#10",
Equal,
);
test("123.0", "0x7b.0#7", -10, 1, "0.1", "0x0.2#1", Greater);
test("123.0", "0x7b.0#7", -10, 10, "0.1201", "0x0.1ec0#10", Equal);
test("-123.0", "-0x7b.0#7", 0, 1, "-1.0e2", "-0x8.0E+1#1", Less);
test("-123.0", "-0x7b.0#7", 0, 10, "-123.0", "-0x7b.0#10", Equal);
test("-123.0", "-0x7b.0#7", 10, 1, "-1.0e5", "-0x2.0E+4#1", Less);
test(
"-123.0",
"-0x7b.0#7",
10,
10,
"-1.26e5",
"-0x1.ec0E+4#10",
Equal,
);
test("-123.0", "-0x7b.0#7", -10, 1, "-0.1", "-0x0.2#1", Less);
test(
"-123.0",
"-0x7b.0#7",
-10,
10,
"-0.1201",
"-0x0.1ec0#10",
Equal,
);
test(
"too_big",
"0x4.0E+268435455#1",
1,
1,
"Infinity",
"Infinity",
Greater,
);
test(
"-too_big",
"-0x4.0E+268435455#1",
1,
1,
"-Infinity",
"-Infinity",
Less,
);
test(
"too_small",
"0x1.0E-268435456#1",
-1,
1,
"0.0",
"0x0.0",
Less,
);
test(
"-too_small",
"-0x1.0E-268435456#1",
-1,
1,
"-0.0",
"-0x0.0",
Greater,
);
test(
"too_small",
"0x4.df81e47e11c9aa6dE-268435455#67",
-7,
66,
"too_small",
"0x1.00000000000000000E-268435456#66",
Greater,
);
test(
"-too_small",
"-0x4.df81e47e11c9aa6dE-268435455#67",
-7,
66,
"-too_small",
"-0x1.00000000000000000E-268435456#66",
Less,
);
}
#[test]
fn test_shl_prec_signed() {
test_shl_prec_signed_helper::<i8, _>(|_, _, _, _, _| {});
test_shl_prec_signed_helper::<i16, _>(|_, _, _, _, _| {});
test_shl_prec_signed_helper::<i32, _>(|x, v, prec, shifted, o_out| {
let (n, o) = rug_shl_prec_signed(&rug::Float::exact_from(&x), v, prec);
assert_eq!(
ComparableFloatRef(&Float::from(&n)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, o_out);
});
test_shl_prec_signed_helper::<i64, _>(|_, _, _, _, _| {});
test_shl_prec_signed_helper::<i128, _>(|_, _, _, _, _| {});
test_shl_prec_signed_helper::<isize, _>(|_, _, _, _, _| {});
}
fn test_shl_round_unsigned_helper<
T: PrimitiveUnsigned,
F: Fn(Float, T, RoundingMode, Float, Ordering),
>(
f: F,
) where
Float: ShlRoundAssign<T> + ShlRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>,
{
let test = |s, s_hex, v: u64, out: &str, out_hex: &str| {
for rm in exhaustive_rounding_modes() {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_round_assign(v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, Equal);
let (n, o) = x.clone().shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, Equal);
let (n, o) = (&x).shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, Equal);
let (n, o) = shl_round_naive(x.clone(), v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, Equal);
f(x, v, rm, n, Equal);
}
};
test("NaN", "NaN", 0, "NaN", "NaN");
test("NaN", "NaN", 10, "NaN", "NaN");
test("Infinity", "Infinity", 0, "Infinity", "Infinity");
test("Infinity", "Infinity", 10, "Infinity", "Infinity");
test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity");
test("0.0", "0x0.0", 10, "0.0", "0x0.0");
test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0");
test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7");
test("123.0", "0x7b.0#7", 1, "246.0", "0xf6.0#7");
test("123.0", "0x7b.0#7", 10, "1.26e5", "0x1.ecE+4#7");
test("123.0", "0x7b.0#7", 100, "1.56e32", "0x7.bE+26#7");
test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7");
test("-123.0", "-0x7b.0#7", 1, "-246.0", "-0xf6.0#7");
test("-123.0", "-0x7b.0#7", 10, "-1.26e5", "-0x1.ecE+4#7");
test("-123.0", "-0x7b.0#7", 100, "-1.56e32", "-0x7.bE+26#7");
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
0,
"3.1415926535897931",
"0x3.243f6a8885a30#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
"6.283185307179586",
"0x6.487ed5110b460#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
"3216.9908772759482",
"0xc90.fdaa22168c0#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
100,
"3.9824418129956972e30",
"0x3.243f6a8885a30E+25#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
0,
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
"-6.283185307179586",
"-0x6.487ed5110b460#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
"-3216.9908772759482",
"-0xc90.fdaa22168c0#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
100,
"-3.9824418129956972e30",
"-0x3.243f6a8885a30E+25#53",
);
let test_extreme =
|s, s_hex, v: i32, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| {
let v = u64::exact_from(v);
if T::convertible_from(v) {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_round_assign(v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.clone().shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = (&x).shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = shl_round_naive(x.clone(), v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, out_o);
f(x, v, rm, n, out_o);
}
};
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Floor,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Ceiling,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Down,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Up,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Nearest,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Exact,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Floor,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Ceiling,
"Infinity",
"Infinity",
Greater,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Down,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Up,
"Infinity",
"Infinity",
Greater,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Nearest,
"Infinity",
"Infinity",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Floor,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Ceiling,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Down,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Up,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Nearest,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Exact,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Floor,
"-Infinity",
"-Infinity",
Less,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Ceiling,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Down,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Up,
"-Infinity",
"-Infinity",
Less,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Nearest,
"-Infinity",
"-Infinity",
Less,
);
}
#[test]
fn test_shl_round_unsigned() {
test_shl_round_unsigned_helper::<u8, _>(|_, _, _, _, _| {});
test_shl_round_unsigned_helper::<u16, _>(|_, _, _, _, _| {});
test_shl_round_unsigned_helper::<u32, _>(|x, v, rm, shifted, o_out| {
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (n, o) = rug_shl_round_unsigned(&rug::Float::exact_from(&x), v, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&n)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, o_out);
}
});
test_shl_round_unsigned_helper::<u64, _>(|_, _, _, _, _| {});
test_shl_round_unsigned_helper::<u128, _>(|_, _, _, _, _| {});
test_shl_round_unsigned_helper::<usize, _>(|_, _, _, _, _| {});
}
fn test_shl_round_signed_helper<
T: PrimitiveSigned,
F: Fn(Float, T, RoundingMode, Float, Ordering),
>(
f: F,
) where
Float: ShlRoundAssign<T> + ShlRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>,
{
let test = |s, s_hex, v: i64, out: &str, out_hex: &str| {
for rm in exhaustive_rounding_modes() {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_round_assign(v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, Equal);
let (n, o) = x.clone().shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert!(n.is_valid());
assert_eq!(o, Equal);
let (n, o) = (&x).shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert!(n.is_valid());
assert_eq!(o, Equal);
let (n, o) = shl_round_naive(x.clone(), v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, Equal);
f(x, v, rm, n, Equal);
}
};
test("NaN", "NaN", 0, "NaN", "NaN");
test("NaN", "NaN", 10, "NaN", "NaN");
test("NaN", "NaN", -10, "NaN", "NaN");
test("Infinity", "Infinity", 0, "Infinity", "Infinity");
test("Infinity", "Infinity", 10, "Infinity", "Infinity");
test("Infinity", "Infinity", -10, "Infinity", "Infinity");
test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity");
test("-Infinity", "-Infinity", -10, "-Infinity", "-Infinity");
test("0.0", "0x0.0", 10, "0.0", "0x0.0");
test("0.0", "0x0.0", -10, "0.0", "0x0.0");
test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0");
test("-0.0", "-0x0.0", -10, "-0.0", "-0x0.0");
test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7");
test("123.0", "0x7b.0#7", 1, "246.0", "0xf6.0#7");
test("123.0", "0x7b.0#7", 10, "1.26e5", "0x1.ecE+4#7");
test("123.0", "0x7b.0#7", 100, "1.56e32", "0x7.bE+26#7");
test("123.0", "0x7b.0#7", -1, "61.5", "0x3d.8#7");
test("123.0", "0x7b.0#7", -10, "0.12", "0x0.1ec#7");
test("123.0", "0x7b.0#7", -100, "9.7e-29", "0x7.bE-24#7");
test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7");
test("-123.0", "-0x7b.0#7", 1, "-246.0", "-0xf6.0#7");
test("-123.0", "-0x7b.0#7", 10, "-1.26e5", "-0x1.ecE+4#7");
test("-123.0", "-0x7b.0#7", 100, "-1.56e32", "-0x7.bE+26#7");
test("-123.0", "-0x7b.0#7", -1, "-61.5", "-0x3d.8#7");
test("-123.0", "-0x7b.0#7", -10, "-0.12", "-0x0.1ec#7");
test("-123.0", "-0x7b.0#7", -100, "-9.7e-29", "-0x7.bE-24#7");
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
0,
"3.1415926535897931",
"0x3.243f6a8885a30#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
"6.283185307179586",
"0x6.487ed5110b460#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
"3216.9908772759482",
"0xc90.fdaa22168c0#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
100,
"3.9824418129956972e30",
"0x3.243f6a8885a30E+25#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
-1,
"1.5707963267948966",
"0x1.921fb54442d18#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
-10,
"0.0030679615757712823",
"0x0.00c90fdaa22168c0#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
-100,
"2.4782796245465248e-30",
"0x3.243f6a8885a30E-25#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
0,
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
"-6.283185307179586",
"-0x6.487ed5110b460#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
"-3216.9908772759482",
"-0xc90.fdaa22168c0#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
100,
"-3.9824418129956972e30",
"-0x3.243f6a8885a30E+25#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
-1,
"-1.5707963267948966",
"-0x1.921fb54442d18#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
-10,
"-0.0030679615757712823",
"-0x0.00c90fdaa22168c0#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
-100,
"-2.4782796245465248e-30",
"-0x3.243f6a8885a30E-25#53",
);
let test_extreme =
|s, s_hex, v: i32, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| {
let v = i64::from(v);
if T::convertible_from(v) {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let v = T::exact_from(v);
let mut n = x.clone();
let o = n.shl_round_assign(v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = x.clone().shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = (&x).shl_round(v, rm);
assert_eq!(n.to_string(), out);
assert!(n.is_valid());
assert_eq!(o, out_o);
let (n, o) = shl_round_naive(x.clone(), v, rm);
assert_eq!(n.to_string(), out);
assert_eq!(to_hex_string(&n), out_hex);
assert_eq!(o, out_o);
f(x, v, rm, n, out_o);
}
};
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Floor,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Ceiling,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Down,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Up,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Nearest,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT - 1,
Exact,
"too_big",
"0x4.0E+268435455#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Floor,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Ceiling,
"Infinity",
"Infinity",
Greater,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Down,
"too_big",
"0x4.0E+268435455#1",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Up,
"Infinity",
"Infinity",
Greater,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MAX_EXPONENT,
Nearest,
"Infinity",
"Infinity",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Floor,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Ceiling,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Down,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Up,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Nearest,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT - 1,
Exact,
"-too_big",
"-0x4.0E+268435455#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Floor,
"-Infinity",
"-Infinity",
Less,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Ceiling,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Down,
"-too_big",
"-0x4.0E+268435455#1",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Up,
"-Infinity",
"-Infinity",
Less,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MAX_EXPONENT,
Nearest,
"-Infinity",
"-Infinity",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 1,
Floor,
"too_small",
"0x1.0E-268435456#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 1,
Ceiling,
"too_small",
"0x1.0E-268435456#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 1,
Down,
"too_small",
"0x1.0E-268435456#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 1,
Up,
"too_small",
"0x1.0E-268435456#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 1,
Nearest,
"too_small",
"0x1.0E-268435456#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 1,
Exact,
"too_small",
"0x1.0E-268435456#1",
Equal,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 2,
Floor,
"0.0",
"0x0.0",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 2,
Ceiling,
"too_small",
"0x1.0E-268435456#1",
Greater,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 2,
Down,
"0.0",
"0x0.0",
Less,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 2,
Up,
"too_small",
"0x1.0E-268435456#1",
Greater,
);
test_extreme(
"1.0",
"0x1.0#1",
Float::MIN_EXPONENT - 2,
Nearest,
"0.0",
"0x0.0",
Less,
);
test_extreme(
"1.5",
"0x1.8#2",
Float::MIN_EXPONENT - 2,
Floor,
"0.0",
"0x0.0",
Less,
);
test_extreme(
"1.5",
"0x1.8#2",
Float::MIN_EXPONENT - 2,
Ceiling,
"too_small",
"0x1.0E-268435456#2",
Greater,
);
test_extreme(
"1.5",
"0x1.8#2",
Float::MIN_EXPONENT - 2,
Down,
"0.0",
"0x0.0",
Less,
);
test_extreme(
"1.5",
"0x1.8#2",
Float::MIN_EXPONENT - 2,
Up,
"too_small",
"0x1.0E-268435456#2",
Greater,
);
test_extreme(
"1.5",
"0x1.8#2",
Float::MIN_EXPONENT - 2,
Nearest,
"too_small",
"0x1.0E-268435456#2",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 1,
Floor,
"-too_small",
"-0x1.0E-268435456#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 1,
Ceiling,
"-too_small",
"-0x1.0E-268435456#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 1,
Down,
"-too_small",
"-0x1.0E-268435456#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 1,
Up,
"-too_small",
"-0x1.0E-268435456#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 1,
Nearest,
"-too_small",
"-0x1.0E-268435456#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 1,
Exact,
"-too_small",
"-0x1.0E-268435456#1",
Equal,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 2,
Floor,
"-too_small",
"-0x1.0E-268435456#1",
Less,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 2,
Ceiling,
"-0.0",
"-0x0.0",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 2,
Down,
"-0.0",
"-0x0.0",
Greater,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 2,
Up,
"-too_small",
"-0x1.0E-268435456#1",
Less,
);
test_extreme(
"-1.0",
"-0x1.0#1",
Float::MIN_EXPONENT - 2,
Nearest,
"-0.0",
"-0x0.0",
Greater,
);
test_extreme(
"-1.5",
"-0x1.8#2",
Float::MIN_EXPONENT - 2,
Floor,
"-too_small",
"-0x1.0E-268435456#2",
Less,
);
test_extreme(
"-1.5",
"-0x1.8#2",
Float::MIN_EXPONENT - 2,
Ceiling,
"-0.0",
"-0x0.0",
Greater,
);
test_extreme(
"-1.5",
"-0x1.8#2",
Float::MIN_EXPONENT - 2,
Down,
"-0.0",
"-0x0.0",
Greater,
);
test_extreme(
"-1.5",
"-0x1.8#2",
Float::MIN_EXPONENT - 2,
Up,
"-too_small",
"-0x1.0E-268435456#2",
Less,
);
test_extreme(
"-1.5",
"-0x1.8#2",
Float::MIN_EXPONENT - 2,
Nearest,
"-too_small",
"-0x1.0E-268435456#2",
Less,
);
}
#[test]
fn shl_round_fail() {
assert_panic!(Float::ONE.shl_round(Float::MAX_EXPONENT, Exact));
assert_panic!(Float::ONE.shl_round(Float::MIN_EXPONENT - 2, Exact));
assert_panic!(Float::NEGATIVE_ONE.shl_round(Float::MAX_EXPONENT, Exact));
assert_panic!(Float::NEGATIVE_ONE.shl_round(Float::MIN_EXPONENT - 2, Exact));
}
#[test]
fn test_shl_round_signed() {
test_shl_round_signed_helper::<i8, _>(|_, _, _, _, _| {});
test_shl_round_signed_helper::<i16, _>(|_, _, _, _, _| {});
test_shl_round_signed_helper::<i32, _>(|x, v, rm, shifted, o_out| {
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (n, o) = rug_shl_round_signed(&rug::Float::exact_from(&x), v, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&n)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, o_out);
}
});
test_shl_round_signed_helper::<i64, _>(|_, _, _, _, _| {});
test_shl_round_signed_helper::<i128, _>(|_, _, _, _, _| {});
test_shl_round_signed_helper::<isize, _>(|_, _, _, _, _| {});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_properties_helper_unsigned_helper<T: PrimitiveUnsigned>(n: Float, u: T, prec: u64)
where
i128: TryFrom<T>,
u64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
{
let mut mut_n = n.clone();
let o = mut_n.shl_prec_assign(u, prec);
assert!(mut_n.is_valid());
let shifted = mut_n;
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, Equal);
}
}
let (shifted_alt, o_alt) = n.shl_prec_ref(u, prec);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.clone().shl_prec(u, prec);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
if i128::from(n.get_exponent().unwrap_or(1))
.wrapping_add(i128::exact_from(u))
.lt_abs(&1_000_000)
{
let (shifted_alt, o_alt) = shl_prec_naive(n.clone(), u, prec);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted),
);
assert_eq!(o_alt, o);
}
if shifted.is_normal() {
assert_eq!(shifted.get_prec(), Some(prec));
}
let (shifted_2, o_2) = (-&n).shl_prec(u, prec);
let (shifted_2_alt, o_2_alt) = n.shl_prec_ref(u, prec);
assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2));
assert_eq!(o_2_alt.reverse(), o_2);
if shifted.is_normal() {
let (shifted_alt, o_alt) = n.mul_prec(Float::power_of_2(u64::exact_from(u)), prec);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
}
fn shl_prec_properties_helper_unsigned<T: PrimitiveUnsigned>()
where
i128: TryFrom<T>,
u64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
{
float_unsigned_unsigned_triple_gen_var_1::<T, _>().test_properties(|(n, u, prec)| {
shl_prec_properties_helper_unsigned_helper(n, u, prec);
});
float_unsigned_unsigned_triple_gen_var_2::<T, _>().test_properties(|(n, u, prec)| {
shl_prec_properties_helper_unsigned_helper(n, u, prec);
});
float_unsigned_pair_gen_var_1().test_properties(|(n, prec)| {
let (shifted, o) = n.shl_prec_ref(T::ZERO, prec);
let (shifted_alt, o_alt) = Float::from_float_prec(n, prec);
assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt));
assert_eq!(o, o_alt);
});
unsigned_pair_gen_var_18::<T, _>().test_properties(|(u, prec)| {
let (shifted, o) = Float::NAN.shl_prec(u, prec);
assert!(shifted.is_nan());
assert_eq!(o, Equal);
assert_eq!(Float::INFINITY.shl_prec(u, prec), (Float::INFINITY, Equal));
assert_eq!(
Float::NEGATIVE_INFINITY.shl_prec(u, prec),
(Float::NEGATIVE_INFINITY, Equal)
);
let (shifted, o) = Float::ZERO.shl_prec(u, prec);
assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec(u, prec);
assert_eq!(
ComparableFloat(shifted),
ComparableFloat(Float::NEGATIVE_ZERO)
);
assert_eq!(o, Equal);
});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_properties_helper_signed_helper<T: PrimitiveSigned>(n: Float, i: T, prec: u64)
where
i128: TryFrom<T>,
i64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
<T as UnsignedAbs>::Output: PrimitiveUnsigned,
{
let mut mut_n = n.clone();
let o = mut_n.shl_prec_assign(i, prec);
assert!(mut_n.is_valid());
let shifted = mut_n;
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, Equal);
}
}
let (shifted_alt, o_alt) = n.shl_prec_ref(i, prec);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.clone().shl_prec(i, prec);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
if i128::from(n.get_exponent().unwrap_or(1))
.wrapping_add(i128::exact_from(i))
.lt_abs(&1_000_000)
{
let (shifted_alt, o_alt) = shl_prec_naive(n.clone(), i, prec);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
if shifted.is_normal() {
assert_eq!(shifted.get_prec(), Some(prec));
}
if i >= T::ZERO {
let (shifted_alt, o_alt) = n.shl_prec_ref(i.unsigned_abs(), prec);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
} else if i != T::MIN {
let (shifted_alt, o_alt) = n.shr_prec_ref(i.unsigned_abs(), prec);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
};
let (shifted_2, o_2) = (-&n).shl_prec(i, prec);
let (shifted_2_alt, o_2_alt) = n.shl_prec_ref(i, prec);
assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2));
assert_eq!(o_2_alt.reverse(), o_2);
if shifted.is_normal() {
let (shifted_alt, o_alt) = n.mul_prec(Float::power_of_2(i64::exact_from(i)), prec);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
}
fn shl_prec_properties_helper_signed<T: PrimitiveSigned>()
where
i128: TryFrom<T>,
i64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
<T as UnsignedAbs>::Output: PrimitiveUnsigned,
{
float_signed_unsigned_triple_gen_var_1::<T, _>().test_properties(|(n, i, prec)| {
shl_prec_properties_helper_signed_helper(n, i, prec);
});
float_signed_unsigned_triple_gen_var_2::<T, _>().test_properties(|(n, i, prec)| {
shl_prec_properties_helper_signed_helper(n, i, prec);
});
float_unsigned_pair_gen_var_1().test_properties(|(n, prec)| {
let (shifted, o) = n.shl_prec_ref(T::ZERO, prec);
let (shifted_alt, o_alt) = Float::from_float_prec(n, prec);
assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt));
assert_eq!(o, o_alt);
});
signed_unsigned_pair_gen_var_19::<T, _>().test_properties(|(i, prec)| {
let (shifted, o) = Float::NAN.shl_prec(i, prec);
assert!(shifted.is_nan());
assert_eq!(o, Equal);
assert_eq!(Float::INFINITY.shl_prec(i, prec), (Float::INFINITY, Equal));
assert_eq!(
Float::NEGATIVE_INFINITY.shl_prec(i, prec),
(Float::NEGATIVE_INFINITY, Equal)
);
let (shifted, o) = Float::ZERO.shl_prec(i, prec);
assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec(i, prec);
assert_eq!(
ComparableFloat(shifted),
ComparableFloat(Float::NEGATIVE_ZERO)
);
assert_eq!(o, Equal);
});
signed_unsigned_pair_gen_var_20::<T, _>().test_properties(|(i, prec)| {
let (shifted, o) = Float::ONE.shl_prec(i, prec);
if shifted.is_normal() {
assert!(shifted.is_power_of_2());
assert_eq!(o, Equal);
}
});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_rug_unsigned_helper(n: Float, u: u32, prec: u64) {
let (shifted, o) = n.shl_prec_ref(u, prec);
let (rug_shifted, rug_o) = rug_shl_prec_unsigned(&rug::Float::exact_from(&n), u, prec);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_shifted)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, rug_o);
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_rug_signed_helper(n: Float, i: i32, prec: u64) {
let (shifted, o) = n.shl_prec_ref(i, prec);
let (rug_shifted, rug_o) = rug_shl_prec_signed(&rug::Float::exact_from(&n), i, prec);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_shifted)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, rug_o);
}
#[test]
fn shl_prec_properties() {
apply_fn_to_unsigneds!(shl_prec_properties_helper_unsigned);
apply_fn_to_signeds!(shl_prec_properties_helper_signed);
float_unsigned_unsigned_triple_gen_var_1::<u32, _>()
.test_properties(|(n, u, prec)| shl_prec_rug_unsigned_helper(n, u, prec));
float_unsigned_unsigned_triple_gen_var_2::<u32, _>()
.test_properties(|(n, u, prec)| shl_prec_rug_unsigned_helper(n, u, prec));
float_signed_unsigned_triple_gen_var_1::<i32, _>()
.test_properties(|(n, i, prec)| shl_prec_rug_signed_helper(n, i, prec));
float_signed_unsigned_triple_gen_var_2::<i32, _>()
.test_properties(|(n, i, prec)| shl_prec_rug_signed_helper(n, i, prec));
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_round_properties_helper_unsigned_helper<T: PrimitiveUnsigned>(
n: Float,
u: T,
prec: u64,
rm: RoundingMode,
) where
i128: TryFrom<T>,
u64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
{
let mut mut_n = n.clone();
let o = mut_n.shl_prec_round_assign(u, prec, rm);
assert!(mut_n.is_valid());
let shifted = mut_n;
match (n >= 0, rm) {
(_, Floor) | (true, Down) | (false, Up) => {
assert_ne!(o, Greater);
}
(_, Ceiling) | (true, Up) | (false, Down) => {
assert_ne!(o, Less);
}
(_, Exact) => assert_eq!(o, Equal),
_ => {}
}
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, Equal);
}
}
let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, prec, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.clone().shl_prec_round(u, prec, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
if i128::from(n.get_exponent().unwrap_or(1))
.wrapping_add(i128::exact_from(u))
.lt_abs(&1_000_000)
{
let (shifted_alt, o_alt) = shl_prec_round_naive(n.clone(), u, prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted),
);
assert_eq!(o_alt, o);
}
if shifted.is_normal() {
assert_eq!(shifted.get_prec(), Some(prec));
}
let (shifted_2, o_2) = (-&n).shl_prec_round(u, prec, rm);
let (shifted_2_alt, o_2_alt) = n.shl_prec_round_ref(u, prec, -rm);
assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2));
assert_eq!(o_2_alt.reverse(), o_2);
if shifted.is_normal() {
let (shifted_alt, o_alt) =
n.mul_prec_round(Float::power_of_2(u64::exact_from(u)), prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
}
fn shl_prec_round_properties_helper_unsigned<T: PrimitiveUnsigned>()
where
i128: TryFrom<T>,
u64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
{
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::<T>().test_properties(
|(n, u, prec, rm)| {
shl_prec_round_properties_helper_unsigned_helper(n, u, prec, rm);
},
);
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2::<T>().test_properties(
|(n, u, prec, rm)| {
shl_prec_round_properties_helper_unsigned_helper(n, u, prec, rm);
},
);
float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, prec, rm)| {
let (shifted, o) = n.shl_prec_round_ref(T::ZERO, prec, rm);
let (shifted_alt, o_alt) = Float::from_float_prec_round(n, prec, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt));
assert_eq!(o, o_alt);
});
unsigned_unsigned_rounding_mode_triple_gen_var_7::<T, _>().test_properties(|(u, prec, rm)| {
let (shifted, o) = Float::NAN.shl_prec_round(u, prec, rm);
assert!(shifted.is_nan());
assert_eq!(o, Equal);
assert_eq!(
Float::INFINITY.shl_prec_round(u, prec, rm),
(Float::INFINITY, Equal)
);
assert_eq!(
Float::NEGATIVE_INFINITY.shl_prec_round(u, prec, rm),
(Float::NEGATIVE_INFINITY, Equal)
);
let (shifted, o) = Float::ZERO.shl_prec_round(u, prec, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec_round(u, prec, rm);
assert_eq!(
ComparableFloat(shifted),
ComparableFloat(Float::NEGATIVE_ZERO)
);
assert_eq!(o, Equal);
});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_round_properties_helper_signed_helper<T: PrimitiveSigned>(
n: Float,
i: T,
prec: u64,
rm: RoundingMode,
) where
i128: TryFrom<T>,
i64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
<T as UnsignedAbs>::Output: PrimitiveUnsigned,
{
let mut mut_n = n.clone();
let o = mut_n.shl_prec_round_assign(i, prec, rm);
assert!(mut_n.is_valid());
let shifted = mut_n;
match (n >= 0, rm) {
(_, Floor) | (true, Down) | (false, Up) => {
assert_ne!(o, Greater);
}
(_, Ceiling) | (true, Up) | (false, Down) => {
assert_ne!(o, Less);
}
(_, Exact) => assert_eq!(o, Equal),
_ => {}
}
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, Equal);
}
}
let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, prec, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.clone().shl_prec_round(i, prec, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
if i128::from(n.get_exponent().unwrap_or(1))
.wrapping_add(i128::exact_from(i))
.lt_abs(&1_000_000)
{
let (shifted_alt, o_alt) = shl_prec_round_naive(n.clone(), i, prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
if shifted.is_normal() {
assert_eq!(shifted.get_prec(), Some(prec));
}
if i >= T::ZERO {
let (shifted_alt, o_alt) = n.shl_prec_round_ref(i.unsigned_abs(), prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
} else if i != T::MIN {
let (shifted_alt, o_alt) = n.shr_prec_round_ref(i.unsigned_abs(), prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
};
let (shifted_2, o_2) = (-&n).shl_prec_round(i, prec, rm);
let (shifted_2_alt, o_2_alt) = n.shl_prec_round_ref(i, prec, -rm);
assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2));
assert_eq!(o_2_alt.reverse(), o_2);
if shifted.is_normal() {
let (shifted_alt, o_alt) =
n.mul_prec_round(Float::power_of_2(i64::exact_from(i)), prec, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
}
fn shl_prec_round_properties_helper_signed<T: PrimitiveSigned>()
where
i128: TryFrom<T>,
i64: TryFrom<T>,
Rational: Shl<T, Output = Rational>,
<T as UnsignedAbs>::Output: PrimitiveUnsigned,
{
float_signed_unsigned_rounding_mode_quadruple_gen_var_1::<T>().test_properties(
|(n, i, prec, rm)| {
shl_prec_round_properties_helper_signed_helper(n, i, prec, rm);
},
);
float_signed_unsigned_rounding_mode_quadruple_gen_var_2::<T>().test_properties(
|(n, i, prec, rm)| {
shl_prec_round_properties_helper_signed_helper(n, i, prec, rm);
},
);
float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, prec, rm)| {
let (shifted, o) = n.shl_prec_round_ref(T::ZERO, prec, rm);
let (shifted_alt, o_alt) = Float::from_float_prec_round(n, prec, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt));
assert_eq!(o, o_alt);
});
signed_unsigned_rounding_mode_triple_gen_var_7::<T, _>().test_properties(|(i, prec, rm)| {
let (shifted, o) = Float::NAN.shl_prec_round(i, prec, rm);
assert!(shifted.is_nan());
assert_eq!(o, Equal);
assert_eq!(
Float::INFINITY.shl_prec_round(i, prec, rm),
(Float::INFINITY, Equal)
);
assert_eq!(
Float::NEGATIVE_INFINITY.shl_prec_round(i, prec, rm),
(Float::NEGATIVE_INFINITY, Equal)
);
let (shifted, o) = Float::ZERO.shl_prec_round(i, prec, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec_round(i, prec, rm);
assert_eq!(
ComparableFloat(shifted),
ComparableFloat(Float::NEGATIVE_ZERO)
);
assert_eq!(o, Equal);
});
signed_unsigned_rounding_mode_triple_gen_var_8::<T, _>().test_properties(|(i, prec, rm)| {
let (shifted, o) = Float::ONE.shl_prec_round(i, prec, rm);
assert!(shifted.is_power_of_2());
assert_eq!(o, Equal);
});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_round_rug_unsigned_helper(n: Float, u: u32, prec: u64, rm: RoundingMode) {
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (shifted, o) = n.shl_prec_round_ref(u, prec, rm);
let (rug_shifted, rug_o) =
rug_shl_prec_round_unsigned(&rug::Float::exact_from(&n), u, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_shifted)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, rug_o);
}
}
#[allow(clippy::needless_pass_by_value)]
fn shl_prec_round_rug_signed_helper(n: Float, i: i32, prec: u64, rm: RoundingMode) {
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (shifted, o) = n.shl_prec_round_ref(i, prec, rm);
let (rug_shifted, rug_o) =
rug_shl_prec_round_signed(&rug::Float::exact_from(&n), i, prec, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_shifted)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, rug_o);
}
}
#[test]
fn shl_prec_round_properties() {
apply_fn_to_unsigneds!(shl_prec_round_properties_helper_unsigned);
apply_fn_to_signeds!(shl_prec_round_properties_helper_signed);
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::<u32>()
.test_properties(|(n, u, prec, rm)| shl_prec_round_rug_unsigned_helper(n, u, prec, rm));
float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2::<u32>()
.test_properties(|(n, u, prec, rm)| shl_prec_round_rug_unsigned_helper(n, u, prec, rm));
float_signed_unsigned_rounding_mode_quadruple_gen_var_1::<i32>()
.test_properties(|(n, i, prec, rm)| shl_prec_round_rug_signed_helper(n, i, prec, rm));
float_signed_unsigned_rounding_mode_quadruple_gen_var_2::<i32>()
.test_properties(|(n, i, prec, rm)| shl_prec_round_rug_signed_helper(n, i, prec, rm));
}
#[allow(clippy::needless_pass_by_value)]
fn shl_round_properties_helper_unsigned_helper<T: PrimitiveUnsigned>(
n: Float,
u: T,
rm: RoundingMode,
) where
for<'a> &'a Integer: Shl<T, Output = Integer>,
Float: ShlRound<T, Output = Float> + ShlRoundAssign<T> + ShrRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>,
u64: TryFrom<T>,
i128: TryFrom<T>,
{
let mut mut_n = n.clone();
let o = mut_n.shl_round_assign(u, rm);
assert!(mut_n.is_valid());
let shifted = mut_n;
match (n >= 0, rm) {
(_, Floor) | (true, Down) | (false, Up) => {
assert_ne!(o, Greater);
}
(_, Ceiling) | (true, Up) | (false, Down) => {
assert_ne!(o, Less);
}
(_, Exact) => assert_eq!(o, Equal),
_ => {}
}
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (shifted_alt, o_alt) = (&n).shl_round(u, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, Equal);
}
}
let (shifted_alt, o_alt) = (&n).shl_round(u, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.clone().shl_round(u, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, n.get_prec().unwrap_or(1), rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
if i128::from(n.get_exponent().unwrap_or(1))
.wrapping_add(i128::exact_from(u))
.lt_abs(&1_000_000)
{
let (shifted_alt, o_alt) = shl_round_naive(n.clone(), u, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
if shifted.is_normal() {
assert_eq!(n.get_prec(), shifted.get_prec());
}
if !n.is_nan() {
assert!((&n).shl_round(u, rm).0.ge_abs(&n));
}
let (shifted_2, o_2) = (-&n).shl_round(u, rm);
let (shifted_2_alt, o_2_alt) = (&n).shl_round(u, -rm);
assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2));
assert_eq!(o_2_alt.reverse(), o_2);
if shifted.is_normal() {
let (shifted_alt, o_alt) = n.mul_round(Float::power_of_2(u64::exact_from(u)), rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
}
fn shl_round_properties_helper_unsigned<T: PrimitiveUnsigned>()
where
for<'a> &'a Integer: Shl<T, Output = Integer>,
Float: ShlRound<T, Output = Float> + ShrRound<T, Output = Float> + ShlRoundAssign<T>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>,
u64: TryFrom<T>,
i128: TryFrom<T>,
{
float_unsigned_rounding_mode_triple_gen_var_5::<T>().test_properties(|(n, u, rm)| {
shl_round_properties_helper_unsigned_helper(n, u, rm);
});
float_unsigned_rounding_mode_triple_gen_var_6::<T>().test_properties(|(n, u, rm)| {
shl_round_properties_helper_unsigned_helper(n, u, rm);
});
float_rounding_mode_pair_gen().test_properties(|(n, rm)| {
let (shifted, o) = (&n).shl_round(T::ZERO, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(n));
assert_eq!(o, Equal);
});
unsigned_rounding_mode_pair_gen::<T>().test_properties(|(u, rm)| {
let (shifted, o) = Float::NAN.shl_round(u, rm);
assert!(shifted.is_nan());
assert_eq!(o, Equal);
assert_eq!(Float::INFINITY.shl_round(u, rm), (Float::INFINITY, Equal));
assert_eq!(
Float::NEGATIVE_INFINITY.shl_round(u, rm),
(Float::NEGATIVE_INFINITY, Equal)
);
let (shifted, o) = Float::ZERO.shl_round(u, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (shifted, o) = Float::NEGATIVE_ZERO.shl_round(u, rm);
assert_eq!(
ComparableFloat(shifted),
ComparableFloat(Float::NEGATIVE_ZERO)
);
assert_eq!(o, Equal);
});
unsigned_rounding_mode_pair_gen_var_5::<T>().test_properties(|(u, rm)| {
let (shifted, o) = Float::ONE.shl_round(u, rm);
assert!(shifted.is_power_of_2());
assert_eq!(o, Equal);
});
integer_unsigned_rounding_mode_triple_gen_var_5::<T>().test_properties(|(n, u, rm)| {
let (shifted, o) = Float::exact_from(&n).shl_round(u, rm);
assert_eq!(&n << u, shifted);
assert_eq!(o, Equal);
});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_round_properties_helper_signed_helper<T: PrimitiveSigned>(n: Float, i: T, rm: RoundingMode)
where
for<'a> &'a Integer: Shl<T, Output = Integer>,
Float: ShlRound<T, Output = Float> + ShlRoundAssign<T> + ShrRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>
+ ShlRound<<T as UnsignedAbs>::Output, Output = Float>
+ ShrRound<<T as UnsignedAbs>::Output, Output = Float>
+ ShrRound<T, Output = Float>,
i64: TryFrom<T>,
i128: TryFrom<T>,
{
let mut mut_n = n.clone();
let o = mut_n.shl_round_assign(i, rm);
assert!(mut_n.is_valid());
let shifted = mut_n;
match (n >= 0, rm) {
(_, Floor) | (true, Down) | (false, Up) => {
assert_ne!(o, Greater);
}
(_, Ceiling) | (true, Up) | (false, Down) => {
assert_ne!(o, Less);
}
(_, Exact) => assert_eq!(o, Equal),
_ => {}
}
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (shifted_alt, o_alt) = (&n).shl_round(i, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, Equal);
}
}
let (shifted_alt, o_alt) = (&n).shl_round(i, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.clone().shl_round(i, rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, n.get_prec().unwrap_or(1), rm);
assert!(shifted_alt.is_valid());
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
if i128::from(n.get_exponent().unwrap_or(1))
.wrapping_add(i128::exact_from(i))
.lt_abs(&1_000_000)
{
let (shifted_alt, o_alt) = shl_round_naive(n.clone(), i, rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
if shifted.is_normal() {
assert_eq!(n.get_prec(), shifted.get_prec());
}
if !n.is_nan() {
if i >= T::ZERO {
assert!((&n).shl_round(i, rm).0.ge_abs(&n));
} else {
assert!((&n).shl_round(i, rm).0.le_abs(&n));
}
}
if i >= T::ZERO {
let (shifted_alt, o_alt) = (&n).shl_round(i.unsigned_abs(), rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
} else if i != T::MIN {
let (shifted_alt, o_alt) = (&n).shr_round(i.unsigned_abs(), rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
};
let (shifted_2, o_2) = (-&n).shl_round(i, rm);
let (shifted_2_alt, o_2_alt) = (&n).shl_round(i, -rm);
assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2));
assert_eq!(o_2_alt.reverse(), o_2);
if shifted.is_normal() {
let (shifted_alt, o_alt) = n.mul_round(Float::power_of_2(i64::exact_from(i)), rm);
assert_eq!(
ComparableFloatRef(&shifted_alt),
ComparableFloatRef(&shifted)
);
assert_eq!(o_alt, o);
}
}
fn shl_round_properties_helper_signed<T: PrimitiveSigned>()
where
for<'a> &'a Integer: Shl<T, Output = Integer>,
Float: ShlRound<T, Output = Float> + ShlRoundAssign<T> + ShrRound<T, Output = Float>,
Rational: Shl<T, Output = Rational>,
for<'a> &'a Float: ShlRound<T, Output = Float>
+ ShlRound<<T as UnsignedAbs>::Output, Output = Float>
+ ShrRound<<T as UnsignedAbs>::Output, Output = Float>
+ ShrRound<T, Output = Float>,
i64: TryFrom<T>,
i128: TryFrom<T>,
{
float_signed_rounding_mode_triple_gen_var_1::<T>().test_properties(|(n, i, rm)| {
shl_round_properties_helper_signed_helper(n, i, rm);
});
float_signed_rounding_mode_triple_gen_var_2::<T>().test_properties(|(n, i, rm)| {
shl_round_properties_helper_signed_helper(n, i, rm);
});
float_rounding_mode_pair_gen().test_properties(|(n, rm)| {
let (shifted, o) = (&n).shl_round(T::ZERO, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(n));
assert_eq!(o, Equal);
});
signed_rounding_mode_pair_gen::<T>().test_properties(|(i, rm)| {
let (shifted, o) = Float::NAN.shl_round(i, rm);
assert!(shifted.is_nan());
assert_eq!(o, Equal);
assert_eq!(Float::INFINITY.shl_round(i, rm), (Float::INFINITY, Equal));
assert_eq!(
Float::NEGATIVE_INFINITY.shl_round(i, rm),
(Float::NEGATIVE_INFINITY, Equal)
);
let (shifted, o) = Float::ZERO.shl_round(i, rm);
assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (shifted, o) = Float::NEGATIVE_ZERO.shl_round(i, rm);
assert_eq!(
ComparableFloat(shifted),
ComparableFloat(Float::NEGATIVE_ZERO)
);
assert_eq!(o, Equal);
});
signed_rounding_mode_pair_gen_var_5::<T>().test_properties(|(i, rm)| {
let (shifted, o) = Float::ONE.shl_round(i, rm);
assert!(shifted.is_power_of_2());
assert_eq!(o, Equal);
});
}
#[allow(clippy::needless_pass_by_value)]
fn shl_round_rug_unsigned_helper(n: Float, u: u32, rm: RoundingMode) {
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (shifted, o) = (&n).shl_round(u, rm);
let (rug_shifted, rug_o) = rug_shl_round_unsigned(&rug::Float::exact_from(&n), u, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_shifted)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, rug_o);
}
}
#[allow(clippy::needless_pass_by_value)]
fn shl_round_rug_signed_helper(n: Float, i: i32, rm: RoundingMode) {
if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) {
let (shifted, o) = (&n).shl_round(i, rm);
let (rug_shifted, rug_o) = rug_shl_round_signed(&rug::Float::exact_from(&n), i, rug_rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_shifted)),
ComparableFloatRef(&shifted)
);
assert_eq!(o, rug_o);
}
}
#[test]
fn shl_round_properties() {
apply_fn_to_unsigneds!(shl_round_properties_helper_unsigned);
apply_fn_to_signeds!(shl_round_properties_helper_signed);
float_unsigned_rounding_mode_triple_gen_var_5::<u32>()
.test_properties(|(n, u, rm)| shl_round_rug_unsigned_helper(n, u, rm));
float_unsigned_rounding_mode_triple_gen_var_6::<u32>()
.test_properties(|(n, u, rm)| shl_round_rug_unsigned_helper(n, u, rm));
float_signed_rounding_mode_triple_gen_var_1::<i32>()
.test_properties(|(n, i, rm)| shl_round_rug_signed_helper(n, i, rm));
float_signed_rounding_mode_triple_gen_var_2::<i32>()
.test_properties(|(n, i, rm)| shl_round_rug_signed_helper(n, i, rm));
}