use malachite_base::num::arithmetic::traits::IsPowerOf2;
use malachite_base::num::basic::traits::Pi;
use malachite_base::rounding_modes::RoundingMode::{self, *};
use malachite_base::test_util::generators::{
unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4,
};
use malachite_float::test_util::common::{
rug_round_try_from_rounding_mode, test_constant, to_hex_string,
};
use malachite_float::test_util::constants::pi::rug_pi_prec_round;
use malachite_float::{ComparableFloat, ComparableFloatRef, Float};
use std::cmp::Ordering::{self, *};
use std::panic::catch_unwind;
fn test_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) {
let (x, o) = Float::pi_prec(prec);
assert!(x.is_valid());
assert_eq!(x.to_string(), out);
assert_eq!(to_hex_string(&x), out_hex);
assert_eq!(o, out_o);
let (rug_x, rug_o) =
rug_pi_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap());
assert_eq!(
ComparableFloatRef(&Float::from(&rug_x)),
ComparableFloatRef(&x)
);
assert_eq!(rug_o, o);
}
fn test_pi_prec_helper_big(prec: u64) {
let (x, o) = Float::pi_prec(prec);
assert!(x.is_valid());
let (rug_x, rug_o) =
rug_pi_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap());
assert_eq!(
ComparableFloatRef(&Float::from(&rug_x)),
ComparableFloatRef(&x)
);
assert_eq!(rug_o, o);
}
#[test]
pub fn test_pi_prec() {
test_pi_prec_helper(1, "4.0", "0x4.0#1", Greater);
test_pi_prec_helper(2, "3.0", "0x3.0#2", Less);
test_pi_prec_helper(3, "3.0", "0x3.0#3", Less);
test_pi_prec_helper(4, "3.2", "0x3.4#4", Greater);
test_pi_prec_helper(5, "3.1", "0x3.2#5", Less);
test_pi_prec_helper(6, "3.12", "0x3.2#6", Less);
test_pi_prec_helper(7, "3.16", "0x3.28#7", Greater);
test_pi_prec_helper(8, "3.14", "0x3.24#8", Less);
test_pi_prec_helper(9, "3.14", "0x3.24#9", Less);
test_pi_prec_helper(10, "3.141", "0x3.24#10", Less);
test_pi_prec_helper(
100,
"3.141592653589793238462643383279",
"0x3.243f6a8885a308d313198a2e0#100",
Less,
);
test_pi_prec_helper(
1000,
"3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034\
825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105\
559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348\
6104543266482133936072602491412736",
"0x3.243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be546\
6cf34e90c6cc0ac29b7c97c50dd3f84d5b5b54709179216d5d98979fb1bd1310ba698dfb5ac2ffd72dbd01adfb\
7b8e1afed6a267e96ba7c9045f12c7f9924a19947b3916cf70801f2e2858efc16636920d870#1000",
Less,
);
test_pi_prec_helper(
10000,
"3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034\
825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105\
559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348\
610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590\
360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118\
548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224\
737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771\
342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021\
960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459\
455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147\
303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195\
909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413\
891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319\
255060400927701671139009848824012858361603563707660104710181942955596198946767837449448255\
379774726847104047534646208046684259069491293313677028989152104752162056966024058038150193\
511253382430035587640247496473263914199272604269922796782354781636009341721641219924586315\
030286182974555706749838505494588586926995690927210797509302955321165344987202755960236480\
665499119881834797753566369807426542527862551818417574672890977772793800081647060016145249\
192173217214772350141441973568548161361157352552133475741849468438523323907394143334547762\
416862518983569485562099219222184272550254256887671790494601653466804988627232791786085784\
383827967976681454100953883786360950680064225125205117392984896084128488626945604241965285\
022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832\
645995813390478027590099465764078951269468398352595709825822620522489407726719478268482601\
476990902640136394437455305068203496252451749399651431429809190659250937221696461515709858\
387410597885959772975498930161753928468138268683868942774155991855925245953959431049972524\
680845987273644695848653836736222626099124608051243884390451244136549762780797715691435997\
700129616089441694868555848406353422072225828488648158456028506016842739452267467678895252\
138522549954666727823986456596116354886230577456498035593634568174324112515076069479451096\
596094025228879710893145669136867228748940560101503308617928680920874760917824938589009714\
909675985261365549781893129784821682998948722658804857564014270477555132379641451523746234\
364542858444795265867821051141354735739523113427166102135969536231442952484937187110145765\
403590279934403742007310578539062198387447808478489683321445713868751943506430218453191048\
481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814\
675142691239748940907186494231961567945208",
"0x3.243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be546\
6cf34e90c6cc0ac29b7c97c50dd3f84d5b5b54709179216d5d98979fb1bd1310ba698dfb5ac2ffd72dbd01adfb\
7b8e1afed6a267e96ba7c9045f12c7f9924a19947b3916cf70801f2e2858efc16636920d871574e69a458fea3f\
4933d7e0d95748f728eb658718bcd5882154aee7b54a41dc25a59b59c30d5392af26013c5d1b023286085f0ca4\
17918b8db38ef8e79dcb0603a180e6c9e0e8bb01e8a3ed71577c1bd314b2778af2fda55605c60e65525f3aa55a\
b945748986263e8144055ca396a2aab10b6b4cc5c341141e8cea15486af7c72e993b3ee1411636fbc2a2ba9c55\
d741831f6ce5c3e169b87931eafd6ba336c24cf5c7a325381289586773b8f48986b4bb9afc4bfe81b662821936\
1d809ccfb21a991487cac605dec8032ef845d5de98575b1dc262302eb651b8823893e81d396acc50f6d6ff383f\
442392e0b4482a484200469c8f04a9e1f9b5e21c66842f6e96c9a670c9c61abd388f06a51a0d2d8542f68960fa\
728ab5133a36eef0b6c137a3be4ba3bf0507efb2a98a1f1651d39af017666ca593e82430e888cee8619456f9fb\
47d84a5c33b8b5ebee06f75d885c12073401a449f56c16aa64ed3aa62363f77061bfedf72429b023d37d0d724d\
00a1248db0fead349f1c09b075372c980991b7b25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a\
94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5eb\
d09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c\
6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd2387605\
3317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbc\
a58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf\
2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a\
0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b\
3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc\
43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e8\
9a0d6411bd3ae1e7e4900250e2d2071b35e226800bb57b8e0af2464369bf009b91e5563911d59dfa6aa78c1438\
9d95a537f207d5ba202e5b9c5832603766295cfa911c819684e734a41b3472dca7b14a94a1b5100529a532915d\
60f573fbc9bc6e42b60a47681e6740008ba6fb5571be91ff296ec6b2a0dd915b6636521e7b9f9b6ff34052ec58\
5566453b02d5da99f8fa108ba47996e85076a4b7a70e9b5b32944db75092ec4192623ad6ea6b049a7df7d9cee6\
0b88fedb266ecaa8c71699a17ff5664526cc2b19ee1193602a575094c29a0591340e4183a3e3f54989a5b429d6\
56b8fe4d699f73fd6a1d29c07efe830f54d2d38e6f0255dc14cdd20868470eb266382e9c6021ecc5e09686b3f3\
ebaefc93c9718146b6a70a1687f358452a0e286b79c5305aa5007373e07841c7fdeae5c8e7c#10000",
Less,
);
test_pi_prec_helper_big(1000000);
let pi_f32 = Float::pi_prec(u64::from(f32::MANTISSA_DIGITS)).0;
assert_eq!(pi_f32.to_string(), "3.1415927");
assert_eq!(to_hex_string(&pi_f32), "0x3.243f6c#24");
assert_eq!(pi_f32, f32::PI);
let pi_f64 = Float::pi_prec(u64::from(f64::MANTISSA_DIGITS)).0;
assert_eq!(pi_f64.to_string(), "3.1415926535897931");
assert_eq!(to_hex_string(&pi_f64), "0x3.243f6a8885a30#53");
assert_eq!(pi_f64, f64::PI);
}
#[test]
#[should_panic]
fn pi_prec_fail_1() {
Float::pi_prec(0);
}
fn test_pi_prec_round_helper(
prec: u64,
rm: RoundingMode,
out: &str,
out_hex: &str,
out_o: Ordering,
) {
let (x, o) = Float::pi_prec_round(prec, rm);
assert!(x.is_valid());
assert_eq!(x.to_string(), out);
assert_eq!(to_hex_string(&x), out_hex);
assert_eq!(o, out_o);
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_x, rug_o) = rug_pi_prec_round(prec, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_x)),
ComparableFloatRef(&x)
);
assert_eq!(rug_o, o);
}
}
#[test]
pub fn test_pi_prec_round() {
test_pi_prec_round_helper(1, Floor, "2.0", "0x2.0#1", Less);
test_pi_prec_round_helper(1, Ceiling, "4.0", "0x4.0#1", Greater);
test_pi_prec_round_helper(1, Down, "2.0", "0x2.0#1", Less);
test_pi_prec_round_helper(1, Up, "4.0", "0x4.0#1", Greater);
test_pi_prec_round_helper(1, Nearest, "4.0", "0x4.0#1", Greater);
test_pi_prec_round_helper(2, Floor, "3.0", "0x3.0#2", Less);
test_pi_prec_round_helper(2, Ceiling, "4.0", "0x4.0#2", Greater);
test_pi_prec_round_helper(2, Down, "3.0", "0x3.0#2", Less);
test_pi_prec_round_helper(2, Up, "4.0", "0x4.0#2", Greater);
test_pi_prec_round_helper(2, Nearest, "3.0", "0x3.0#2", Less);
test_pi_prec_round_helper(3, Floor, "3.0", "0x3.0#3", Less);
test_pi_prec_round_helper(3, Ceiling, "3.5", "0x3.8#3", Greater);
test_pi_prec_round_helper(3, Down, "3.0", "0x3.0#3", Less);
test_pi_prec_round_helper(3, Up, "3.5", "0x3.8#3", Greater);
test_pi_prec_round_helper(3, Nearest, "3.0", "0x3.0#3", Less);
test_pi_prec_round_helper(4, Floor, "3.0", "0x3.0#4", Less);
test_pi_prec_round_helper(4, Ceiling, "3.2", "0x3.4#4", Greater);
test_pi_prec_round_helper(4, Down, "3.0", "0x3.0#4", Less);
test_pi_prec_round_helper(4, Up, "3.2", "0x3.4#4", Greater);
test_pi_prec_round_helper(4, Nearest, "3.2", "0x3.4#4", Greater);
test_pi_prec_round_helper(5, Floor, "3.1", "0x3.2#5", Less);
test_pi_prec_round_helper(5, Ceiling, "3.2", "0x3.4#5", Greater);
test_pi_prec_round_helper(5, Down, "3.1", "0x3.2#5", Less);
test_pi_prec_round_helper(5, Up, "3.2", "0x3.4#5", Greater);
test_pi_prec_round_helper(5, Nearest, "3.1", "0x3.2#5", Less);
test_pi_prec_round_helper(6, Floor, "3.12", "0x3.2#6", Less);
test_pi_prec_round_helper(6, Ceiling, "3.19", "0x3.3#6", Greater);
test_pi_prec_round_helper(6, Down, "3.12", "0x3.2#6", Less);
test_pi_prec_round_helper(6, Up, "3.19", "0x3.3#6", Greater);
test_pi_prec_round_helper(6, Nearest, "3.12", "0x3.2#6", Less);
test_pi_prec_round_helper(7, Floor, "3.12", "0x3.20#7", Less);
test_pi_prec_round_helper(7, Ceiling, "3.16", "0x3.28#7", Greater);
test_pi_prec_round_helper(7, Down, "3.12", "0x3.20#7", Less);
test_pi_prec_round_helper(7, Up, "3.16", "0x3.28#7", Greater);
test_pi_prec_round_helper(7, Nearest, "3.16", "0x3.28#7", Greater);
test_pi_prec_round_helper(8, Floor, "3.14", "0x3.24#8", Less);
test_pi_prec_round_helper(8, Ceiling, "3.16", "0x3.28#8", Greater);
test_pi_prec_round_helper(8, Down, "3.14", "0x3.24#8", Less);
test_pi_prec_round_helper(8, Up, "3.16", "0x3.28#8", Greater);
test_pi_prec_round_helper(8, Nearest, "3.14", "0x3.24#8", Less);
test_pi_prec_round_helper(9, Floor, "3.14", "0x3.24#9", Less);
test_pi_prec_round_helper(9, Ceiling, "3.15", "0x3.26#9", Greater);
test_pi_prec_round_helper(9, Down, "3.14", "0x3.24#9", Less);
test_pi_prec_round_helper(9, Up, "3.15", "0x3.26#9", Greater);
test_pi_prec_round_helper(9, Nearest, "3.14", "0x3.24#9", Less);
test_pi_prec_round_helper(10, Floor, "3.141", "0x3.24#10", Less);
test_pi_prec_round_helper(10, Ceiling, "3.145", "0x3.25#10", Greater);
test_pi_prec_round_helper(10, Down, "3.141", "0x3.24#10", Less);
test_pi_prec_round_helper(10, Up, "3.145", "0x3.25#10", Greater);
test_pi_prec_round_helper(10, Nearest, "3.141", "0x3.24#10", Less);
test_pi_prec_round_helper(
100,
Floor,
"3.141592653589793238462643383279",
"0x3.243f6a8885a308d313198a2e0#100",
Less,
);
test_pi_prec_round_helper(
100,
Ceiling,
"3.141592653589793238462643383282",
"0x3.243f6a8885a308d313198a2e4#100",
Greater,
);
test_pi_prec_round_helper(
100,
Down,
"3.141592653589793238462643383279",
"0x3.243f6a8885a308d313198a2e0#100",
Less,
);
test_pi_prec_round_helper(
100,
Up,
"3.141592653589793238462643383282",
"0x3.243f6a8885a308d313198a2e4#100",
Greater,
);
test_pi_prec_round_helper(
100,
Nearest,
"3.141592653589793238462643383279",
"0x3.243f6a8885a308d313198a2e0#100",
Less,
);
}
#[test]
#[should_panic]
fn pi_prec_round_fail_1() {
Float::pi_prec_round(0, Floor);
}
#[test]
#[should_panic]
fn pi_prec_round_fail_2() {
Float::pi_prec_round(1, Exact);
}
#[test]
#[should_panic]
fn pi_prec_round_fail_3() {
Float::pi_prec_round(1000, Exact);
}
#[test]
fn pi_prec_properties() {
unsigned_gen_var_11().test_properties(|prec| {
let (pi, o) = Float::pi_prec(prec);
assert!(pi.is_valid());
assert_eq!(pi.get_prec(), Some(prec));
assert_eq!(pi.get_exponent(), Some(if prec == 1 { 3 } else { 2 }));
assert_ne!(o, Equal);
if o == Less {
let (pi_alt, o_alt) = Float::pi_prec_round(prec, Ceiling);
let mut next_upper = pi.clone();
next_upper.increment();
if !next_upper.is_power_of_2() {
assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_upper));
assert_eq!(o_alt, Greater);
}
} else if !pi.is_power_of_2() {
let (pi_alt, o_alt) = Float::pi_prec_round(prec, Floor);
let mut next_lower = pi.clone();
next_lower.decrement();
assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_lower));
assert_eq!(o_alt, Less);
}
let (pi_alt, o_alt) = Float::pi_prec_round(prec, Nearest);
assert_eq!(ComparableFloatRef(&pi_alt), ComparableFloatRef(&pi));
assert_eq!(o_alt, o);
let (rug_pi, rug_o) =
rug_pi_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap());
assert_eq!(
ComparableFloatRef(&Float::from(&rug_pi)),
ComparableFloatRef(&pi)
);
assert_eq!(rug_o, o);
});
}
#[test]
fn pi_prec_round_properties() {
unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| {
let (pi, o) = Float::pi_prec_round(prec, rm);
assert!(pi.is_valid());
assert_eq!(pi.get_prec(), Some(prec));
let expected_exponent = match (prec, rm) {
(1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 3,
_ => 2,
};
assert_eq!(pi.get_exponent(), Some(expected_exponent));
assert_ne!(o, Equal);
if o == Less {
let (pi_alt, o_alt) = Float::pi_prec_round(prec, Ceiling);
let mut next_upper = pi.clone();
next_upper.increment();
if !next_upper.is_power_of_2() {
assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_upper));
assert_eq!(o_alt, Greater);
}
} else if !pi.is_power_of_2() {
let (pi_alt, o_alt) = Float::pi_prec_round(prec, Floor);
let mut next_lower = pi.clone();
next_lower.decrement();
assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_lower));
assert_eq!(o_alt, Less);
}
if let Ok(rm) = rug_round_try_from_rounding_mode(rm) {
let (rug_pi, rug_o) = rug_pi_prec_round(prec, rm);
assert_eq!(
ComparableFloatRef(&Float::from(&rug_pi)),
ComparableFloatRef(&pi)
);
assert_eq!(rug_o, o);
}
});
unsigned_gen_var_11().test_properties(|prec| {
assert_panic!(Float::pi_prec_round(prec, Exact));
});
test_constant(Float::pi_prec_round, 10000);
}