// 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 core::cmp::Ordering::{self, *};
use malachite_base::num::arithmetic::traits::{Square, SquareAssign};
use malachite_base::num::basic::floats::PrimitiveFloat;
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::{
Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, 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::common::GenConfig;
use malachite_base::test_util::generators::{
primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11,
unsigned_rounding_mode_pair_gen_var_3,
};
use malachite_float::arithmetic::square::square_prec_round_naive;
use malachite_float::test_util::arithmetic::square::{
rug_square, rug_square_prec, rug_square_prec_round, rug_square_round,
};
use malachite_float::test_util::common::{
emulate_primitive_float_fn, parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string,
};
use malachite_float::test_util::generators::{
float_gen, float_gen_var_10, float_gen_var_6, float_gen_var_7, float_gen_var_8,
float_gen_var_9, float_rounding_mode_pair_gen_var_10, float_rounding_mode_pair_gen_var_11,
float_rounding_mode_pair_gen_var_12, float_rounding_mode_pair_gen_var_7,
float_rounding_mode_pair_gen_var_8, float_rounding_mode_pair_gen_var_9,
float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_2,
};
use malachite_float::{ComparableFloat, ComparableFloatRef, Float};
use malachite_nz::platform::Limb;
use malachite_q::Rational;
use std::panic::catch_unwind;
#[test]
fn test_square() {
let test = |s, s_hex, out: &str, out_hex: &str| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let square = x.clone().square();
assert!(square.is_valid());
assert_eq!(square.to_string(), out);
assert_eq!(to_hex_string(&square), out_hex);
let square_alt = (&x).square();
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
let mut square_alt = x.clone();
square_alt.square_assign();
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square(&rug::Float::exact_from(&x)))),
ComparableFloatRef(&square)
);
let square_alt = square_prec_round_naive(x.clone(), x.significant_bits(), Nearest).0;
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
};
test("NaN", "NaN", "NaN", "NaN");
test("Infinity", "Infinity", "Infinity", "Infinity");
test("-Infinity", "-Infinity", "Infinity", "Infinity");
test("0.0", "0x0.0", "0.0", "0x0.0");
test("-0.0", "-0x0.0", "0.0", "0x0.0");
test("1.0", "0x1.0#1", "1.0", "0x1.0#1");
test("-1.0", "-0x1.0#1", "1.0", "0x1.0#1");
test(
"1.0",
"0x1.0000000000000000000000000#100",
"1.0",
"0x1.0000000000000000000000000#100",
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
"1.0",
"0x1.0000000000000000000000000#100",
);
test("123.0", "0x7b.0#7", "1.51e4", "0x3.b0E+3#7");
test("-123.0", "-0x7b.0#7", "1.51e4", "0x3.b0E+3#7");
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
"2.0000000000000004",
"0x2.0000000000002#53",
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
"2.0000000000000004",
"0x2.0000000000002#53",
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
"9.869604401089358",
"0x9.de9e64df22ef0#53",
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
"9.869604401089358",
"0x9.de9e64df22ef0#53",
);
// - in square_float_significand_same_prec_lt_w
// - decrement_exp in square_float_significand_same_prec_lt_w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_lt_w
test("1.0", "0x1.0#1", "1.0", "0x1.0#1");
// - !decrement_exp in square_float_significand_same_prec_lt_w
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_lt_w
// - rm == Nearest in square_float_significand_same_prec_lt_w
// - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && square & shift_bit == 0)) in
// square_float_significand_same_prec_lt_w
test("1.5", "0x1.8#2", "2.0", "0x2.0#2");
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) &&
// !overflow in square_float_significand_same_prec_lt_w
test("1.6", "0x1.a#4", "2.8", "0x2.c#4");
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) && overflow
// in square_float_significand_same_prec_lt_w
test("1.414", "0x1.6a#8", "2.0", "0x2.00#8");
// - in square_float_significand_same_prec_w
// - decrement_exp in square_float_significand_same_prec_w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_w
test(
"1.0",
"0x1.0000000000000000#64",
"1.0",
"0x1.0000000000000000#64",
);
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_w
// - rm == Nearest in square_float_significand_same_prec_w
// - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && product.even())) in
// square_float_significand_same_prec_w
test(
"1.0000000000000000001",
"0x1.0000000000000002#64",
"1.0000000000000000002",
"0x1.0000000000000004#64",
);
// - !decrement_exp in square_float_significand_same_prec_w
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.odd()) && !overflow in
// square_float_significand_same_prec_w
test(
"3.2729513077064011786e-37",
"0x6.f5f6d50e7b8f6eb0E-31#64",
"1.0712210262617041571e-73",
"0x3.073e45e79ac604c4E-61#64",
);
test(
"1.9999999999999999999",
"0x1.fffffffffffffffe#64",
"3.9999999999999999996",
"0x3.fffffffffffffff8#64",
);
test(
"1.9999999999999999998",
"0x1.fffffffffffffffc#64",
"3.9999999999999999991",
"0x3.fffffffffffffff0#64",
);
test(
"1.4142135623730950488",
"0x1.6a09e667f3bcc908#64",
"1.9999999999999999999",
"0x1.fffffffffffffffe#64",
);
test(
"1.4142135623730950489",
"0x1.6a09e667f3bcc90a#64",
"2.0000000000000000002",
"0x2.0000000000000004#64",
);
// - in square_float_significand_same_prec_gt_w_lt_2w
// - lo.wrapping_add(2) & (mask >> 2) <= 2 in square_float_significand_same_prec_gt_w_lt_2w
// - decrement_exp in square_float_significand_same_prec_gt_w_lt_2w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.0",
"0x1.0000000000000000#65",
"1.0",
"0x1.0000000000000000#65",
);
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_w_lt_2w
// - rm == Nearest in square_float_significand_same_prec_gt_w_lt_2w
// - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && (z_0 & shift_bit) == 0) in
// square_float_significand_same_prec_gt_w_lt_2w
test(
"1.00000000000000000005",
"0x1.0000000000000001#65",
"1.00000000000000000011",
"0x1.0000000000000002#65",
);
// - lo.wrapping_add(2) & (mask >> 2) > 2 in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.00000000000000000011",
"0x1.0000000000000002#65",
"1.00000000000000000022",
"0x1.0000000000000004#65",
);
// - !decrement_exp in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.44020837962004126031156726e28",
"0x2.e891fdf020840728c0894E+23#85",
"2.0742001767277848782373298e56",
"0x8.7590e74562e8c0aeed1d0E+46#85",
);
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow
// in square_float_significand_same_prec_gt_w_lt_2w
test(
"119368.6474438890389479272222539538",
"0x1d248.a5bee1f96ad66a5061314f7#109",
"14248873992.58347719172623084795998",
"0x3514c9008.955ec2e06d13cb2d862#109",
);
// - in square_float_significand_same_prec_gt_2w_lt_3w
// - a0.wrapping_add(4) & (mask >> 2) <= 4 in square_float_significand_same_prec_gt_2w_lt_3w
// - decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_2w_lt_3w
test(
"1.0",
"0x1.00000000000000000000000000000000#129",
"1.0",
"0x1.00000000000000000000000000000000#129",
);
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_2w_lt_3w
// - rm == Nearest in square_float_significand_same_prec_gt_2w_lt_3w
// - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in
// square_float_significand_same_prec_gt_2w_lt_3w
test(
"1.000000000000000000000000000000000000003",
"0x1.00000000000000000000000000000001#129",
"1.000000000000000000000000000000000000006",
"0x1.00000000000000000000000000000002#129",
);
// - a0.wrapping_add(4) & (mask >> 2) > 4 in square_float_significand_same_prec_gt_2w_lt_3w
// - !decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w
test(
"2.024076700393272432111968987625898501371897741e-29",
"0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149",
"4.09688648907491713333499964381160220254051958e-58",
"0x2.9258227caed7c4000630a1192a20211680c74E-48#149",
);
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) in
// square_float_significand_same_prec_gt_2w_lt_3w
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !overflow
// in square_float_significand_same_prec_gt_2w_lt_3w
test(
"4.9709672065181108960570410290811793724062284431352e-48",
"0x7.43dc113e95ca123693650af31435eac45c0e7a680E-40#165",
"2.47105149682784709830100902225310999174453232836862e-95",
"0x3.4c805dfa0982f9705aa6bbd6840b755493beef234E-79#165",
);
}
#[test]
fn test_square_prec() {
let test = |s, s_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 (square, o) = x.clone().square_prec(prec);
assert!(square.is_valid());
assert_eq!(square.to_string(), out);
assert_eq!(to_hex_string(&square), out_hex);
assert_eq!(o, o_out);
let (square_alt, o_alt) = x.square_prec_ref(prec);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(o_alt, o_out);
let mut square_alt = x.clone();
let o_alt = square_alt.square_prec_assign(prec);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(o_alt, o_out);
let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, Nearest);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let (rug_square, rug_o) = rug_square_prec(&rug::Float::exact_from(&x), prec);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(rug_o, o);
};
test("NaN", "NaN", 1, "NaN", "NaN", Equal);
test("Infinity", "Infinity", 1, "Infinity", "Infinity", Equal);
test("-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal);
test("0.0", "0x0.0", 1, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal);
test("1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 10, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 1, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 10, "1.0", "0x1.000#10", Equal);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
"1.0",
"0x1.000#10",
Equal,
);
test("123.0", "0x7b.0#7", 1, "2.0e4", "0x4.0E+3#1", Greater);
test("123.0", "0x7b.0#7", 10, "1.514e4", "0x3.b2E+3#10", Greater);
test("-123.0", "-0x7b.0#7", 1, "2.0e4", "0x4.0E+3#1", Greater);
test(
"-123.0",
"-0x7b.0#7",
10,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
1,
"2.0",
"0x2.0#1",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
10,
"2.0",
"0x2.00#10",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
1,
"2.0",
"0x2.0#1",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
10,
"2.0",
"0x2.00#10",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
"8.0",
"0x8.0#1",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
"9.88",
"0x9.e0#10",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
"8.0",
"0x8.0#1",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
"9.88",
"0x9.e0#10",
Greater,
);
// - in square_float_significands_general
// - xs_len <= 2 in square_float_significands_general
// - xs_len == 1 in square_float_significands_general
// - !b1 first time in square_float_significands_general
// - !goto_full_square second time in square_float_significands_general
// - !increment_exp in square_float_significands_general
test("1.0", "0x1.0#1", 2, "1.0", "0x1.0#2", Equal);
// - b1 first time in square_float_significands_general
test("1.5", "0x1.8#2", 1, "2.0", "0x2.0#1", Less);
// - increment_exp in square_float_significands_general
test("1.2", "0x1.4#3", 1, "2.0", "0x2.0#1", Greater);
// - xs_len < 2 <= MPFR_SQR_THRESHOLD in square_float_significands_general
// - goto_full_square second time in square_float_significands_general
// - b1 third time in square_float_significands_general
test(
"0.000199046277632504184666664672269768242929310652018203552191617720205649",
"0x0.000d0b7140b8f3aea60aad60c1dc3b2ee0d83e2eba33dcfb6f874df52d78#225",
26,
"3.9619421e-8",
"0xa.a2a038E-7#26",
Less,
);
// - xs_len == 2 in square_float_significands_general
test(
"330.3297903358337046735382484655688",
"0x14a.546d23b2f14f71a1f4c12ddaa88#115",
45,
"109117.770383317",
"0x1aa3d.c537d75#45",
Greater,
);
// - !b1 third time in square_float_significands_general
test(
"88.32972592752556369746097031876493672699524930031683012093294198918",
"0x58.5468eb1b5d957d68d5c161060f2abd3d11568e57fb44ace5b9530c#222",
41,
"7802.140482433",
"0x1e7a.23f6a82#41",
Greater,
);
// - xs_len > MPFR_SQR_THRESHOLD in square_float_significands_general
// - xs[0] != 0 || xs[1] != 0 in square_float_significands_general
// - out_prec <= p - 5 in square_float_significands_general
// - !goto_full_square first time in square_float_significands_general
// - in limbs_float_square_high
// - k.is_none() in limbs_float_square_high
// - b1 second time in square_float_significands_general
// - can_round in square_float_significands_general
test(
"396.3412272551190567593891335756570564001425784787446073953740531440207891605323131867948\
869355406520857599475406495997289490143735096829625551391579153111055037678989978858579586\
021105696471344997604889396207883425571313379937012790014662248134632025438319010426957144\
355546486040271820495868974546882981476343977667254209899704548500299738343700283443799494\
532151589935402512791651191411866655264587358069356924819557816073395721436815590916015139\
840293409397442",
"0x18c.575aab5d3d7d931fe7b1df9a17c5180eb11799ddcdb0b514b818c68be091c380b4f49e26c6357fc5521\
89c83f7fb1af51d3ad56a7621351488217dec257419292d332960be3dcbdbf0989c56e4cc82fcee123ce6c00b8\
63f9e45062bf3fbae296936b2ab5e3779905657246488ffaf88040c9e3456d8e0dcb25c0b55feba5452509320e\
91f9be5ce584d555f8c77c79aeec4f5bb5aff76c235d04d87f5adafe9a729dccc5692f11d14f4aeeec72b2dc3e\
c35bf6b0a8d1d636bb2afad1ab82c0#1539",
41,
"157086.3684222",
"0x2659e.5e50ea#41",
Greater,
);
// - !b1 second time in square_float_significands_general
test(
"0.289565969492664694638578202456729810638628879666435586140728331245058747654800231361781\
733367215018660480916949243715433401890725345322341436886642908102373347900363371546861032\
804628537167569586473086484745604528149555432827776527274466086199528238950727774219761110\
278394595668030807862161516149163941956835588098749888947102946654461061159884953097421811\
149735301912628233431116932895412543378996752139902311082164451547359831823770756258588441\
392364079976282812844068282256919410425900496233045740740436555471195699615728406687884353\
411870520651275282496307876556394549674324563102261561135259821040813150131202195032317605\
601108576080171231347456850423368707704016287732147225807113778613580546356726188558446009\
37667532705200099920676965417288103441",
"0x0.4a20fed1016a521a64864d01138a193df1e23f2f35edd21912c8d7ea345216c5ec7c59aca3d2ce1378dd1\
89d7419984353ecef1dc303caddc54cc6cf871a7d44df07922bfe75b3e27fa2ac58a45a2700c2b9d233b14afbe\
c4aeeed4683073d061d99c2f92084cbae1d1bf26f8fb2323910d590864daa5f4b534e0509ff60a7238357ab7ff\
36bcc0024c64f4507f522e91df687d9649e2e609840feea945bd53cec1fec45c7ccee6ad51aacd8c59427836f6\
871c316bc3ba008d00a81638ec6c5630fafa1ebe3c492a94c04c96f772e57d74f808872161bf166402ea4e9dd0\
42397a51a2e1ffd33b8865cca279beaaf61c288bdc67dceb9e84f124abd1c1016bfc1d67e916ef24dc5a541f8c\
e0888c25325a3955899b701e5035429c76e90b7de02973eaa08674d6315156df3c4afdd962afc0b2fb855c12c7\
cb#2507",
41,
"0.08384845068821",
"0x0.1577179186b#41",
Less,
);
// - k == Some(0) in limbs_float_square_high
// - in limbs_float_square_high_basecase
test(
"2.534905093269173913399961419051078001207362536676304036217117050023406987769089211085345\
845282321276763762108762278121117963061716139888836603176571082592497694546991532956806762\
060078393566599448512584861538013806584451166069797239642908909634341260487656925769615819\
575456879212968568058838065343005029399246396366977778814769813140337173953816940118229696\
975910769633258534685767958638383299293048391708530965415961893726949253541358150164947850\
354131943712963257075685505691799739914956071583726713409225265256065457404089250831362505\
964054898560581202320837085103659819920563909237065863856674551755094031141043600118470396\
110548066038755307598657006758419658655479386061317383935495778887020750969220495044500181\
502836698351684979845272389537925642124685759621079734656489541651071700522564930994999675\
548215393164945318735677787876975365012973524228071379171196099071790619084107585184183873\
649229987470512431316532998401599147457982188040992886626796443210441148620644905909977484\
092106548023293796713001951271606863906640116960398160889963208431853184379130926702446309\
16665296291511e-18",
"0x2.ec2c037afc439f03a036777b3b49c929652bc0198062ee846d167a89e9a1b649beaab8e3935d29165383b\
8032ab14cd30954f6e10277bf2adbaa3dc7f4af85aa6a3dfe37f0afee4bafa862c5d97d6b0ad6fe3a473f086a0\
d78eaa4db0710879d93d26ada2de74e4133838c88fda61bf559b836a376e2ece72417c51fff1870b23e21aa228\
c6b132e5b2dea393b782ddc27593a878aec5ddd0254c2fe5515f3036b02fc8ab225f7433c0e931717894c1f581\
86927d1a1d3ae8a8d5a52d6ffd5bb9a6f1d8c55f9c54d16411a5a7a6bf1616d3eaf4692379eb81ba2b11179269\
987c75a403cd7845851b66bf9758892745e79ac67a6a8feb7dcdcb16690d8fae58f96bc20e8495bdee03ef7ad7\
d1821419ec1bfe2bb5b49cbfcab0f7a3523939693c97830d3c6e027badb91529d6076972fcea0ace6d83b34f64\
0da99faaa4862efc02a02d3a5066111bfc08e28a6b55ff9e7c245b0232f0a85e97a68fa69e8d218bce6abe990a\
2e0b503cf831ad5df31caba8915c38bad1cc785b9e99b3bb855801ec29ad43668762f37f228f77bf7a8590649f\
937d5dc5039a46479d0dac0be7aa72929e8868980b3f76831bf434c15ba83ba74394414959b1c8bc010f735a6c\
14c8b93afc80E-15#3627",
423,
"6.425743831881999297033060889967219634391598848272085805147756300415778053639020164208035\
3509860715112301888671841760135704785647e-36",
"0x8.8a913be7e47dfd7ad8403512f1a0ee8d3fad7395038c39eb4039b4703fdcd0314b45e761b67375d18eb58\
ced237cd5fd6c79c02dcE-30#423",
Less,
);
// - xs[0] == 0 && xs[1] == 0 in square_float_significands_general
test(
"511.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
999999999999858969189385560189369588899908301051658131815921691396545986807150339147015462\
016914098983479659782731543057846003175884332840513803623318182318832820724717407320371823\
6294395745915856",
"0x1ff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000#1539",
45,
"262144.0",
"0x40000.0000000#45",
Greater,
);
// - !can_round in square_float_significands_general
test(
"5070602400912917605986812821504.000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000072282982868771681166004491412846722101397844122267684138688870467552820474559090102317\
447234871538375909335604136421707865093288809202542467085297095776399695369977155046440218\
72699461509694558652328992590065121835881232",
"0x40000000000000000000000000.000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
fffffffffffffffffffffe#2230",
75,
"2.5711008708143844408671e61",
"0x1.0000000000000000000E+51#75",
Less,
);
// - k != None && k != Some(0) && len <= SQR_FFT_THRESHOLD in limbs_float_square_high
test(
"396.3412272551190567593891335756570564001425784787446073953740531440207891605323131867948\
869355406520857599475406495997289490143735096829625551391579153111055037678989978858579586\
021105696471344997604889396207883425571313379937012790014662248134632025438319010426957144\
355546486040271820495868974546882981476343977667254209899704548500299738343700283443799494\
532151589935402512791651191411866655264587358069356924819557816073395721436815590916015139\
840293409397442",
"0x18c.575aab5d3d7d931fe7b1df9a17c5180eb11799ddcdb0b514b818c68be091c380b4f49e26c6357fc5521\
89c83f7fb1af51d3ad56a7621351488217dec257419292d332960be3dcbdbf0989c56e4cc82fcee123ce6c00b8\
63f9e45062bf3fbae296936b2ab5e3779905657246488ffaf88040c9e3456d8e0dcb25c0b55feba5452509320e\
91f9be5ce584d555f8c77c79aeec4f5bb5aff76c235d04d87f5adafe9a729dccc5692f11d14f4aeeec72b2dc3e\
c35bf6b0a8d1d636bb2afad1ab82c0#1539",
1000,
"157086.3684220939290392835990654860444953123468682922432646919273797192952403374080185049\
441414358725029167080302705853255170809678818388441806686518494713508728113056316939955366\
580321349638671885788642336442940811575310873763709312578497006621517503935000405848895060\
9190911436529068384755172193385643",
"0x2659e.5e50e90c8c8f731b6ec42e31ac581c6d5c6e7051268a54ce30dbe17faafc9ad4523be4827db001d48\
8a322a36c3d610868daa74b44da3bd6945b467643769f500a263ca6634a2786c8e089cd305b177ffba7d9cf923\
74c0483fa9a736b452c7e65bfe13f1fbababe9090e56a0abfa7e4982915fe0dff247e8378e8#1000",
Greater,
);
// - out_prec > p - 5 in square_float_significands_general
// - out_prec > p - 5 + Limb::WIDTH || xs_len <= MPFR_SQR_THRESHOLD + 1 in
// square_float_significands_general
// - goto_full_square first time in square_float_significands_general
test(
"396.3412272551190567593891335756570564001425784787446073953740531440207891605323131867948\
869355406520857599475406495997289490143735096829625551391579153111055037678989978858579586\
021105696471344997604889396207883425571313379937012790014662248134632025438319010426957144\
355546486040271820495868974546882981476343977667254209899704548500299738343700283443799494\
532151589935402512791651191411866655264587358069356924819557816073395721436815590916015139\
840293409397442",
"0x18c.575aab5d3d7d931fe7b1df9a17c5180eb11799ddcdb0b514b818c68be091c380b4f49e26c6357fc5521\
89c83f7fb1af51d3ad56a7621351488217dec257419292d332960be3dcbdbf0989c56e4cc82fcee123ce6c00b8\
63f9e45062bf3fbae296936b2ab5e3779905657246488ffaf88040c9e3456d8e0dcb25c0b55feba5452509320e\
91f9be5ce584d555f8c77c79aeec4f5bb5aff76c235d04d87f5adafe9a729dccc5692f11d14f4aeeec72b2dc3e\
c35bf6b0a8d1d636bb2afad1ab82c0#1539",
5000,
"157086.3684220939290392835990654860444953123468682922432646919273797192952403374080185049\
441414358725029167080302705853255170809678818388441806686518494713508728113056316939955366\
580321349638671885788642336442940811575310873763709312578497006621517503935000405848895060\
919091143652906838475517219338564216871512733323414114900025582889108770319888495423472591\
622217081406162593383439817010743870950284355953948594596501930134914144626602460886577742\
699397445023366416628676609358289067494944516044161793867980863078877928160882497479870173\
995550846564918220947311792283316244784987871826325087158139795457567671300755416634197565\
825272103067497350477832613308006740370014538444363794113999101665422314265225122590389544\
388555686073293478850435707082986891289816937189501867266947100104879700862539689861260203\
303222356049565246944094013202651746222554947384760413370539804854333289940364855469937239\
014120251649267431651939212811005766277308077834857972931251756411522886575455852040387255\
586633599190053514685721006798676467868675709844997689304699851005119605477859913661835009\
980047325267722717984269099465289430789912767924820742466247451598658072993390431860927262\
510441796888642732252820490424273307195428579227975601954580861122408746440602416210603394\
010320119854126656872002234654813295901729990426282838623889803078731960696692381273900064\
363258066357675869791572233715232583553618635258761844046010323346239050118033120274686587\
47626978436794438933236478602171106153180118157402691906229607357337",
"0x2659e.5e50e90c8c8f731b6ec42e31ac581c6d5c6e7051268a54ce30dbe17faafc9ad4523be4827db001d48\
8a322a36c3d610868daa74b44da3bd6945b467643769f500a263ca6634a2786c8e089cd305b177ffba7d9cf923\
74c0483fa9a736b452c7e65bfe13f1fbababe9090e56a0abfa7e4982915fe0dff247e8378e637c71563f40ac88\
bff59ccb63d55f07b40f44324086d33c752ca2a398f8021f9ab7e61160ce80b0eb4d350cfcb2745c0ffb94a7ea\
c2a42031e1d67c39dabea5ed0ed1839b3cb19c95afad38ff4d85fe726701b1400759bff428fc5d441579646a9a\
edbda6e96c39642ea5102dcc1744e2f22bc2669606b02248465eda50f7ab00888fe70cd5b94c6886478a9d89d4\
721fd315aae640835a05a2ac14cf927011012c9a0b12526c935c3b86e035f9369aa246b7f864ac313401679f2d\
585686dd60ca3610690fc6e131d703a07afa9f50e1c62593876e5dfcd53a06dfc5c84a2d7c8129428f50ff8669\
462d4cbbacfe9e72bf3cd17875fb28dd45607447a1bdd656f47900000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
#5000",
Equal,
);
// - out_prec <= p - 5 + Limb::WIDTH && xs_len > MPFR_SQR_THRESHOLD + 1 in
// square_float_significands_general
// - xs_len <= len in square_float_significands_general
// - k < twice_len in square_float_significands_general
test(
"70459532516206275717738.24583571192785940804485220379113093012216854237552273164629839052\
295542459627091867686732592292054910255896821543632944963319945361030770270423888774548519\
352455933682416235026529894320254192088358055829902767990508592251676851896653974385735963\
818455173075208105139936148350808080166279329650970874228499292765775926866402018763767601\
932631118142152227916465948527446827475834919059052275938611139784416871828297279794775881\
754156488112402263366312959738244152841157181731104967167515387928211427131697792191239671\
200062974233522321766736844717284659803787329075216256925936831334895804054605134987158729\
635284806758566129642530508638215601547746106827192539740893000302521313674983124372016914\
389464631779788838617640381788549537988633853246170604449289457144019599904363663940307935\
010893280729695200089400652615175194820160750890242280186267733830422108880046398617008039\
346196610860314292217862221940568925947020858793049858538542201667012791629444317697230994\
497432161328637397726885087365856366871387393212442806903408576734184446519785519751530501\
203958503763892329891980999384336300765212927244594343049091702158556853491733512332595607\
980340866258213963813028256778277899307861580399445091884912999955742998432553541817046928\
089178846440489676733765036119262237349966327782496860922729317780078565098542288671006633\
263750319390117261972206095532634412489779996284041680459224965604552001326514848875913522\
75401658328725688546699002488305760364795486416541",
"0xeeb9e70f8e3103fea6a.3eef16d6eb45c3a998fb982ebe639fc8759b70c44fe5810571a8155bfb031e4bc24\
7dda5a8581f5ab0434d47c9eb35f6a9fb469e23b989044db9aefcec6a8d1de5bf14332cc4bb1bc75c32a4e36cc\
f907a5658e025a6f217cb147f7a8ce671eee07c655ecbe2598eb280ca4d26207f6c1e55ed67b66c69d289c56d3\
4f2d2b25f411c0b9e4696d67a2ebe0b5716309bb26e24a3cc52943382e8956c46f600932e74aed277d50d0b801\
d8cdf51e8d20373cc3c14623e93446643f969b662cd3d7da7f3f840246325c873da49be886e93a9f2b9debb19d\
6b28dc9e7e168f16ac806d56ffbeb1836aff27be850217d6311ab97d9742412187d3ecde0f7d4a0c89c6b46c37\
610de9e5d478f868be38875f5c45f683618305161b4a1e6811cc1c53c2798dddbe1daba42c542637900cae7fe8\
7cb8178a8825ae05ae6c791d728ab540947bc63fcb32f5af0d89b211e00aa940c8ccb7aa1ff76a1590b970f2c4\
010fddbeb773600a0bd98bc005244e5ce6bf94d6ff4be6c4ddaffe2d3f89ae99eb2b79591c994977331c5caa40\
d57d28f6fa0bd1458390ffd906d84e849964bf2c3afb5fa3e251d60fb42251182bc006f0da82dd32c5877d3183\
b771fa955b64fe611c8a57edf9070898139a48e93a9f7cf1bc280142a0c900175e97125e4dba6cd579985765eb\
ea2bf0ecfb3754e8373897fd5f3fbdd8a04c429f1eb274d27b90c5ba4cdc5221ee37d3885cc6b8a0745a21d803\
9a0571a0a77248c1a21338919b63ada2c014b8d1864ad65dc80551ded9cd5e048f7a262866d51e252ee527629b\
0628f7561340ddc20398c57d6f3159cec6f4979a02c5610d3743e31aa8993d652c6ea0#4942",
5000,
"4964545722402329471538520890548020778505727316.714928212970963455240096184214428743957383\
329922752233199764049780878042702316184608300084915002665385500366536453418018453492928341\
017054541630873437214644149654854522755654366831843415669733075028381314388954345055868246\
000218989221937469258574896624097067887464348708304868331849053151758619452575265628276389\
682599022898309226512794404632814475266579950972366209872195059885305874209009896969746959\
550374594439111632193759127250892146888326838744623554050318490109344201586718804154701606\
966010758459087950191998865560033257935278780535428646473292047088396527777426223171234483\
188009004262125992356660280897524089496628310376755558332111429032108512629018171093951768\
666071288536225840334502196980458876275123956423686107784807652541652782835788006847858977\
993995691507283189780038044528425354524130033815262491772309833202212299992561581175232232\
053665702559586771762340461465421956694347639348699503880840804336286789065206696824702252\
001401065405887247144705146834255039213991488108844897575368853688286293567906566377054487\
855713514655373784168449710429759002204390811345191073301339247358231849563161226052987665\
594985477181835691490984499872892234197121121888658800164578709448237427211277623000068159\
736988165669283234595563391379976241167126662466254710156731663896405093320111508971147717\
596133787650005180714732054756611220213766696881623761124569357842183971615077248468826825\
78028047188611500722085706480035062367867718429318751607371955873121",
"0xde9e30a0b16bb9d3b1d41b9ca941523105ed54.b705890db2b0d9f3e32b9f103e1b83c7f9edba5c1f4e2af3\
adeb66de82892d7410e07fd6532bc0baf1535d9dfdf455d02d7b3cdcd6b683dd9909ef54c1c3138d14f10d53ef\
a61999322d530e26efcb69e290c671098fb49bb695602d0e25cb7d993dc249014fc873b17a61bb8c9a878cb42e\
f205fa6138dbfc05bd5c65440690ca6b0054108cab3099860992a8d16ad6797a10fba9af26f477b820e5a0499c\
bf71480aff1edfd22ad78810350210eae0cec2b5d0248df96b630be8372423d110cdd49422b85db636542c44ca\
d9c82a307aaeb2d1795d93184dd19dc0e3bd6c9cdc631fe51a88f0a178def01f6ae41386a6563a14613e79ab7d\
b81b5373a481694455cc8778c037bd3a3c6e2b7a0f448025095104d91359860535455349496f70c9ca535c3e69\
8563c5e868485868fb51e33f09ed11186e72d4c6b2ce9f4b7629a78b907f198ac6cdde2f6642df2b1c9737ce1a\
48ac426a8d401ef2aa8acbd3185bfd87dc282064adc7145f4dc07a12d6b35f38fb04eb2c4da98e45b7287d9982\
2aea6ee0f4d2b8771272e2f4e9d0afb433896b20f842155ae13c2df308b254065539842f8cb05363f97ef29bbb\
6b1fd5ac471efcf6cd026fe29de50b9a08d5e4610e95cba281a1006f876c351b4b8c381caf1f9f849a3ad17f6b\
fed7e727b78c97f11622da2ae8fd3c5759f030ea2800bd1d267f019d2292f18d7360d036e88707bbd93901fda7\
c8fa8cfeeb7aca62069cec0809ae3add2dfdbffa773246c8ae9749ac6c8b0cced5911da8050ea0171f866099b7\
44d3739341181361c2df7c3d9320134683888ed78e4d80fc191958b201777943c0cac9c3c082a01b24d3#5000",
Less,
);
}
#[test]
fn square_prec_fail() {
assert_panic!(Float::NAN.square_prec(0));
assert_panic!(Float::NAN.square_prec_ref(0));
assert_panic!({
let mut x = Float::NAN;
x.square_prec_assign(0)
});
}
#[test]
fn test_square_round() {
let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| {
let x = parse_hex_string(s_hex);
assert_eq!(x.to_string(), s);
let (square, o) = x.clone().square_round(rm);
assert!(square.is_valid());
assert_eq!(square.to_string(), out);
assert_eq!(to_hex_string(&square), out_hex);
assert_eq!(o, o_out);
let (square_alt, o_alt) = x.square_round_ref(rm);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(o_alt, o_out);
let mut square_alt = x.clone();
let o_alt = square_alt.square_round_assign(rm);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(o_alt, o_out);
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_square, rug_o) = rug_square_round(&rug::Float::exact_from(&x), rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(rug_o, o);
}
let (square_alt, o_alt) = square_prec_round_naive(x.clone(), x.significant_bits(), rm);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
};
test("NaN", "NaN", Floor, "NaN", "NaN", Equal);
test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal);
test("NaN", "NaN", Down, "NaN", "NaN", Equal);
test("NaN", "NaN", Up, "NaN", "NaN", Equal);
test("NaN", "NaN", Nearest, "NaN", "NaN", Equal);
test("NaN", "NaN", Exact, "NaN", "NaN", Equal);
test("Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal);
test(
"Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal,
);
test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal);
test("Infinity", "Infinity", Up, "Infinity", "Infinity", Equal);
test(
"Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal,
);
test("Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal);
test(
"-Infinity",
"-Infinity",
Floor,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
Ceiling,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
Down,
"Infinity",
"Infinity",
Equal,
);
test("-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal);
test(
"-Infinity",
"-Infinity",
Nearest,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
Exact,
"Infinity",
"Infinity",
Equal,
);
test("0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", Down, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", Up, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal);
test("1.0", "0x1.0#1", Floor, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", Down, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", Up, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", Exact, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", Floor, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", Down, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", Up, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", Exact, "1.0", "0x1.0#1", Equal);
test(
"1.0",
"0x1.0000000000000000000000000#100",
Floor,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
Ceiling,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
Down,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
Up,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
Nearest,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
Exact,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
Floor,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
Ceiling,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
Down,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
Up,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
Nearest,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
Exact,
"1.0",
"0x1.0000000000000000000000000#100",
Equal,
);
test("123.0", "0x7b.0#7", Floor, "1.51e4", "0x3.b0E+3#7", Less);
test(
"123.0",
"0x7b.0#7",
Ceiling,
"1.52e4",
"0x3.b8E+3#7",
Greater,
);
test("123.0", "0x7b.0#7", Down, "1.51e4", "0x3.b0E+3#7", Less);
test("123.0", "0x7b.0#7", Up, "1.52e4", "0x3.b8E+3#7", Greater);
test("123.0", "0x7b.0#7", Nearest, "1.51e4", "0x3.b0E+3#7", Less);
test("-123.0", "-0x7b.0#7", Floor, "1.51e4", "0x3.b0E+3#7", Less);
test(
"-123.0",
"-0x7b.0#7",
Ceiling,
"1.52e4",
"0x3.b8E+3#7",
Greater,
);
test("-123.0", "-0x7b.0#7", Down, "1.51e4", "0x3.b0E+3#7", Less);
test("-123.0", "-0x7b.0#7", Up, "1.52e4", "0x3.b8E+3#7", Greater);
test(
"-123.0",
"-0x7b.0#7",
Nearest,
"1.51e4",
"0x3.b0E+3#7",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
Floor,
"2.0",
"0x2.0000000000000#53",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
Ceiling,
"2.0000000000000004",
"0x2.0000000000002#53",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
Down,
"2.0",
"0x2.0000000000000#53",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
Up,
"2.0000000000000004",
"0x2.0000000000002#53",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
Nearest,
"2.0000000000000004",
"0x2.0000000000002#53",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
Floor,
"2.0",
"0x2.0000000000000#53",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
Ceiling,
"2.0000000000000004",
"0x2.0000000000002#53",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
Down,
"2.0",
"0x2.0000000000000#53",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
Up,
"2.0000000000000004",
"0x2.0000000000002#53",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
Nearest,
"2.0000000000000004",
"0x2.0000000000002#53",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
Floor,
"9.869604401089356",
"0x9.de9e64df22ee8#53",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
Ceiling,
"9.869604401089358",
"0x9.de9e64df22ef0#53",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
Down,
"9.869604401089356",
"0x9.de9e64df22ee8#53",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
Up,
"9.869604401089358",
"0x9.de9e64df22ef0#53",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
Nearest,
"9.869604401089358",
"0x9.de9e64df22ef0#53",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
Floor,
"9.869604401089356",
"0x9.de9e64df22ee8#53",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
Ceiling,
"9.869604401089358",
"0x9.de9e64df22ef0#53",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
Down,
"9.869604401089356",
"0x9.de9e64df22ee8#53",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
Up,
"9.869604401089358",
"0x9.de9e64df22ef0#53",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
Nearest,
"9.869604401089358",
"0x9.de9e64df22ef0#53",
Greater,
);
// - rm == Floor || rm == Down in square_float_significand_same_prec_lt_w
test("1.5", "0x1.8#2", Down, "2.0", "0x2.0#2", Less);
// - rm == Ceiling || rm == Up in square_float_significand_same_prec_lt_w
// - (rm == Ceiling || rm == Up) && !overflow in square_float_significand_same_prec_lt_w
test("1.5", "0x1.8#2", Up, "3.0", "0x3.0#2", Greater);
// - (rm == Ceiling || rm == Up) && overflow in square_float_significand_same_prec_lt_w
test("1.4", "0x1.6#4", Up, "2.0", "0x2.0#4", Greater);
// - rm == Floor || rm == Down in square_float_significand_same_prec_w
test(
"1.0000000000000000001",
"0x1.0000000000000002#64",
Down,
"1.0000000000000000002",
"0x1.0000000000000004#64",
Less,
);
// - rm == Ceiling || rm == Up in square_float_significand_same_prec_w
// - (rm == Ceiling || rm == Up) && !overflow in square_float_significand_same_prec_w
test(
"1.0000000000000000001",
"0x1.0000000000000002#64",
Up,
"1.0000000000000000003",
"0x1.0000000000000006#64",
Greater,
);
// - rm == Floor || rm == Down in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.00000000000000000005",
"0x1.0000000000000001#65",
Down,
"1.00000000000000000011",
"0x1.0000000000000002#65",
Less,
);
// - rm == Ceiling || rm == Up in square_float_significand_same_prec_gt_w_lt_2w
// - (rm == Ceiling || rm == Up) && !overflow in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.00000000000000000005",
"0x1.0000000000000001#65",
Up,
"1.00000000000000000016",
"0x1.0000000000000003#65",
Greater,
);
// - rm == Floor || rm == Down in square_float_significand_same_prec_gt_2w_lt_3w
test(
"1.000000000000000000000000000000000000003",
"0x1.00000000000000000000000000000001#129",
Down,
"1.000000000000000000000000000000000000006",
"0x1.00000000000000000000000000000002#129",
Less,
);
// - rm == Ceiling || rm == Up in square_float_significand_same_prec_gt_2w_lt_3w
// - (rm == Floor || rm == Down) && !overflow in square_float_significand_same_prec_gt_2w_lt_3w
test(
"1.000000000000000000000000000000000000003",
"0x1.00000000000000000000000000000001#129",
Up,
"1.000000000000000000000000000000000000009",
"0x1.00000000000000000000000000000003#129",
Greater,
);
// - in square_float_significand_same_prec_lt_w
// - decrement_exp in square_float_significand_same_prec_lt_w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_lt_w
test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal);
// - !decrement_exp in square_float_significand_same_prec_lt_w
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_lt_w
// - rm == Nearest in square_float_significand_same_prec_lt_w
// - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && square & shift_bit == 0)) in
// square_float_significand_same_prec_lt_w
test("1.5", "0x1.8#2", Nearest, "2.0", "0x2.0#2", Less);
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) &&
// !overflow in square_float_significand_same_prec_lt_w
test("1.6", "0x1.a#4", Nearest, "2.8", "0x2.c#4", Greater);
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) && overflow
// in square_float_significand_same_prec_lt_w
test("1.414", "0x1.6a#8", Nearest, "2.0", "0x2.00#8", Greater);
// - in square_float_significand_same_prec_w
// - decrement_exp in square_float_significand_same_prec_w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_w
test(
"1.0",
"0x1.0000000000000000#64",
Nearest,
"1.0",
"0x1.0000000000000000#64",
Equal,
);
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_w
// - rm == Nearest in square_float_significand_same_prec_w
// - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && product.even())) in
// square_float_significand_same_prec_w
test(
"1.0000000000000000001",
"0x1.0000000000000002#64",
Nearest,
"1.0000000000000000002",
"0x1.0000000000000004#64",
Less,
);
// - !decrement_exp in square_float_significand_same_prec_w
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.odd()) && !overflow in
// square_float_significand_same_prec_w
test(
"3.2729513077064011786e-37",
"0x6.f5f6d50e7b8f6eb0E-31#64",
Nearest,
"1.0712210262617041571e-73",
"0x3.073e45e79ac604c4E-61#64",
Greater,
);
test(
"1.9999999999999999999",
"0x1.fffffffffffffffe#64",
Nearest,
"3.9999999999999999996",
"0x3.fffffffffffffff8#64",
Less,
);
test(
"1.9999999999999999998",
"0x1.fffffffffffffffc#64",
Nearest,
"3.9999999999999999991",
"0x3.fffffffffffffff0#64",
Less,
);
test(
"1.4142135623730950488",
"0x1.6a09e667f3bcc908#64",
Nearest,
"1.9999999999999999999",
"0x1.fffffffffffffffe#64",
Less,
);
test(
"1.4142135623730950489",
"0x1.6a09e667f3bcc90a#64",
Nearest,
"2.0000000000000000002",
"0x2.0000000000000004#64",
Greater,
);
// - in square_float_significand_same_prec_gt_w_lt_2w
// - lo.wrapping_add(2) & (mask >> 2) <= 2 in square_float_significand_same_prec_gt_w_lt_2w
// - decrement_exp in square_float_significand_same_prec_gt_w_lt_2w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.0",
"0x1.0000000000000000#65",
Nearest,
"1.0",
"0x1.0000000000000000#65",
Equal,
);
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_w_lt_2w
// - rm == Nearest in square_float_significand_same_prec_gt_w_lt_2w
// - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && (z_0 & shift_bit) == 0) in
// square_float_significand_same_prec_gt_w_lt_2w
test(
"1.00000000000000000005",
"0x1.0000000000000001#65",
Nearest,
"1.00000000000000000011",
"0x1.0000000000000002#65",
Less,
);
// - lo.wrapping_add(2) & (mask >> 2) > 2 in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.00000000000000000011",
"0x1.0000000000000002#65",
Nearest,
"1.00000000000000000022",
"0x1.0000000000000004#65",
Less,
);
// - !decrement_exp in square_float_significand_same_prec_gt_w_lt_2w
test(
"1.44020837962004126031156726e28",
"0x2.e891fdf020840728c0894E+23#85",
Nearest,
"2.0742001767277848782373298e56",
"0x8.7590e74562e8c0aeed1d0E+46#85",
Less,
);
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow
// in square_float_significand_same_prec_gt_w_lt_2w
test(
"119368.6474438890389479272222539538",
"0x1d248.a5bee1f96ad66a5061314f7#109",
Nearest,
"14248873992.58347719172623084795998",
"0x3514c9008.955ec2e06d13cb2d862#109",
Greater,
);
// - in square_float_significand_same_prec_gt_2w_lt_3w
// - a0.wrapping_add(4) & (mask >> 2) <= 4 in square_float_significand_same_prec_gt_2w_lt_3w
// - decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w
// - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_2w_lt_3w
test(
"1.0",
"0x1.00000000000000000000000000000000#129",
Nearest,
"1.0",
"0x1.00000000000000000000000000000000#129",
Equal,
);
// - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_2w_lt_3w
// - rm == Nearest in square_float_significand_same_prec_gt_2w_lt_3w
// - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in
// square_float_significand_same_prec_gt_2w_lt_3w
test(
"1.000000000000000000000000000000000000003",
"0x1.00000000000000000000000000000001#129",
Nearest,
"1.000000000000000000000000000000000000006",
"0x1.00000000000000000000000000000002#129",
Less,
);
// - a0.wrapping_add(4) & (mask >> 2) > 4 in square_float_significand_same_prec_gt_2w_lt_3w
// - !decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w
test(
"2.024076700393272432111968987625898501371897741e-29",
"0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149",
Nearest,
"4.09688648907491713333499964381160220254051958e-58",
"0x2.9258227caed7c4000630a1192a20211680c74E-48#149",
Less,
);
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) in
// square_float_significand_same_prec_gt_2w_lt_3w
// - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !overflow
// in square_float_significand_same_prec_gt_2w_lt_3w
test(
"4.9709672065181108960570410290811793724062284431352e-48",
"0x7.43dc113e95ca123693650af31435eac45c0e7a680E-40#165",
Nearest,
"2.47105149682784709830100902225310999174453232836862e-95",
"0x3.4c805dfa0982f9705aa6bbd6840b755493beef234E-79#165",
Greater,
);
}
#[test]
fn square_round_fail() {
const THREE: Float = Float::const_from_unsigned(3);
assert_panic!(THREE.square_round(Exact));
assert_panic!(THREE.square_round_ref(Exact));
assert_panic!({
let mut x = THREE;
x.square_round_assign(Exact);
});
}
#[test]
fn test_square_prec_round() {
let test = |s, s_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 (square, o) = x.clone().square_prec_round(prec, rm);
assert!(square.is_valid());
assert_eq!(square.to_string(), out);
assert_eq!(to_hex_string(&square), out_hex);
assert_eq!(o, o_out);
let (square_alt, o_alt) = x.square_prec_round_ref(prec, rm);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(o_alt, o_out);
let mut square_alt = x.clone();
let o_alt = square_alt.square_prec_round_assign(prec, rm);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt));
assert_eq!(o_alt, o_out);
let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, rm);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_square, rug_o) = rug_square_prec_round(&rug::Float::exact_from(&x), prec, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(rug_o, o);
}
};
test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal);
test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal);
test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal);
test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal);
test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal);
test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal);
test(
"Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal,
);
test(
"Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal,
);
test(
"Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal,
);
test("Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal);
test(
"Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal,
);
test(
"Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal,
);
test(
"-Infinity",
"-Infinity",
1,
Floor,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
1,
Ceiling,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
1,
Down,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
1,
Up,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
1,
Nearest,
"Infinity",
"Infinity",
Equal,
);
test(
"-Infinity",
"-Infinity",
1,
Exact,
"Infinity",
"Infinity",
Equal,
);
test("0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal);
test("0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal);
test("-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal);
test("1.0", "0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal);
test("1.0", "0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal);
test("1.0", "0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal);
test("1.0", "0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal);
test("1.0", "0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal);
test("1.0", "0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal);
test("1.0", "0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal);
test("-1.0", "-0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal);
test("-1.0", "-0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
Floor,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
Ceiling,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
Down,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
Up,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
Nearest,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
1,
Exact,
"1.0",
"0x1.0#1",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
Floor,
"1.0",
"0x1.000#10",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
Ceiling,
"1.0",
"0x1.000#10",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
Down,
"1.0",
"0x1.000#10",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
Up,
"1.0",
"0x1.000#10",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
Nearest,
"1.0",
"0x1.000#10",
Equal,
);
test(
"1.0",
"0x1.0000000000000000000000000#100",
10,
Exact,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
Floor,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
Ceiling,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
Down,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
Up,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
Nearest,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
1,
Exact,
"1.0",
"0x1.0#1",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
Floor,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
Ceiling,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
Down,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
Up,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
Nearest,
"1.0",
"0x1.000#10",
Equal,
);
test(
"-1.0",
"-0x1.0000000000000000000000000#100",
10,
Exact,
"1.0",
"0x1.000#10",
Equal,
);
test("123.0", "0x7b.0#7", 1, Floor, "8.0e3", "0x2.0E+3#1", Less);
test(
"123.0",
"0x7b.0#7",
1,
Ceiling,
"2.0e4",
"0x4.0E+3#1",
Greater,
);
test("123.0", "0x7b.0#7", 1, Down, "8.0e3", "0x2.0E+3#1", Less);
test("123.0", "0x7b.0#7", 1, Up, "2.0e4", "0x4.0E+3#1", Greater);
test(
"123.0",
"0x7b.0#7",
1,
Nearest,
"2.0e4",
"0x4.0E+3#1",
Greater,
);
test(
"123.0",
"0x7b.0#7",
10,
Floor,
"1.512e4",
"0x3.b1E+3#10",
Less,
);
test(
"123.0",
"0x7b.0#7",
10,
Ceiling,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test(
"123.0",
"0x7b.0#7",
10,
Down,
"1.512e4",
"0x3.b1E+3#10",
Less,
);
test(
"123.0",
"0x7b.0#7",
10,
Up,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test(
"123.0",
"0x7b.0#7",
10,
Nearest,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test("-123.0", "-0x7b.0#7", 1, Floor, "8.0e3", "0x2.0E+3#1", Less);
test(
"-123.0",
"-0x7b.0#7",
1,
Ceiling,
"2.0e4",
"0x4.0E+3#1",
Greater,
);
test("-123.0", "-0x7b.0#7", 1, Down, "8.0e3", "0x2.0E+3#1", Less);
test("-123.0", "-0x7b.0#7", 1, Up, "2.0e4", "0x4.0E+3#1", Greater);
test(
"-123.0",
"-0x7b.0#7",
1,
Nearest,
"2.0e4",
"0x4.0E+3#1",
Greater,
);
test(
"-123.0",
"-0x7b.0#7",
10,
Floor,
"1.512e4",
"0x3.b1E+3#10",
Less,
);
test(
"-123.0",
"-0x7b.0#7",
10,
Ceiling,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test(
"-123.0",
"-0x7b.0#7",
10,
Down,
"1.512e4",
"0x3.b1E+3#10",
Less,
);
test(
"-123.0",
"-0x7b.0#7",
10,
Up,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test(
"-123.0",
"-0x7b.0#7",
10,
Nearest,
"1.514e4",
"0x3.b2E+3#10",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
1,
Floor,
"2.0",
"0x2.0#1",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
1,
Ceiling,
"4.0",
"0x4.0#1",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
1,
Down,
"2.0",
"0x2.0#1",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
1,
Up,
"4.0",
"0x4.0#1",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
1,
Nearest,
"2.0",
"0x2.0#1",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
10,
Floor,
"2.0",
"0x2.00#10",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
10,
Ceiling,
"2.004",
"0x2.01#10",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
10,
Down,
"2.0",
"0x2.00#10",
Less,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
10,
Up,
"2.004",
"0x2.01#10",
Greater,
);
test(
"1.4142135623730951",
"0x1.6a09e667f3bcd#53",
10,
Nearest,
"2.0",
"0x2.00#10",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
1,
Floor,
"2.0",
"0x2.0#1",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
1,
Ceiling,
"4.0",
"0x4.0#1",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
1,
Down,
"2.0",
"0x2.0#1",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
1,
Up,
"4.0",
"0x4.0#1",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
1,
Nearest,
"2.0",
"0x2.0#1",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
10,
Floor,
"2.0",
"0x2.00#10",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
10,
Ceiling,
"2.004",
"0x2.01#10",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
10,
Down,
"2.0",
"0x2.00#10",
Less,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
10,
Up,
"2.004",
"0x2.01#10",
Greater,
);
test(
"-1.4142135623730951",
"-0x1.6a09e667f3bcd#53",
10,
Nearest,
"2.0",
"0x2.00#10",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
Floor,
"8.0",
"0x8.0#1",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
Ceiling,
"2.0e1",
"0x1.0E+1#1",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
Down,
"8.0",
"0x8.0#1",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
Up,
"2.0e1",
"0x1.0E+1#1",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
1,
Nearest,
"8.0",
"0x8.0#1",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
Floor,
"9.86",
"0x9.dc#10",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
Ceiling,
"9.88",
"0x9.e0#10",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
Down,
"9.86",
"0x9.dc#10",
Less,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
Up,
"9.88",
"0x9.e0#10",
Greater,
);
test(
"3.1415926535897931",
"0x3.243f6a8885a30#53",
10,
Nearest,
"9.88",
"0x9.e0#10",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
Floor,
"8.0",
"0x8.0#1",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
Ceiling,
"2.0e1",
"0x1.0E+1#1",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
Down,
"8.0",
"0x8.0#1",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
Up,
"2.0e1",
"0x1.0E+1#1",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
1,
Nearest,
"8.0",
"0x8.0#1",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
Floor,
"9.86",
"0x9.dc#10",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
Ceiling,
"9.88",
"0x9.e0#10",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
Down,
"9.86",
"0x9.dc#10",
Less,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
Up,
"9.88",
"0x9.e0#10",
Greater,
);
test(
"-3.1415926535897931",
"-0x3.243f6a8885a30#53",
10,
Nearest,
"9.88",
"0x9.e0#10",
Greater,
);
}
#[test]
fn square_prec_round_fail() {
const THREE: Float = Float::const_from_unsigned(3);
assert_panic!(Float::one_prec(1).square_prec_round(0, Floor));
assert_panic!(Float::one_prec(1).square_prec_round_ref(0, Floor));
assert_panic!({
let mut x = Float::one_prec(1);
x.square_prec_round_assign(0, Floor)
});
assert_panic!(THREE.square_prec_round(1, Exact));
assert_panic!(THREE.square_prec_round_ref(1, Exact));
assert_panic!({
let mut x = THREE;
x.square_prec_round_assign(1, Exact)
});
}
#[test]
fn square_prec_round_properties() {
float_unsigned_rounding_mode_triple_gen_var_2().test_properties(|(x, prec, rm)| {
let (square, o) = x.clone().square_prec_round(prec, rm);
assert!(square.is_valid());
let (square_alt, o_alt) = x.clone().square_prec_round_ref(prec, rm);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let mut x_alt = x.clone();
let o_alt = x_alt.square_prec_round_assign(prec, rm);
assert!(x_alt.is_valid());
assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, rm);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_square, rug_o) = rug_square_prec_round(&rug::Float::exact_from(&x), prec, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(rug_o, o);
}
if !x.is_nan() {
assert!(square.is_sign_positive());
}
let r_square = if square.is_finite() {
if square.is_normal() {
assert_eq!(square.get_prec(), Some(prec));
}
let r_square = Rational::exact_from(&x).square();
assert_eq!(square.partial_cmp(&r_square), Some(o));
if o == Less {
let mut next = square.clone();
next.increment();
assert!(next > r_square);
} else if o == Greater {
let mut next = square.clone();
next.decrement();
assert!(next < r_square);
}
Some(r_square)
} else {
assert_eq!(o, Equal);
None
};
match (
r_square.is_some() && *r_square.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 (square_alt, o_alt) = (-&x).square_prec_round(prec, rm);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (s, oo) = x.square_prec_round_ref(prec, rm);
assert_eq!(
ComparableFloat(s.abs_negative_zero_ref()),
ComparableFloat(square.abs_negative_zero_ref())
);
assert_eq!(oo, Equal);
}
} else {
assert_panic!(x.square_prec_round_ref(prec, Exact));
}
});
unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| {
let (product, o) = Float::NAN.square_prec_round(prec, rm);
assert!(product.is_nan());
assert_eq!(o, Equal);
assert_eq!(
Float::INFINITY.square_prec_round(prec, rm),
(Float::INFINITY, Equal)
);
assert_eq!(
Float::NEGATIVE_INFINITY.square_prec_round(prec, rm),
(Float::INFINITY, Equal)
);
let (s, o) = Float::ZERO.square_prec_round(prec, rm);
assert_eq!(ComparableFloat(s), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (s, o) = Float::NEGATIVE_ZERO.square_prec_round(prec, rm);
assert_eq!(ComparableFloat(s), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
assert_eq!(
Float::ONE.square_prec_round(prec, rm),
(Float::one_prec(prec), Equal)
);
assert_eq!(
Float::NEGATIVE_ONE.square_prec_round(prec, rm),
(Float::one_prec(prec), Equal)
);
});
}
#[allow(clippy::needless_pass_by_value)]
fn square_prec_properties_helper(x: Float, prec: u64) {
let (square, o) = x.clone().square_prec(prec);
assert!(square.is_valid());
let (square_alt, o_alt) = x.square_prec_ref(prec);
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let mut x_alt = x.clone();
let o_alt = x_alt.square_prec_assign(prec);
assert!(x_alt.is_valid());
assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, Nearest);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let (rug_square, rug_o) = rug_square_prec(&rug::Float::exact_from(&x), prec);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(rug_o, o);
let (square_alt, o_alt) = x.square_prec_round_ref(prec, Nearest);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
if !x.is_nan() {
assert!(square.is_sign_positive());
}
if square.is_finite() {
if square.is_normal() {
assert_eq!(square.get_prec(), Some(prec));
}
let r_square = Rational::exact_from(&x).square();
assert_eq!(square.partial_cmp(&r_square), Some(o));
if o == Less {
let mut next = square.clone();
next.increment();
assert!(next > r_square);
} else if o == Greater {
let mut next = square.clone();
next.decrement();
assert!(next < r_square);
}
} else {
assert_eq!(o, Equal);
}
let (square_alt, o_alt) = (-&x).square_prec(prec);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
}
#[test]
fn square_prec_properties() {
float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| {
square_prec_properties_helper(x, prec);
});
let mut config = GenConfig::new();
config.insert("mean_precision_n", 2048);
config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH);
float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| {
square_prec_properties_helper(x, prec);
});
unsigned_gen_var_11().test_properties(|prec| {
let (square, o) = Float::NAN.square_prec(prec);
assert!(square.is_nan());
assert_eq!(o, Equal);
let (square, o) = Float::ZERO.square_prec(prec);
assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (square, o) = Float::NEGATIVE_ZERO.square_prec(prec);
assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
assert_eq!(Float::INFINITY.square_prec(prec), (Float::INFINITY, Equal));
assert_eq!(
Float::NEGATIVE_INFINITY.square_prec(prec),
(Float::INFINITY, Equal)
);
assert_eq!(Float::ONE.square_prec(prec), (Float::one_prec(prec), Equal));
assert_eq!(
Float::NEGATIVE_ONE.square_prec(prec),
(Float::one_prec(prec), Equal)
);
});
}
#[allow(clippy::needless_pass_by_value)]
fn square_round_properties_helper(x: Float, rm: RoundingMode) {
let (square, o) = x.clone().square_round(rm);
assert!(square.is_valid());
let (square_alt, o_alt) = x.square_round_ref(rm);
assert!(square_alt.is_valid());
assert_eq!(o_alt, o);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
let mut x_alt = x.clone();
let o_alt = x_alt.square_round_assign(rm);
assert!(x_alt.is_valid());
assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let (square_alt, o_alt) = square_prec_round_naive(x.clone(), x.significant_bits(), rm);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
let (square_alt, o_alt) = x.square_prec_round_ref(x.significant_bits(), rm);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
assert_eq!(o_alt, o);
if !x.is_nan() {
assert!(square.is_sign_positive());
}
let r_square = if square.is_finite() {
if x.is_normal() && square.is_normal() {
assert_eq!(square.get_prec(), Some(x.get_prec().unwrap()));
}
let r_square = Rational::exact_from(&x).square();
assert_eq!(square.partial_cmp(&r_square), Some(o));
if o == Less {
let mut next = square.clone();
next.increment();
assert!(next > r_square);
} else if o == Greater {
let mut next = square.clone();
next.decrement();
assert!(next < r_square);
}
Some(r_square)
} else {
assert_eq!(o, Equal);
None
};
match (
r_square.is_some() && *r_square.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_square, rug_o) = rug_square_round(&rug::Float::exact_from(&x), rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(rug_o, o);
}
let (square_alt, o_alt) = (-&x).square_round(rm);
assert_eq!(o_alt, o);
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
if o == Equal {
for rm in exhaustive_rounding_modes() {
let (s, oo) = x.square_round_ref(rm);
assert_eq!(
ComparableFloat(s.abs_negative_zero_ref()),
ComparableFloat(square.abs_negative_zero_ref())
);
assert_eq!(oo, Equal);
}
} else {
assert_panic!(x.square_round_ref(Exact));
}
}
#[test]
fn square_round_properties() {
float_rounding_mode_pair_gen_var_7().test_properties(|(x, rm)| {
square_round_properties_helper(x, rm);
});
float_rounding_mode_pair_gen_var_8().test_properties(|(x, rm)| {
square_round_properties_helper(x, rm);
});
float_rounding_mode_pair_gen_var_9().test_properties(|(x, rm)| {
square_round_properties_helper(x, rm);
});
float_rounding_mode_pair_gen_var_10().test_properties(|(x, rm)| {
square_round_properties_helper(x, rm);
});
float_rounding_mode_pair_gen_var_11().test_properties(|(x, rm)| {
square_round_properties_helper(x, rm);
});
float_rounding_mode_pair_gen_var_12().test_properties(|(x, rm)| {
square_round_properties_helper(x, rm);
});
rounding_mode_gen().test_properties(|rm| {
let (square, o) = Float::NAN.square_round(rm);
assert!(square.is_nan());
assert_eq!(o, Equal);
let (square, o) = Float::ZERO.square_round(rm);
assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
let (square, o) = Float::NEGATIVE_ZERO.square_round(rm);
assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO));
assert_eq!(o, Equal);
assert_eq!(Float::INFINITY.square_round(rm), (Float::INFINITY, Equal));
assert_eq!(
Float::NEGATIVE_INFINITY.square_round(rm),
(Float::INFINITY, Equal)
);
assert_eq!(Float::ONE.square_round(rm), (Float::ONE, Equal));
assert_eq!(Float::NEGATIVE_ONE.square_round(rm), (Float::ONE, Equal));
});
}
fn square_properties_helper_1(x: Float) {
let square = x.clone().square();
assert!(square.is_valid());
let square_alt = (&x).square();
assert!(square_alt.is_valid());
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
let mut x_alt = x.clone();
x_alt.square_assign();
assert!(x_alt.is_valid());
assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square));
let square_alt = square_prec_round_naive(x.clone(), x.significant_bits(), Nearest).0;
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
let square_alt = x.square_prec_round_ref(x.significant_bits(), Nearest).0;
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
let square_alt = x.square_prec_ref(x.significant_bits()).0;
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
let square_alt = x.square_round_ref(Nearest).0;
assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square));
if !x.is_nan() {
assert!(square.is_sign_positive());
}
if square.is_finite() && x.is_normal() && square.is_normal() {
assert_eq!(square.get_prec(), Some(x.get_prec().unwrap()));
let r_square = Rational::exact_from(&x).square();
if square < r_square {
let mut next = square.clone();
next.increment();
assert!(next > r_square);
} else if square > r_square {
let mut next = square.clone();
next.decrement();
assert!(next < r_square);
}
}
let rug_square = rug_square(&rug::Float::exact_from(&x));
assert_eq!(
ComparableFloatRef(&Float::from(&rug_square)),
ComparableFloatRef(&square),
);
assert_eq!(ComparableFloat((-x).square()), ComparableFloat(square));
}
#[allow(clippy::type_repetition_in_bounds)]
fn square_properties_helper_2()
where
Float: From + PartialOrd,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_gen::().test_properties(|x| {
let square_1 = x.square();
let square_2 = emulate_primitive_float_fn(|x, prec| x.square_prec(prec).0, x);
assert_eq!(NiceFloat(square_1), NiceFloat(square_2));
});
}
#[test]
fn square_properties() {
float_gen().test_properties(|x| {
square_properties_helper_1(x);
});
float_gen_var_6().test_properties(|x| {
square_properties_helper_1(x);
});
float_gen_var_7().test_properties(|x| {
square_properties_helper_1(x);
});
float_gen_var_8().test_properties(|x| {
square_properties_helper_1(x);
});
float_gen_var_9().test_properties(|x| {
square_properties_helper_1(x);
});
float_gen_var_10().test_properties(|x| {
square_properties_helper_1(x);
});
apply_fn_to_primitive_floats!(square_properties_helper_2);
}