// Copyright © 2024 Mikhail Hogrefe // // This file is part of Malachite. // // Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU // Lesser General Public License (LGPL) as published by the Free Software Foundation; either version // 3 of the License, or (at your option) any later version. See . use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; 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::exhaustive::exhaustive_rounding_modes; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::test_util::arithmetic::add::{ add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_prec, rug_add_prec_round, rug_add_rational, rug_add_rational_prec, rug_add_rational_prec_round, rug_add_rational_round, rug_add_round, }; use malachite_float::test_util::common::{ emulate_primitive_float_fn_2, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_1, float_float_rounding_mode_triple_gen_var_4, float_float_rounding_mode_triple_gen_var_5, float_float_rounding_mode_triple_gen_var_6, float_float_rounding_mode_triple_gen_var_7, float_float_rounding_mode_triple_gen_var_8, float_float_rounding_mode_triple_gen_var_9, float_float_unsigned_rounding_mode_quadruple_gen_var_1, float_float_unsigned_triple_gen_var_1, float_gen, float_pair_gen, float_pair_gen_var_2, float_pair_gen_var_3, float_pair_gen_var_4, float_pair_gen_var_5, float_pair_gen_var_6, float_pair_gen_var_7, float_rational_pair_gen, float_rational_rounding_mode_triple_gen_var_1, float_rational_unsigned_rounding_mode_quadruple_gen_var_1, float_rational_unsigned_triple_gen_var_1, float_rounding_mode_pair_gen, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, rational_rounding_mode_pair_gen_var_6, rational_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use malachite_q::Rational; use std::cmp::{ max, Ordering::{self, *}, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_add() { let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let sum = x.clone() + y.clone(); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_add( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y) ))), ComparableFloatRef(&sum) ); let sum_alt = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); }; test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); test( "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test( "Infinity", "Infinity", "0.0", "0x0.0", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", "Infinity", "Infinity", ); test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); test( "-Infinity", "-Infinity", "Infinity", "Infinity", "NaN", "NaN", ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); test( "0.0", "0x0.0", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("0.0", "0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); test( "-0.0", "-0x0.0", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("-0.0", "-0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("123.0", "0x7b.0#7", "0.0", "0x0.0", "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", "-0.0", "-0x0.0", "123.0", "0x7b.0#7"); test("NaN", "NaN", "123.0", "0x7b.0#7", "NaN", "NaN"); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", "Infinity", "Infinity", ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "123.0", "0x7b.0#7", "123.0", "0x7b.0#7"); test("-0.0", "-0x0.0", "123.0", "0x7b.0#7", "123.0", "0x7b.0#7"); // - in add_float_significands_same_prec_lt_w // - x_exp < y_exp in add_float_significands_same_prec_lt_w // - exp_diff < shift in add_float_significands_same_prec_lt_w // - exp_diff < shift && !overflow in add_float_significands_same_prec_lt_w // - (round_bit != 0 || sticky_bit == 0) && rm == Nearest in // add_float_significands_same_prec_lt_w // - round_bit != 0 && (sticky_bit != 0 || (sum & shift_bit) != 0) in // add_float_significands_same_prec_lt_w // - rm == Nearest && sum == 0 in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "4.0", "0x4.0#1"); // - in add_float_significands_same_prec_general // - out_bits > exp_diff in add_float_significands_same_prec_general // - overlap <= ys_len in add_float_significands_same_prec_general // - shift2 != 0 in add_float_significands_same_prec_general // - out_len - k <= overlap in add_float_significands_same_prec_general // - out_len <= xs_len second time in add_float_significands_same_prec_general // - !y in add_float_significands_same_prec_general // - round_bit == Uninitialized && shift != 0 in add_float_significands_same_prec_general // - shift > 1 in add_float_significands_same_prec_general // - x == 0 second time in add_float_significands_same_prec_general // - xs_len <= out_len && following_bits != True in add_float_significands_same_prec_general // - difw > 0 && difw > ys_len && exp_diff <= out_bits in // add_float_significands_same_prec_general // - exp_diff_rem != 0 || yi != 0 second time in add_float_significands_same_prec_general // - exp_diff_rem != 0 second time in add_float_significands_same_prec_general // - round_bit != Uninitialized seventh time in add_float_significands_same_prec_general // - yi == 0 second time in add_float_significands_same_prec_general // - in add_float_significands_same_prec_general_round // - following_bits == False && round_bit == False in // add_float_significands_same_prec_general_round test("1.0", "0x1.0#1", "2.0", "0x2.0#2", "3.0", "0x3.0#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "3.0", "0x3.0#2"); // round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#2", "2.0", "0x2.0#2", "3.0", "0x3.0#2"); test("1.0", "0x1.000#10", "2.0", "0x2.00#10", "3.0", "0x3.00#10"); // - exp_diff < shift && overflow in add_float_significands_same_prec_lt_w // - round_bit == 0 || (sticky_bit == 0 && (sum & shift_bit) == 0) // - in add_float_significands_same_prec_lt_w test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "4.555806215962888", "0x4.8e4950f0795fc#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1.727379091216698", "-0x1.ba35842091e63#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "1.727379091216698", "0x1.ba35842091e63#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-4.555806215962888", "-0x4.8e4950f0795fc#53", ); // - x_exp > y_exp in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "0.0002", "0x0.001#1", "1.0", "0x1.0#1"); test("1.0", "0x1.0#1", "-1.0", "-0x1.0#1", "0.0", "0x0.0"); // - x_exp == y_exp in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1", "2.0", "0x2.0#1"); // - rm == Nearest && sum != 0 in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#3", "1.8", "0x1.c#3", "3.0", "0x3.0#3"); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_lt_w test( "7.7e14", "0x2.bcE+12#8", "1.237e-9", "0x5.50E-8#8", "7.7e14", "0x2.bcE+12#8", ); // - shift <= exp_diff < Limb::WIDTH in add_float_significands_same_prec_lt_w // - shift <= exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_lt_w test( "1.852193494e22", "0x3.ec137baE+18#29", "241425944.0", "0xe63de18.0#29", "1.852193494e22", "0x3.ec137baE+18#29", ); // - shift <= exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_lt_w test( "1.999999999999993", "0x1.fffffffffffe#48", "5.96046447753906e-8", "0x1.000000000000E-6#48", "2.00000005960464", "0x2.000001000000#48", ); // - in add_float_significands_same_prec_w // - x_exp == y_exp in add_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", ); // - x_exp < y_exp in add_float_significands_same_prec_w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_w // - !overflow in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", "3.0", "0x3.0000000000000000#64", ); // - x_exp > y_exp in add_float_significands_same_prec_w test( "2.0", "0x2.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "3.0", "0x3.0000000000000000#64", ); // - (round_bit != 0) || (sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_w // - round_bit == 0 || (sticky_bit == 0 && (sum & 1) == 0) in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", "2.0", "0x2.0000000000000000#64", ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) in add_float_significands_same_prec_w // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and !overflow in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000003", "0x1.0000000000000006#64", "2.0000000000000000004", "0x2.0000000000000008#64", ); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_w test( "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", "2.9347251290514630352e-45", "0x1.0c11b075f03d6daeE-37#64", "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", ); // - overflow in add_float_significands_same_prec_w test( "0.00022185253582909293959", "0x0.000e8a1162cbb1a4265#64", "0.000029745661521717034001", "0x0.0001f30ca4b8117ff0a0#64", "0.0002515981973508099736", "0x0.00107d1e0783c324170#64", ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and overflow in // add_float_significands_same_prec_w test( "63.999999999999999997", "0x3f.ffffffffffffffc#64", "64.0", "0x40.000000000000000#64", "128.0", "0x80.00000000000000#64", ); // - in add_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp in add_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", ); // - x_exp < y_exp in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", "3.0", "0x3.0000000000000000#65", ); // - x_exp > y_exp in add_float_significands_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "3.0", "0x3.0000000000000000#65", ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (sum_0 != 0 || sum_1 != 0) in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", "2.0", "0x2.0000000000000000#65", ); // - rm == Nearest && sum_1 != 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000016", "0x1.0000000000000003#65", "2.0000000000000000002", "0x2.0000000000000004#65", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "18.63123034252626794758647", "0x12.a1984fcd64a8ae228eef#85", "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", ); // - exp_diff >= Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w test( "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", "1.14823551075108882469e-96", "0x2.73dea72af3fe6314E-80#65", "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w test( "19585.2851423168986928116147584507795", "0x4c81.48ff163dc91a0d4bd90309b0f8#116", "372369974082165972902790.766638151683", "0x4eda377c7f0d747fa386.c44265dd58#116", "372369974082165972922376.05178046858", "0x4eda377c7f0d747ff008.0d417c1b20#116", ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_w_lt_2w test( "18.492649216180435830000529", "0x12.7e1e424fe51f1bb914c0#85", "56.637589789906471403844847", "0x38.a339159fe96c1722fdfe#85", "75.130239006086907233845378", "0x4b.215757efce8b32dc12c0#85", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "5.29395592276605355108231857701752e-23", "0x4.00000007e000fffffff0000000E-19#107", "255.999999999999999999999947060441", "0xff.ffffffffffffffffffc000000#107", "256.0", "0x100.0000000000000000000000000#107", ); // - rm == Nearest && sum_1 == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "0.0000610351562499999999996", "0x0.0003ffffffffffffffff8#67", "17179869183.9999389648", "0x3ffffffff.fffc00000#67", "17179869184.0", "0x400000000.00000000#67", ); // - in add_float_significands_same_prec_2w // - x_exp == y_exp in add_float_significands_same_prec_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", ); // - x_exp < y_exp in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", "3.0", "0x3.00000000000000000000000000000000#128", ); // - x_exp > y_exp in add_float_significands_same_prec_2w test( "2.0", "0x2.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", "3.0", "0x3.00000000000000000000000000000000#128", ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_2w // - rm == Nearest in add_float_significands_same_prec_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (sum_0 & 1) == 0)) in // add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "2.0", "0x2.00000000000000000000000000000000#128", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (sum_0 & 1) != 0) in // add_float_significands_same_prec_2w // - rm == Nearest && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000018", "0x1.00000000000000000000000000000006#128", "2.00000000000000000000000000000000000002", "0x2.00000000000000000000000000000008#128", ); // - exp_diff >= TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff > TWICE_WIDTH in add_float_significands_same_prec_2w test( "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", "5.07801249136957145270807726205511855421e-45", "0x1.cfd8608b7c32de2bbcfecf8bcf8a2d00E-37#128", "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", ); // - Limb::WIDTH <= exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - Limb::WIDTH < exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w test( "4354249796990942.35435357526597783143164", "0xf782ac869b7de.5ab6ea78fcf0cc5079f#128", "8.03239453825726512240307053405256016022e-10", "0x3.732bce7aa121827a284545a25f32dc68E-8#128", "4354249796990942.35435357606921728525736", "0xf782ac869b7de.5ab6ea7c701c9acb1b1#128", ); // - exp_diff == TWICE_WIDTH in add_float_significands_same_prec_2w test( "15732412727332569995335732833027757624.44", "0xbd5f3d586bc01069a1d94f5ab5a1638.7#128", "0.0373708302820085888760745841639896128921", "0x0.0991227de2b63edc67164401ce8ebdb04#128", "15732412727332569995335732833027757624.5", "0xbd5f3d586bc01069a1d94f5ab5a1638.8#128", ); // - Limb::WIDTH == exp_diff in add_float_significands_same_prec_2w test( "1.057437459917463716438672572710788562701e-17", "0xc.310127aae1df1a1cb12f60c4d339d76E-15#128", "148.0549133677002965445211858794413066474", "0x94.0e0ecd6e62d0a8c7c7c2a633277e3e#128", "148.054913367700296555095560478615943812", "0x94.0e0ecd6e62d0a98ad7d520e1456fe0#128", ); // - exp_diff < TWICE_WIDTH && overflow in add_float_significands_same_prec_2w test( "990.890284854484258981204316304960898664", "0x3de.e3e9b54e224e900a8701c94cea27bc#128", "111.972242543885876168914754084523121772", "0x6f.f8e4e329c509f04b7f9497ec8ce6438#128", "1102.862527398370135150119070389484020437", "0x44e.dcce9877e758805606966139770e00#128", ); // - rm == Nearest && overflow in add_float_significands_same_prec_2w test( "1152920954851033088.0", "0xfffff8000000000.00000000000000000#128", "549755813887.999999999999999999999999998", "0x7fffffffff.ffffffffffffffffffffff8#128", "1152921504606846976.0", "0x1000000000000000.00000000000000000#128", ); // - in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - x_exp > y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "2.0", "0x2.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "3.0", "0x3.00000000000000000000000000000000#129", ); // - x_exp < y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "2.0", "0x2.00000000000000000000000000000000#129", "3.0", "0x3.00000000000000000000000000000000#129", ); // - x_exp == y_exp in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", "2.0", "0x2.00000000000000000000000000000000#129", ); // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", "2.000000000000000000000000000000000000012", "0x2.00000000000000000000000000000004#129", ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 < exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", ); // - exp_diff >= Limb::WIDTH * 3 in add_float_significands_same_prec_gt_2w_lt_3w test( "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", "6.8892360159362421595728818935378487832685754059e-50", "0x1.9c693c182df3035eef00d41638bbdd942f4d498E-41#155", "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "4.2850537238606374652351877988811796373898773e-22", "0x2.0607fd4819748c532aad3528693c1e3c1966E-18#146", "978.49328809934495391839880801989439981236569", "0x3d2.7e4820fe314caadcb9a156bef2f1c8e53c#146", "978.49328809934495391839923652526678587611222", "0x3d2.7e4820fe314caadcbba75ebc3b0b3d718f#146", ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_2w_lt_3w test( "4499918.46219262840948309077470961400786337", "0x44a9ce.7652418f789422bc22220831e2030#137", "64560208.0262619516023687759351781439347886", "0x3d91c50.06b91a6f42e5205070f82f89eefa#137", "69060126.488454580011851866709887757942652", "0x41dc61e.7d0b5bfebb79430c931a37bbd0fc#137", ); // - exp_diff == Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w test( "563971925627753843356041629019151473018178607215.42", "0x62c960337e963a378ba6626ea422d8a5e623986f.6c#165", "1301375421.83361702516620516356439489325145225661938", "0x4d9169bd.d567ece47a47ef60371d48c969ba8765d4#165", "563971925627753843356041629019151473019479982637.25", "0x62c960337e963a378ba6626ea422d8a633b5022d.40#165", ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w test( "226.9305090753243797994707628568605406194", "0xe2.ee35d7bf263fda8c632644ad7c49d98#130", "4262448175090788889452.984188256984861391", "0xe71159efd3a67e736c.fbf3c2f8db72fb8#130", "4262448175090788889679.91469733230924119", "0xe71159efd3a67e744f.ea299ab801b2d60#130", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "1180591620717411303423.999999999999999999999999997", "0x3fffffffffffffffff.ffffffffffffffffffffff#158", "5.68434188616351954822429632036496545806324230121e-14", "0x1.000000000fffffffffffe0000000000000000038E-11#158", "1180591620717411303424.00000000000005684341886163", "0x400000000000000000.00000000001000000000fe#158", ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum == 0 test( "4503599627370495.9999999999999999999999999996", "0xfffffffffffff.ffffffffffffffffffffffe#143", "3.3087224509824797385046520537834728287650668e-24", "0x4.00000003ffff0000000000000000fffffffE-20#143", "4503599627370496.000000000000000000000003309", "0x10000000000000.00000000000000000004000#143", ); // - in add_float_significands_same_prec_ge_3w // - exp_diff == 0 in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && round_bit == 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", ); // - x_exp < y_exp in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec in add_float_significands_same_prec_ge_3w // - in add_significands_rsh_to_out // - exp_diff < Limb::WIDTH in add_significands_rsh_to_out // - 0 < exp_diff < prec && shift == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && limb == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "3.0", "0x3.000000000000000000000000000000000000000000000000#192", ); // - x_exp > y_exp in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "3.0", "0x3.000000000000000000000000000000000000000000000000#192", ); // - 0 < exp_diff < prec && shift != 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#193", "2.0", "0x2.000000000000000000000000000000000000000000000000#193", "3.0", "0x3.000000000000000000000000000000000000000000000000#193", ); // - exp_diff == 0 && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && sticky_bit == 0 && out[0] & // shift_bit == 0 test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "3.0", "0x3.000000000000000000000000000000000000000000000000#192", ); // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 in // add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", "2.0000000000000000000000000000000000000000000000000000000013", "0x2.000000000000000000000000000000000000000000000008#192", ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && !carry in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", "3.0000000000000000000000000000000000000000000000000000000013", "0x3.000000000000000000000000000000000000000000000008#192", ); // - exp_diff >= Limb::WIDTH in add_significands_rsh_to_out // - exp_diff >= Limb::WIDTH && r != 0 in add_significands_rsh_to_out test( "7.28057116938384227432903448367767196428679514765398378973101e-48", "0xa.a3fc2da1f20fb2d9771f86d3c16a444cd62d5d139e3935f24E-40#198", "3.5123473778825578958968695187657587760357139395948269588971e-27", "0x1.1646de419a6dbd3466f3081403a87d719b7a765a1ec69e4658E-22#198", "3.5123473778825578959041500899351426183100429740785046308614e-27", "0x1.1646de419a6dbd3471970441a59a8d2474f195e0f288088aa8E-22#198", ); // - exp_diff >= prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Nearest || rm == Floor // || rm == Down) test( "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", "0.023991386767031193042066748710708351501952890752924613005724", "0x0.06244cad8cd272134e34b325815ad281733f2c06231a0ee744#193", "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", ); // - 0 < exp_diff < prec && limb != 0 in add_float_significands_same_prec_ge_3w test( "8.699772042374378140693728074838279708562673799416097107796", "0x8.b32442b4a730454d66b1b2bdf7a2863d417e6ff22d7f6c58#193", "7.5897463681962395437740598844462353563682906392115908083148", "0x7.96f99e34566e7be1960d023e431dc5e0a7ad24ad691a1ac4#193", "16.289518410570617684467787959284515064930964438627687916112", "0x10.4a1de0e8fd9ec12efcbeb4fc3ac04c1de92b949f9699872#193", ); // - exp_diff >= Limb::WIDTH && r == 0 in add_significands_rsh_to_out test( "6.442552350746554109885349691592991892989624685631192235549e-6", "0x0.00006c168d38e231899f0fc85d1888549d5177bdceaee72e15060#192", "1476808010161862576835936576709144.7975622615653024045505082", "0x48cff00a780a50d34bb694ada218.cc2d0a55f25f9f9126258#192", "1476808010161862576835936576709144.797568704117653151104618", "0x48cff00a780a50d34bb694ada218.cc2d766c7f9881c2afc48#192", ); // - exp_diff == prec in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && power && !carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power in add_float_significands_same_prec_ge_3w test( "4.0635838402455207229400698207668893925379768151364313942222e-23", "0x3.1202ecf10ff40b477337957dede18bd7b746884ec977474eE-19#194", "1174582238252884689829665592721065057.76655867827770290150723", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d4#194", "1174582238252884689829665592721065057.76655867827770290150729", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d8#194", ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && carry in add_float_significands_same_prec_ge_3w test( "4.336808689942017736029811203479766845699938816177735095446e-19", "0x7.fffffffffffffffffffffffffffffffe0000000000000000E-16#192", "5192296858534827628530496329220095.999999999999999999566319", "0xffffffffffffffffffffffffffff.fffffffffffffff80000#192", "5192296858534827628530496329220096.0", "0x10000000000000000000000000000.00000000000000000000#192", ); // - exp_diff == prec && rm == Nearest && power && carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power && carry in // add_float_significands_same_prec_ge_3w test( "158456325028528675187087900671.99999999999999999999999999997", "0x1ffffffffffffffffffffffff.fffffffffffffffffffffffe#192", "2.5243548967072377773175314089049159349542605923488736152645e-29", "0x1.fffffffffffffffffffffffffffffffffffffffffffffffeE-24#192", "158456325028528675187087900672.0", "0x2000000000000000000000000.000000000000000000000000#192", ); // - exp_diff == prec && rm == Nearest && power in add_float_significands_same_prec_ge_3w test( "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", "2.6469779601696885595885078146238811314105987548828125e-23", "0x2.000000000000000000000000000000000000000000000000E-19#192", "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", ); // - shift2 == 0 in add_float_significands_same_prec_general // - y in add_float_significands_same_prec_general // - shift != 0 in add_float_significands_same_prec_general // - x == 0 first time in add_float_significands_same_prec_general // - shift == 0 || following_bits != Uninitialized in add_float_significands_same_prec_general // - round_bit != Uninitialized || shift == 0 in add_float_significands_same_prec_general // - exp_diff_rem == 0 && yi == 0 second time in add_float_significands_same_prec_general // - round_bit != Uninitialized sixth time in add_float_significands_same_prec_general test("1.0", "0x1.0#1", "1.0", "0x1.0#2", "2.0", "0x2.0#2"); // - following_bits != False || round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit == 0 in // add_float_significands_same_prec_general_round test("1.0", "0x1.0#1", "1.5", "0x1.8#2", "2.0", "0x2.0#2"); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && carry in // add_float_significands_same_prec_general_round test("2.0", "0x2.0#1", "1.5", "0x1.8#2", "4.0", "0x4.0#2"); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_general_round test("1.0", "0x1.0#1", "1.8", "0x1.c#3", "3.0", "0x3.0#3"); // - x != 0 && x != mask second time in add_float_significands_same_prec_general // - rm == Nearest && following_bits != False && round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits != False && round_bit != False && !carry in // add_float_significands_same_prec_general_round test("1.5", "0x1.8#2", "4.0", "0x4.0#1", "6.0", "0x6.0#2"); // - rm == Nearest && following_bits != False && round_bit == False in // add_float_significands_same_prec_general_round test("4.0", "0x4.0#1", "1.2", "0x1.4#3", "5.0", "0x5.0#3"); // - x != 0 && x != mask first time in add_float_significands_same_prec_general // - shift != 0 && following_bits == Uninitialized in add_float_significands_same_prec_general test("1.2", "0x1.4#3", "3.0", "0x3.0#2", "4.0", "0x4.0#3"); // - rm == Nearest && following_bits != False && round_bit != False && carry in // add_float_significands_same_prec_general_round test("1.8", "0x1.c#3", "6.0", "0x6.0#2", "8.0", "0x8.0#3"); // - out_bits <= exp_diff in add_float_significands_same_prec_general // - out_len <= xs_len first time in add_float_significands_same_prec_general // - difw > 0 && difw > ys_len && exp_diff > out_bits in // add_float_significands_same_prec_general // - round_bit != Uninitialized fifth time in add_float_significands_same_prec_general test( "8.82188e11", "0xc.d668E+9#18", "9.75459983374e122", "0x1.79c17f063aE+102#40", "9.75459983374e122", "0x1.79c17f063aE+102#40", ); // - out_len > xs_len first time in add_float_significands_same_prec_general test( "2.8577648979177105962332201291018926848163080599637e-19", "0x5.458a93bffa7b1c05bdd1c0552b60196746d9083cE-16#162", "3.569720699507868e50", "0xf.4400d3acf388E+41#51", "3.5697206995078675404584127554321345196383736430592e50", "0xf.4400d3acf3880000000000000000000000000000E+41#162", ); // - overlap > ys_len in add_float_significands_same_prec_general // - out_len - k > overlap in add_float_significands_same_prec_general // - difw <= 0 || difw <= ys_len in add_float_significands_same_prec_general // - round_bit != Uninitialized fourth time in add_float_significands_same_prec_general test( "29780282551.762684458936866363165", "0x6ef0b0cb7.c33f49e84d21bb6040#104", "0.00003945598947538", "0x0.000295f62f36adb#46", "29780282551.762723914926341743141", "0x6ef0b0cb7.c341dfde7c58691040#104", ); // - out_len > xs_len second time in add_float_significands_same_prec_general test( "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222828352849", "0x0.00f5402c178824#46", "0.00374222829424688982311482391965285", "0x0.00f5402c235119eafa12eb9821602#107", ); // - exp_diff_rem == 0 second time in add_float_significands_same_prec_general test( "5.19192095203e-15", "0x1.761e097c5E-12#37", "7.4e4", "0x1.2E+4#5", "73728.0", "0x12000.00000#37", ); // - shift <= 1 in add_float_significands_same_prec_general test( "15135.895602865542606017656527713819177465060416097749360065", "0x3b1f.e5463ab9b599ce49b83c7988b324dc93ce50b2ed51a18#191", "3.581529624499970047886732225242180736649e-8", "0x9.9d355ad2b99a587727da095fa3226bf0E-7#130", "15135.895602901357902262656228192686499717482223464235884113", "0x3b1f.e5463b5388ef7b7551e200fb30c5728e007771ed51a18#191", ); // - round_bit == Uninitialized fourth time in add_float_significands_same_prec_general // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "8.63643735016344467819174862798332593462e-6", "0x0.000090e5374a001358c6606f968bf3813ad9#128", "1.84904e-8", "0x4.f6a6E-7#18", "8.65492771851100147411665059026359937212e-6", "0x0.00009134a1aa001358c6606f968bf3813ad9#128", ); // - round_bit == Uninitialized fifth time in add_float_significands_same_prec_general test( "2.389545997e25", "0x1.3c40f7bE+21#29", "0.078263259824284000402", "0x0.14090f9d6c745bc06#64", "2.389545996756557709e25", "0x1.3c40f7b000000000E+21#64", ); // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "5.7505515877842013577e-7", "0x9.a5d7d56cabed47dE-6#64", "1.1758894e-14", "0x3.4f515E-12#22", "5.7505517053731436845e-7", "0x9.a5d7d8bbfd3d47dE-6#64", ); // - x != 0 && x == mask second time in add_float_significands_same_prec_general // - xs_len <= out_len && following_bits == True in add_float_significands_same_prec_general test( "1.081090215247020702e-18", "0x1.3f14ddfe22c0634E-15#59", "6.3799657596147e-8", "0x1.12047722d26cE-6#47", "6.37996575972280156e-8", "0x1.12047722e65d4dcE-6#59", ); // - shift == 0 in add_float_significands_same_prec_general test( "4.3055451539258443718732375731462554408177909736937057433067e-16", "0x1.f06543668e6018c20c17efed72ff6d3d65a4c5dc9db475b0E-13#192", "1.6388436e-15", "0x7.61754E-13#21", "2.0693980969049410047184094732421002104686218250305033868307e-15", "0x9.51da83668e6018c20c17efed72ff6d3d65a4c5dc9db475bE-13#192", ); // - yi != 0 second time in add_float_significands_same_prec_general test( "2.24181435676546e-16", "0x1.0276ae5de1e8E-13#47", "7.6430700039878539638425372386462404393e-36", "0xa.28cd4cb186f5925ddb0d1ecb9681103E-30#128", "2.24181435676546206911083333246297446029e-16", "0x1.0276ae5de1e80000a28cd4cb186f5926E-13#128", ); // - x != 0 && x == mask first time in add_float_significands_same_prec_general test( "2.1474796e9", "0x7.ffff00E+7#24", "8191.9998788833609", "0x1fff.fff80fffff0#54", "2147487743.9998789", "0x80000fff.fff810#54", ); } #[test] fn test_add_prec() { let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (sum, o) = x.clone().add_prec(y.clone(), prec); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); assert_eq!(o, o_out); let (sum_alt, o_alt) = x.clone().add_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_assign(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_assign_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (rug_sum, rug_o) = rug_add_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "-0.0", "-0x0.0", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test("NaN", "NaN", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-2.0", "-0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-1.727", "-0x1.ba0#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "2.0", "0x2.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-4.555", "-0x4.8e#10", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 1, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, "0.0", "0x0.0", Equal, ); // - xs_len > out_len in add_float_significands_same_prec_general // - following_bits != False || difw > 0 in add_float_significands_same_prec_general // - difw <= ys_len in add_float_significands_same_prec_general // - exp_diff_rem != 0 || yi != 0 first time in add_float_significands_same_prec_general // - yi >= 0 && yi == ys_len in add_float_significands_same_prec_general // - following_bits != Uninitialized first time in add_float_significands_same_prec_general // - exp_diff_rem != 0 first time in add_float_significands_same_prec_general // - yi >= 0 second time in add_float_significands_same_prec_general // - yi >= 0 third time in add_float_significands_same_prec_general // - x >= y in add_float_significands_same_prec_general // - following_bits != False || x == 0 in add_float_significands_same_prec_general // - following_bits != False && x != Limb::MAX second time in // add_float_significands_same_prec_general test( "1.73414747294406e-17", "0x1.3fe4cc8cf520E-14#48", "5095194424.1679374580403939884785489", "0x12fb27f38.2afdf3020e8eaac84a7ec#116", 62, "5095194424.167937458", "0x12fb27f38.2afdf300#62", Less, ); // - yi < 0 || yi != ys_len in add_float_significands_same_prec_general // - yi < 0 third time in add_float_significands_same_prec_general test( "102490490.309858195", "0x61be17a.4f52dde#54", "140024642456267714260687682888.7395345704093208802906032076327334", "0x1c471ab65a12bae8410f87d48.bd52233a2b6095a9fa45bd79bbfc#209", 126, "140024642456267714260790173379.049392765", "0x1c471ab65a12bae8417145ec3.0ca50118#126", Less, ); // - following_bits != 0 && following_bits != Limb::MAX in // add_float_significands_same_prec_general // - x != Limb::MAX first time in add_float_significands_same_prec_general test( "3.6587e-6", "0x0.00003d62#14", "2.26998937985590408943624715555e46", "0x3.f9e6004fa97f534f98cad274E+38#96", 61, "2.269989379855904089e46", "0x3.f9e6004fa97f534E+38#61", Less, ); // - following_bits == Uninitialized first time in add_float_significands_same_prec_general // - exp_diff_rem != 0 in add_float_significands_same_prec_general // - yi < 0 first time in add_float_significands_same_prec_general // - x >= y or not other conditions in add_float_significands_same_prec_general // - round_bit == Limb::MAX second time in add_float_significands_same_prec_general // - following_bits != False && x != Limb::MAX first time in // add_float_significands_same_prec_general test( "6058.05208272591415306446968882359605946955168456454", "0x17aa.0d554b247ce1b6ab28ba39c8d5992a74c7ac91a#169", "0.000144566892208323", "0x0.0009796e12f9784#47", 64, "6058.0522272928063612", "0x17aa.0d5ec4928fdb2#64", Less, ); // - following_bits == True in add_float_significands_same_prec_general // - round_bit == Uninitialized first time in add_float_significands_same_prec_general // - x != Limb::MAX second time in add_float_significands_same_prec_general test( "3.6596517369110659089355442395654891585e48", "0x2.810875a0ca3206afd8c6cf841941830E+40#123", "1545.699550397407201099813420288295", "0x609.b315bc1ec48a143a74bd53048#109", 64, "3.6596517369110659089e48", "0x2.810875a0ca3206b0E+40#64", Greater, ); // - yi >= 0 first time in add_float_significands_same_prec_general test( "2.80915429604669102593383052436808885401854724410738829e-11", "0x1.ee310ffa09a06a6361f52c2cd8a9569a780b775dc213E-9#177", "519241072363118296470.333928838103121952666621563036", "0x1c25eadc41d4907d96.557c5c3ed81cab65dab0cf920#166", 64, "5.1924107236311829648e20", "0x1.c25eadc41d4907daE+17#64", Greater, ); // - round_bit != Uninitialized second time in add_float_significands_same_prec_general test( "559935046210054011882951826578284118061013900.5853448", "0x191bbd3588c78488c2f4d122814d5fb34edb8c.95d928#170", "3.027932e11", "0x4.67fe2E+9#22", 63, "5.599350462100540119e44", "0x1.91bbd3588c78488cE+37#63", Less, ); // - following_bits == False && difw <= 0 in add_float_significands_same_prec_general test( "7184368264698708563285024670194469326968686224.86386349506591", "0x1422880c600dc4fd90a02f1814859aafd658690.dd2628738430#198", "1.0296060328202e-24", "0x1.3ea5cb49bdaE-20#44", 61, "7.184368264698708565e45", "0x1.422880c600dc4feE+38#61", Greater, ); // - following_bits == False && x != 0 in add_float_significands_same_prec_general test( "19710666.821984898059985706849", "0x12cc2ca.d26d9a2ef9396c5108#94", "7.0e4", "0x1.0E+4#2", 61, "19776202.82198489807", "0x12dc2ca.d26d9a2f0#61", Greater, ); // - round_bit != Uninitialized first time in add_float_significands_same_prec_general test( "2.3370796820961060045359802932823709e39", "0x6.de392c9978b4267553b428865de8E+32#112", "1.187719715482312494e-58", "0xb.edbf4827e1e28aaE-49#64", 63, "2.3370796820961060044e39", "0x6.de392c9978b4267E+32#63", Less, ); // - difw > ys_len in add_float_significands_same_prec_general // - difw > ys_len || goto_c_read in add_float_significands_same_prec_general // - following_bits != Uninitialized second time in add_float_significands_same_prec_general // - following_bits == False second time in add_float_significands_same_prec_general // - xs[xi] != 0 in add_float_significands_same_prec_general test( "1248577957.9617995883835430866672787859939813175787209064549678049868", "0x4a6bc9a5.f6387f7169e05140ece8db047baba25ac8c576b8fed10fa4#221", "1.65314121012e-6", "0x0.00001bbc2ffb9e#36", 126, "1248577957.96180124152475320394882420796", "0x4a6bc9a5.f6389b2d99dbef40ece8db04#126", Less, ); // - x < y in add_float_significands_same_prec_general // - following_bits == False first time in add_float_significands_same_prec_general // - round_bit != False or not other condition in add_float_significands_same_prec_general test( "1.85445e-25", "0x3.9648E-21#15", "1.2975739042614492272769355049909712560463719657882671587557999636387971206e-6", "0x0.000015c509987b7b0dbb1bf2aae59a4afde515d3ec2c3af539738e362659e1f1b0#243", 62, "1.2975739042614492276e-6", "0x0.000015c509987b7b0dbb8#62", Greater, ); // - following_bits == Uninitialized second time in add_float_significands_same_prec_general // - round_bit == Uninitialized third time in add_float_significands_same_prec_general // - following_bits != False second time in add_float_significands_same_prec_general test( "1.3111820218254081035114504135472568116036464005e-6", "0x0.000015ff7be10e865ada82cd25acef5baa9c89c25f4#152", "2.51465891601e-20", "0x7.6c05c64a8E-17#38", 128, "1.311182021825433250100610518712675662596e-6", "0x0.000015ff7be10e86d19adf31cdacef5baa9c8#128", Less, ); // - following_bits == False || x == Limb::MAX second time in // add_float_significands_same_prec_general // - !goto_c_read in add_float_significands_same_prec_general // - following_bits != False || yi < 0 in add_float_significands_same_prec_general test( "7.9999999999995452526491135358810425", "0x7.ffffffffff800000000000000000#114", "0.0039062797764", "0x0.0100007fe38#34", 49, "8.00390627977595", "0x8.0100007fe300#49", Equal, ); // - following_bits != False first time in add_float_significands_same_prec_general test( "2.89901505570589585435e-11", "0x1.fe0007ffc00000000E-9#67", "134217728.00000381469725", "0x8000000.00003ffffffc#74", 51, "134217728.0000038", "0x8000000.000040#51", Less, ); // - yi < 0 second time in add_float_significands_same_prec_general; // - goto_c_read in add_float_significands_same_prec_general test( "4.4474794e-47", "0x4.0ffff0E-39#25", "7.523135146670945963453530822847271532226579417449854573285752516755e-37", "0xf.fffc000001fffffffffffffffffffffffffffc03fffffffc001ffeE-31#219", 57, "7.52313514711569391e-37", "0xf.fffc000411fff0E-31#57", Greater, ); // - round_bit == False and other condition in add_float_significands_same_prec_general test( "1048575.9999999999999999965", "0xfffff.ffffffffffffffc0#81", "1.1102230204892534781399170051165479471979625e-16", "0x7.ffffff800000003ffe000001fffffffc0000E-14#145", 48, "1048576.0", "0x100000.0000000#48", Less, ); // - x == Limb::MAX first time in add_float_significands_same_prec_general // - xi != 0 in add_float_significands_same_prec_general test( "3.810971975326539e-6", "0x0.00003ff00000000004#52", "4.90398573077084434674671048688098938757996518e55", "0x1.ffffffffffffffffffffffffffffffffffffeE+46#148", 21, "4.903986e55", "0x2.00000E+46#21", Greater, ); // - xs[xi] == 0 in add_float_significands_same_prec_general test( "135.998", "0x87.ff8#19", "8796093087743.998046875", "0x8000000ffff.ff80000000000000000000000000000#168", 114, "8796093087879.99609375", "0x80000010087.ff0000000000000000#114", Equal, ); // - following_bits == False && yi >= 0 in add_float_significands_same_prec_general // - exp_diff_rem != 0 && y_prec << (Limb::WIDTH - exp_diff_rem) != 0 in // add_float_significands_same_prec_general test( "4610525002867933183.9999999999998", "0x3ffbe00fffffffff.ffffffffffc#104", "2.27373688992450493e-13", "0x4.000003ffc00000E-11#58", 47, "4.61052500286793e18", "0x3.ffbe01000000E+15#47", Less, ); // - exp_diff_rem == 0 first time in add_float_significands_same_prec_general test( "199484.9246647061832808582", "0x30b3c.ecb6d380d2988d78#79", "9.2945767606483e-15", "0x2.9dbeadc4568E-12#45", 63, "199484.92466470618328", "0x30b3c.ecb6d380d298#63", Less, ); // - exp_diff_rem == 0 || y_prec << (Limb::WIDTH - exp_diff_rem) == 0 in // add_float_significands_same_prec_general // - difw <= ys_len && !goto_c_read in add_float_significands_same_prec_general test( "128.000244140566792339087", "0x80.000fffffc00000000#75", "7.5", "0x7.800000000000000000000#87", 60, "135.5002441405667923", "0x87.800fffffc0000#60", Equal, ); // - exp_diff_rem == 0 second time in add_float_significands_same_prec_general // - yi != 0 first time in add_float_significands_same_prec_general test( "127.9999999999999997744859485366053840029607161188794193511", "0x7f.ffffffffffffefc000007fffffffffff0000000001e000#190", "64.0000000000000000000000000000000000000000000000410536659471", "0x40.000000000000000000000000000000000000003c000000008#200", 90, "191.9999999999999997744859485", "0xbf.ffffffffffffefc000008#90", Greater, ); // - following_bits == False || x == Limb::MAX first time in // add_float_significands_same_prec_general test( "1927941831.98168915743", "0x72ea0ec7.fb4ffb0a0#65", "10702647.0", "0xa34f37.0#24", 63, "1938644478.9816891574", "0x738d5dfe.fb4ffb0a#63", Equal, ); // - round_bit == Uninitialized sixth time in add_float_significands_same_prec_general test( "8.69134330408049e-16", "0x3.ea0b2d4be674E-13#48", "15492.756587362761273446", "0x3c84.c1afb59ba066160#71", 128, "15492.75658736276127431557748582959734014", "0x3c84.c1afb59ba06654a0b2d4be6740000#128", Equal, ); // - ys[yi] != 0 in add_float_significands_same_prec_general test( "2.384181243542116135358810424804687500000000000000000024885983948e-7", "0x3.ffff8000000000000000000000000000000000000003ffc00000E-6#210", "1.5", "0x1.8000000000000000000#75", 55, "1.50000023841812435", "0x1.800003ffff8000#55", Less, ); // - x == Limb::MAX second time in add_float_significands_same_prec_general test( "98079714615416886934934209737619787751599303785390800896.0002441405", "0x3fffffffffffffffffffffffffffffffffffff800000000.000fffff8#219", "5.8207660907e-11", "0x3.fffffffe0E-9#35", 63, "9.807971461541688693e55", "0x4.000000000000000E+46#63", Greater, ); // - xi == 0 in add_float_significands_same_prec_general test( "2.996272864212510369e-95", "0x3.fffffff00000000E-79#60", "1.49012180372665170580148696899414062499e-8", "0x4.0000fffffffffffffffffffffffffff8E-7#128", 27, "1.4901218e-8", "0x4.000100E-7#27", Greater, ); // - x < y and other conditions in add_float_significands_same_prec_general test( "0.00024414062499999999999999979805160826342", "0x0.000ffffffffffffffffffff00000000000#124", "1.32348897761965396e-23", "0xf.ffffff80000008E-20#57", 63, "0.000244140625", "0x0.0010000000000000000#63", Less, ); // - ys[yi] == 0 in add_float_significands_same_prec_general test( "0.99951171875", "0x0.ffe00000000000000000000#92", "0.017578124999996447286321199499070644378662109375", "0x0.047fffffffff00000000000000000000000000000000000000000000#217", 48, "1.01708984375", "0x1.046000000000#48", Greater, ); // - yi == 0 first time in add_float_significands_same_prec_general test( "67108864.000000000000000000027105054312137610850186320021748542784370058", "0x4000000.00000000000000007ffffffffffffffffffffffffffffff800000#236", "3.63797880709171295166015625e-12", "0x4.000000000000000000000E-10#86", 103, "67108864.0000000000036379788342", "0x4000000.0000000004000000800#103", Greater, ); test( "3.91923414751995775967065104797896464447978457860112833061347e-17", "0x2.d2f8998a5fa796b9de129923cf4d51e04f27e6b6a368fadb0E-14#197", "2.75164948336014612968759798085025748008e-17", "0x1.fb96f911d37dd9fe4933cbeee25d7ddeE-14#128", 8, "6.68e-17", "0x4.d0E-14#8", Greater, ); } #[test] fn add_prec_fail() { assert_panic!(Float::NAN.add_prec(Float::NAN, 0)); assert_panic!(Float::NAN.add_prec_val_ref(&Float::NAN, 0)); assert_panic!(Float::NAN.add_prec_ref_val(Float::NAN, 0)); assert_panic!(Float::NAN.add_prec_ref_ref(&Float::NAN, 0)); assert_panic!({ let mut x = Float::NAN; x.add_prec_assign(Float::NAN, 0) }); assert_panic!({ let mut x = Float::NAN; x.add_prec_assign_ref(&Float::NAN, 0) }); } #[test] fn test_add_round() { let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (sum, o) = x.clone().add_round(y.clone(), rm); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); assert_eq!(o, o_out); let (sum_alt, o_alt) = x.clone().add_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_round_assign(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_round_assign_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); // Note different behavior for Floor test( "0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); // Note different behavior for Floor test( "-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Exact, "123.0", "0x7b.0#7", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); // - (round_bit != 0 || sticky_bit == 0) && (rm == Floor || rm == Down) in // add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Floor, "2.0", "0x2.0#1", Less, ); // - (round_bit != 0 || sticky_bit == 0) && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_lt_w // - (rm == Ceiling || rm == Up) && sum == 0 in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Exact, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); // - (rm == Ceiling || rm == Up) && sum != 0 in add_float_significands_same_prec_lt_w test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "4.555806215962889", "0x4.8e4950f079600#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "4.555806215962889", "0x4.8e4950f079600#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Exact, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Exact, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-4.555806215962888", "-0x4.8e4950f0795fc#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-4.555806215962888", "-0x4.8e4950f0795fc#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Nearest, "1.0", "0x1.0#1", Less, ); // Note different behavior for Floor test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp == y_exp in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "2.0", "0x2.0#1", Equal, ); // - rm == Nearest && sum != 0 in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#3", "1.8", "0x1.c#3", Nearest, "3.0", "0x3.0#3", Greater, ); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_lt_w test( "7.7e14", "0x2.bcE+12#8", "1.237e-9", "0x5.50E-8#8", Nearest, "7.7e14", "0x2.bcE+12#8", Less, ); // - shift <= exp_diff < Limb::WIDTH in add_float_significands_same_prec_lt_w // - shift <= exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_lt_w test( "1.852193494e22", "0x3.ec137baE+18#29", "241425944.0", "0xe63de18.0#29", Nearest, "1.852193494e22", "0x3.ec137baE+18#29", Less, ); test( "1.999999999999993", "0x1.fffffffffffe#48", "5.96046447753906e-8", "0x1.000000000000E-6#48", Nearest, "2.00000005960464", "0x2.000001000000#48", Greater, ); // - in add_float_significands_same_prec_w // - x_exp == y_exp in add_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "2.0", "0x2.0000000000000000#64", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_w // - !overflow in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", Nearest, "3.0", "0x3.0000000000000000#64", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_w test( "2.0", "0x2.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "3.0", "0x3.0000000000000000#64", Equal, ); // - (round_bit != 0) || (sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_w // - round_bit == 0 || (sticky_bit == 0 && (sum & 1) == 0) in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "2.0", "0x2.0000000000000000#64", Less, ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) in add_float_significands_same_prec_w // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and !overflow in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000003", "0x1.0000000000000006#64", Nearest, "2.0000000000000000004", "0x2.0000000000000008#64", Greater, ); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_w test( "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", "2.9347251290514630352e-45", "0x1.0c11b075f03d6daeE-37#64", Nearest, "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", Less, ); // - overflow in add_float_significands_same_prec_w test( "0.00022185253582909293959", "0x0.000e8a1162cbb1a4265#64", "0.000029745661521717034001", "0x0.0001f30ca4b8117ff0a0#64", Nearest, "0.0002515981973508099736", "0x0.00107d1e0783c324170#64", Greater, ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and overflow in // add_float_significands_same_prec_w test( "63.999999999999999997", "0x3f.ffffffffffffffc#64", "64.0", "0x40.000000000000000#64", Nearest, "128.0", "0x80.00000000000000#64", Greater, ); // - (round_bit != 0) || (sticky_bit != 0) && (rm == Floor || rm == Down) in // add_float_significands_same_prec_w // - (round_bit != 0) || (sticky_bit != 0) && (rm == Floor || rm == Down) && sum != 0 in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Down, "2.0", "0x2.0000000000000000#64", Less, ); // - (round_bit != 0) || (sticky_bit != 0) && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_w // - (round_bit != 0) || (sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum != 0 in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Up, "2.0000000000000000002", "0x2.0000000000000004#64", Greater, ); // - (round_bit != 0) || (sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum == 0 in // add_float_significands_same_prec_w test( "536870911.99999999997", "0x1fffffff.ffffffffe#64", "1.00974195868289511071e-28", "0x7.ffffffffffffffe0E-24#64", Up, "536870912.0", "0x20000000.000000000#64", Greater, ); // - in add_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp in add_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "2.0", "0x2.0000000000000000#65", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", Nearest, "3.0", "0x3.0000000000000000#65", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "3.0", "0x3.0000000000000000#65", Equal, ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (sum_0 != 0 || sum_1 != 0) in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "2.0", "0x2.0000000000000000#65", Less, ); // - rm == Nearest && sum_1 != 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000016", "0x1.0000000000000003#65", Nearest, "2.0000000000000000002", "0x2.0000000000000004#65", Greater, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "18.63123034252626794758647", "0x12.a1984fcd64a8ae228eef#85", Nearest, "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", Less, ); // - exp_diff >= Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w test( "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", "1.14823551075108882469e-96", "0x2.73dea72af3fe6314E-80#65", Nearest, "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", Less, ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w test( "19585.2851423168986928116147584507795", "0x4c81.48ff163dc91a0d4bd90309b0f8#116", "372369974082165972902790.766638151683", "0x4eda377c7f0d747fa386.c44265dd58#116", Nearest, "372369974082165972922376.05178046858", "0x4eda377c7f0d747ff008.0d417c1b20#116", Less, ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_w_lt_2w test( "18.492649216180435830000529", "0x12.7e1e424fe51f1bb914c0#85", "56.637589789906471403844847", "0x38.a339159fe96c1722fdfe#85", Nearest, "75.130239006086907233845378", "0x4b.215757efce8b32dc12c0#85", Greater, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "5.29395592276605355108231857701752e-23", "0x4.00000007e000fffffff0000000E-19#107", "255.999999999999999999999947060441", "0xff.ffffffffffffffffffc000000#107", Nearest, "256.0", "0x100.0000000000000000000000000#107", Less, ); // - rm == Nearest && sum_1 == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "0.0000610351562499999999996", "0x0.0003ffffffffffffffff8#67", "17179869183.9999389648", "0x3ffffffff.fffc00000#67", Nearest, "17179869184.0", "0x400000000.00000000#67", Greater, ); // - rm == Floor || rm == Down in add_float_significands_same_prec_gt_w_lt_2w // - (rm == Floor || rm == Down) && (sum_0 != 0 || sum_1 != 0) in // add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Floor, "2.0", "0x2.0000000000000000#65", Less, ); // - rm == Ceiling || rm == Up in add_float_significands_same_prec_gt_w_lt_2w // - rm == Ceiling || rm == Up && sum_1 != 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Ceiling, "2.0000000000000000001", "0x2.0000000000000002#65", Greater, ); // - rm == Ceiling || rm == Up && sum_1 == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.9999999999999999999999998", "0x1.ffffffffffffffffffffc#83", "2.4074118565121938372272894e-35", "0x1.fffff8000000007fffff8E-29#83", Ceiling, "2.0", "0x2.000000000000000000000#83", Greater, ); // - in add_float_significands_same_prec_2w // - x_exp == y_exp in add_float_significands_same_prec_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", Nearest, "2.0", "0x2.00000000000000000000000000000000#128", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", Nearest, "3.0", "0x3.00000000000000000000000000000000#128", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_2w test( "2.0", "0x2.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", Nearest, "3.0", "0x3.00000000000000000000000000000000#128", Equal, ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_2w // - rm == Nearest in add_float_significands_same_prec_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (sum_0 & 1) == 0)) in // add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Nearest, "2.0", "0x2.00000000000000000000000000000000#128", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (sum_0 & 1) != 0) in // add_float_significands_same_prec_2w // - rm == Nearest && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000018", "0x1.00000000000000000000000000000006#128", Nearest, "2.00000000000000000000000000000000000002", "0x2.00000000000000000000000000000008#128", Greater, ); // - exp_diff >= TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff > TWICE_WIDTH in add_float_significands_same_prec_2w test( "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", "5.07801249136957145270807726205511855421e-45", "0x1.cfd8608b7c32de2bbcfecf8bcf8a2d00E-37#128", Nearest, "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", Less, ); // - Limb::WIDTH <= exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - Limb::WIDTH < exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w test( "4354249796990942.35435357526597783143164", "0xf782ac869b7de.5ab6ea78fcf0cc5079f#128", "8.03239453825726512240307053405256016022e-10", "0x3.732bce7aa121827a284545a25f32dc68E-8#128", Nearest, "4354249796990942.35435357606921728525736", "0xf782ac869b7de.5ab6ea7c701c9acb1b1#128", Less, ); // - exp_diff == TWICE_WIDTH in add_float_significands_same_prec_2w test( "15732412727332569995335732833027757624.44", "0xbd5f3d586bc01069a1d94f5ab5a1638.7#128", "0.0373708302820085888760745841639896128921", "0x0.0991227de2b63edc67164401ce8ebdb04#128", Nearest, "15732412727332569995335732833027757624.5", "0xbd5f3d586bc01069a1d94f5ab5a1638.8#128", Greater, ); // - Limb::WIDTH == exp_diff in add_float_significands_same_prec_2w test( "1.057437459917463716438672572710788562701e-17", "0xc.310127aae1df1a1cb12f60c4d339d76E-15#128", "148.0549133677002965445211858794413066474", "0x94.0e0ecd6e62d0a8c7c7c2a633277e3e#128", Nearest, "148.054913367700296555095560478615943812", "0x94.0e0ecd6e62d0a98ad7d520e1456fe0#128", Greater, ); // - exp_diff < TWICE_WIDTH && overflow in add_float_significands_same_prec_2w test( "990.890284854484258981204316304960898664", "0x3de.e3e9b54e224e900a8701c94cea27bc#128", "111.972242543885876168914754084523121772", "0x6f.f8e4e329c509f04b7f9497ec8ce6438#128", Nearest, "1102.862527398370135150119070389484020437", "0x44e.dcce9877e758805606966139770e00#128", Greater, ); // - rm == Nearest && overflow in add_float_significands_same_prec_2w test( "1152920954851033088.0", "0xfffff8000000000.00000000000000000#128", "549755813887.999999999999999999999999998", "0x7fffffffff.ffffffffffffffffffffff8#128", Nearest, "1152921504606846976.0", "0x1000000000000000.00000000000000000#128", Greater, ); // - rm == Floor || m == Down in add_float_significands_same_prec_2w // - (rm == Floor || m == Down) && (sum_0 != 0 || sum_1 != 0) in // add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Floor, "2.0", "0x2.00000000000000000000000000000000#128", Less, ); // - rm == Ceiling || m == Up in add_float_significands_same_prec_2w // - (rm == Ceiling || m == Up) && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Ceiling, "2.00000000000000000000000000000000000001", "0x2.00000000000000000000000000000004#128", Greater, ); // - (rm == Ceiling || m == Up) && overflow in add_float_significands_same_prec_2w test( "69631.9999999850988390281969486491823076", "0x10fff.ffffffc000000ffffffff80007fc#128", "1.255420347077336152767157884641533283217e58", "0x1.fffffffffffffffffffffffffffffffeE+48#128", Ceiling, "1.25542034707733615276715788464153328322e58", "0x2.00000000000000000000000000000000E+48#128", Greater, ); // - (round_bit != 0 || sticky_bit != 0) && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum_2 != 0 in // add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", Up, "2.000000000000000000000000000000000000012", "0x2.00000000000000000000000000000004#129", Greater, ); test( "9903517953099800764370386944.0000000000291038304566", "0x1fffff800000000000000000.000000001fffffffff8#166", "1.68499666669691498716668845382709804457445989930032e66", "0x1.0000000000000000000001fff80000000000000000E+55#166", Up, "1.68499666669691498716668845382709804458436341725346e66", "0x1.0000000000000000000001fff8000001fffff80008E+55#166", Greater, ); // - in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - x_exp > y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "2.0", "0x2.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "3.0", "0x3.00000000000000000000000000000000#129", Less, ); // - x_exp < y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "2.0", "0x2.00000000000000000000000000000000#129", Nearest, "3.0", "0x3.00000000000000000000000000000000#129", Less, ); // - x_exp == y_exp in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "2.0", "0x2.00000000000000000000000000000000#129", Equal, ); // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", Nearest, "2.000000000000000000000000000000000000012", "0x2.00000000000000000000000000000004#129", Greater, ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 < exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Nearest, "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Less, ); // - exp_diff >= Limb::WIDTH * 3 in add_float_significands_same_prec_gt_2w_lt_3w test( "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", "6.8892360159362421595728818935378487832685754059e-50", "0x1.9c693c182df3035eef00d41638bbdd942f4d498E-41#155", Nearest, "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", Less, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "4.2850537238606374652351877988811796373898773e-22", "0x2.0607fd4819748c532aad3528693c1e3c1966E-18#146", "978.49328809934495391839880801989439981236569", "0x3d2.7e4820fe314caadcb9a156bef2f1c8e53c#146", Nearest, "978.49328809934495391839923652526678587611222", "0x3d2.7e4820fe314caadcbba75ebc3b0b3d718f#146", Less, ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_2w_lt_3w test( "4499918.46219262840948309077470961400786337", "0x44a9ce.7652418f789422bc22220831e2030#137", "64560208.0262619516023687759351781439347886", "0x3d91c50.06b91a6f42e5205070f82f89eefa#137", Nearest, "69060126.488454580011851866709887757942652", "0x41dc61e.7d0b5bfebb79430c931a37bbd0fc#137", Less, ); // - exp_diff == Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w test( "563971925627753843356041629019151473018178607215.42", "0x62c960337e963a378ba6626ea422d8a5e623986f.6c#165", "1301375421.83361702516620516356439489325145225661938", "0x4d9169bd.d567ece47a47ef60371d48c969ba8765d4#165", Nearest, "563971925627753843356041629019151473019479982637.25", "0x62c960337e963a378ba6626ea422d8a633b5022d.40#165", Less, ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w test( "226.9305090753243797994707628568605406194", "0xe2.ee35d7bf263fda8c632644ad7c49d98#130", "4262448175090788889452.984188256984861391", "0xe71159efd3a67e736c.fbf3c2f8db72fb8#130", Nearest, "4262448175090788889679.91469733230924119", "0xe71159efd3a67e744f.ea299ab801b2d60#130", Less, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "1180591620717411303423.999999999999999999999999997", "0x3fffffffffffffffff.ffffffffffffffffffffff#158", "5.68434188616351954822429632036496545806324230121e-14", "0x1.000000000fffffffffffe0000000000000000038E-11#158", Nearest, "1180591620717411303424.00000000000005684341886163", "0x400000000000000000.00000000001000000000fe#158", Less, ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum == 0 test( "4503599627370495.9999999999999999999999999996", "0xfffffffffffff.ffffffffffffffffffffffe#143", "3.3087224509824797385046520537834728287650668e-24", "0x4.00000003ffff0000000000000000fffffffE-20#143", Nearest, "4503599627370496.000000000000000000000003309", "0x10000000000000.00000000000000000004000#143", Greater, ); // - (round_bit != 0 || sticky_bit != 0) && (rm == Floor || rm == Down) in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && (rm == Floor || rm == Down) && sum != 0 in // add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Down, "2.0", "0x2.00000000000000000000000000000000#129", Less, ); // - (round_bit != 0 || sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum_2 == 0 in // add_float_significands_same_prec_gt_2w_lt_3w test( "18014398509481983.9999999999999999999999999999999998", "0x3fffffffffffff.ffffffffffffffffffffffffffff#166", "9.6296497219361792652798897129246365926905082410768e-35", "0x7.ffffffffffffffffffffffffffffffffffffffffeE-29#166", Up, "18014398509481984.0", "0x40000000000000.0000000000000000000000000000#166", Greater, ); // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && round_bit == 0 && sticky_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Up, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - in add_float_significands_same_prec_ge_3w // - exp_diff == 0 in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && round_bit == 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec in add_float_significands_same_prec_ge_3w // - in add_significands_rsh_to_out // - exp_diff < Limb::WIDTH in add_significands_rsh_to_out // - 0 < exp_diff < prec && shift == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && limb == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - 0 < exp_diff < prec && shift != 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#193", "2.0", "0x2.000000000000000000000000000000000000000000000000#193", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#193", Equal, ); // - exp_diff == 0 && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Nearest, "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Less, ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && sticky_bit == 0 && out[0] & // shift_bit == 0 in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Less, ); // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 in // add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", Nearest, "2.0000000000000000000000000000000000000000000000000000000013", "0x2.000000000000000000000000000000000000000000000008#192", Greater, ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && !carry in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", Nearest, "3.0000000000000000000000000000000000000000000000000000000013", "0x3.000000000000000000000000000000000000000000000008#192", Greater, ); // - exp_diff >= Limb::WIDTH in add_significands_rsh_to_out // - exp_diff >= Limb::WIDTH && r != 0 in add_significands_rsh_to_out test( "7.28057116938384227432903448367767196428679514765398378973101e-48", "0xa.a3fc2da1f20fb2d9771f86d3c16a444cd62d5d139e3935f24E-40#198", "3.5123473778825578958968695187657587760357139395948269588971e-27", "0x1.1646de419a6dbd3466f3081403a87d719b7a765a1ec69e4658E-22#198", Nearest, "3.5123473778825578959041500899351426183100429740785046308614e-27", "0x1.1646de419a6dbd3471970441a59a8d2474f195e0f288088aa8E-22#198", Greater, ); // - exp_diff >= prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Nearest || rm == Floor // || rm == Down) test( "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", "0.023991386767031193042066748710708351501952890752924613005724", "0x0.06244cad8cd272134e34b325815ad281733f2c06231a0ee744#193", Nearest, "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", Less, ); // - 0 < exp_diff < prec && limb != 0 in add_float_significands_same_prec_ge_3w test( "8.699772042374378140693728074838279708562673799416097107796", "0x8.b32442b4a730454d66b1b2bdf7a2863d417e6ff22d7f6c58#193", "7.5897463681962395437740598844462353563682906392115908083148", "0x7.96f99e34566e7be1960d023e431dc5e0a7ad24ad691a1ac4#193", Nearest, "16.289518410570617684467787959284515064930964438627687916112", "0x10.4a1de0e8fd9ec12efcbeb4fc3ac04c1de92b949f9699872#193", Greater, ); // - exp_diff >= Limb::WIDTH && r == 0 in add_significands_rsh_to_out test( "6.442552350746554109885349691592991892989624685631192235549e-6", "0x0.00006c168d38e231899f0fc85d1888549d5177bdceaee72e15060#192", "1476808010161862576835936576709144.7975622615653024045505082", "0x48cff00a780a50d34bb694ada218.cc2d0a55f25f9f9126258#192", Nearest, "1476808010161862576835936576709144.797568704117653151104618", "0x48cff00a780a50d34bb694ada218.cc2d766c7f9881c2afc48#192", Less, ); // - exp_diff == prec in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && power && !carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power in add_float_significands_same_prec_ge_3w test( "4.0635838402455207229400698207668893925379768151364313942222e-23", "0x3.1202ecf10ff40b477337957dede18bd7b746884ec977474eE-19#194", "1174582238252884689829665592721065057.76655867827770290150723", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d4#194", Nearest, "1174582238252884689829665592721065057.76655867827770290150729", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d8#194", Greater, ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && carry in add_float_significands_same_prec_ge_3w test( "4.336808689942017736029811203479766845699938816177735095446e-19", "0x7.fffffffffffffffffffffffffffffffe0000000000000000E-16#192", "5192296858534827628530496329220095.999999999999999999566319", "0xffffffffffffffffffffffffffff.fffffffffffffff80000#192", Nearest, "5192296858534827628530496329220096.0", "0x10000000000000000000000000000.00000000000000000000#192", Greater, ); // - exp_diff == prec && rm == Nearest && power && carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power && carry in // add_float_significands_same_prec_ge_3w test( "158456325028528675187087900671.99999999999999999999999999997", "0x1ffffffffffffffffffffffff.fffffffffffffffffffffffe#192", "2.5243548967072377773175314089049159349542605923488736152645e-29", "0x1.fffffffffffffffffffffffffffffffffffffffffffffffeE-24#192", Nearest, "158456325028528675187087900672.0", "0x2000000000000000000000000.000000000000000000000000#192", Greater, ); // - exp_diff == prec && rm == Nearest && power in add_float_significands_same_prec_ge_3w test( "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", "2.6469779601696885595885078146238811314105987548828125e-23", "0x2.000000000000000000000000000000000000000000000000E-19#192", Nearest, "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", Less, ); // - 0 < exp_diff < prec && (rm == Floor || rm == Down || rm == Exact) in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Down, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - exp_diff == 0 && (rm == Floor || rm == Down) in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Down, "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Less, ); // - exp_diff == 0 && (rm == Ceiling || rm == Up) in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && (rm == Ceiling || rm == Up) && !carry in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Up, "2.0000000000000000000000000000000000000000000000000000000006", "0x2.000000000000000000000000000000000000000000000004#192", Greater, ); // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) // in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) // && !carry in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Up, "3.0000000000000000000000000000000000000000000000000000000006", "0x3.000000000000000000000000000000000000000000000004#192", Greater, ); // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Ceiling || rm == Up) // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Ceiling || rm == Up) && // !carry test( "6823.472967851766873629348006893003460678376513514025568927", "0x1aa7.79146bcf65e9c10b73dc31b712bdbba94db27f42827ee#192", "3.4171243258195824440860481554099490634319461554553884152664e-68", "0xe.bd75c60b3fb1b2daadd125b174611af23cd95ed37b18fd3E-57#192", Up, "6823.472967851766873629348006893003460678376513514025568928", "0x1aa7.79146bcf65e9c10b73dc31b712bdbba94db27f42827f0#192", Greater, ); // - exp_diff == prec && (rm == Ceiling || rm == Up) in add_float_significands_same_prec_ge_3w // - exp_diff == prec && (rm == Ceiling || rm == Up) && !carry in // add_float_significands_same_prec_ge_3w test( "1.1549982013361157285883413763473468330143594437077681839568e-64", "0xc.29de762f7d1efb4e2c76c8e4086645c726cd7efd160d9b2E-54#192", "7.183764682683218761534928278745259569270911336851315880289e-7", "0xc.0d6747ace11077b45ef60fe0663937937659be6facba820E-6#192", Up, "7.183764682683218761534928278745259569270911336851315880291e-7", "0xc.0d6747ace11077b45ef60fe0663937937659be6facba821E-6#192", Greater, ); // - exp_diff == prec && (rm == Floor || rm == Down) in add_float_significands_same_prec_ge_3w test( "1.633185017652497317802829911277029120405335932425346213043e-62", "0x6.b7f1cf4acb21f3fca0c966202fee44bb9bb293511aa1d780E-52#192", "0.00010303969992625256008619861293450462215178250710705317873879", "0x0.0006c0b8243103d1ef7ab2f1e9a66ec9ee623a5e72e237199db8#192", Floor, "0.00010303969992625256008619861293450462215178250710705317873879", "0x0.0006c0b8243103d1ef7ab2f1e9a66ec9ee623a5e72e237199db8#192", Less, ); // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Ceiling || rm == Up) && // carry test( "2.3509707655716138708899159999241985031053943929132983433321e-38", "0x7.fffc0007ffffffff0000000007ffffffffffffffffffffffE-32#195", "2.15679573337205118357336120696157045389097155380324579848825e68", "0x7.ffffffffffffffffffffffffffffffffffffffffffffffffE+56#195", Up, "2.1567957333720511835733612069615704538909715538032457984883e68", "0x8.000000000000000000000000000000000000000000000000E+56#195", Greater, ); // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) // && carry in add_float_significands_same_prec_ge_3w test( "8388607.9999999995343387126922607421875", "0x7fffff.fffffffe00000000000000000000000000000000000#192", "4.6566128730773925781249999999999999999999999999999999999993e-10", "0x1.fffffffffffffffffffffffffffffffffffffffffffffffeE-8#192", Up, "8388608.0", "0x800000.000000000000000000000000000000000000000000#192", Greater, ); // - exp_diff == prec && (rm == Ceiling || rm == Up) && carry in // add_float_significands_same_prec_ge_3w test( "511.9999999999999999999999999999999999999999999999999999999", "0x1ff.fffffffffffffffffffffffffffffffffffffffffffffe#192", "8.156630584998155601789981346010670828251902552640272418926e-56", "0x1.ffffffffffffff00001ffffffffffffff80003f003000000E-46#192", Up, "512.0", "0x200.0000000000000000000000000000000000000000000000#192", Greater, ); // - rm == Floor || rm == Down in add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Down, "2.0", "0x2.0#2", Less, ); // - rm == Ceiling || rm == Up in add_float_significands_same_prec_general_round // - (rm == Ceiling || rm == Up) && !carry in add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Up, "3.0", "0x3.0#2", Greater, ); // - (rm == Ceiling || rm == Up) && carry in add_float_significands_same_prec_general_round test( "2.0", "0x2.0#1", "1.5", "0x1.8#2", Up, "4.0", "0x4.0#2", Greater, ); // - shift2 == 0 in add_float_significands_same_prec_general // - y in add_float_significands_same_prec_general // - shift != 0 in add_float_significands_same_prec_general // - x == 0 first time in add_float_significands_same_prec_general // - shift == 0 || following_bits != Uninitialized in add_float_significands_same_prec_general // - round_bit != Uninitialized || shift == 0 in add_float_significands_same_prec_general // - exp_diff_rem == 0 && yi == 0 second time in add_float_significands_same_prec_general // - round_bit != Uninitialized sixth time in add_float_significands_same_prec_general test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Nearest, "2.0", "0x2.0#2", Equal, ); // - following_bits != False || round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit == 0 in // add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Nearest, "2.0", "0x2.0#2", Less, ); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && carry in // add_float_significands_same_prec_general_round test( "2.0", "0x2.0#1", "1.5", "0x1.8#2", Nearest, "4.0", "0x4.0#2", Greater, ); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.8", "0x1.c#3", Nearest, "3.0", "0x3.0#3", Greater, ); // - x != 0 && x != mask second time in add_float_significands_same_prec_general // - rm == Nearest && following_bits != False && round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits != False && round_bit != False && !carry in // add_float_significands_same_prec_general_round test( "1.5", "0x1.8#2", "4.0", "0x4.0#1", Nearest, "6.0", "0x6.0#2", Greater, ); // - rm == Nearest && following_bits != False && round_bit == False in // add_float_significands_same_prec_general_round test( "4.0", "0x4.0#1", "1.2", "0x1.4#3", Nearest, "5.0", "0x5.0#3", Less, ); // - x != 0 && x != mask first time in add_float_significands_same_prec_general // - shift != 0 && following_bits == Uninitialized in add_float_significands_same_prec_general test( "1.2", "0x1.4#3", "3.0", "0x3.0#2", Nearest, "4.0", "0x4.0#3", Less, ); // - rm == Nearest && following_bits != False && round_bit != False && carry in // add_float_significands_same_prec_general_round test( "1.8", "0x1.c#3", "6.0", "0x6.0#2", Nearest, "8.0", "0x8.0#3", Greater, ); // - out_bits <= exp_diff in add_float_significands_same_prec_general // - out_len <= xs_len first time in add_float_significands_same_prec_general // - difw > 0 && difw > ys_len && exp_diff > out_bits in // add_float_significands_same_prec_general // - round_bit != Uninitialized fifth time in add_float_significands_same_prec_general test( "8.82188e11", "0xc.d668E+9#18", "9.75459983374e122", "0x1.79c17f063aE+102#40", Nearest, "9.75459983374e122", "0x1.79c17f063aE+102#40", Less, ); // - out_len > xs_len first time in add_float_significands_same_prec_general test( "2.8577648979177105962332201291018926848163080599637e-19", "0x5.458a93bffa7b1c05bdd1c0552b60196746d9083cE-16#162", "3.569720699507868e50", "0xf.4400d3acf388E+41#51", Nearest, "3.5697206995078675404584127554321345196383736430592e50", "0xf.4400d3acf3880000000000000000000000000000E+41#162", Less, ); // - overlap > ys_len in add_float_significands_same_prec_general // - out_len - k > overlap in add_float_significands_same_prec_general // - difw <= 0 || difw <= ys_len in add_float_significands_same_prec_general // - round_bit != Uninitialized fourth time in add_float_significands_same_prec_general test( "29780282551.762684458936866363165", "0x6ef0b0cb7.c33f49e84d21bb6040#104", "0.00003945598947538", "0x0.000295f62f36adb#46", Nearest, "29780282551.762723914926341743141", "0x6ef0b0cb7.c341dfde7c58691040#104", Equal, ); // - out_len > xs_len second time in add_float_significands_same_prec_general test( "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222828352849", "0x0.00f5402c178824#46", Nearest, "0.00374222829424688982311482391965285", "0x0.00f5402c235119eafa12eb9821602#107", Greater, ); // - exp_diff_rem == 0 second time in add_float_significands_same_prec_general test( "5.19192095203e-15", "0x1.761e097c5E-12#37", "7.4e4", "0x1.2E+4#5", Nearest, "73728.0", "0x12000.00000#37", Less, ); // - shift <= 1 in add_float_significands_same_prec_general test( "15135.895602865542606017656527713819177465060416097749360065", "0x3b1f.e5463ab9b599ce49b83c7988b324dc93ce50b2ed51a18#191", "3.581529624499970047886732225242180736649e-8", "0x9.9d355ad2b99a587727da095fa3226bf0E-7#130", Nearest, "15135.895602901357902262656228192686499717482223464235884113", "0x3b1f.e5463b5388ef7b7551e200fb30c5728e007771ed51a18#191", Equal, ); // - round_bit == Uninitialized fourth time in add_float_significands_same_prec_general // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "8.63643735016344467819174862798332593462e-6", "0x0.000090e5374a001358c6606f968bf3813ad9#128", "1.84904e-8", "0x4.f6a6E-7#18", Nearest, "8.65492771851100147411665059026359937212e-6", "0x0.00009134a1aa001358c6606f968bf3813ad9#128", Equal, ); // - round_bit == Uninitialized fifth time in add_float_significands_same_prec_general test( "2.389545997e25", "0x1.3c40f7bE+21#29", "0.078263259824284000402", "0x0.14090f9d6c745bc06#64", Nearest, "2.389545996756557709e25", "0x1.3c40f7b000000000E+21#64", Less, ); // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "5.7505515877842013577e-7", "0x9.a5d7d56cabed47dE-6#64", "1.1758894e-14", "0x3.4f515E-12#22", Nearest, "5.7505517053731436845e-7", "0x9.a5d7d8bbfd3d47dE-6#64", Equal, ); // - x != 0 && x == mask second time in add_float_significands_same_prec_general // - xs_len <= out_len && following_bits == True in add_float_significands_same_prec_general test( "1.081090215247020702e-18", "0x1.3f14ddfe22c0634E-15#59", "6.3799657596147e-8", "0x1.12047722d26cE-6#47", Nearest, "6.37996575972280156e-8", "0x1.12047722e65d4dcE-6#59", Less, ); // - shift == 0 in add_float_significands_same_prec_general test( "4.3055451539258443718732375731462554408177909736937057433067e-16", "0x1.f06543668e6018c20c17efed72ff6d3d65a4c5dc9db475b0E-13#192", "1.6388436e-15", "0x7.61754E-13#21", Nearest, "2.0693980969049410047184094732421002104686218250305033868307e-15", "0x9.51da83668e6018c20c17efed72ff6d3d65a4c5dc9db475bE-13#192", Equal, ); // - yi != 0 second time in add_float_significands_same_prec_general test( "2.24181435676546e-16", "0x1.0276ae5de1e8E-13#47", "7.6430700039878539638425372386462404393e-36", "0xa.28cd4cb186f5925ddb0d1ecb9681103E-30#128", Nearest, "2.24181435676546206911083333246297446029e-16", "0x1.0276ae5de1e80000a28cd4cb186f5926E-13#128", Greater, ); // - x != 0 && x == mask first time in add_float_significands_same_prec_general test( "2.1474796e9", "0x7.ffff00E+7#24", "8191.9998788833609", "0x1fff.fff80fffff0#54", Nearest, "2147487743.9998789", "0x80000fff.fff810#54", Greater, ); } #[test] fn add_round_fail() { assert_panic!(Float::one_prec(1).add_round(Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).add_round_val_ref(&Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).add_round_ref_val(Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).add_round_ref_ref(&Float::two_prec(1), Exact)); assert_panic!(parse_hex_string("0x1.0#1").add_round(parse_hex_string("0x0.001#1"), Exact)); assert_panic!( parse_hex_string("0x1.0#1").add_round_val_ref(&parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0#1").add_round_ref_val(parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0#1").add_round_ref_ref(&parse_hex_string("0x0.001#1"), Exact) ); assert_panic!(parse_hex_string("0x1.0000000000000000#64") .add_round(parse_hex_string("0x1.0000000000000002#64"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#64") .add_round_val_ref(&parse_hex_string("0x1.0000000000000002#64"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#64") .add_round_ref_val(parse_hex_string("0x1.0000000000000002#64"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#64") .add_round_ref_ref(&parse_hex_string("0x1.0000000000000002#64"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#65") .add_round(parse_hex_string("0x1.0000000000000001#65"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#65") .add_round_val_ref(&parse_hex_string("0x1.0000000000000001#65"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#65") .add_round_ref_val(parse_hex_string("0x1.0000000000000001#65"), Exact)); assert_panic!(parse_hex_string("0x1.0000000000000000#65") .add_round_ref_ref(&parse_hex_string("0x1.0000000000000001#65"), Exact)); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round( parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round_val_ref( &parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round_ref_val( parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round_ref_ref( &parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round( parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round_val_ref( &parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round_ref_val( parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round_ref_ref( &parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192").add_round( parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .add_round_val_ref( &parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .add_round_ref_val( parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .add_round_ref_ref( &parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!(parse_hex_string("0x1.0#1").add_round(parse_hex_string("0x1.8#2"), Exact)); assert_panic!( parse_hex_string("0x1.0#1").add_round_val_ref(&parse_hex_string("0x1.8#2"), Exact) ); assert_panic!({ parse_hex_string("0x1.0#1").add_round_ref_val(parse_hex_string("0x1.8#2"), Exact) }); assert_panic!( parse_hex_string("0x1.0#1").add_round_ref_ref(&parse_hex_string("0x1.8#2"), Exact) ); assert_panic!({ let mut x = Float::one_prec(1); x.add_round_assign(Float::two_prec(1), Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_round_assign_ref(&Float::two_prec(1), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign(parse_hex_string("0x0.001#1"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign_ref(&parse_hex_string("0x0.001#1"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#64"); x.add_round_assign(parse_hex_string("0x1.0000000000000002#64"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#64"); x.add_round_assign_ref(&parse_hex_string("0x1.0000000000000002#64"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#65"); x.add_round_assign(parse_hex_string("0x1.0000000000000001#65"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#65"); x.add_round_assign_ref(&parse_hex_string("0x1.0000000000000001#65"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#128"); x.add_round_assign( parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#128"); x.add_round_assign_ref( &parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#129"); x.add_round_assign( parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#129"); x.add_round_assign_ref( &parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192"); x.add_round_assign( parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192"); x.add_round_assign_ref( &parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign(parse_hex_string("0x1.8#2"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign_ref(&parse_hex_string("0x1.8#2"), Exact) }); } #[test] fn test_add_prec_round() { let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (sum, o) = x.clone().add_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); assert_eq!(o, o_out); let (sum_alt, o_alt) = x.clone().add_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_round_assign(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_round_assign_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); // Note different behavior for Floor test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); // Note different behavior for Floor test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "4.56", "0x4.90#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "4.56", "0x4.90#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-1.729", "-0x1.ba8#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-1.727", "-0x1.ba0#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-1.727", "-0x1.ba0#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-1.729", "-0x1.ba8#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-1.727", "-0x1.ba0#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "1.729", "0x1.ba8#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "1.729", "0x1.ba8#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-4.56", "-0x4.90#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-4.555", "-0x4.8e#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-4.555", "-0x4.8e#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-4.56", "-0x4.90#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-4.555", "-0x4.8e#10", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Floor, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Ceiling, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Down, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Up, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Nearest, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Exact, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Exact, "0.0", "0x0.0", Equal, ); // - exp_diff_rem == 0 && yi == 0 first time in add_float_significands_same_prec_general test( "0.000487804412841796875000000000000000000000000000000000000000291703841149741293879771765\ 542", "0x0.001ff8000000000000000000000000000000000000000000007800000000001fffffffffffe#288", "0.000488281249999997", "0x0.001fffffffffffc#47", 53, Ceiling, "0.0009760856628417935", "0x0.003ff7ffffffffc2#53", Greater, ); test( "0.000488281249999997", "0x0.001fffffffffffc#47", "0.000487804412841796875000000000000000000000000000000000000000291703841149741293879771765\ 542", "0x0.001ff8000000000000000000000000000000000000000000007800000000001fffffffffffe#288", 53, Ceiling, "0.0009760856628417935", "0x0.003ff7ffffffffc2#53", Greater, ); // - round_bit != Uninitialized third time in add_float_significands_same_prec_general test( "54004143877011445683.03364332940006328475124657021", "0x2ed7542badc5a97b3.089cd9678077bdca8dabe52c#160", "8.0", "0x8.0#1", 127, Up, "54004143877011445691.033643329400063285", "0x2ed7542badc5a97bb.089cd9678077bdd0#127", Greater, ); } #[test] fn add_prec_round_fail() { assert_panic!(Float::one_prec(1).add_prec_round(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).add_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).add_prec_round_ref_val(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).add_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign(Float::two_prec(1), 0, Floor) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) }); assert_panic!(Float::one_prec(1).add_prec_round(Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).add_prec_round_val_ref(&Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).add_prec_round_ref_val(Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).add_prec_round_ref_ref(&Float::two_prec(1), 1, Exact)); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign(Float::two_prec(1), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign_ref(&Float::two_prec(1), 1, Exact) }); } #[test] fn test_add_rational() { let test = |s, s_hex, t, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let sum = x.clone() + y.clone(); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = y.clone() + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = y.clone() + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &y + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &y + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_add_rational( &rug::Float::exact_from(&x), &rug::Rational::from(&y) ))), ComparableFloatRef(&sum) ); let sum_alt = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); }; test("NaN", "NaN", "123", "NaN", "NaN"); test("Infinity", "Infinity", "123", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "123", "-Infinity", "-Infinity"); test("0.0", "0x0.0", "0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "123", "1.0e2", "0x8.0E+1#1"); test("-0.0", "-0x0.0", "123", "1.0e2", "0x8.0E+1#1"); test("0.0", "0x0.0", "1/3", "0.2", "0x0.4#1"); test("-0.0", "-0x0.0", "1/3", "0.2", "0x0.4#1"); test("123.0", "0x7b.0#7", "0", "123.0", "0x7b.0#7"); test("1.0", "0x1.0#1", "2", "4.0", "0x4.0#1"); test("1.0", "0x1.0#2", "2", "3.0", "0x3.0#2"); test("1.0", "0x1.000#10", "2", "3.0", "0x3.00#10"); test("1.0", "0x1.000#10", "1/3", "1.334", "0x1.558#10"); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", "3.4749259869231266", "0x3.7994bfdddaf86#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", "2.8082593202564596", "0x2.ceea1533304da#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", "-2.8082593202564596", "-0x2.ceea1533304da#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", "-3.4749259869231266", "-0x3.7994bfdddaf86#53", ); test("1.0", "0x1.0#1", "1/50000", "1.0", "0x1.0#1"); test("1.0", "0x1.0#1", "-1", "0.0", "0x0.0"); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", "1.832e180", "0x7.10E+149#10", ); test("1.0", "0x1.0#1", "0", "1.0", "0x1.0#1"); // - o == Equal in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1", "2.0", "0x2.0#1"); // - o != Equal in add_rational_prec_round_assign_helper // - t != 0 in add_rational_prec_round_assign_helper // - small Natural in float_can_round // - err0 > prec && err > prec in float_can_round // - s != Limb::WIDTH first time in float_can_round // - n == 0 in float_can_round // - float_can_round in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1/3", "1.0", "0x1.0#1"); // - large Natural in float_can_round // - n != 0 && tmp != 0 && tmp != mask in float_can_round test( "269104312292334.303", "0xf4bfbaf113ee.4d8#57", "517543599148951977/6042448266342026218192", "269104312292334.303", "0xf4bfbaf113ee.4d8#57", ); // - s == Limb::WIDTH first time in float_can_round test( "1.1595752615776271305e-33", "0x6.055703bef650178E-28#63", "-2457795567751474853961645492284796573970712506001349310379799846240055987994196472114730\ 61298054082441720799/23", "-1.0686067685875977626e106", "-0x1.2a31c100f5e98110E+88#63", ); // - !float_can_round in add_rational_prec_round_assign_helper // - n != 0 && tmp == 0 in float_can_round // - n <= 0 first time in float_can_round // - s != Limb::WIDTH second time in float_can_round // - n > 0 first time in float_can_round // - x == 0 in float_can_round // - x != 0 in float_can_round test( "5.82156e33", "0x1.1f066E+28#20", "8238723/1413731881599214931", "5.82156e33", "0x1.1f066E+28#20", ); // - n != 0 && tmp != 0 && tmp == mask in float_can_round // - n <= 0 second time in float_can_round // - s != Limb::WIDTH third time in float_can_round test( "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", "-3183521742267703581572109801877979/35801077870645726", "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", ); // - s == Limb::WIDTH second time in float_can_round // - n > 0 second time in float_can_round // - x == Limb::MAX in float_can_round test( "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", "-808694/11557016618486698036897716112870533564271922504817764249868611771", "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", ); // - x != Limb::MAX in float_can_round test( "4.9046e10", "0xb.6b5eE+8#19", "-182971083215/47776579472461276067598384651239241670113870043", "4.9046e10", "0xb.6b5eE+8#19", ); // - s == Limb::WIDTH third time in float_can_round test( "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", "-3161/286335616056113777", "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", ); // - err0 <= prec || err <= prec in float_can_round test( "5.96046446e-8", "0xf.ffffffE-7#28", "-255/4261412864", "-2.34664179e-10", "-0x1.0204182E-8#28", ); // - t == 0 in add_rational_prec_round_assign_helper test( "64.0", "0x40.00000#24", "-215679573337202053366254388918461596342975394375083745820919489101824/336999333319768176\ 9435117813341997219028918889483691361889027096575", "-3.7241676e-9", "-0xf.fec40E-8#24", ); } #[test] fn test_add_rational_prec() { let test = |s, s_hex, t, prec, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (sum, o) = x.clone().add_rational_prec(y.clone(), prec); assert!(sum.is_valid()); assert_eq!(o, o_out); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let (sum_alt, o_alt) = x.clone().add_rational_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_assign(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_assign_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (rug_sum, rug_o) = rug_add_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("-0.0", "-0x0.0", "123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("0.0", "0x0.0", "1/3", 1, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", 1, "0.2", "0x0.4#1", Less); test("123.0", "0x7b.0#7", "0", 1, "1.0e2", "0x8.0E+1#1", Greater); test("1.0", "0x1.0#1", "2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 2, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#2", "2", 2, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.000#10", "2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.000#10", "2", 2, "3.0", "0x3.0#2", Equal); test( "1.0", "0x1.000#10", "1/3", 100, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, "2.809", "0x2.cf#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, "-3.477", "-0x3.7a#10", Less, ); test("1.0", "0x1.0#1", "1/50000", 10, "1.0", "0x1.000#10", Less); test("1.0", "0x1.0#1", "-1", 10, "0.0", "0x0.0", Equal); test( "4.547473508864641189582899002890190173e-13", "0x8.00000000000000003ffff000000000E-11#123", "-4194304/9223372019742015487", 3, "-8.0e-22", "-0x4.0E-18#3", Less, ); } #[test] fn add_rational_prec_fail() { assert_panic!(Float::NAN.add_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::NAN.add_rational_prec_val_ref(&Rational::ZERO, 0)); assert_panic!(Float::NAN.add_rational_prec_ref_val(Rational::ZERO, 0)); assert_panic!(Float::NAN.add_rational_prec_ref_ref(&Rational::ZERO, 0)); assert_panic!({ let mut x = Float::NAN; x.add_rational_prec_assign(Rational::ZERO, 0) }); assert_panic!({ let mut x = Float::NAN; x.add_rational_prec_assign_ref(&Rational::ZERO, 0) }); } #[test] fn test_add_rational_round() { let test = |s, s_hex, t, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (sum, o) = x.clone().add_rational_round(y.clone(), rm); assert!(sum.is_valid()); assert_eq!(o, o_out); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let (sum_alt, o_alt) = x.clone().add_rational_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_round_assign(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_round_assign_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "123", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", Floor, "6.0e1", "0x4.0E+1#1", Less); test( "0.0", "0x0.0", "123", Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "123", Down, "6.0e1", "0x4.0E+1#1", Less); test("0.0", "0x0.0", "123", Up, "1.0e2", "0x8.0E+1#1", Greater); test( "0.0", "0x0.0", "123", Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("-0.0", "-0x0.0", "123", Floor, "6.0e1", "0x4.0E+1#1", Less); test( "-0.0", "-0x0.0", "123", Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("-0.0", "-0x0.0", "123", Down, "6.0e1", "0x4.0E+1#1", Less); test("-0.0", "-0x0.0", "123", Up, "1.0e2", "0x8.0E+1#1", Greater); test( "-0.0", "-0x0.0", "123", Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("123.0", "0x7b.0#7", "0", Floor, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "0", Down, "123.0", "0x7b.0#7", Equal); test("123.0", "0x7b.0#7", "0", Up, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Nearest, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "0", Exact, "123.0", "0x7b.0#7", Equal); test("0.0", "0x0.0", "1/3", Floor, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", Ceiling, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", Down, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", Up, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", Nearest, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", Floor, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", Ceiling, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "1/3", Down, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", Up, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "1/3", Nearest, "0.2", "0x0.4#1", Less); test("1.0", "0x1.0#1", "2", Floor, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", Ceiling, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", Down, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", Up, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", Nearest, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#2", "2", Floor, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Ceiling, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Down, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Up, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Nearest, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Exact, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.000#10", "2", Floor, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Ceiling, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Down, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Up, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Nearest, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Exact, "3.0", "0x3.00#10", Equal); test( "1.0", "0x1.000#10", "1/3", Floor, "1.332", "0x1.550#10", Less, ); test( "1.0", "0x1.000#10", "1/3", Ceiling, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", Down, "1.332", "0x1.550#10", Less, ); test( "1.0", "0x1.000#10", "1/3", Up, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", Nearest, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Floor, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Ceiling, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Down, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Up, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Nearest, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Floor, "3.4749259869231262", "0x3.7994bfdddaf84#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Ceiling, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Down, "3.4749259869231262", "0x3.7994bfdddaf84#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Up, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Nearest, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Floor, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Ceiling, "2.8082593202564601", "0x2.ceea1533304dc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Down, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Up, "2.8082593202564601", "0x2.ceea1533304dc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Nearest, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Floor, "-2.8082593202564601", "-0x2.ceea1533304dc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Ceiling, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Down, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Up, "-2.8082593202564601", "-0x2.ceea1533304dc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Nearest, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Floor, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Ceiling, "-3.4749259869231262", "-0x3.7994bfdddaf84#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Down, "-3.4749259869231262", "-0x3.7994bfdddaf84#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Up, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Nearest, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test("1.0", "0x1.0#1", "1/50000", Floor, "1.0", "0x1.0#1", Less); test( "1.0", "0x1.0#1", "1/50000", Ceiling, "2.0", "0x2.0#1", Greater, ); test("1.0", "0x1.0#1", "1/50000", Down, "1.0", "0x1.0#1", Less); test("1.0", "0x1.0#1", "1/50000", Up, "2.0", "0x2.0#1", Greater); test("1.0", "0x1.0#1", "1/50000", Nearest, "1.0", "0x1.0#1", Less); test("1.0", "0x1.0#1", "-1", Floor, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Exact, "0.0", "0x0.0", Equal); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Floor, "1.83e180", "0x7.0eE+149#10", Less, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Ceiling, "1.832e180", "0x7.10E+149#10", Greater, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Down, "1.83e180", "0x7.0eE+149#10", Less, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Up, "1.832e180", "0x7.10E+149#10", Greater, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Nearest, "1.832e180", "0x7.10E+149#10", Greater, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Nearest, "1.832e180", "0x7.10E+149#10", Greater, ); test("1.0", "0x1.0#1", "0", Nearest, "1.0", "0x1.0#1", Equal); // - o == Equal in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1", Nearest, "2.0", "0x2.0#1", Equal); // - o != Equal in add_rational_prec_round_assign_helper // - t != 0 in add_rational_prec_round_assign_helper // - small Natural in float_can_round // - err0 > prec && err > prec in float_can_round // - s != Limb::WIDTH first time in float_can_round // - n == 0 in float_can_round // - float_can_round in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1/3", Nearest, "1.0", "0x1.0#1", Less); // - large Natural in float_can_round // - n != 0 && tmp != 0 && tmp != mask in float_can_round test( "269104312292334.303", "0xf4bfbaf113ee.4d8#57", "517543599148951977/6042448266342026218192", Nearest, "269104312292334.303", "0xf4bfbaf113ee.4d8#57", Less, ); // - s == Limb::WIDTH first time in float_can_round test( "1.1595752615776271305e-33", "0x6.055703bef650178E-28#63", "-2457795567751474853961645492284796573970712506001349310379799846240055987994196472114730\ 61298054082441720799/23", Nearest, "-1.0686067685875977626e106", "-0x1.2a31c100f5e98110E+88#63", Less, ); // - !float_can_round in add_rational_prec_round_assign_helper // - n != 0 && tmp == 0 in float_can_round // - n <= 0 first time in float_can_round // - s != Limb::WIDTH second time in float_can_round // - n > 0 first time in float_can_round // - x == 0 in float_can_round // - x != 0 in float_can_round test( "5.82156e33", "0x1.1f066E+28#20", "8238723/1413731881599214931", Nearest, "5.82156e33", "0x1.1f066E+28#20", Less, ); // - n != 0 && tmp != 0 && tmp == mask in float_can_round // - n <= 0 second time in float_can_round // - s != Limb::WIDTH third time in float_can_round test( "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", "-3183521742267703581572109801877979/35801077870645726", Nearest, "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", Greater, ); // - s == Limb::WIDTH second time in float_can_round // - n > 0 second time in float_can_round // - x == Limb::MAX in float_can_round test( "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", "-808694/11557016618486698036897716112870533564271922504817764249868611771", Nearest, "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", Greater, ); // - x != Limb::MAX in float_can_round test( "4.9046e10", "0xb.6b5eE+8#19", "-182971083215/47776579472461276067598384651239241670113870043", Nearest, "4.9046e10", "0xb.6b5eE+8#19", Greater, ); // - s == Limb::WIDTH third time in float_can_round test( "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", "-3161/286335616056113777", Nearest, "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", Greater, ); // - err0 <= prec || err <= prec in float_can_round test( "5.96046446e-8", "0xf.ffffffE-7#28", "-255/4261412864", Nearest, "-2.34664179e-10", "-0x1.0204182E-8#28", Less, ); // - t == 0 in add_rational_prec_round_assign_helper test( "64.0", "0x40.00000#24", "-215679573337202053366254388918461596342975394375083745820919489101824/336999333319768176\ 9435117813341997219028918889483691361889027096575", Nearest, "-3.7241676e-9", "-0xf.fec40E-8#24", Greater, ); } #[test] fn add_rational_round_fail() { assert_panic!(Float::one_prec(1).add_rational_round(Rational::from_unsigneds(1u32, 3), Exact)); assert_panic!( Float::one_prec(1).add_rational_round_val_ref(&Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!( Float::one_prec(1).add_rational_round_ref_val(Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!( Float::one_prec(1).add_rational_round_ref_ref(&Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_round_assign(Rational::from_unsigneds(1u32, 3), Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_round_assign_ref(&Rational::from_unsigneds(1u32, 3), Exact) }); } #[test] fn test_add_rational_prec_round() { let test = |s, s_hex, t, prec, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (sum, o) = x.clone().add_rational_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); assert_eq!(o, o_out); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let (sum_alt, o_alt) = x.clone().add_rational_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_round_assign(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_round_assign_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less); test( "0.0", "0x0.0", "123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "123", 1, Down, "6.0e1", "0x4.0E+1#1", Less); test("0.0", "0x0.0", "123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater); test( "0.0", "0x0.0", "123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", 1, Down, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "-0.0", "-0x0.0", "1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test("-0.0", "-0x0.0", "1/3", 1, Down, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "123.0", "0x7b.0#7", "0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("1.0", "0x1.0#1", "2", 1, Floor, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", 1, Ceiling, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 1, Down, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", 1, Up, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 1, Nearest, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 2, Floor, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Ceiling, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Down, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Up, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Nearest, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Exact, "3.0", "0x3.0#2", Equal); test( "1.0", "0x1.000#10", "1/3", 100, Floor, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.000#10", "1/3", 100, Ceiling, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.000#10", "1/3", 100, Down, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.000#10", "1/3", 100, Up, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.000#10", "1/3", 100, Nearest, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Floor, "3.473", "0x3.79#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Down, "3.473", "0x3.79#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Up, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Nearest, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Floor, "2.805", "0x2.ce#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "2.809", "0x2.cf#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Down, "2.805", "0x2.ce#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Up, "2.809", "0x2.cf#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "2.809", "0x2.cf#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Floor, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "-2.805", "-0x2.ce#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Down, "-2.805", "-0x2.ce#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Up, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Nearest, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Floor, "-3.477", "-0x3.7a#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "-3.473", "-0x3.79#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Down, "-3.473", "-0x3.79#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Up, "-3.477", "-0x3.7a#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "-3.477", "-0x3.7a#10", Less, ); test( "1.0", "0x1.0#1", "1/50000", 10, Floor, "1.0", "0x1.000#10", Less, ); test( "1.0", "0x1.0#1", "1/50000", 10, Ceiling, "1.002", "0x1.008#10", Greater, ); test( "1.0", "0x1.0#1", "1/50000", 10, Down, "1.0", "0x1.000#10", Less, ); test( "1.0", "0x1.0#1", "1/50000", 10, Up, "1.002", "0x1.008#10", Greater, ); test( "1.0", "0x1.0#1", "1/50000", 10, Nearest, "1.0", "0x1.000#10", Less, ); test("1.0", "0x1.0#1", "-1", 10, Floor, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Exact, "0.0", "0x0.0", Equal); } #[test] fn add_rational_prec_round_fail() { assert_panic!(Float::one_prec(1).add_rational_prec_round( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).add_rational_prec_round_val_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).add_rational_prec_round_ref_val( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).add_rational_prec_round_ref_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_prec_round_assign(Rational::from_unsigneds(5u32, 8), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(5u32, 8), 1, Exact) }); } #[test] fn add_prec_round_properties() { float_float_unsigned_rounding_mode_quadruple_gen_var_1().test_properties(|(x, y, prec, rm)| { let (sum, o) = x.clone().add_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_prec_round_ref_ref(&x, y.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(y.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat( sum.sub_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); } let r_sum = if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } Some(r_sum) } else { assert_eq!(o, Equal); None }; match (r_sum.is_some() && *r_sum.as_ref().unwrap() >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } let (sum_alt, o_alt) = y.add_prec_round_ref_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.sub_prec_round_ref_val(-&y, prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).sub_prec_round_val_ref(&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).add_prec_round(-&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_prec_round_ref_ref(&y, prec, Exact)); } }); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (sum, o) = x.add_prec_round_ref_val(Float::NAN, prec, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); let (sum, o) = Float::NAN.add_prec_round_val_ref(&x, prec, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!( x.add_prec_round_ref_val(Float::INFINITY, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::INFINITY.add_prec_round_val_ref(&x, prec, rm), (Float::INFINITY, Equal) ); } if x != Float::INFINITY { assert_eq!( x.add_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_prec_round_val_ref(&x, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (sum, o) = x.add_prec_round_ref_val(Float::ZERO, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::ZERO.add_prec_round_val_ref(&x, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } if rm != Floor || !x.is_positive_zero() { let (sum, o) = x.add_prec_round_ref_val(Float::NEGATIVE_ZERO, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_prec_round_val_ref(&x, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } }); } #[test] fn add_prec_properties() { float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { let (sum, o) = x.clone().add_prec(y.clone(), prec); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (rug_sum, rug_o) = rug_add_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_prec_ref_ref(&x, y.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(y.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat( sum.sub_prec_ref_ref(&y, x.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); } if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } else { assert_eq!(o, Equal); } let (sum_alt, o_alt) = y.add_prec_ref_ref(&x, prec); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.sub_prec_ref_val(-&y, prec); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let (mut sum_alt, mut o_alt) = (-&x).sub_prec_val_ref(&y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-x).add_prec(-y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { let (sum, o) = x.add_prec_ref_val(Float::NAN, prec); assert!(sum.is_nan()); assert_eq!(o, Equal); let (sum, o) = Float::NAN.add_prec_val_ref(&x, prec); assert!(sum.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!( x.add_prec_ref_val(Float::INFINITY, prec), (Float::INFINITY, Equal) ); assert_eq!( Float::INFINITY.add_prec_val_ref(&x, prec), (Float::INFINITY, Equal) ); } if x != Float::INFINITY { assert_eq!( x.add_prec_ref_val(Float::NEGATIVE_INFINITY, prec), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_prec_val_ref(&x, prec), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (sum, o) = x.add_prec_ref_val(Float::ZERO, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::ZERO.add_prec_val_ref(&x, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } let (sum, o) = x.add_prec_ref_val(Float::NEGATIVE_ZERO, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_prec_val_ref(&x, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn add_round_properties_helper(x: Float, y: Float, rm: RoundingMode) { let (sum, o) = x.clone().add_round(y.clone(), rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); let o_alt = x_alt.add_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if o == Equal && sum.is_finite() { assert_eq!(sum.sub_round_ref_ref(&x, Exact).0, y); assert_eq!(sum.sub_round_ref_ref(&y, Exact).0, x); } let r_sum = if sum.is_finite() { if x.is_normal() && y.is_normal() && sum.is_normal() { assert_eq!( sum.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); } let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } Some(r_sum) } else { assert_eq!(o, Equal); None }; match (r_sum.is_some() && *r_sum.as_ref().unwrap() >= 0u32, 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 let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = y.add_round_ref_ref(&x, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.sub_round_ref_val(-&y, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (mut sum_alt, mut o_alt) = (-&x).sub_round_val_ref(&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); let (mut sum_alt, mut o_alt) = (-&x).add_round(-&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_round_ref_ref(&y, Exact)); } } #[test] fn add_round_properties() { float_float_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_float_rounding_mode_triple_gen_var_4().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_float_rounding_mode_triple_gen_var_5().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_float_rounding_mode_triple_gen_var_6().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_float_rounding_mode_triple_gen_var_7().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_float_rounding_mode_triple_gen_var_8().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_float_rounding_mode_triple_gen_var_9().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (sum, o) = x.add_round_ref_val(Float::NAN, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); let (sum, o) = Float::NAN.add_round_val_ref(&x, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!( x.add_round_ref_val(Float::INFINITY, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::INFINITY.add_round_val_ref(&x, rm), (Float::INFINITY, Equal) ); } if x != Float::INFINITY { assert_eq!( x.add_round_ref_val(Float::NEGATIVE_INFINITY, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_round_val_ref(&x, rm), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (sum, o) = x.add_round_ref_val(Float::ZERO, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); let (sum, o) = Float::ZERO.add_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); } if rm != Floor || !x.is_positive_zero() { let (sum, o) = x.add_round_ref_val(Float::NEGATIVE_ZERO, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); let (sum, o) = Float::NEGATIVE_ZERO.add_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); } }); } #[allow(clippy::type_repetition_in_bounds)] fn add_properties_helper_1() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_pair_gen::().test_properties(|(x, y)| { let sum_1 = x + y; let sum_2 = emulate_primitive_float_fn_2(|x, y, prec| x.add_prec(y, prec).0, x, y); assert_eq!(NiceFloat(sum_1), NiceFloat(sum_2)); }); } #[allow(clippy::needless_pass_by_value)] fn add_properties_helper_2(x: Float, y: Float) { let sum = x.clone() + y.clone(); assert!(sum.is_valid()); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); let sum_alt = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x .add_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x .add_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o) = x.add_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if o == Equal && sum.is_finite() { assert_eq!(&sum - &x, y); assert_eq!(&sum - &y, x); } if sum.is_finite() && x.is_normal() && y.is_normal() && sum.is_normal() { assert_eq!( sum.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); if sum < r_sum { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if sum > r_sum { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } let rug_sum = rug_add(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); let sum_alt = &y + &x; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x - -&y; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let sum_alt = (-(-&x - &y)).abs_negative_zero(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = (-(-&x + -&y)).abs_negative_zero(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); } // example of associativity failure: 0x1.0#1 0x2.0#1 -0x1.0#1 } #[test] fn add_properties() { float_pair_gen().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); float_pair_gen_var_2().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); float_pair_gen_var_3().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); float_pair_gen_var_4().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); float_pair_gen_var_5().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); float_pair_gen_var_6().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); float_pair_gen_var_7().test_properties(|(x, y)| { add_properties_helper_2(x, y); }); apply_fn_to_primitive_floats!(add_properties_helper_1); float_gen().test_properties(|x| { assert!((&x + Float::NAN).is_nan()); assert!((Float::NAN + &x).is_nan()); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!(&x + Float::INFINITY, Float::INFINITY); assert_eq!(Float::INFINITY + &x, Float::INFINITY); } if x != Float::INFINITY { assert_eq!(&x + Float::NEGATIVE_INFINITY, Float::NEGATIVE_INFINITY); assert_eq!(Float::NEGATIVE_INFINITY + &x, Float::NEGATIVE_INFINITY); } } if !x.is_negative_zero() { assert_eq!( ComparableFloatRef(&(&x + Float::ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Float::ZERO + &x)), ComparableFloatRef(&x) ); } assert_eq!( ComparableFloatRef(&(&x + Float::NEGATIVE_ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Float::NEGATIVE_ZERO + &x)), ComparableFloatRef(&x) ); assert_eq!(ComparableFloat(&x + &x), ComparableFloat(x << 1u32)); }); } #[test] fn add_rational_prec_round_properties() { float_rational_unsigned_rounding_mode_quadruple_gen_var_1().test_properties( |(x, y, prec, rm)| { let (sum, o) = x.clone().add_rational_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_rational_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); // TODO additional test } let r_sum = if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } let r_sum = Rational::exact_from(&x) + &y; assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } Some(r_sum) } else { assert_eq!(o, Equal); None }; match (r_sum.is_some() && *r_sum.as_ref().unwrap() >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } let (sum_alt, o_alt) = x.sub_rational_prec_round_ref_val(-&y, prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).sub_rational_prec_round_val_ref(&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).add_rational_prec_round(-&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_rational_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { // QQQ assert_panic!(x.add_rational_prec_round_ref_ref(&y, prec, Exact)); } }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_negative_zero() { let (sum, o) = x.add_rational_prec_round_ref_val(Rational::ZERO, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (sum, o) = Float::NAN.add_rational_prec_round_val_ref(&x, prec, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.add_rational_prec_round_val_ref(&x, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_rational_prec_round_val_ref(&x, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (sum, o) = Float::ZERO.add_rational_prec_round_val_ref(&x, prec, rm); let (sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_rational_prec_round_val_ref(&x, prec, rm); let (mut sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, rm); if x == 0u32 { sum_alt.neg_assign(); } assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[test] fn add_rational_prec_properties() { float_rational_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { let (sum, o) = x.clone().add_rational_prec(y.clone(), prec); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_rational_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (rug_sum, rug_o) = rug_add_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_rational_prec_ref_ref(&y, x.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); // TODO additional test } let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } let r_sum = Rational::exact_from(&x) + &y; assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } else { assert_eq!(o, Equal); } let (sum_alt, o_alt) = x.sub_rational_prec_ref_val(-&y, prec); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || x.is_sign_positive() { let (mut sum_alt, mut o_alt) = (-&x).sub_rational_prec_val_ref(&y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-x).add_rational_prec(-y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if !x.is_negative_zero() { let (sum, o) = x.add_rational_prec_ref_val(Rational::ZERO, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (sum, o) = Float::NAN.add_rational_prec_val_ref(&x, prec); assert!(sum.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.add_rational_prec_val_ref(&x, prec), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_rational_prec_val_ref(&x, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (sum, o) = Float::ZERO.add_rational_prec_val_ref(&x, prec); let (sum_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_rational_prec_val_ref(&x, prec); let (mut sum_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); if x == 0u32 { sum_alt.neg_assign(); } assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[test] fn add_rational_round_properties() { float_rational_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { let (sum, o) = x.clone().add_rational_round(y.clone(), rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_rational_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_rational_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_rational_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if o == Equal && sum.is_finite() && sum != 0 { assert_eq!(sum.sub_rational_round_ref_ref(&y, Exact).0, x); // TODO additional test } let r_sum = if sum.is_finite() { if x.is_normal() && sum.is_normal() { assert_eq!(sum.get_prec(), Some(x.get_prec().unwrap())); } let r_sum = Rational::exact_from(&x) + &y; assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } Some(r_sum) } else { assert_eq!(o, Equal); None }; match (r_sum.is_some() && *r_sum.as_ref().unwrap() >= 0u32, 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 let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = x.sub_rational_round_ref_val(-&y, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (mut sum_alt, mut o_alt) = (-&x).sub_rational_round_val_ref(&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); let (mut sum_alt, mut o_alt) = (-&x).add_rational_round(-&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_rational_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_rational_round_ref_ref(&y, Exact)); } }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { if !x.is_negative_zero() { let (sum, o) = x.add_rational_round_ref_val(Rational::ZERO, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(x)); assert_eq!(o, Equal); } }); rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { let (sum, o) = Float::NAN.add_rational_round_val_ref(&x, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.add_rational_round_val_ref(&x, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_rational_round_val_ref(&x, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (sum, o) = Float::ZERO.add_rational_round_val_ref(&x, rm); let (sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, 1, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_rational_round_val_ref(&x, rm); let (mut sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, 1, rm); if x == 0u32 { sum_alt.neg_assign(); } assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[test] fn add_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { let sum = x.clone() + y.clone(); assert!(sum.is_valid()); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = y.clone() + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = y.clone() + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &y + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &y + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); let sum_alt = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x .add_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x.add_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o) = x.add_rational_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if o == Equal && sum.is_finite() && sum != 0 { assert_eq!(&sum - &y, x); // TODO additional test } if sum.is_finite() && x.is_normal() && sum.is_normal() { assert_eq!(sum.get_prec(), Some(x.get_prec().unwrap())); let r_sum = Rational::exact_from(&x) + &y; if sum < r_sum { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if sum > r_sum { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } let rug_sum = rug_add_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); let sum_alt = &x - -&y; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if (x != 0u32 && y != 0u32) || x.is_sign_positive() { let sum_alt = (-(-&x - &y)).abs_negative_zero(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = (-(-&x + -&y)).abs_negative_zero(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); } }); float_gen().test_properties(|x| { assert_eq!( ComparableFloatRef(&(&x + Rational::ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Rational::ZERO + &x)), ComparableFloatRef(&x) ); }); rational_gen().test_properties(|x| { assert!((&x + Float::NAN).is_nan()); assert!((Float::NAN + &x).is_nan()); assert_eq!(&x + Float::INFINITY, Float::INFINITY); assert_eq!(Float::INFINITY + &x, Float::INFINITY); assert_eq!(&x + Float::NEGATIVE_INFINITY, Float::NEGATIVE_INFINITY); assert_eq!(Float::NEGATIVE_INFINITY + &x, Float::NEGATIVE_INFINITY); let sum_alt = Float::from_rational_prec_ref(&x, 1).0; assert_eq!( ComparableFloat(&x + Float::ZERO), ComparableFloat(sum_alt.clone()) ); assert_eq!( ComparableFloat(Float::ZERO + &x), ComparableFloat(sum_alt.clone()) ); assert_eq!( ComparableFloat((&x + Float::NEGATIVE_ZERO).abs_negative_zero()), ComparableFloat(sum_alt.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat((Float::NEGATIVE_ZERO + &x).abs_negative_zero()), ComparableFloat(sum_alt.abs_negative_zero()) ); }); }