diff --git a/.cargo/config.in b/.cargo/config.in index ba9a973e5086..c29d6f544551 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -15,7 +15,7 @@ tag = "v0.4.10" [source."https://github.com/mozilla/mp4parse-rust"] git = "https://github.com/mozilla/mp4parse-rust" replace-with = "vendored-sources" -rev = "6ebb531e1b0381c7a5980279637ef6ae7a3b6bc2" +rev = "63325444ae3388599f2f222775eebdde4c2f9f30" [source."https://github.com/mozilla/application-services"] git = "https://github.com/mozilla/application-services" diff --git a/Cargo.lock b/Cargo.lock index ee79c48aa8d3..e217894544ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2344,7 +2344,7 @@ dependencies = [ "bytemuck", "byteorder", "num-iter", - "num-rational 0.2.1", + "num-rational", "num-traits", "png", ] @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mp4parse" version = "0.11.4" -source = "git+https://github.com/mozilla/mp4parse-rust?rev=6ebb531e1b0381c7a5980279637ef6ae7a3b6bc2#6ebb531e1b0381c7a5980279637ef6ae7a3b6bc2" +source = "git+https://github.com/mozilla/mp4parse-rust?rev=63325444ae3388599f2f222775eebdde4c2f9f30#63325444ae3388599f2f222775eebdde4c2f9f30" dependencies = [ "bitreader", "byteorder", @@ -3138,12 +3138,12 @@ version = "0.1.0" [[package]] name = "mp4parse_capi" version = "0.11.4" -source = "git+https://github.com/mozilla/mp4parse-rust?rev=6ebb531e1b0381c7a5980279637ef6ae7a3b6bc2#6ebb531e1b0381c7a5980279637ef6ae7a3b6bc2" +source = "git+https://github.com/mozilla/mp4parse-rust?rev=63325444ae3388599f2f222775eebdde4c2f9f30#63325444ae3388599f2f222775eebdde4c2f9f30" dependencies = [ "byteorder", "log", "mp4parse", - "num", + "num-traits", ] [[package]] @@ -3364,20 +3364,6 @@ dependencies = [ "nsstring", ] -[[package]] -name = "num" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3e176191bc4faad357e3122c4747aa098ac880e88b168f106386128736cf4a" -dependencies = [ - "num-bigint 0.3.0", - "num-complex", - "num-integer", - "num-iter", - "num-rational 0.3.0", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.2.3" @@ -3389,26 +3375,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" -dependencies = [ - "autocfg 1.0.0", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05ad05bd8977050b171b3f6b48175fea6e0565b7981059b486075e1026a9fb5" -dependencies = [ - "num-traits", -] - [[package]] name = "num-derive" version = "0.3.0" @@ -3422,21 +3388,19 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.43" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +checksum = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" dependencies = [ - "autocfg 1.0.0", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.41" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" +checksum = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" dependencies = [ - "autocfg 1.0.0", "num-integer", "num-traits", ] @@ -3451,25 +3415,13 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138" -dependencies = [ - "autocfg 1.0.0", - "num-bigint 0.3.0", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" dependencies = [ - "autocfg 1.0.0", + "autocfg 0.1.6", ] [[package]] @@ -3767,7 +3719,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c20593a99fe08068cbe2b59001527f36021d6ad53ac5f2d8793fcf2fe94015a0" dependencies = [ "libloading 0.5.2", - "num-bigint 0.2.3", + "num-bigint", ] [[package]] diff --git a/third_party/rust/mp4parse/.cargo-checksum.json b/third_party/rust/mp4parse/.cargo-checksum.json index 12bb60482b1e..6fc356ff099b 100644 --- a/third_party/rust/mp4parse/.cargo-checksum.json +++ b/third_party/rust/mp4parse/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"107804fbf8f667fbad45e7dea9fa1bb32ce8ef5580b543a54455e678d7769708","src/boxes.rs":"5f84805435af90034075709867e02c74a198e26dc628a9fc95df034928ee5bbc","src/fallible.rs":"7dc89699f1e75433ab5c6bbd23807383b3b918fe572d41e68e5a270591b0a4ab","src/lib.rs":"ff16461743a5e09c2dc8ade092206e4c84ddcae061766b38d53eff6f94916b2e","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"f1a27e785d4006cd910ca3c48c8a972da1db9c9b4a67185f67a191ddc3c69328","tests/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"fd646ffd5fab8beed5949b87482048ba400438fa90860f86f357a7f6141dc649"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"107804fbf8f667fbad45e7dea9fa1bb32ce8ef5580b543a54455e678d7769708","src/boxes.rs":"5f84805435af90034075709867e02c74a198e26dc628a9fc95df034928ee5bbc","src/fallible.rs":"836a36c2bc9803aead4bb24621e4fa6176c77b3752e69459a1f36555eb8bf2ec","src/lib.rs":"7c8bde48b42f5470a937d3affc4452e06b2158ff07c207f39376bdca11efa832","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"f1a27e785d4006cd910ca3c48c8a972da1db9c9b4a67185f67a191ddc3c69328","tests/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"fd646ffd5fab8beed5949b87482048ba400438fa90860f86f357a7f6141dc649"},"package":null} \ No newline at end of file diff --git a/third_party/rust/mp4parse/src/fallible.rs b/third_party/rust/mp4parse/src/fallible.rs index 1246a3d8df61..d0494448214b 100644 --- a/third_party/rust/mp4parse/src/fallible.rs +++ b/third_party/rust/mp4parse/src/fallible.rs @@ -256,7 +256,7 @@ impl TryVec { Ok(()) } - pub fn reserve(&mut self, additional: usize) -> Result<()> { + fn reserve(&mut self, additional: usize) -> Result<()> { #[cfg(feature = "mp4parse_fallible")] { let available = self diff --git a/third_party/rust/mp4parse/src/lib.rs b/third_party/rust/mp4parse/src/lib.rs index 872bfdcd32ae..0df227b86a72 100644 --- a/third_party/rust/mp4parse/src/lib.rs +++ b/third_party/rust/mp4parse/src/lib.rs @@ -58,7 +58,7 @@ impl ToU64 for usize { /// A trait to indicate a type can be infallibly converted to `usize`. /// This should only be implemented for infallible conversions, so only unsigned types are valid. -pub trait ToUsize { +trait ToUsize { fn to_usize(self) -> usize; } @@ -975,16 +975,16 @@ pub struct TrackTimeScale(pub T, pub usize); /// A time to be scaled by the track's local (mdhd) timescale. /// Members are time in scale units and the track id. #[derive(Debug, Copy, Clone, PartialEq)] -pub struct TrackScaledTime(pub T, pub usize); +pub struct TrackScaledTime(pub T, pub usize); impl std::ops::Add for TrackScaledTime where - T: num_traits::CheckedAdd, + T: Num, { - type Output = Option; + type Output = TrackScaledTime; - fn add(self, other: TrackScaledTime) -> Self::Output { - self.0.checked_add(&other.0).map(|sum| Self(sum, self.1)) + fn add(self, other: TrackScaledTime) -> TrackScaledTime { + TrackScaledTime::(self.0 + other.0, self.1) } } @@ -1953,7 +1953,6 @@ fn read_stbl(f: &mut BMFFBox, track: &mut Track) -> Result<()> { } /// Parse an ftyp box. -/// See ISO 14496-12:2015 § 4.3 fn read_ftyp(src: &mut BMFFBox) -> Result { let major = be_u32(src)?; let minor = be_u32(src)?; @@ -1963,7 +1962,7 @@ fn read_ftyp(src: &mut BMFFBox) -> Result { } // Is a brand_count of zero valid? let brand_count = bytes_left / 4; - let mut brands = TryVec::with_capacity(brand_count.try_into()?)?; + let mut brands = TryVec::new(); for _ in 0..brand_count { brands.push(be_u32(src)?.into())?; } @@ -2059,11 +2058,10 @@ fn read_tkhd(src: &mut BMFFBox) -> Result { } /// Parse a elst box. -/// See ISO 14496-12:2015 § 8.6.6 fn read_elst(src: &mut BMFFBox) -> Result { let (version, _) = read_fullbox_extra(src)?; let edit_count = be_u32_with_limit(src)?; - let mut edits = TryVec::with_capacity(edit_count.to_usize())?; + let mut edits = TryVec::new(); for _ in 0..edit_count { let (segment_duration, media_time) = match version { 1 => { @@ -2135,11 +2133,10 @@ fn read_mdhd(src: &mut BMFFBox) -> Result { } /// Parse a stco box. -/// See ISO 14496-12:2015 § 8.7.5 fn read_stco(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let offset_count = be_u32_with_limit(src)?; - let mut offsets = TryVec::with_capacity(offset_count.to_usize())?; + let mut offsets = TryVec::new(); for _ in 0..offset_count { offsets.push(be_u32(src)?.into())?; } @@ -2151,11 +2148,10 @@ fn read_stco(src: &mut BMFFBox) -> Result { } /// Parse a co64 box. -/// See ISO 14496-12:2015 § 8.7.5 fn read_co64(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let offset_count = be_u32_with_limit(src)?; - let mut offsets = TryVec::with_capacity(offset_count.to_usize())?; + let mut offsets = TryVec::new(); for _ in 0..offset_count { offsets.push(be_u64(src)?)?; } @@ -2167,11 +2163,10 @@ fn read_co64(src: &mut BMFFBox) -> Result { } /// Parse a stss box. -/// See ISO 14496-12:2015 § 8.6.2 fn read_stss(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_count = be_u32_with_limit(src)?; - let mut samples = TryVec::with_capacity(sample_count.to_usize())?; + let mut samples = TryVec::new(); for _ in 0..sample_count { samples.push(be_u32(src)?)?; } @@ -2183,11 +2178,10 @@ fn read_stss(src: &mut BMFFBox) -> Result { } /// Parse a stsc box. -/// See ISO 14496-12:2015 § 8.7.4 fn read_stsc(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_count = be_u32_with_limit(src)?; - let mut samples = TryVec::with_capacity(sample_count.to_usize())?; + let mut samples = TryVec::new(); for _ in 0..sample_count { let first_chunk = be_u32(src)?; let samples_per_chunk = be_u32_with_limit(src)?; @@ -2205,23 +2199,16 @@ fn read_stsc(src: &mut BMFFBox) -> Result { Ok(SampleToChunkBox { samples }) } -/// Parse a Composition Time to Sample Box -/// See ISO 14496-12:2015 § 8.6.1.3 fn read_ctts(src: &mut BMFFBox) -> Result { let (version, _) = read_fullbox_extra(src)?; - let counts = be_u32_with_limit(src)?; + let counts = u64::from(be_u32_with_limit(src)?); - if src.bytes_left() - < counts - .checked_mul(8) - .expect("counts -> bytes overflow") - .into() - { + if src.bytes_left() < counts.checked_mul(8).expect("counts -> bytes overflow") { return Err(Error::InvalidData("insufficient data in 'ctts' box")); } - let mut offsets = TryVec::with_capacity(counts.to_usize())?; + let mut offsets = TryVec::new(); for _ in 0..counts { let (sample_count, time_offset) = match version { // According to spec, Version0 shoule be used when version == 0; @@ -2248,14 +2235,12 @@ fn read_ctts(src: &mut BMFFBox) -> Result { } /// Parse a stsz box. -/// See ISO 14496-12:2015 § 8.7.3.2 fn read_stsz(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_size = be_u32(src)?; let sample_count = be_u32_with_limit(src)?; let mut sample_sizes = TryVec::new(); if sample_size == 0 { - sample_sizes.reserve(sample_count.to_usize())?; for _ in 0..sample_count { sample_sizes.push(be_u32(src)?)?; } @@ -2271,11 +2256,10 @@ fn read_stsz(src: &mut BMFFBox) -> Result { } /// Parse a stts box. -/// See ISO 14496-12:2015 § 8.6.1.2 fn read_stts(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_count = be_u32_with_limit(src)?; - let mut samples = TryVec::with_capacity(sample_count.to_usize())?; + let mut samples = TryVec::new(); for _ in 0..sample_count { let sample_count = be_u32_with_limit(src)?; let sample_delta = be_u32(src)?; @@ -2437,7 +2421,7 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { let des = &mut Cursor::new(remains); let tag = des.read_u8()?; - // See ISO 14496-1:2010 § 8.3.3 for interpreting size of expandable classes + // See ISO 14496-1:2010 § 8.3.3 for interpreting size of exandable classes let mut end: u32 = 0; // It's u8 without declaration type that is incorrect. // MSB of extend_or_len indicates more bytes, up to 4 bytes. @@ -2643,11 +2627,7 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { esds.extended_audio_object_type = extended_audio_object_type; esds.audio_sample_rate = Some(sample_frequency_value); esds.audio_channel_count = Some(channel_counts); - if !esds.decoder_specific_data.is_empty() { - return Err(Error::InvalidData( - "There can be only one DecSpecificInfoTag descriptor", - )); - } + assert!(esds.decoder_specific_data.is_empty()); esds.decoder_specific_data.extend_from_slice(data)?; Ok(()) @@ -2715,7 +2695,6 @@ fn read_es_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { Ok(()) } -/// See ISO 14496-14:2010 § 6.7.2 fn read_esds(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; @@ -2730,7 +2709,6 @@ fn read_esds(src: &mut BMFFBox) -> Result { } /// Parse `FLACSpecificBox`. -/// See https://github.com/xiph/flac/blob/master/doc/isoflac.txt § 3.3.2 fn read_dfla(src: &mut BMFFBox) -> Result { let (version, flags) = read_fullbox_extra(src)?; if version != 0 { @@ -3157,7 +3135,6 @@ fn read_audio_sample_entry(src: &mut BMFFBox) -> Result /// Parse a stsd box. /// See ISO 14496-12:2015 § 8.5.2 -/// See ISO 14496-14:2010 § 6.7.2 fn read_stsd(src: &mut BMFFBox, track: &mut Track) -> Result { let (_, _) = read_fullbox_extra(src)?; diff --git a/third_party/rust/mp4parse_capi/.cargo-checksum.json b/third_party/rust/mp4parse_capi/.cargo-checksum.json index 25ebfea13781..00fb14d110e8 100644 --- a/third_party/rust/mp4parse_capi/.cargo-checksum.json +++ b/third_party/rust/mp4parse_capi/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"1ea27367203b20aa8992320d1a561f0bf98e309d3f799ffa2c3eea3159d1ee57","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"e9b6b19c43962e0b21bbcbcab89c8acb09185f18939ccdf25534971e1146410c","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"13408d7785c5fe40f9db2bac1f93e8cf2aca7c35b5d2ba9acbbb23eb3a71e40a","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"598f828f07bac9b204d3eb7af4efd7158087382fc322dcce913a28729f854f70","src/lib.rs":"dfd3bccfb80aaab2389d11ae00242709d6c5dae8a299b55098bf5ec39698a097","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"adc8d264c46aef78c047377fbb792a4400d6db98bc44583b464d7b3dc182c884","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null} \ No newline at end of file diff --git a/third_party/rust/mp4parse_capi/Cargo.toml b/third_party/rust/mp4parse_capi/Cargo.toml index d6fae5030021..2904775e7214 100644 --- a/third_party/rust/mp4parse_capi/Cargo.toml +++ b/third_party/rust/mp4parse_capi/Cargo.toml @@ -26,7 +26,7 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" } byteorder = "1.2.1" log = "0.4" mp4parse = {version = "0.11.2", path = "../mp4parse"} -num = "0.3.0" +num-traits = "0.2.0" [dev-dependencies] env_logger = "0.7.1" diff --git a/third_party/rust/mp4parse_capi/examples/dump.rs b/third_party/rust/mp4parse_capi/examples/dump.rs index d00fdf5e9334..5907f5d701b6 100644 --- a/third_party/rust/mp4parse_capi/examples/dump.rs +++ b/third_party/rust/mp4parse_capi/examples/dump.rs @@ -62,7 +62,9 @@ fn dump_file(filename: &str) { for i in 0..counts { let mut track_info = Mp4parseTrackInfo { track_type: Mp4parseTrackType::Audio, - ..Default::default() + track_id: 0, + duration: 0, + media_time: 0, }; match mp4parse_get_track_info(parser, i, &mut track_info) { Mp4parseStatus::Ok => { diff --git a/third_party/rust/mp4parse_capi/src/lib.rs b/third_party/rust/mp4parse_capi/src/lib.rs index 648dd7d59e2a..ff26d2dfb49f 100644 --- a/third_party/rust/mp4parse_capi/src/lib.rs +++ b/third_party/rust/mp4parse_capi/src/lib.rs @@ -37,17 +37,11 @@ extern crate byteorder; extern crate mp4parse; -extern crate num; +extern crate num_traits; use byteorder::WriteBytesExt; -use num::{CheckedAdd, CheckedSub}; -use num::{PrimInt, Zero}; -use std::convert::TryFrom; -use std::convert::TryInto; - +use num_traits::{PrimInt, Zero}; use std::io::Read; -use std::ops::Neg; -use std::ops::{Add, Sub}; // Symbols we need from our rust api. use mp4parse::read_avif; @@ -61,7 +55,6 @@ use mp4parse::MediaContext; use mp4parse::MediaScaledTime; use mp4parse::MediaTimeScale; use mp4parse::SampleEntry; -use mp4parse::ToUsize; use mp4parse::Track; use mp4parse::TrackScaledTime; use mp4parse::TrackTimeScale; @@ -151,134 +144,36 @@ impl Default for Mp4ParseEncryptionSchemeType { } } -/// A zero-overhead wrapper around integer types for the sake of always -/// requiring checked arithmetic -#[repr(transparent)] -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct CheckedInteger(pub T); - -impl From for CheckedInteger { - fn from(i: T) -> Self { - Self(i) - } -} - -// Orphan rules prevent a more general implementation, but this suffices -impl From> for i64 { - fn from(checked: CheckedInteger) -> i64 { - checked.0 - } -} - -impl> Add for CheckedInteger -where - T: CheckedAdd, -{ - type Output = Option; - - fn add(self, other: U) -> Self::Output { - self.0.checked_add(&other.into()).map(Into::into) - } -} - -impl> Sub for CheckedInteger -where - T: CheckedSub, -{ - type Output = Option; - - fn sub(self, other: U) -> Self::Output { - self.0.checked_sub(&other.into()).map(Into::into) - } -} - -/// Implement subtraction of checked `u64`s returning i64 -// This is necessary for handling Mp4parseTrackInfo::media_time gracefully -impl Sub for CheckedInteger { - type Output = Option>; - - fn sub(self, other: Self) -> Self::Output { - if self >= other { - self.0 - .checked_sub(other.0) - .and_then(|u| i64::try_from(u).ok()) - .map(CheckedInteger) - } else { - other - .0 - .checked_sub(self.0) - .and_then(|u| i64::try_from(u).ok()) - .map(i64::neg) - .map(CheckedInteger) - } - } -} - -#[test] -fn u64_subtraction_returning_i64() { - // self > other - assert_eq!( - CheckedInteger(2u64) - CheckedInteger(1u64), - Some(CheckedInteger(1i64)) - ); - - // self == other - assert_eq!( - CheckedInteger(1u64) - CheckedInteger(1u64), - Some(CheckedInteger(0i64)) - ); - - // difference too large to store in i64 - assert_eq!(CheckedInteger(u64::MAX) - CheckedInteger(1u64), None); - - // self < other - assert_eq!( - CheckedInteger(1u64) - CheckedInteger(2u64), - Some(CheckedInteger(-1i64)) - ); - - // difference not representable due to overflow - assert_eq!(CheckedInteger(1u64) - CheckedInteger(u64::MAX), None); -} - -impl PartialEq for CheckedInteger { - fn eq(&self, other: &T) -> bool { - self.0 == *other - } -} - #[repr(C)] #[derive(Default, Debug)] pub struct Mp4parseTrackInfo { pub track_type: Mp4parseTrackType, pub track_id: u32, pub duration: u64, - pub media_time: CheckedInteger, // wants to be u64? understand how elst adjustment works - // TODO(kinetik): include crypto guff - // If this changes to u64, we can get rid of the strange - // impl Sub for CheckedInteger + pub media_time: i64, // wants to be u64? understand how elst adjustment works + // TODO(kinetik): include crypto guff } #[repr(C)] #[derive(Default, Debug, PartialEq)] pub struct Mp4parseIndice { /// The byte offset in the file where the indexed sample begins. - pub start_offset: CheckedInteger, + pub start_offset: u64, /// The byte offset in the file where the indexed sample ends. This is /// equivalent to `start_offset` + the length in bytes of the indexed /// sample. Typically this will be the `start_offset` of the next sample /// in the file. - pub end_offset: CheckedInteger, + pub end_offset: u64, /// The time in microseconds when the indexed sample should be displayed. /// Analogous to the concept of presentation time stamp (pts). - pub start_composition: CheckedInteger, + pub start_composition: i64, /// The time in microseconds when the indexed sample should stop being /// displayed. Typically this would be the `start_composition` time of the /// next sample if samples were ordered by composition time. - pub end_composition: CheckedInteger, + pub end_composition: i64, /// The time in microseconds that the indexed sample should be decoded at. /// Analogous to the concept of decode time stamp (dts). - pub start_decode: CheckedInteger, + pub start_decode: i64, /// Set if the indexed sample is a sync sample. The meaning of sync is /// somewhat codec specific, but essentially amounts to if the sample is a /// key frame. @@ -704,7 +599,7 @@ where let integer = numerator / denominator; let remainder = numerator % denominator; - num::cast(scale2).and_then(|s| match integer.checked_mul(&s) { + num_traits::cast(scale2).and_then(|s| match integer.checked_mul(&s) { Some(integer) => remainder .checked_mul(&s) .and_then(|remainder| (remainder / denominator).checked_add(&integer)), @@ -765,23 +660,19 @@ pub unsafe extern "C" fn mp4parse_get_track_info( let track = &context.tracks[track_index]; if let (Some(track_timescale), Some(context_timescale)) = (track.timescale, context.timescale) { - let media_time: CheckedInteger<_> = match track.media_time.map_or(Some(0), |media_time| { + let media_time = match track.media_time.map_or(Some(0), |media_time| { track_time_to_us(media_time, track_timescale) }) { - Some(time) => time.into(), + Some(time) => time as i64, None => return Mp4parseStatus::Invalid, }; - let empty_duration: CheckedInteger<_> = - match track.empty_duration.map_or(Some(0), |empty_duration| { - media_time_to_us(empty_duration, context_timescale) - }) { - Some(time) => time.into(), - None => return Mp4parseStatus::Invalid, - }; - info.media_time = match media_time - empty_duration { - Some(difference) => difference, + let empty_duration = match track.empty_duration.map_or(Some(0), |empty_duration| { + media_time_to_us(empty_duration, context_timescale) + }) { + Some(time) => time as i64, None => return Mp4parseStatus::Invalid, }; + info.media_time = media_time - empty_duration; if let Some(track_duration) = track.duration { match track_time_to_us(track_duration, track_timescale) { @@ -1244,28 +1135,23 @@ fn get_indice_table( } let media_time = match (&track.media_time, &track.timescale) { - (&Some(t), &Some(s)) => track_time_to_us(t, s) - .and_then(|v| i64::try_from(v).ok()) - .map(Into::into), + (&Some(t), &Some(s)) => track_time_to_us(t, s).map(|v| v as i64), _ => None, }; - let empty_duration: Option> = - match (&track.empty_duration, &context.timescale) { - (&Some(e), &Some(s)) => media_time_to_us(e, s) - .and_then(|v| i64::try_from(v).ok()) - .map(Into::into), - _ => None, - }; + let empty_duration = match (&track.empty_duration, &context.timescale) { + (&Some(e), &Some(s)) => media_time_to_us(e, s).map(|v| v as i64), + _ => None, + }; // Find the track start offset time from 'elst'. // 'media_time' maps start time onward, 'empty_duration' adds time offset // before first frame is displayed. let offset_time = match (empty_duration, media_time) { - (Some(e), Some(m)) => (e - m).ok_or(Err(Mp4parseStatus::Invalid))?, + (Some(e), Some(m)) => e - m, (Some(e), None) => e, (None, Some(m)) => m, - _ => 0.into(), + _ => 0, }; if let Some(v) = create_sample_table(track, offset_time) { @@ -1292,7 +1178,6 @@ struct TimeOffsetIterator<'a> { impl<'a> Iterator for TimeOffsetIterator<'a> { type Item = i64; - #[allow(clippy::reversed_empty_ranges)] fn next(&mut self) -> Option { let has_sample = self.cur_sample_range.next().or_else(|| { // At end of current TimeOffset, find the next TimeOffset. @@ -1349,7 +1234,6 @@ struct TimeToSampleIterator<'a> { impl<'a> Iterator for TimeToSampleIterator<'a> { type Item = u32; - #[allow(clippy::reversed_empty_ranges)] fn next(&mut self) -> Option { let has_sample = self.cur_sample_count.next().or_else(|| { self.cur_sample_count = match self.stts_iter.next() { @@ -1387,21 +1271,6 @@ impl<'a> TimeToSampleIterator<'a> { // For example: // (1, 5), (5, 10), (9, 2) => (1, 5), (2, 5), (3, 5), (4, 5), (5, 10), (6, 10), // (7, 10), (8, 10), (9, 2) -fn sample_to_chunk_iter<'a>( - stsc_samples: &'a TryVec, - stco_offsets: &'a TryVec, -) -> SampleToChunkIterator<'a> { - SampleToChunkIterator { - chunks: (0..0), - sample_count: 0, - stsc_peek_iter: stsc_samples.as_slice().iter().peekable(), - remain_chunk_count: stco_offsets - .len() - .try_into() - .expect("stco.entry_count is u32"), - } -} - struct SampleToChunkIterator<'a> { chunks: std::ops::Range, sample_count: u32, @@ -1416,12 +1285,7 @@ impl<'a> Iterator for SampleToChunkIterator<'a> { let has_chunk = self.chunks.next().or_else(|| { self.chunks = self.locate(); self.remain_chunk_count - .checked_sub( - self.chunks - .len() - .try_into() - .expect("len() of a Range must fit in u32"), - ) + .checked_sub(self.chunks.len() as u32) .and_then(|res| { self.remain_chunk_count = res; self.chunks.next() @@ -1433,7 +1297,6 @@ impl<'a> Iterator for SampleToChunkIterator<'a> { } impl<'a> SampleToChunkIterator<'a> { - #[allow(clippy::reversed_empty_ranges)] fn locate(&mut self) -> std::ops::Range { loop { return match (self.stsc_peek_iter.next(), self.stsc_peek_iter.peek()) { @@ -1461,11 +1324,7 @@ impl<'a> SampleToChunkIterator<'a> { } } -#[allow(clippy::reversed_empty_ranges)] -fn create_sample_table( - track: &Track, - track_offset_time: CheckedInteger, -) -> Option> { +fn create_sample_table(track: &Track, track_offset_time: i64) -> Option> { let timescale = match track.timescale { Some(ref t) => TrackTimeScale::(t.0 as i64, t.1), _ => return None, @@ -1482,32 +1341,31 @@ fn create_sample_table( _ => false, }; + let mut sample_table = TryVec::new(); let mut sample_size_iter = stsz.sample_sizes.iter(); // Get 'stsc' iterator for (chunk_id, chunk_sample_count) and calculate the sample // offset address. + let stsc_iter = SampleToChunkIterator { + chunks: (0..0), + sample_count: 0, + stsc_peek_iter: stsc.samples.as_slice().iter().peekable(), + remain_chunk_count: stco.offsets.len() as u32, + }; - // With large numbers of samples, the cost of many allocations dominates, - // so it's worth iterating twice to allocate sample_table just once. - let total_sample_count = sample_to_chunk_iter(&stsc.samples, &stco.offsets) - .by_ref() - .map(|(_, sample_counts)| sample_counts.to_usize()) - .sum(); - let mut sample_table = TryVec::with_capacity(total_sample_count).ok()?; - - for i in sample_to_chunk_iter(&stsc.samples, &stco.offsets) { + for i in stsc_iter { let chunk_id = i.0 as usize; let sample_counts = i.1; let mut cur_position = match stco.offsets.get(chunk_id) { - Some(&i) => i.into(), + Some(&i) => i, _ => return None, }; for _ in 0..sample_counts { let start_offset = cur_position; let end_offset = match (stsz.sample_size, sample_size_iter.next()) { - (_, Some(t)) => (start_offset + *t)?, - (t, _) if t > 0 => (start_offset + t)?, - _ => 0.into(), + (_, Some(t)) => start_offset + u64::from(*t), + (t, _) if t > 0 => start_offset + u64::from(t), + _ => 0, }; if end_offset == 0 { return None; @@ -1518,8 +1376,10 @@ fn create_sample_table( .push(Mp4parseIndice { start_offset, end_offset, + start_composition: 0, + end_composition: 0, + start_decode: 0, sync: !has_sync_table, - ..Default::default() }) .ok()?; } @@ -1529,7 +1389,7 @@ fn create_sample_table( if let Some(ref v) = track.stss { for iter in &v.samples { match iter - .checked_sub(&1) + .checked_sub(1) .and_then(|idx| sample_table.get_mut(idx as usize)) { Some(elem) => elem.sync = true, @@ -1566,20 +1426,25 @@ fn create_sample_table( let mut sum_delta = TrackScaledTime::(0, track.id); for sample in sample_table.as_mut_slice() { let decode_time = sum_delta; - sum_delta = (sum_delta + stts_iter.next_delta())?; + sum_delta = sum_delta + stts_iter.next_delta(); // ctts_offset is the current sample offset time. let ctts_offset = ctts_offset_iter.next_offset_time(); - let start_composition = track_time_to_us((decode_time + ctts_offset)?, timescale)?; + let start_composition = track_time_to_us(decode_time + ctts_offset, timescale); - let end_composition = track_time_to_us((sum_delta + ctts_offset)?, timescale)?; + let end_composition = track_time_to_us(sum_delta + ctts_offset, timescale); - let start_decode = track_time_to_us(decode_time, timescale)?; + let start_decode = track_time_to_us(decode_time, timescale); - sample.start_composition = (track_offset_time + start_composition)?; - sample.end_composition = (track_offset_time + end_composition)?; - sample.start_decode = start_decode.into(); + match (start_composition, end_composition, start_decode) { + (Some(s_c), Some(e_c), Some(s_d)) => { + sample.start_composition = s_c + track_offset_time; + sample.end_composition = e_c + track_offset_time; + sample.start_decode = s_d; + } + _ => return None, + } } // Correct composition end time due to 'ctts' causes composition time re-ordering. @@ -1588,15 +1453,14 @@ fn create_sample_table( // calculate to correct the composition end time. if !sample_table.is_empty() { // Create an index table refers to sample_table and sorted by start_composisiton time. - let mut sort_table = TryVec::with_capacity(sample_table.len()).ok()?; - + let mut sort_table = TryVec::new(); for i in 0..sample_table.len() { sort_table.push(i).ok()?; } sort_table.sort_by_key(|i| match sample_table.get(*i) { Some(v) => v.start_composition, - _ => 0.into(), + _ => 0, }); for indices in sort_table.windows(2) { @@ -1736,14 +1600,13 @@ fn get_pssh_info( pssh_data.clear(); for pssh in &context.psshs { - let content_len = pssh - .box_content - .len() - .try_into() - .map_err(|_| Mp4parseStatus::Invalid)?; + let content_len = pssh.box_content.len(); + if content_len > std::u32::MAX as usize { + return Err(Mp4parseStatus::Invalid); + } let mut data_len = TryVec::new(); if data_len - .write_u32::(content_len) + .write_u32::(content_len as u32) .is_err() { return Err(Mp4parseStatus::Io); @@ -1821,7 +1684,9 @@ fn arg_validation() { let mut dummy_info = Mp4parseTrackInfo { track_type: Mp4parseTrackType::Video, - ..Default::default() + track_id: 0, + duration: 0, + media_time: 0, }; assert_eq!( Mp4parseStatus::BadArg, @@ -1889,7 +1754,9 @@ fn arg_validation_with_parser() { let mut dummy_info = Mp4parseTrackInfo { track_type: Mp4parseTrackType::Video, - ..Default::default() + track_id: 0, + duration: 0, + media_time: 0, }; assert_eq!( Mp4parseStatus::BadArg, @@ -1961,7 +1828,9 @@ fn minimal_mp4_get_track_info() { let mut info = Mp4parseTrackInfo { track_type: Mp4parseTrackType::Video, - ..Default::default() + track_id: 0, + duration: 0, + media_time: 0, }; assert_eq!(Mp4parseStatus::Ok, unsafe { mp4parse_get_track_info(parser, 0, &mut info) @@ -2033,7 +1902,9 @@ fn minimal_mp4_get_track_info_invalid_track_number() { let mut info = Mp4parseTrackInfo { track_type: Mp4parseTrackType::Video, - ..Default::default() + track_id: 0, + duration: 0, + media_time: 0, }; assert_eq!(Mp4parseStatus::BadArg, unsafe { mp4parse_get_track_info(parser, 3, &mut info) diff --git a/third_party/rust/mp4parse_capi/tests/test_sample_table.rs b/third_party/rust/mp4parse_capi/tests/test_sample_table.rs index 018bfc8e9bc4..d86ce8eda64c 100644 --- a/third_party/rust/mp4parse_capi/tests/test_sample_table.rs +++ b/third_party/rust/mp4parse_capi/tests/test_sample_table.rs @@ -48,19 +48,19 @@ fn parse_sample_table() { // Compare the value from stagefright. let audio_indice_0 = Mp4parseIndice { - start_offset: 27_046.into(), - end_offset: 27_052.into(), - start_composition: 0.into(), - end_composition: 46_439.into(), - start_decode: 0.into(), + start_offset: 27_046, + end_offset: 27_052, + start_composition: 0, + end_composition: 46_439, + start_decode: 0, sync: true, }; let audio_indice_215 = Mp4parseIndice { - start_offset: 283_550.into(), - end_offset: 283_556.into(), - start_composition: 9_984_580.into(), - end_composition: 10_031_020.into(), - start_decode: 9_984_580.into(), + start_offset: 283_550, + end_offset: 283_556, + start_composition: 9_984_580, + end_composition: 10_031_020, + start_decode: 9_984_580, sync: true, }; assert_eq!(indice.length, 216); @@ -83,19 +83,19 @@ fn parse_sample_table() { // Compare the last few data from stagefright. let video_indice_291 = Mp4parseIndice { - start_offset: 280_226.into(), - end_offset: 280_855.into(), - start_composition: 9_838_333.into(), - end_composition: 9_871_677.into(), - start_decode: 9_710_000.into(), + start_offset: 280_226, + end_offset: 280_855, + start_composition: 9_838_333, + end_composition: 9_871_677, + start_decode: 9_710_000, sync: false, }; let video_indice_292 = Mp4parseIndice { - start_offset: 280_855.into(), - end_offset: 281_297.into(), - start_composition: 9_805_011.into(), - end_composition: 9_838_333.into(), - start_decode: 9_710_011.into(), + start_offset: 280_855, + end_offset: 281_297, + start_composition: 9_805_011, + end_composition: 9_838_333, + start_decode: 9_710_011, sync: false, }; // TODO: start_composition time in stagefright is 9905000, but it is 9904999 in parser, it @@ -103,19 +103,19 @@ fn parse_sample_table() { //let video_indice_293 = Mp4parseIndice { start_offset: 281_297, end_offset: 281_919, start_composition: 9_905_000, end_composition: 9_938_344, start_decode: 9_776_666, sync: false }; //let video_indice_294 = Mp4parseIndice { start_offset: 281_919, end_offset: 282_391, start_composition: 9_871_677, end_composition: 9_905_000, start_decode: 9_776_677, sync: false }; let video_indice_295 = Mp4parseIndice { - start_offset: 282_391.into(), - end_offset: 283_032.into(), - start_composition: 9_971_666.into(), - end_composition: 9_971_677.into(), - start_decode: 9_843_333.into(), + start_offset: 282_391, + end_offset: 283_032, + start_composition: 9_971_666, + end_composition: 9_971_677, + start_decode: 9_843_333, sync: false, }; let video_indice_296 = Mp4parseIndice { - start_offset: 283_092.into(), - end_offset: 283_526.into(), - start_composition: 9_938_344.into(), - end_composition: 9_971_666.into(), - start_decode: 9_843_344.into(), + start_offset: 283_092, + end_offset: 283_526, + start_composition: 9_938_344, + end_composition: 9_971_666, + start_decode: 9_843_344, sync: false, }; @@ -169,27 +169,27 @@ fn parse_sample_table_with_elst() { // Due to 'elst', the start_composition and end_composition are negative // at first two samples. let audio_indice_0 = Mp4parseIndice { - start_offset: 6992.into(), - end_offset: 7363.into(), - start_composition: (-36281).into(), - end_composition: (-13062).into(), - start_decode: 0.into(), + start_offset: 6992, + end_offset: 7363, + start_composition: -36281, + end_composition: -13062, + start_decode: 0, sync: true, }; let audio_indice_1 = Mp4parseIndice { - start_offset: 7363.into(), - end_offset: 7735.into(), - start_composition: (-13062).into(), - end_composition: 10158.into(), - start_decode: 23219.into(), + start_offset: 7363, + end_offset: 7735, + start_composition: -13062, + end_composition: 10158, + start_decode: 23219, sync: true, }; let audio_indice_2 = Mp4parseIndice { - start_offset: 7735.into(), - end_offset: 8106.into(), - start_composition: 10158.into(), - end_composition: 33378.into(), - start_decode: 46439.into(), + start_offset: 7735, + end_offset: 8106, + start_composition: 10158, + end_composition: 33378, + start_decode: 46439, sync: true, }; assert_eq!(indice.length, 21); @@ -236,35 +236,35 @@ fn parse_sample_table_with_negative_ctts() { // There are negative value in 'ctts' table. let video_indice_0 = Mp4parseIndice { - start_offset: 48.into(), - end_offset: 890.into(), - start_composition: 0.into(), - end_composition: 33_333.into(), - start_decode: 0.into(), + start_offset: 48, + end_offset: 890, + start_composition: 0, + end_composition: 33_333, + start_decode: 0, sync: true, }; let video_indice_1 = Mp4parseIndice { - start_offset: 890.into(), - end_offset: 913.into(), - start_composition: 133_333.into(), - end_composition: 166_666.into(), - start_decode: 33_333.into(), + start_offset: 890, + end_offset: 913, + start_composition: 133_333, + end_composition: 166_666, + start_decode: 33_333, sync: false, }; let video_indice_2 = Mp4parseIndice { - start_offset: 913.into(), - end_offset: 934.into(), - start_composition: 66_666.into(), - end_composition: 100_000.into(), - start_decode: 66_666.into(), + start_offset: 913, + end_offset: 934, + start_composition: 66_666, + end_composition: 100_000, + start_decode: 66_666, sync: false, }; let video_indice_3 = Mp4parseIndice { - start_offset: 934.into(), - end_offset: 955.into(), - start_composition: 33_333.into(), - end_composition: 66_666.into(), - start_decode: 100_000.into(), + start_offset: 934, + end_offset: 955, + start_composition: 33_333, + end_composition: 66_666, + start_decode: 100_000, sync: false, }; assert_eq!(indice.length, 300); diff --git a/third_party/rust/num-bigint-0.2.3/.cargo-checksum.json b/third_party/rust/num-bigint-0.2.3/.cargo-checksum.json deleted file mode 100644 index 288114fb2c67..000000000000 --- a/third_party/rust/num-bigint-0.2.3/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"ba1041ccca008388ab7d7432ae63b811d8e744c8fa9e50f371bfbeb78acd1995","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"25f684f15b0ed6ea216c3831e567a9b5dc02b78ff7e579e0d7323305db75218c","RELEASES.md":"5a3045437dc1850ae4e39acd14f2660ed7bace9b0c4d7dae3950f049dbfd4d65","benches/bigint.rs":"252c0dc1f220a6fbdc151e729069260c2f5909516467ceb873e412e5691d7042","benches/factorial.rs":"d536f5584987847f10321b94175a0d8fd2beb14b7c814ec28eef1f96ca081fbe","benches/gcd.rs":"7ec5ce7174e1d31bd08ccc5670f5a32a5c084f258d7980cd6d02e0a8bb5562c4","benches/roots.rs":"3f87db894c379122aee5cd8520c7c759c26d8a9649ac47f45d1bf4d560e1cb07","benches/shootout-pidigits.rs":"985b76d6dba05c396efe4da136c6a0bb2c02bcf5b05cbb346f0f802a891629bb","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"56d4fbb7a55750e61d2074df2735a31995c1decbd988c0e722926235e0fed487","ci/rustup.sh":"c976bb2756da3876363b01fdbf06c13de20df421e5add45e4017c4df42ed06a6","ci/test_full.sh":"a0ac26b85809eb43edd813c9dc88f34a1a8227b7618f4bede89c8f2ac9a4c05a","src/algorithms.rs":"8827c46df051214d1d0e7670680ca9f4834eae678ed340c86b5ea32fddbc7c3c","src/bigint.rs":"7f113fdc034c566bc8475ff0a7d136aa8250cae047b4356084e6797a15f968e1","src/bigrand.rs":"d2f72b8833f367dd8990b4b026f302d838144c5a4de942135d39a3a9932f137d","src/biguint.rs":"b95bfcf84e3f831fb07982aa4b058cd16a524eaa493946eed8e8c5fb8d65797a","src/lib.rs":"d5cc50306f73f07555e7d3413edd2ca5c7d54cbc80a2e83844d77fb8750ae314","src/macros.rs":"2e763517922d960c06e3ac4d319b1d81e66dffadfde8fdf300ff8b8bb95bd8cd","src/monty.rs":"6a867846b7f6af9115add2fd59fccd0651c71dd7f2316e8fb9c812ff3c27da12","tests/bigint.rs":"f7df454f085a862ad5a98e3a802303a3fdf06275a7a1b92074b40b76a715bed2","tests/bigint_bitwise.rs":"dc9436c8f200f2b0ac08cefb23bb8e39c4e688e9026a506a678416c3d573128b","tests/bigint_scalar.rs":"aa176ed102cafd425a215a93460806914d8f3ac288c98ec3e56772fa17379838","tests/biguint.rs":"9ae79f96d1a3beca5be95dffe9d79dc3436f886edc6cae51faf4203c3e0c4681","tests/biguint_scalar.rs":"9cc6f2bf2fe77f34b09eb2266c23aded3b27a60dc1859eb60d3013164292467e","tests/consts/mod.rs":"f9ea5f40733e2f5f432803d830be9db929d91e5e5efd8510b07c6ced2fe554be","tests/macros/mod.rs":"2789b680dd14a770d5ceef430018be0ada85098d69e218c61c17214084c4f763","tests/modpow.rs":"f14cdea11e355a371b314cc866dfa13281a3226706ab2cf01c1485273afde300","tests/quickcheck.rs":"6d6c1ec244b2384a8b34e989870aef8bcedccf6cc46e2626b29a032703bef03c","tests/rand.rs":"08370135bd78432660cfcd708a9ea852022d555bc92c1f3c482fabd17faa64a0","tests/roots.rs":"9ec1bdb0cd1c72402a41e5470325a5276af75979b7fc0f0b63e7bbbb9f3505b2","tests/serde.rs":"79d7a0347207b3a3666af67d2ed97fa34f2922732121a3cb8f5b9f990846acfa","tests/torture.rs":"9fe4897580c0ebe2b7062f5b0b890b4b03510daa45c9236f0edba7144f9eb6f8"},"package":"f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a"} \ No newline at end of file diff --git a/third_party/rust/num-bigint-0.2.3/Cargo.toml b/third_party/rust/num-bigint-0.2.3/Cargo.toml deleted file mode 100644 index d8403a5659fc..000000000000 --- a/third_party/rust/num-bigint-0.2.3/Cargo.toml +++ /dev/null @@ -1,81 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "num-bigint" -version = "0.2.3" -authors = ["The Rust Project Developers"] -build = "build.rs" -description = "Big integer implementation for Rust" -homepage = "https://github.com/rust-num/num-bigint" -documentation = "https://docs.rs/num-bigint" -readme = "README.md" -keywords = ["mathematics", "numerics", "bignum"] -categories = ["algorithms", "data-structures", "science"] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num-bigint" -[package.metadata.docs.rs] -features = ["std", "serde", "rand", "quickcheck"] - -[[bench]] -name = "bigint" - -[[bench]] -name = "factorial" - -[[bench]] -name = "gcd" - -[[bench]] -name = "roots" - -[[bench]] -name = "shootout-pidigits" -harness = false -[dependencies.num-integer] -version = "0.1.39" -default-features = false - -[dependencies.num-traits] -version = "0.2.7" -default-features = false - -[dependencies.quickcheck] -version = "0.8" -optional = true -default-features = false - -[dependencies.quickcheck_macros] -version = "0.8" -optional = true -default-features = false - -[dependencies.rand] -version = "0.5" -features = ["std"] -optional = true -default-features = false - -[dependencies.serde] -version = "1.0" -features = ["std"] -optional = true -default-features = false -[dev-dependencies.serde_test] -version = "1.0" -[build-dependencies.autocfg] -version = "0.1.2" - -[features] -default = ["std"] -i128 = ["num-integer/i128", "num-traits/i128"] -std = ["num-integer/std", "num-traits/std"] diff --git a/third_party/rust/num-bigint-0.2.3/LICENSE-APACHE b/third_party/rust/num-bigint-0.2.3/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/third_party/rust/num-bigint-0.2.3/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/third_party/rust/num-bigint-0.2.3/LICENSE-MIT b/third_party/rust/num-bigint-0.2.3/LICENSE-MIT deleted file mode 100644 index 39d4bdb5acd3..000000000000 --- a/third_party/rust/num-bigint-0.2.3/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/num-bigint-0.2.3/README.md b/third_party/rust/num-bigint-0.2.3/README.md deleted file mode 100644 index f7eefed87e69..000000000000 --- a/third_party/rust/num-bigint-0.2.3/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# num-bigint - -[![crate](https://img.shields.io/crates/v/num-bigint.svg)](https://crates.io/crates/num-bigint) -[![documentation](https://docs.rs/num-bigint/badge.svg)](https://docs.rs/num-bigint) -![minimum rustc 1.15](https://img.shields.io/badge/rustc-1.15+-red.svg) -[![Travis status](https://travis-ci.org/rust-num/num-bigint.svg?branch=master)](https://travis-ci.org/rust-num/num-bigint) - -Big integer types for Rust, `BigInt` and `BigUint`. - -## Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] -num-bigint = "0.2" -``` - -and this to your crate root: - -```rust -extern crate num_bigint; -``` - -## Features - -The `std` crate feature is mandatory and enabled by default. If you depend on -`num-bigint` with `default-features = false`, you must manually enable the -`std` feature yourself. In the future, we hope to support `#![no_std]` with -the `alloc` crate when `std` is not enabled. - -Implementations for `i128` and `u128` are only available with Rust 1.26 and -later. The build script automatically detects this, but you can make it -mandatory by enabling the `i128` crate feature. - -## Releases - -Release notes are available in [RELEASES.md](RELEASES.md). - -## Compatibility - -The `num-bigint` crate is tested for rustc 1.15 and greater. - -## Alternatives - -While `num-bigint` strives for good performance in pure Rust code, other -crates may offer better performance with different trade-offs. The following -table offers a brief comparison to a few alternatives. - -| Crate | License | Min rustc | Implementation | -| :--------------- | :------------- | :-------- | :------------- | -| **`num-bigint`** | MIT/Apache-2.0 | 1.15 | pure rust | -| [`ramp`] | Apache-2.0 | nightly | rust and inline assembly | -| [`rug`] | LGPL-3.0+ | 1.31 | bundles [GMP] via [`gmp-mpfr-sys`] | -| [`rust-gmp`] | MIT | stable? | links to [GMP] | -| [`apint`] | MIT/Apache-2.0 | 1.26 | pure rust (unfinished) | - -[GMP]: https://gmplib.org/ -[`gmp-mpfr-sys`]: https://crates.io/crates/gmp-mpfr-sys -[`rug`]: https://crates.io/crates/rug -[`rust-gmp`]: https://crates.io/crates/rust-gmp -[`ramp`]: https://crates.io/crates/ramp -[`apint`]: https://crates.io/crates/apint diff --git a/third_party/rust/num-bigint-0.2.3/RELEASES.md b/third_party/rust/num-bigint-0.2.3/RELEASES.md deleted file mode 100644 index 911dd7835f87..000000000000 --- a/third_party/rust/num-bigint-0.2.3/RELEASES.md +++ /dev/null @@ -1,134 +0,0 @@ -# Release 0.2.3 (2019-09-03) - -- [`Pow` is now implemented for `BigUint` exponents][77]. -- [The optional `quickcheck` feature enables implementations of `Arbitrary`][99]. -- See the [full comparison][compare-0.2.3] for performance enhancements and more! - -[77]: https://github.com/rust-num/num-bigint/pull/77 -[99]: https://github.com/rust-num/num-bigint/pull/99 -[compare-0.2.3]: https://github.com/rust-num/num-bigint/compare/num-bigint-0.2.2...num-bigint-0.2.3 - -**Contributors**: @cuviper, @lcnr, @maxbla, @mikelodder7, @mikong, -@TheLetterTheta, @tspiteri, @XAMPPRocky, @youknowone - -# Release 0.2.2 (2018-12-14) - -- [The `Roots` implementations now use better initial guesses][71]. -- [Fixed `to_signed_bytes_*` for some positive numbers][72], where the - most-significant byte is `0x80` and the rest are `0`. - -[71]: https://github.com/rust-num/num-bigint/pull/71 -[72]: https://github.com/rust-num/num-bigint/pull/72 - -**Contributors**: @cuviper, @leodasvacas - -# Release 0.2.1 (2018-11-02) - -- [`RandBigInt` now uses `Rng::fill_bytes`][53] to improve performance, instead - of repeated `gen::` calls. The also affects the implementations of the - other `rand` traits. This may potentially change the values produced by some - seeded RNGs on previous versions, but the values were tested to be stable - with `ChaChaRng`, `IsaacRng`, and `XorShiftRng`. -- [`BigInt` and `BigUint` now implement `num_integer::Roots`][56]. -- [`BigInt` and `BigUint` now implement `num_traits::Pow`][54]. -- [`BigInt` and `BigUint` now implement operators with 128-bit integers][64]. - -**Contributors**: @cuviper, @dignifiedquire, @mancabizjak, @Robbepop, -@TheIronBorn, @thomwiggers - -[53]: https://github.com/rust-num/num-bigint/pull/53 -[54]: https://github.com/rust-num/num-bigint/pull/54 -[56]: https://github.com/rust-num/num-bigint/pull/56 -[64]: https://github.com/rust-num/num-bigint/pull/64 - -# Release 0.2.0 (2018-05-25) - -### Enhancements - -- [`BigInt` and `BigUint` now implement `Product` and `Sum`][22] for iterators - of any item that we can `Mul` and `Add`, respectively. For example, a - factorial can now be simply: `let f: BigUint = (1u32..1000).product();` -- [`BigInt` now supports two's-complement logic operations][26], namely - `BitAnd`, `BitOr`, `BitXor`, and `Not`. These act conceptually as if each - number had an infinite prefix of `0` or `1` bits for positive or negative. -- [`BigInt` now supports assignment operators][41] like `AddAssign`. -- [`BigInt` and `BigUint` now support conversions with `i128` and `u128`][44], - if sufficient compiler support is detected. -- [`BigInt` and `BigUint` now implement rand's `SampleUniform` trait][48], and - [a custom `RandomBits` distribution samples by bit size][49]. -- The release also includes other miscellaneous improvements to performance. - -### Breaking Changes - -- [`num-bigint` now requires rustc 1.15 or greater][23]. -- [The crate now has a `std` feature, and won't build without it][46]. This is - in preparation for someday supporting `#![no_std]` with `alloc`. -- [The `serde` dependency has been updated to 1.0][24], still disabled by - default. The `rustc-serialize` crate is no longer supported by `num-bigint`. -- [The `rand` dependency has been updated to 0.5][48], now disabled by default. - This requires rustc 1.22 or greater for `rand`'s own requirement. -- [`Shr for BigInt` now rounds down][8] rather than toward zero, matching the - behavior of the primitive integers for negative values. -- [`ParseBigIntError` is now an opaque type][37]. -- [The `big_digit` module is no longer public][38], nor are the `BigDigit` and - `DoubleBigDigit` types and `ZERO_BIG_DIGIT` constant that were re-exported in - the crate root. Public APIs which deal in digits, like `BigUint::from_slice`, - will now always be base-`u32`. - -**Contributors**: @clarcharr, @cuviper, @dodomorandi, @tiehuis, @tspiteri - -[8]: https://github.com/rust-num/num-bigint/pull/8 -[22]: https://github.com/rust-num/num-bigint/pull/22 -[23]: https://github.com/rust-num/num-bigint/pull/23 -[24]: https://github.com/rust-num/num-bigint/pull/24 -[26]: https://github.com/rust-num/num-bigint/pull/26 -[37]: https://github.com/rust-num/num-bigint/pull/37 -[38]: https://github.com/rust-num/num-bigint/pull/38 -[41]: https://github.com/rust-num/num-bigint/pull/41 -[44]: https://github.com/rust-num/num-bigint/pull/44 -[46]: https://github.com/rust-num/num-bigint/pull/46 -[48]: https://github.com/rust-num/num-bigint/pull/48 -[49]: https://github.com/rust-num/num-bigint/pull/49 - -# Release 0.1.44 (2018-05-14) - -- [Division with single-digit divisors is now much faster.][42] -- The README now compares [`ramp`, `rug`, `rust-gmp`][20], and [`apint`][21]. - -**Contributors**: @cuviper, @Robbepop - -[20]: https://github.com/rust-num/num-bigint/pull/20 -[21]: https://github.com/rust-num/num-bigint/pull/21 -[42]: https://github.com/rust-num/num-bigint/pull/42 - -# Release 0.1.43 (2018-02-08) - -- [The new `BigInt::modpow`][18] performs signed modular exponentiation, using - the existing `BigUint::modpow` and rounding negatives similar to `mod_floor`. - -**Contributors**: @cuviper - -[18]: https://github.com/rust-num/num-bigint/pull/18 - - -# Release 0.1.42 (2018-02-07) - -- [num-bigint now has its own source repository][num-356] at [rust-num/num-bigint][home]. -- [`lcm` now avoids creating a large intermediate product][num-350]. -- [`gcd` now uses Stein's algorithm][15] with faster shifts instead of division. -- [`rand` support is now extended to 0.4][11] (while still allowing 0.3). - -**Contributors**: @cuviper, @Emerentius, @ignatenkobrain, @mhogrefe - -[home]: https://github.com/rust-num/num-bigint -[num-350]: https://github.com/rust-num/num/pull/350 -[num-356]: https://github.com/rust-num/num/pull/356 -[11]: https://github.com/rust-num/num-bigint/pull/11 -[15]: https://github.com/rust-num/num-bigint/pull/15 - - -# Prior releases - -No prior release notes were kept. Thanks all the same to the many -contributors that have made this crate what it is! - diff --git a/third_party/rust/num-bigint-0.2.3/benches/bigint.rs b/third_party/rust/num-bigint-0.2.3/benches/bigint.rs deleted file mode 100644 index bc0875d8f6c2..000000000000 --- a/third_party/rust/num-bigint-0.2.3/benches/bigint.rs +++ /dev/null @@ -1,368 +0,0 @@ -#![feature(test)] -#![cfg(feature = "rand")] - -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; -extern crate rand; -extern crate test; - -use num_bigint::{BigInt, BigUint, RandBigInt}; -use num_traits::{FromPrimitive, Num, One, Pow, Zero}; -use rand::{SeedableRng, StdRng}; -use std::mem::replace; -use test::Bencher; - -fn get_rng() -> StdRng { - let mut seed = [0; 32]; - for i in 1..32 { - seed[usize::from(i)] = i; - } - SeedableRng::from_seed(seed) -} - -fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) { - let mut rng = get_rng(); - let x = rng.gen_bigint(xbits); - let y = rng.gen_bigint(ybits); - - b.iter(|| &x * &y); -} - -fn divide_bench(b: &mut Bencher, xbits: usize, ybits: usize) { - let mut rng = get_rng(); - let x = rng.gen_bigint(xbits); - let y = rng.gen_bigint(ybits); - - b.iter(|| &x / &y); -} - -fn remainder_bench(b: &mut Bencher, xbits: usize, ybits: usize) { - let mut rng = get_rng(); - let x = rng.gen_bigint(xbits); - let y = rng.gen_bigint(ybits); - - b.iter(|| &x % &y); -} - -fn factorial(n: usize) -> BigUint { - let mut f: BigUint = One::one(); - for i in 1..(n + 1) { - let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); - f = f * bu; - } - f -} - -/// Compute Fibonacci numbers -fn fib(n: usize) -> BigUint { - let mut f0: BigUint = Zero::zero(); - let mut f1: BigUint = One::one(); - for _ in 0..n { - let f2 = f0 + &f1; - f0 = replace(&mut f1, f2); - } - f0 -} - -/// Compute Fibonacci numbers with two ops per iteration -/// (add and subtract, like issue #200) -fn fib2(n: usize) -> BigUint { - let mut f0: BigUint = Zero::zero(); - let mut f1: BigUint = One::one(); - for _ in 0..n { - f1 = f1 + &f0; - f0 = &f1 - f0; - } - f0 -} - -#[bench] -fn multiply_0(b: &mut Bencher) { - multiply_bench(b, 1 << 8, 1 << 8); -} - -#[bench] -fn multiply_1(b: &mut Bencher) { - multiply_bench(b, 1 << 8, 1 << 16); -} - -#[bench] -fn multiply_2(b: &mut Bencher) { - multiply_bench(b, 1 << 16, 1 << 16); -} - -#[bench] -fn multiply_3(b: &mut Bencher) { - multiply_bench(b, 1 << 16, 1 << 17); -} - -#[bench] -fn divide_0(b: &mut Bencher) { - divide_bench(b, 1 << 8, 1 << 6); -} - -#[bench] -fn divide_1(b: &mut Bencher) { - divide_bench(b, 1 << 12, 1 << 8); -} - -#[bench] -fn divide_2(b: &mut Bencher) { - divide_bench(b, 1 << 16, 1 << 12); -} - -#[bench] -fn remainder_0(b: &mut Bencher) { - remainder_bench(b, 1 << 8, 1 << 6); -} - -#[bench] -fn remainder_1(b: &mut Bencher) { - remainder_bench(b, 1 << 12, 1 << 8); -} - -#[bench] -fn remainder_2(b: &mut Bencher) { - remainder_bench(b, 1 << 16, 1 << 12); -} - -#[bench] -fn factorial_100(b: &mut Bencher) { - b.iter(|| factorial(100)); -} - -#[bench] -fn fib_100(b: &mut Bencher) { - b.iter(|| fib(100)); -} - -#[bench] -fn fib_1000(b: &mut Bencher) { - b.iter(|| fib(1000)); -} - -#[bench] -fn fib_10000(b: &mut Bencher) { - b.iter(|| fib(10000)); -} - -#[bench] -fn fib2_100(b: &mut Bencher) { - b.iter(|| fib2(100)); -} - -#[bench] -fn fib2_1000(b: &mut Bencher) { - b.iter(|| fib2(1000)); -} - -#[bench] -fn fib2_10000(b: &mut Bencher) { - b.iter(|| fib2(10000)); -} - -#[bench] -fn fac_to_string(b: &mut Bencher) { - let fac = factorial(100); - b.iter(|| fac.to_string()); -} - -#[bench] -fn fib_to_string(b: &mut Bencher) { - let fib = fib(100); - b.iter(|| fib.to_string()); -} - -fn to_str_radix_bench(b: &mut Bencher, radix: u32) { - let mut rng = get_rng(); - let x = rng.gen_bigint(1009); - b.iter(|| x.to_str_radix(radix)); -} - -#[bench] -fn to_str_radix_02(b: &mut Bencher) { - to_str_radix_bench(b, 2); -} - -#[bench] -fn to_str_radix_08(b: &mut Bencher) { - to_str_radix_bench(b, 8); -} - -#[bench] -fn to_str_radix_10(b: &mut Bencher) { - to_str_radix_bench(b, 10); -} - -#[bench] -fn to_str_radix_16(b: &mut Bencher) { - to_str_radix_bench(b, 16); -} - -#[bench] -fn to_str_radix_36(b: &mut Bencher) { - to_str_radix_bench(b, 36); -} - -fn from_str_radix_bench(b: &mut Bencher, radix: u32) { - let mut rng = get_rng(); - let x = rng.gen_bigint(1009); - let s = x.to_str_radix(radix); - assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap()); - b.iter(|| BigInt::from_str_radix(&s, radix)); -} - -#[bench] -fn from_str_radix_02(b: &mut Bencher) { - from_str_radix_bench(b, 2); -} - -#[bench] -fn from_str_radix_08(b: &mut Bencher) { - from_str_radix_bench(b, 8); -} - -#[bench] -fn from_str_radix_10(b: &mut Bencher) { - from_str_radix_bench(b, 10); -} - -#[bench] -fn from_str_radix_16(b: &mut Bencher) { - from_str_radix_bench(b, 16); -} - -#[bench] -fn from_str_radix_36(b: &mut Bencher) { - from_str_radix_bench(b, 36); -} - -fn rand_bench(b: &mut Bencher, bits: usize) { - let mut rng = get_rng(); - - b.iter(|| rng.gen_bigint(bits)); -} - -#[bench] -fn rand_64(b: &mut Bencher) { - rand_bench(b, 1 << 6); -} - -#[bench] -fn rand_256(b: &mut Bencher) { - rand_bench(b, 1 << 8); -} - -#[bench] -fn rand_1009(b: &mut Bencher) { - rand_bench(b, 1009); -} - -#[bench] -fn rand_2048(b: &mut Bencher) { - rand_bench(b, 1 << 11); -} - -#[bench] -fn rand_4096(b: &mut Bencher) { - rand_bench(b, 1 << 12); -} - -#[bench] -fn rand_8192(b: &mut Bencher) { - rand_bench(b, 1 << 13); -} - -#[bench] -fn rand_65536(b: &mut Bencher) { - rand_bench(b, 1 << 16); -} - -#[bench] -fn rand_131072(b: &mut Bencher) { - rand_bench(b, 1 << 17); -} - -#[bench] -fn shl(b: &mut Bencher) { - let n = BigUint::one() << 1000; - b.iter(|| { - let mut m = n.clone(); - for i in 0..50 { - m = m << i; - } - }) -} - -#[bench] -fn shr(b: &mut Bencher) { - let n = BigUint::one() << 2000; - b.iter(|| { - let mut m = n.clone(); - for i in 0..50 { - m = m >> i; - } - }) -} - -#[bench] -fn hash(b: &mut Bencher) { - use std::collections::HashSet; - let mut rng = get_rng(); - let v: Vec = (1000..2000).map(|bits| rng.gen_bigint(bits)).collect(); - b.iter(|| { - let h: HashSet<&BigInt> = v.iter().collect(); - assert_eq!(h.len(), v.len()); - }); -} - -#[bench] -fn pow_bench(b: &mut Bencher) { - b.iter(|| { - let upper = 100_usize; - for i in 2..upper + 1 { - for j in 2..upper + 1 { - let i_big = BigUint::from_usize(i).unwrap(); - i_big.pow(j); - } - } - }); -} - -/// This modulus is the prime from the 2048-bit MODP DH group: -/// https://tools.ietf.org/html/rfc3526#section-3 -const RFC3526_2048BIT_MODP_GROUP: &'static str = - "\ - FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ - 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ - EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ - E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ - EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ - C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ - 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ - 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ - E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ - DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ - 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; - -#[bench] -fn modpow(b: &mut Bencher) { - let mut rng = get_rng(); - let base = rng.gen_biguint(2048); - let e = rng.gen_biguint(2048); - let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap(); - - b.iter(|| base.modpow(&e, &m)); -} - -#[bench] -fn modpow_even(b: &mut Bencher) { - let mut rng = get_rng(); - let base = rng.gen_biguint(2048); - let e = rng.gen_biguint(2048); - // Make the modulus even, so monty (base-2^32) doesn't apply. - let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap() - 1u32; - - b.iter(|| base.modpow(&e, &m)); -} diff --git a/third_party/rust/num-bigint-0.2.3/benches/factorial.rs b/third_party/rust/num-bigint-0.2.3/benches/factorial.rs deleted file mode 100644 index 4392df831915..000000000000 --- a/third_party/rust/num-bigint-0.2.3/benches/factorial.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![feature(test)] - -extern crate num_bigint; -extern crate num_traits; -extern crate test; - -use num_bigint::BigUint; -use num_traits::One; -use std::ops::{Div, Mul}; -use test::Bencher; - -#[bench] -fn factorial_mul_biguint(b: &mut Bencher) { - b.iter(|| { - (1u32..1000) - .map(BigUint::from) - .fold(BigUint::one(), Mul::mul) - }); -} - -#[bench] -fn factorial_mul_u32(b: &mut Bencher) { - b.iter(|| (1u32..1000).fold(BigUint::one(), Mul::mul)); -} - -// The division test is inspired by this blog comparison: -// - -#[bench] -fn factorial_div_biguint(b: &mut Bencher) { - let n: BigUint = (1u32..1000).fold(BigUint::one(), Mul::mul); - b.iter(|| { - (1u32..1000) - .rev() - .map(BigUint::from) - .fold(n.clone(), Div::div) - }); -} - -#[bench] -fn factorial_div_u32(b: &mut Bencher) { - let n: BigUint = (1u32..1000).fold(BigUint::one(), Mul::mul); - b.iter(|| (1u32..1000).rev().fold(n.clone(), Div::div)); -} diff --git a/third_party/rust/num-bigint-0.2.3/benches/gcd.rs b/third_party/rust/num-bigint-0.2.3/benches/gcd.rs deleted file mode 100644 index 5fe5260ddfa0..000000000000 --- a/third_party/rust/num-bigint-0.2.3/benches/gcd.rs +++ /dev/null @@ -1,86 +0,0 @@ -#![feature(test)] -#![cfg(feature = "rand")] - -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; -extern crate rand; -extern crate test; - -use num_bigint::{BigUint, RandBigInt}; -use num_integer::Integer; -use num_traits::Zero; -use rand::{SeedableRng, StdRng}; -use test::Bencher; - -fn get_rng() -> StdRng { - let mut seed = [0; 32]; - for i in 1..32 { - seed[usize::from(i)] = i; - } - SeedableRng::from_seed(seed) -} - -fn bench(b: &mut Bencher, bits: usize, gcd: fn(&BigUint, &BigUint) -> BigUint) { - let mut rng = get_rng(); - let x = rng.gen_biguint(bits); - let y = rng.gen_biguint(bits); - - assert_eq!(euclid(&x, &y), x.gcd(&y)); - - b.iter(|| gcd(&x, &y)); -} - -fn euclid(x: &BigUint, y: &BigUint) -> BigUint { - // Use Euclid's algorithm - let mut m = x.clone(); - let mut n = y.clone(); - while !m.is_zero() { - let temp = m; - m = n % &temp; - n = temp; - } - return n; -} - -#[bench] -fn gcd_euclid_0064(b: &mut Bencher) { - bench(b, 64, euclid); -} - -#[bench] -fn gcd_euclid_0256(b: &mut Bencher) { - bench(b, 256, euclid); -} - -#[bench] -fn gcd_euclid_1024(b: &mut Bencher) { - bench(b, 1024, euclid); -} - -#[bench] -fn gcd_euclid_4096(b: &mut Bencher) { - bench(b, 4096, euclid); -} - -// Integer for BigUint now uses Stein for gcd - -#[bench] -fn gcd_stein_0064(b: &mut Bencher) { - bench(b, 64, BigUint::gcd); -} - -#[bench] -fn gcd_stein_0256(b: &mut Bencher) { - bench(b, 256, BigUint::gcd); -} - -#[bench] -fn gcd_stein_1024(b: &mut Bencher) { - bench(b, 1024, BigUint::gcd); -} - -#[bench] -fn gcd_stein_4096(b: &mut Bencher) { - bench(b, 4096, BigUint::gcd); -} diff --git a/third_party/rust/num-bigint-0.2.3/benches/roots.rs b/third_party/rust/num-bigint-0.2.3/benches/roots.rs deleted file mode 100644 index 51e67d9f3d7e..000000000000 --- a/third_party/rust/num-bigint-0.2.3/benches/roots.rs +++ /dev/null @@ -1,176 +0,0 @@ -#![feature(test)] -#![cfg(feature = "rand")] - -extern crate num_bigint; -extern crate num_traits; -extern crate rand; -extern crate test; - -use num_bigint::{BigUint, RandBigInt}; -use num_traits::Pow; -use rand::{SeedableRng, StdRng}; -use test::Bencher; - -// The `big64` cases demonstrate the speed of cases where the value -// can be converted to a `u64` primitive for faster calculation. -// -// The `big1k` cases demonstrate those that can convert to `f64` for -// a better initial guess of the actual value. -// -// The `big2k` and `big4k` cases are too big for `f64`, and use a simpler guess. - -fn get_rng() -> StdRng { - let mut seed = [0; 32]; - for i in 1..32 { - seed[usize::from(i)] = i; - } - SeedableRng::from_seed(seed) -} - -fn check(x: &BigUint, n: u32) { - let root = x.nth_root(n); - if n == 2 { - assert_eq!(root, x.sqrt()) - } else if n == 3 { - assert_eq!(root, x.cbrt()) - } - - let lo = root.pow(n); - assert!(lo <= *x); - assert_eq!(lo.nth_root(n), root); - assert_eq!((&lo - 1u32).nth_root(n), &root - 1u32); - - let hi = (&root + 1u32).pow(n); - assert!(hi > *x); - assert_eq!(hi.nth_root(n), &root + 1u32); - assert_eq!((&hi - 1u32).nth_root(n), root); -} - -fn bench_sqrt(b: &mut Bencher, bits: usize) { - let x = get_rng().gen_biguint(bits); - eprintln!("bench_sqrt({})", x); - - check(&x, 2); - b.iter(|| x.sqrt()); -} - -#[bench] -fn big64_sqrt(b: &mut Bencher) { - bench_sqrt(b, 64); -} - -#[bench] -fn big1k_sqrt(b: &mut Bencher) { - bench_sqrt(b, 1024); -} - -#[bench] -fn big2k_sqrt(b: &mut Bencher) { - bench_sqrt(b, 2048); -} - -#[bench] -fn big4k_sqrt(b: &mut Bencher) { - bench_sqrt(b, 4096); -} - -fn bench_cbrt(b: &mut Bencher, bits: usize) { - let x = get_rng().gen_biguint(bits); - eprintln!("bench_cbrt({})", x); - - check(&x, 3); - b.iter(|| x.cbrt()); -} - -#[bench] -fn big64_cbrt(b: &mut Bencher) { - bench_cbrt(b, 64); -} - -#[bench] -fn big1k_cbrt(b: &mut Bencher) { - bench_cbrt(b, 1024); -} - -#[bench] -fn big2k_cbrt(b: &mut Bencher) { - bench_cbrt(b, 2048); -} - -#[bench] -fn big4k_cbrt(b: &mut Bencher) { - bench_cbrt(b, 4096); -} - -fn bench_nth_root(b: &mut Bencher, bits: usize, n: u32) { - let x = get_rng().gen_biguint(bits); - eprintln!("bench_{}th_root({})", n, x); - - check(&x, n); - b.iter(|| x.nth_root(n)); -} - -#[bench] -fn big64_nth_10(b: &mut Bencher) { - bench_nth_root(b, 64, 10); -} - -#[bench] -fn big1k_nth_10(b: &mut Bencher) { - bench_nth_root(b, 1024, 10); -} - -#[bench] -fn big1k_nth_100(b: &mut Bencher) { - bench_nth_root(b, 1024, 100); -} - -#[bench] -fn big1k_nth_1000(b: &mut Bencher) { - bench_nth_root(b, 1024, 1000); -} - -#[bench] -fn big1k_nth_10000(b: &mut Bencher) { - bench_nth_root(b, 1024, 10000); -} - -#[bench] -fn big2k_nth_10(b: &mut Bencher) { - bench_nth_root(b, 2048, 10); -} - -#[bench] -fn big2k_nth_100(b: &mut Bencher) { - bench_nth_root(b, 2048, 100); -} - -#[bench] -fn big2k_nth_1000(b: &mut Bencher) { - bench_nth_root(b, 2048, 1000); -} - -#[bench] -fn big2k_nth_10000(b: &mut Bencher) { - bench_nth_root(b, 2048, 10000); -} - -#[bench] -fn big4k_nth_10(b: &mut Bencher) { - bench_nth_root(b, 4096, 10); -} - -#[bench] -fn big4k_nth_100(b: &mut Bencher) { - bench_nth_root(b, 4096, 100); -} - -#[bench] -fn big4k_nth_1000(b: &mut Bencher) { - bench_nth_root(b, 4096, 1000); -} - -#[bench] -fn big4k_nth_10000(b: &mut Bencher) { - bench_nth_root(b, 4096, 10000); -} diff --git a/third_party/rust/num-bigint-0.2.3/benches/shootout-pidigits.rs b/third_party/rust/num-bigint-0.2.3/benches/shootout-pidigits.rs deleted file mode 100644 index f90a6973575b..000000000000 --- a/third_party/rust/num-bigint-0.2.3/benches/shootout-pidigits.rs +++ /dev/null @@ -1,142 +0,0 @@ -// The Computer Language Benchmarks Game -// http://benchmarksgame.alioth.debian.org/ -// -// contributed by the Rust Project Developers - -// Copyright (c) 2013-2014 The Rust Project Developers -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of "The Computer Language Benchmarks Game" nor -// the name of "The Computer Language Shootout Benchmarks" nor the -// names of its contributors may be used to endorse or promote -// products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; - -use std::io; -use std::str::FromStr; - -use num_bigint::BigInt; -use num_integer::Integer; -use num_traits::{FromPrimitive, One, ToPrimitive, Zero}; - -struct Context { - numer: BigInt, - accum: BigInt, - denom: BigInt, -} - -impl Context { - fn new() -> Context { - Context { - numer: One::one(), - accum: Zero::zero(), - denom: One::one(), - } - } - - fn from_i32(i: i32) -> BigInt { - FromPrimitive::from_i32(i).unwrap() - } - - fn extract_digit(&self) -> i32 { - if self.numer > self.accum { - return -1; - } - let (q, r) = (&self.numer * Context::from_i32(3) + &self.accum).div_rem(&self.denom); - if r + &self.numer >= self.denom { - return -1; - } - q.to_i32().unwrap() - } - - fn next_term(&mut self, k: i32) { - let y2 = Context::from_i32(k * 2 + 1); - self.accum = (&self.accum + (&self.numer << 1)) * &y2; - self.numer = &self.numer * Context::from_i32(k); - self.denom = &self.denom * y2; - } - - fn eliminate_digit(&mut self, d: i32) { - let d = Context::from_i32(d); - let ten = Context::from_i32(10); - self.accum = (&self.accum - &self.denom * d) * &ten; - self.numer = &self.numer * ten; - } -} - -fn pidigits(n: isize, out: &mut dyn io::Write) -> io::Result<()> { - let mut k = 0; - let mut context = Context::new(); - - for i in 1..(n + 1) { - let mut d; - loop { - k += 1; - context.next_term(k); - d = context.extract_digit(); - if d != -1 { - break; - } - } - - write!(out, "{}", d)?; - if i % 10 == 0 { - write!(out, "\t:{}\n", i)?; - } - - context.eliminate_digit(d); - } - - let m = n % 10; - if m != 0 { - for _ in m..10 { - write!(out, " ")?; - } - write!(out, "\t:{}\n", n)?; - } - Ok(()) -} - -const DEFAULT_DIGITS: isize = 512; - -fn main() { - let args = std::env::args().collect::>(); - let n = if args.len() < 2 { - DEFAULT_DIGITS - } else if args[1] == "--bench" { - return pidigits(DEFAULT_DIGITS, &mut std::io::sink()).unwrap(); - } else { - FromStr::from_str(&args[1]).unwrap() - }; - pidigits(n, &mut std::io::stdout()).unwrap(); -} diff --git a/third_party/rust/num-bigint-0.2.3/build.rs b/third_party/rust/num-bigint-0.2.3/build.rs deleted file mode 100644 index 15590bbc12bb..000000000000 --- a/third_party/rust/num-bigint-0.2.3/build.rs +++ /dev/null @@ -1,14 +0,0 @@ -extern crate autocfg; - -use std::env; - -fn main() { - let ac = autocfg::new(); - if ac.probe_type("i128") { - println!("cargo:rustc-cfg=has_i128"); - } else if env::var_os("CARGO_FEATURE_I128").is_some() { - panic!("i128 support was not detected!"); - } - - autocfg::rerun_path(file!()); -} diff --git a/third_party/rust/num-bigint-0.2.3/src/algorithms.rs b/third_party/rust/num-bigint-0.2.3/src/algorithms.rs deleted file mode 100644 index 26f29b81546f..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/algorithms.rs +++ /dev/null @@ -1,789 +0,0 @@ -use std::borrow::Cow; -use std::cmp; -use std::cmp::Ordering::{self, Equal, Greater, Less}; -use std::iter::repeat; -use std::mem; -use traits; -use traits::{One, Zero}; - -use biguint::BigUint; - -use bigint::BigInt; -use bigint::Sign; -use bigint::Sign::{Minus, NoSign, Plus}; - -use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; - -// Generic functions for add/subtract/multiply with carry/borrow: - -// Add with carry: -#[inline] -fn adc(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { - *acc += DoubleBigDigit::from(a); - *acc += DoubleBigDigit::from(b); - let lo = *acc as BigDigit; - *acc >>= big_digit::BITS; - lo -} - -// Subtract with borrow: -#[inline] -fn sbb(a: BigDigit, b: BigDigit, acc: &mut SignedDoubleBigDigit) -> BigDigit { - *acc += SignedDoubleBigDigit::from(a); - *acc -= SignedDoubleBigDigit::from(b); - let lo = *acc as BigDigit; - *acc >>= big_digit::BITS; - lo -} - -#[inline] -pub fn mac_with_carry(a: BigDigit, b: BigDigit, c: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { - *acc += DoubleBigDigit::from(a); - *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c); - let lo = *acc as BigDigit; - *acc >>= big_digit::BITS; - lo -} - -#[inline] -pub fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { - *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b); - let lo = *acc as BigDigit; - *acc >>= big_digit::BITS; - lo -} - -/// Divide a two digit numerator by a one digit divisor, returns quotient and remainder: -/// -/// Note: the caller must ensure that both the quotient and remainder will fit into a single digit. -/// This is _not_ true for an arbitrary numerator/denominator. -/// -/// (This function also matches what the x86 divide instruction does). -#[inline] -fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) { - debug_assert!(hi < divisor); - - let lhs = big_digit::to_doublebigdigit(hi, lo); - let rhs = DoubleBigDigit::from(divisor); - ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit) -} - -pub fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) { - let mut rem = 0; - - for d in a.data.iter_mut().rev() { - let (q, r) = div_wide(rem, *d, b); - *d = q; - rem = r; - } - - (a.normalized(), rem) -} - -pub fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit { - let mut rem: DoubleBigDigit = 0; - for &digit in a.data.iter().rev() { - rem = (rem << big_digit::BITS) + DoubleBigDigit::from(digit); - rem %= DoubleBigDigit::from(b); - } - - rem as BigDigit -} - -// Only for the Add impl: -#[inline] -pub fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit { - debug_assert!(a.len() >= b.len()); - - let mut carry = 0; - let (a_lo, a_hi) = a.split_at_mut(b.len()); - - for (a, b) in a_lo.iter_mut().zip(b) { - *a = adc(*a, *b, &mut carry); - } - - if carry != 0 { - for a in a_hi { - *a = adc(*a, 0, &mut carry); - if carry == 0 { - break; - } - } - } - - carry as BigDigit -} - -/// Two argument addition of raw slices: -/// a += b -/// -/// The caller _must_ ensure that a is big enough to store the result - typically this means -/// resizing a to max(a.len(), b.len()) + 1, to fit a possible carry. -pub fn add2(a: &mut [BigDigit], b: &[BigDigit]) { - let carry = __add2(a, b); - - debug_assert!(carry == 0); -} - -pub fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { - let mut borrow = 0; - - let len = cmp::min(a.len(), b.len()); - let (a_lo, a_hi) = a.split_at_mut(len); - let (b_lo, b_hi) = b.split_at(len); - - for (a, b) in a_lo.iter_mut().zip(b_lo) { - *a = sbb(*a, *b, &mut borrow); - } - - if borrow != 0 { - for a in a_hi { - *a = sbb(*a, 0, &mut borrow); - if borrow == 0 { - break; - } - } - } - - // note: we're _required_ to fail on underflow - assert!( - borrow == 0 && b_hi.iter().all(|x| *x == 0), - "Cannot subtract b from a because b is larger than a." - ); -} - -// Only for the Sub impl. `a` and `b` must have same length. -#[inline] -pub fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit { - debug_assert!(b.len() == a.len()); - - let mut borrow = 0; - - for (ai, bi) in a.iter().zip(b) { - *bi = sbb(*ai, *bi, &mut borrow); - } - - borrow as BigDigit -} - -pub fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { - debug_assert!(b.len() >= a.len()); - - let len = cmp::min(a.len(), b.len()); - let (a_lo, a_hi) = a.split_at(len); - let (b_lo, b_hi) = b.split_at_mut(len); - - let borrow = __sub2rev(a_lo, b_lo); - - assert!(a_hi.is_empty()); - - // note: we're _required_ to fail on underflow - assert!( - borrow == 0 && b_hi.iter().all(|x| *x == 0), - "Cannot subtract b from a because b is larger than a." - ); -} - -pub fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) { - // Normalize: - let a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; - let b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; - - match cmp_slice(a, b) { - Greater => { - let mut a = a.to_vec(); - sub2(&mut a, b); - (Plus, BigUint::new(a)) - } - Less => { - let mut b = b.to_vec(); - sub2(&mut b, a); - (Minus, BigUint::new(b)) - } - _ => (NoSign, Zero::zero()), - } -} - -/// Three argument multiply accumulate: -/// acc += b * c -pub fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { - if c == 0 { - return; - } - - let mut carry = 0; - let (a_lo, a_hi) = acc.split_at_mut(b.len()); - - for (a, &b) in a_lo.iter_mut().zip(b) { - *a = mac_with_carry(*a, b, c, &mut carry); - } - - let mut a = a_hi.iter_mut(); - while carry != 0 { - let a = a.next().expect("carry overflow during multiplication!"); - *a = adc(*a, 0, &mut carry); - } -} - -/// Three argument multiply accumulate: -/// acc += b * c -fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) { - let (x, y) = if b.len() < c.len() { (b, c) } else { (c, b) }; - - // We use three algorithms for different input sizes. - // - // - For small inputs, long multiplication is fastest. - // - Next we use Karatsuba multiplication (Toom-2), which we have optimized - // to avoid unnecessary allocations for intermediate values. - // - For the largest inputs we use Toom-3, which better optimizes the - // number of operations, but uses more temporary allocations. - // - // The thresholds are somewhat arbitrary, chosen by evaluating the results - // of `cargo bench --bench bigint multiply`. - - if x.len() <= 32 { - // Long multiplication: - for (i, xi) in x.iter().enumerate() { - mac_digit(&mut acc[i..], y, *xi); - } - } else if x.len() <= 256 { - /* - * Karatsuba multiplication: - * - * The idea is that we break x and y up into two smaller numbers that each have about half - * as many digits, like so (note that multiplying by b is just a shift): - * - * x = x0 + x1 * b - * y = y0 + y1 * b - * - * With some algebra, we can compute x * y with three smaller products, where the inputs to - * each of the smaller products have only about half as many digits as x and y: - * - * x * y = (x0 + x1 * b) * (y0 + y1 * b) - * - * x * y = x0 * y0 - * + x0 * y1 * b - * + x1 * y0 * b - * + x1 * y1 * b^2 - * - * Let p0 = x0 * y0 and p2 = x1 * y1: - * - * x * y = p0 - * + (x0 * y1 + x1 * y0) * b - * + p2 * b^2 - * - * The real trick is that middle term: - * - * x0 * y1 + x1 * y0 - * - * = x0 * y1 + x1 * y0 - p0 + p0 - p2 + p2 - * - * = x0 * y1 + x1 * y0 - x0 * y0 - x1 * y1 + p0 + p2 - * - * Now we complete the square: - * - * = -(x0 * y0 - x0 * y1 - x1 * y0 + x1 * y1) + p0 + p2 - * - * = -((x1 - x0) * (y1 - y0)) + p0 + p2 - * - * Let p1 = (x1 - x0) * (y1 - y0), and substitute back into our original formula: - * - * x * y = p0 - * + (p0 + p2 - p1) * b - * + p2 * b^2 - * - * Where the three intermediate products are: - * - * p0 = x0 * y0 - * p1 = (x1 - x0) * (y1 - y0) - * p2 = x1 * y1 - * - * In doing the computation, we take great care to avoid unnecessary temporary variables - * (since creating a BigUint requires a heap allocation): thus, we rearrange the formula a - * bit so we can use the same temporary variable for all the intermediate products: - * - * x * y = p2 * b^2 + p2 * b - * + p0 * b + p0 - * - p1 * b - * - * The other trick we use is instead of doing explicit shifts, we slice acc at the - * appropriate offset when doing the add. - */ - - /* - * When x is smaller than y, it's significantly faster to pick b such that x is split in - * half, not y: - */ - let b = x.len() / 2; - let (x0, x1) = x.split_at(b); - let (y0, y1) = y.split_at(b); - - /* - * We reuse the same BigUint for all the intermediate multiplies and have to size p - * appropriately here: x1.len() >= x0.len and y1.len() >= y0.len(): - */ - let len = x1.len() + y1.len() + 1; - let mut p = BigUint { data: vec![0; len] }; - - // p2 = x1 * y1 - mac3(&mut p.data[..], x1, y1); - - // Not required, but the adds go faster if we drop any unneeded 0s from the end: - p.normalize(); - - add2(&mut acc[b..], &p.data[..]); - add2(&mut acc[b * 2..], &p.data[..]); - - // Zero out p before the next multiply: - p.data.truncate(0); - p.data.extend(repeat(0).take(len)); - - // p0 = x0 * y0 - mac3(&mut p.data[..], x0, y0); - p.normalize(); - - add2(&mut acc[..], &p.data[..]); - add2(&mut acc[b..], &p.data[..]); - - // p1 = (x1 - x0) * (y1 - y0) - // We do this one last, since it may be negative and acc can't ever be negative: - let (j0_sign, j0) = sub_sign(x1, x0); - let (j1_sign, j1) = sub_sign(y1, y0); - - match j0_sign * j1_sign { - Plus => { - p.data.truncate(0); - p.data.extend(repeat(0).take(len)); - - mac3(&mut p.data[..], &j0.data[..], &j1.data[..]); - p.normalize(); - - sub2(&mut acc[b..], &p.data[..]); - } - Minus => { - mac3(&mut acc[b..], &j0.data[..], &j1.data[..]); - } - NoSign => (), - } - } else { - // Toom-3 multiplication: - // - // Toom-3 is like Karatsuba above, but dividing the inputs into three parts. - // Both are instances of Toom-Cook, using `k=3` and `k=2` respectively. - // - // The general idea is to treat the large integers digits as - // polynomials of a certain degree and determine the coefficients/digits - // of the product of the two via interpolation of the polynomial product. - let i = y.len() / 3 + 1; - - let x0_len = cmp::min(x.len(), i); - let x1_len = cmp::min(x.len() - x0_len, i); - - let y0_len = i; - let y1_len = cmp::min(y.len() - y0_len, i); - - // Break x and y into three parts, representating an order two polynomial. - // t is chosen to be the size of a digit so we can use faster shifts - // in place of multiplications. - // - // x(t) = x2*t^2 + x1*t + x0 - let x0 = BigInt::from_slice(Plus, &x[..x0_len]); - let x1 = BigInt::from_slice(Plus, &x[x0_len..x0_len + x1_len]); - let x2 = BigInt::from_slice(Plus, &x[x0_len + x1_len..]); - - // y(t) = y2*t^2 + y1*t + y0 - let y0 = BigInt::from_slice(Plus, &y[..y0_len]); - let y1 = BigInt::from_slice(Plus, &y[y0_len..y0_len + y1_len]); - let y2 = BigInt::from_slice(Plus, &y[y0_len + y1_len..]); - - // Let w(t) = x(t) * y(t) - // - // This gives us the following order-4 polynomial. - // - // w(t) = w4*t^4 + w3*t^3 + w2*t^2 + w1*t + w0 - // - // We need to find the coefficients w4, w3, w2, w1 and w0. Instead - // of simply multiplying the x and y in total, we can evaluate w - // at 5 points. An n-degree polynomial is uniquely identified by (n + 1) - // points. - // - // It is arbitrary as to what points we evaluate w at but we use the - // following. - // - // w(t) at t = 0, 1, -1, -2 and inf - // - // The values for w(t) in terms of x(t)*y(t) at these points are: - // - // let a = w(0) = x0 * y0 - // let b = w(1) = (x2 + x1 + x0) * (y2 + y1 + y0) - // let c = w(-1) = (x2 - x1 + x0) * (y2 - y1 + y0) - // let d = w(-2) = (4*x2 - 2*x1 + x0) * (4*y2 - 2*y1 + y0) - // let e = w(inf) = x2 * y2 as t -> inf - - // x0 + x2, avoiding temporaries - let p = &x0 + &x2; - - // y0 + y2, avoiding temporaries - let q = &y0 + &y2; - - // x2 - x1 + x0, avoiding temporaries - let p2 = &p - &x1; - - // y2 - y1 + y0, avoiding temporaries - let q2 = &q - &y1; - - // w(0) - let r0 = &x0 * &y0; - - // w(inf) - let r4 = &x2 * &y2; - - // w(1) - let r1 = (p + x1) * (q + y1); - - // w(-1) - let r2 = &p2 * &q2; - - // w(-2) - let r3 = ((p2 + x2) * 2 - x0) * ((q2 + y2) * 2 - y0); - - // Evaluating these points gives us the following system of linear equations. - // - // 0 0 0 0 1 | a - // 1 1 1 1 1 | b - // 1 -1 1 -1 1 | c - // 16 -8 4 -2 1 | d - // 1 0 0 0 0 | e - // - // The solved equation (after gaussian elimination or similar) - // in terms of its coefficients: - // - // w0 = w(0) - // w1 = w(0)/2 + w(1)/3 - w(-1) + w(2)/6 - 2*w(inf) - // w2 = -w(0) + w(1)/2 + w(-1)/2 - w(inf) - // w3 = -w(0)/2 + w(1)/6 + w(-1)/2 - w(1)/6 - // w4 = w(inf) - // - // This particular sequence is given by Bodrato and is an interpolation - // of the above equations. - let mut comp3: BigInt = (r3 - &r1) / 3; - let mut comp1: BigInt = (r1 - &r2) / 2; - let mut comp2: BigInt = r2 - &r0; - comp3 = (&comp2 - comp3) / 2 + &r4 * 2; - comp2 = comp2 + &comp1 - &r4; - comp1 = comp1 - &comp3; - - // Recomposition. The coefficients of the polynomial are now known. - // - // Evaluate at w(t) where t is our given base to get the result. - let result = r0 - + (comp1 << 32 * i) - + (comp2 << 2 * 32 * i) - + (comp3 << 3 * 32 * i) - + (r4 << 4 * 32 * i); - let result_pos = result.to_biguint().unwrap(); - add2(&mut acc[..], &result_pos.data); - } -} - -pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { - let len = x.len() + y.len() + 1; - let mut prod = BigUint { data: vec![0; len] }; - - mac3(&mut prod.data[..], x, y); - prod.normalized() -} - -pub fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit { - let mut carry = 0; - for a in a.iter_mut() { - *a = mul_with_carry(*a, b, &mut carry); - } - carry as BigDigit -} - -pub fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { - if d.is_zero() { - panic!() - } - if u.is_zero() { - return (Zero::zero(), Zero::zero()); - } - - if d.data.len() == 1 { - if d.data == [1] { - return (u, Zero::zero()); - } - let (div, rem) = div_rem_digit(u, d.data[0]); - // reuse d - d.data.clear(); - d += rem; - return (div, d); - } - - // Required or the q_len calculation below can underflow: - match u.cmp(&d) { - Less => return (Zero::zero(), u), - Equal => { - u.set_one(); - return (u, Zero::zero()); - } - Greater => {} // Do nothing - } - - // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D: - // - // First, normalize the arguments so the highest bit in the highest digit of the divisor is - // set: the main loop uses the highest digit of the divisor for generating guesses, so we - // want it to be the largest number we can efficiently divide by. - // - let shift = d.data.last().unwrap().leading_zeros() as usize; - let (q, r) = if shift == 0 { - // no need to clone d - div_rem_core(u, &d) - } else { - div_rem_core(u << shift, &(d << shift)) - }; - // renormalize the remainder - (q, r >> shift) -} - -pub fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { - if d.is_zero() { - panic!() - } - if u.is_zero() { - return (Zero::zero(), Zero::zero()); - } - - if d.data.len() == 1 { - if d.data == [1] { - return (u.clone(), Zero::zero()); - } - - let (div, rem) = div_rem_digit(u.clone(), d.data[0]); - return (div, rem.into()); - } - - // Required or the q_len calculation below can underflow: - match u.cmp(d) { - Less => return (Zero::zero(), u.clone()), - Equal => return (One::one(), Zero::zero()), - Greater => {} // Do nothing - } - - // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D: - // - // First, normalize the arguments so the highest bit in the highest digit of the divisor is - // set: the main loop uses the highest digit of the divisor for generating guesses, so we - // want it to be the largest number we can efficiently divide by. - // - let shift = d.data.last().unwrap().leading_zeros() as usize; - - let (q, r) = if shift == 0 { - // no need to clone d - div_rem_core(u.clone(), d) - } else { - div_rem_core(u << shift, &(d << shift)) - }; - // renormalize the remainder - (q, r >> shift) -} - -/// an implementation of Knuth, TAOCP vol 2 section 4.3, algorithm D -/// -/// # Correctness -/// -/// This function requires the following conditions to run correctly and/or effectively -/// -/// - `a > b` -/// - `d.data.len() > 1` -/// - `d.data.last().unwrap().leading_zeros() == 0` -fn div_rem_core(mut a: BigUint, b: &BigUint) -> (BigUint, BigUint) { - // The algorithm works by incrementally calculating "guesses", q0, for part of the - // remainder. Once we have any number q0 such that q0 * b <= a, we can set - // - // q += q0 - // a -= q0 * b - // - // and then iterate until a < b. Then, (q, a) will be our desired quotient and remainder. - // - // q0, our guess, is calculated by dividing the last few digits of a by the last digit of b - // - this should give us a guess that is "close" to the actual quotient, but is possibly - // greater than the actual quotient. If q0 * b > a, we simply use iterated subtraction - // until we have a guess such that q0 * b <= a. - // - - let bn = *b.data.last().unwrap(); - let q_len = a.data.len() - b.data.len() + 1; - let mut q = BigUint { - data: vec![0; q_len], - }; - - // We reuse the same temporary to avoid hitting the allocator in our inner loop - this is - // sized to hold a0 (in the common case; if a particular digit of the quotient is zero a0 - // can be bigger). - // - let mut tmp = BigUint { - data: Vec::with_capacity(2), - }; - - for j in (0..q_len).rev() { - /* - * When calculating our next guess q0, we don't need to consider the digits below j - * + b.data.len() - 1: we're guessing digit j of the quotient (i.e. q0 << j) from - * digit bn of the divisor (i.e. bn << (b.data.len() - 1) - so the product of those - * two numbers will be zero in all digits up to (j + b.data.len() - 1). - */ - let offset = j + b.data.len() - 1; - if offset >= a.data.len() { - continue; - } - - /* just avoiding a heap allocation: */ - let mut a0 = tmp; - a0.data.truncate(0); - a0.data.extend(a.data[offset..].iter().cloned()); - - /* - * q0 << j * big_digit::BITS is our actual quotient estimate - we do the shifts - * implicitly at the end, when adding and subtracting to a and q. Not only do we - * save the cost of the shifts, the rest of the arithmetic gets to work with - * smaller numbers. - */ - let (mut q0, _) = div_rem_digit(a0, bn); - let mut prod = b * &q0; - - while cmp_slice(&prod.data[..], &a.data[j..]) == Greater { - let one: BigUint = One::one(); - q0 = q0 - one; - prod = prod - b; - } - - add2(&mut q.data[j..], &q0.data[..]); - sub2(&mut a.data[j..], &prod.data[..]); - a.normalize(); - - tmp = q0; - } - - debug_assert!(&a < b); - - (q.normalized(), a) -} - -/// Find last set bit -/// fls(0) == 0, fls(u32::MAX) == 32 -pub fn fls(v: T) -> usize { - mem::size_of::() * 8 - v.leading_zeros() as usize -} - -pub fn ilog2(v: T) -> usize { - fls(v) - 1 -} - -#[inline] -pub fn biguint_shl(n: Cow, bits: usize) -> BigUint { - let n_unit = bits / big_digit::BITS; - let mut data = match n_unit { - 0 => n.into_owned().data, - _ => { - let len = n_unit + n.data.len() + 1; - let mut data = Vec::with_capacity(len); - data.extend(repeat(0).take(n_unit)); - data.extend(n.data.iter().cloned()); - data - } - }; - - let n_bits = bits % big_digit::BITS; - if n_bits > 0 { - let mut carry = 0; - for elem in data[n_unit..].iter_mut() { - let new_carry = *elem >> (big_digit::BITS - n_bits); - *elem = (*elem << n_bits) | carry; - carry = new_carry; - } - if carry != 0 { - data.push(carry); - } - } - - BigUint::new(data) -} - -#[inline] -pub fn biguint_shr(n: Cow, bits: usize) -> BigUint { - let n_unit = bits / big_digit::BITS; - if n_unit >= n.data.len() { - return Zero::zero(); - } - let mut data = match n { - Cow::Borrowed(n) => n.data[n_unit..].to_vec(), - Cow::Owned(mut n) => { - n.data.drain(..n_unit); - n.data - } - }; - - let n_bits = bits % big_digit::BITS; - if n_bits > 0 { - let mut borrow = 0; - for elem in data.iter_mut().rev() { - let new_borrow = *elem << (big_digit::BITS - n_bits); - *elem = (*elem >> n_bits) | borrow; - borrow = new_borrow; - } - } - - BigUint::new(data) -} - -pub fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { - debug_assert!(a.last() != Some(&0)); - debug_assert!(b.last() != Some(&0)); - - let (a_len, b_len) = (a.len(), b.len()); - if a_len < b_len { - return Less; - } - if a_len > b_len { - return Greater; - } - - for (&ai, &bi) in a.iter().rev().zip(b.iter().rev()) { - if ai < bi { - return Less; - } - if ai > bi { - return Greater; - } - } - return Equal; -} - -#[cfg(test)] -mod algorithm_tests { - use big_digit::BigDigit; - use traits::Num; - use Sign::Plus; - use {BigInt, BigUint}; - - #[test] - fn test_sub_sign() { - use super::sub_sign; - - fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt { - let (sign, val) = sub_sign(a, b); - BigInt::from_biguint(sign, val) - } - - let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap(); - let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap(); - let a_i = BigInt::from_biguint(Plus, a.clone()); - let b_i = BigInt::from_biguint(Plus, b.clone()); - - assert_eq!(sub_sign_i(&a.data[..], &b.data[..]), &a_i - &b_i); - assert_eq!(sub_sign_i(&b.data[..], &a.data[..]), &b_i - &a_i); - } -} diff --git a/third_party/rust/num-bigint-0.2.3/src/bigint.rs b/third_party/rust/num-bigint-0.2.3/src/bigint.rs deleted file mode 100644 index 93c72be6af49..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/bigint.rs +++ /dev/null @@ -1,3084 +0,0 @@ -#[allow(deprecated, unused_imports)] -use std::ascii::AsciiExt; -use std::cmp::Ordering::{self, Equal, Greater, Less}; -use std::default::Default; -use std::fmt; -use std::iter::{Product, Sum}; -use std::mem; -use std::ops::{ - Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, - Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, -}; -use std::str::{self, FromStr}; -#[cfg(has_i128)] -use std::{i128, u128}; -use std::{i64, u64}; - -#[cfg(feature = "serde")] -use serde; - -use integer::{Integer, Roots}; -use traits::{ - CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, Signed, - ToPrimitive, Zero, -}; - -use self::Sign::{Minus, NoSign, Plus}; - -use super::ParseBigIntError; -use big_digit::{self, BigDigit, DoubleBigDigit}; -use biguint; -use biguint::to_str_radix_reversed; -use biguint::{BigUint, IntDigits}; - -use IsizePromotion; -use UsizePromotion; - -#[cfg(feature = "quickcheck")] -use quickcheck::{Arbitrary, Gen}; - -/// A Sign is a `BigInt`'s composing element. -#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] -pub enum Sign { - Minus, - NoSign, - Plus, -} - -impl Neg for Sign { - type Output = Sign; - - /// Negate Sign value. - #[inline] - fn neg(self) -> Sign { - match self { - Minus => Plus, - NoSign => NoSign, - Plus => Minus, - } - } -} - -impl Mul for Sign { - type Output = Sign; - - #[inline] - fn mul(self, other: Sign) -> Sign { - match (self, other) { - (NoSign, _) | (_, NoSign) => NoSign, - (Plus, Plus) | (Minus, Minus) => Plus, - (Plus, Minus) | (Minus, Plus) => Minus, - } - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Sign { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - // Note: do not change the serialization format, or it may break - // forward and backward compatibility of serialized data! - match *self { - Sign::Minus => (-1i8).serialize(serializer), - Sign::NoSign => 0i8.serialize(serializer), - Sign::Plus => 1i8.serialize(serializer), - } - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for Sign { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - use serde::de::Error; - use serde::de::Unexpected; - - let sign: i8 = serde::Deserialize::deserialize(deserializer)?; - match sign { - -1 => Ok(Sign::Minus), - 0 => Ok(Sign::NoSign), - 1 => Ok(Sign::Plus), - _ => Err(D::Error::invalid_value( - Unexpected::Signed(sign.into()), - &"a sign of -1, 0, or 1", - )), - } - } -} - -/// A big signed integer type. -#[derive(Clone, Debug, Hash)] -pub struct BigInt { - sign: Sign, - data: BigUint, -} - -#[cfg(feature = "quickcheck")] -impl Arbitrary for BigInt { - fn arbitrary(g: &mut G) -> Self { - let positive = bool::arbitrary(g); - let sign = if positive { Sign::Plus } else { Sign::Minus }; - Self::from_biguint(sign, BigUint::arbitrary(g)) - } - - #[allow(bare_trait_objects)] // `dyn` needs Rust 1.27 to parse, even when cfg-disabled - fn shrink(&self) -> Box> { - let sign = self.sign(); - let unsigned_shrink = self.data.shrink(); - Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x))) - } -} - -/// Return the magnitude of a `BigInt`. -/// -/// This is in a private module, pseudo pub(crate) -#[cfg(feature = "rand")] -pub fn magnitude(i: &BigInt) -> &BigUint { - &i.data -} - -/// Return the owned magnitude of a `BigInt`. -/// -/// This is in a private module, pseudo pub(crate) -#[cfg(feature = "rand")] -pub fn into_magnitude(i: BigInt) -> BigUint { - i.data -} - -impl PartialEq for BigInt { - #[inline] - fn eq(&self, other: &BigInt) -> bool { - self.cmp(other) == Equal - } -} - -impl Eq for BigInt {} - -impl PartialOrd for BigInt { - #[inline] - fn partial_cmp(&self, other: &BigInt) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for BigInt { - #[inline] - fn cmp(&self, other: &BigInt) -> Ordering { - let scmp = self.sign.cmp(&other.sign); - if scmp != Equal { - return scmp; - } - - match self.sign { - NoSign => Equal, - Plus => self.data.cmp(&other.data), - Minus => other.data.cmp(&self.data), - } - } -} - -impl Default for BigInt { - #[inline] - fn default() -> BigInt { - Zero::zero() - } -} - -impl fmt::Display for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "", &self.data.to_str_radix(10)) - } -} - -impl fmt::Binary for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "0b", &self.data.to_str_radix(2)) - } -} - -impl fmt::Octal for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "0o", &self.data.to_str_radix(8)) - } -} - -impl fmt::LowerHex for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "0x", &self.data.to_str_radix(16)) - } -} - -impl fmt::UpperHex for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut s = self.data.to_str_radix(16); - s.make_ascii_uppercase(); - f.pad_integral(!self.is_negative(), "0x", &s) - } -} - -// Negation in two's complement. -// acc must be initialized as 1 for least-significant digit. -// -// When negating, a carry (acc == 1) means that all the digits -// considered to this point were zero. This means that if all the -// digits of a negative BigInt have been considered, carry must be -// zero as we cannot have negative zero. -// -// 01 -> ...f ff -// ff -> ...f 01 -// 01 00 -> ...f ff 00 -// 01 01 -> ...f fe ff -// 01 ff -> ...f fe 01 -// ff 00 -> ...f 01 00 -// ff 01 -> ...f 00 ff -// ff ff -> ...f 00 01 -#[inline] -fn negate_carry(a: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { - *acc += DoubleBigDigit::from(!a); - let lo = *acc as BigDigit; - *acc >>= big_digit::BITS; - lo -} - -// !-2 = !...f fe = ...0 01 = +1 -// !-1 = !...f ff = ...0 00 = 0 -// ! 0 = !...0 00 = ...f ff = -1 -// !+1 = !...0 01 = ...f fe = -2 -impl Not for BigInt { - type Output = BigInt; - - fn not(mut self) -> BigInt { - match self.sign { - NoSign | Plus => { - self.data += 1u32; - self.sign = Minus; - } - Minus => { - self.data -= 1u32; - self.sign = if self.data.is_zero() { NoSign } else { Plus }; - } - } - self - } -} - -impl<'a> Not for &'a BigInt { - type Output = BigInt; - - fn not(self) -> BigInt { - match self.sign { - NoSign | Plus => BigInt::from_biguint(Minus, &self.data + 1u32), - Minus => BigInt::from_biguint(Plus, &self.data - 1u32), - } - } -} - -// + 1 & -ff = ...0 01 & ...f 01 = ...0 01 = + 1 -// +ff & - 1 = ...0 ff & ...f ff = ...0 ff = +ff -// answer is pos, has length of a -fn bitand_pos_neg(a: &mut Vec, b: &[BigDigit]) { - let mut carry_b = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_b = negate_carry(bi, &mut carry_b); - *ai &= twos_b; - } - debug_assert!(b.len() > a.len() || carry_b == 0); -} - -// - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff -// -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1 -// answer is pos, has length of b -fn bitand_neg_pos(a: &mut Vec, b: &[BigDigit]) { - let mut carry_a = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = twos_a & bi; - } - debug_assert!(a.len() > b.len() || carry_a == 0); - if a.len() > b.len() { - a.truncate(b.len()); - } else if b.len() > a.len() { - let extra = &b[a.len()..]; - a.extend(extra.iter().cloned()); - } -} - -// - 1 & -ff = ...f ff & ...f 01 = ...f 01 = - ff -// -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff -// -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100 -// answer is neg, has length of longest with a possible carry -fn bitand_neg_neg(a: &mut Vec, b: &[BigDigit]) { - let mut carry_a = 1; - let mut carry_b = 1; - let mut carry_and = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_a = negate_carry(*ai, &mut carry_a); - let twos_b = negate_carry(bi, &mut carry_b); - *ai = negate_carry(twos_a & twos_b, &mut carry_and); - } - debug_assert!(a.len() > b.len() || carry_a == 0); - debug_assert!(b.len() > a.len() || carry_b == 0); - if a.len() > b.len() { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a, &mut carry_and); - } - debug_assert!(carry_a == 0); - } else if b.len() > a.len() { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_b = negate_carry(bi, &mut carry_b); - negate_carry(twos_b, &mut carry_and) - })); - debug_assert!(carry_b == 0); - } - if carry_and != 0 { - a.push(1); - } -} - -forward_val_val_binop!(impl BitAnd for BigInt, bitand); -forward_ref_val_binop!(impl BitAnd for BigInt, bitand); - -// do not use forward_ref_ref_binop_commutative! for bitand so that we can -// clone as needed, avoiding over-allocation -impl<'a, 'b> BitAnd<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn bitand(self, other: &BigInt) -> BigInt { - match (self.sign, other.sign) { - (NoSign, _) | (_, NoSign) => BigInt::from_slice(NoSign, &[]), - (Plus, Plus) => BigInt::from_biguint(Plus, &self.data & &other.data), - (Plus, Minus) => self.clone() & other, - (Minus, Plus) => other.clone() & self, - (Minus, Minus) => { - // forward to val-ref, choosing the larger to clone - if self.len() >= other.len() { - self.clone() & other - } else { - other.clone() & self - } - } - } - } -} - -impl<'a> BitAnd<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn bitand(mut self, other: &BigInt) -> BigInt { - self &= other; - self - } -} - -forward_val_assign!(impl BitAndAssign for BigInt, bitand_assign); - -impl<'a> BitAndAssign<&'a BigInt> for BigInt { - fn bitand_assign(&mut self, other: &BigInt) { - match (self.sign, other.sign) { - (NoSign, _) => {} - (_, NoSign) => self.assign_from_slice(NoSign, &[]), - (Plus, Plus) => { - self.data &= &other.data; - if self.data.is_zero() { - self.sign = NoSign; - } - } - (Plus, Minus) => { - bitand_pos_neg(self.digits_mut(), other.digits()); - self.normalize(); - } - (Minus, Plus) => { - bitand_neg_pos(self.digits_mut(), other.digits()); - self.sign = Plus; - self.normalize(); - } - (Minus, Minus) => { - bitand_neg_neg(self.digits_mut(), other.digits()); - self.normalize(); - } - } - } -} - -// + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff -// +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1 -// answer is neg, has length of b -fn bitor_pos_neg(a: &mut Vec, b: &[BigDigit]) { - let mut carry_b = 1; - let mut carry_or = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_b = negate_carry(bi, &mut carry_b); - *ai = negate_carry(*ai | twos_b, &mut carry_or); - } - debug_assert!(b.len() > a.len() || carry_b == 0); - if a.len() > b.len() { - a.truncate(b.len()); - } else if b.len() > a.len() { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_b = negate_carry(bi, &mut carry_b); - negate_carry(twos_b, &mut carry_or) - })); - debug_assert!(carry_b == 0); - } - // for carry_or to be non-zero, we would need twos_b == 0 - debug_assert!(carry_or == 0); -} - -// - 1 | +ff = ...f ff | ...0 ff = ...f ff = - 1 -// -ff | + 1 = ...f 01 | ...0 01 = ...f 01 = -ff -// answer is neg, has length of a -fn bitor_neg_pos(a: &mut Vec, b: &[BigDigit]) { - let mut carry_a = 1; - let mut carry_or = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a | bi, &mut carry_or); - } - debug_assert!(a.len() > b.len() || carry_a == 0); - if a.len() > b.len() { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a, &mut carry_or); - } - debug_assert!(carry_a == 0); - } - // for carry_or to be non-zero, we would need twos_a == 0 - debug_assert!(carry_or == 0); -} - -// - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1 -// -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1 -// answer is neg, has length of shortest -fn bitor_neg_neg(a: &mut Vec, b: &[BigDigit]) { - let mut carry_a = 1; - let mut carry_b = 1; - let mut carry_or = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_a = negate_carry(*ai, &mut carry_a); - let twos_b = negate_carry(bi, &mut carry_b); - *ai = negate_carry(twos_a | twos_b, &mut carry_or); - } - debug_assert!(a.len() > b.len() || carry_a == 0); - debug_assert!(b.len() > a.len() || carry_b == 0); - if a.len() > b.len() { - a.truncate(b.len()); - } - // for carry_or to be non-zero, we would need twos_a == 0 or twos_b == 0 - debug_assert!(carry_or == 0); -} - -forward_val_val_binop!(impl BitOr for BigInt, bitor); -forward_ref_val_binop!(impl BitOr for BigInt, bitor); - -// do not use forward_ref_ref_binop_commutative! for bitor so that we can -// clone as needed, avoiding over-allocation -impl<'a, 'b> BitOr<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn bitor(self, other: &BigInt) -> BigInt { - match (self.sign, other.sign) { - (NoSign, _) => other.clone(), - (_, NoSign) => self.clone(), - (Plus, Plus) => BigInt::from_biguint(Plus, &self.data | &other.data), - (Plus, Minus) => other.clone() | self, - (Minus, Plus) => self.clone() | other, - (Minus, Minus) => { - // forward to val-ref, choosing the smaller to clone - if self.len() <= other.len() { - self.clone() | other - } else { - other.clone() | self - } - } - } - } -} - -impl<'a> BitOr<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn bitor(mut self, other: &BigInt) -> BigInt { - self |= other; - self - } -} - -forward_val_assign!(impl BitOrAssign for BigInt, bitor_assign); - -impl<'a> BitOrAssign<&'a BigInt> for BigInt { - fn bitor_assign(&mut self, other: &BigInt) { - match (self.sign, other.sign) { - (_, NoSign) => {} - (NoSign, _) => self.assign_from_slice(other.sign, other.digits()), - (Plus, Plus) => self.data |= &other.data, - (Plus, Minus) => { - bitor_pos_neg(self.digits_mut(), other.digits()); - self.sign = Minus; - self.normalize(); - } - (Minus, Plus) => { - bitor_neg_pos(self.digits_mut(), other.digits()); - self.normalize(); - } - (Minus, Minus) => { - bitor_neg_neg(self.digits_mut(), other.digits()); - self.normalize(); - } - } - } -} - -// + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100 -// +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100 -// answer is neg, has length of longest with a possible carry -fn bitxor_pos_neg(a: &mut Vec, b: &[BigDigit]) { - let mut carry_b = 1; - let mut carry_xor = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_b = negate_carry(bi, &mut carry_b); - *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); - } - debug_assert!(b.len() > a.len() || carry_b == 0); - if a.len() > b.len() { - for ai in a[b.len()..].iter_mut() { - let twos_b = !0; - *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); - } - } else if b.len() > a.len() { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_b = negate_carry(bi, &mut carry_b); - negate_carry(twos_b, &mut carry_xor) - })); - debug_assert!(carry_b == 0); - } - if carry_xor != 0 { - a.push(1); - } -} - -// - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100 -// -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100 -// answer is neg, has length of longest with a possible carry -fn bitxor_neg_pos(a: &mut Vec, b: &[BigDigit]) { - let mut carry_a = 1; - let mut carry_xor = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a ^ bi, &mut carry_xor); - } - debug_assert!(a.len() > b.len() || carry_a == 0); - if a.len() > b.len() { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a, &mut carry_xor); - } - debug_assert!(carry_a == 0); - } else if b.len() > a.len() { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_a = !0; - negate_carry(twos_a ^ bi, &mut carry_xor) - })); - } - if carry_xor != 0 { - a.push(1); - } -} - -// - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe -// -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe -// answer is pos, has length of longest -fn bitxor_neg_neg(a: &mut Vec, b: &[BigDigit]) { - let mut carry_a = 1; - let mut carry_b = 1; - for (ai, &bi) in a.iter_mut().zip(b.iter()) { - let twos_a = negate_carry(*ai, &mut carry_a); - let twos_b = negate_carry(bi, &mut carry_b); - *ai = twos_a ^ twos_b; - } - debug_assert!(a.len() > b.len() || carry_a == 0); - debug_assert!(b.len() > a.len() || carry_b == 0); - if a.len() > b.len() { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - let twos_b = !0; - *ai = twos_a ^ twos_b; - } - debug_assert!(carry_a == 0); - } else if b.len() > a.len() { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_a = !0; - let twos_b = negate_carry(bi, &mut carry_b); - twos_a ^ twos_b - })); - debug_assert!(carry_b == 0); - } -} - -forward_all_binop_to_val_ref_commutative!(impl BitXor for BigInt, bitxor); - -impl<'a> BitXor<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn bitxor(mut self, other: &BigInt) -> BigInt { - self ^= other; - self - } -} - -forward_val_assign!(impl BitXorAssign for BigInt, bitxor_assign); - -impl<'a> BitXorAssign<&'a BigInt> for BigInt { - fn bitxor_assign(&mut self, other: &BigInt) { - match (self.sign, other.sign) { - (_, NoSign) => {} - (NoSign, _) => self.assign_from_slice(other.sign, other.digits()), - (Plus, Plus) => { - self.data ^= &other.data; - if self.data.is_zero() { - self.sign = NoSign; - } - } - (Plus, Minus) => { - bitxor_pos_neg(self.digits_mut(), other.digits()); - self.sign = Minus; - self.normalize(); - } - (Minus, Plus) => { - bitxor_neg_pos(self.digits_mut(), other.digits()); - self.normalize(); - } - (Minus, Minus) => { - bitxor_neg_neg(self.digits_mut(), other.digits()); - self.sign = Plus; - self.normalize(); - } - } - } -} - -impl FromStr for BigInt { - type Err = ParseBigIntError; - - #[inline] - fn from_str(s: &str) -> Result { - BigInt::from_str_radix(s, 10) - } -} - -impl Num for BigInt { - type FromStrRadixErr = ParseBigIntError; - - /// Creates and initializes a BigInt. - #[inline] - fn from_str_radix(mut s: &str, radix: u32) -> Result { - let sign = if s.starts_with('-') { - let tail = &s[1..]; - if !tail.starts_with('+') { - s = tail - } - Minus - } else { - Plus - }; - let bu = BigUint::from_str_radix(s, radix)?; - Ok(BigInt::from_biguint(sign, bu)) - } -} - -impl Shl for BigInt { - type Output = BigInt; - - #[inline] - fn shl(mut self, rhs: usize) -> BigInt { - self <<= rhs; - self - } -} - -impl<'a> Shl for &'a BigInt { - type Output = BigInt; - - #[inline] - fn shl(self, rhs: usize) -> BigInt { - BigInt::from_biguint(self.sign, &self.data << rhs) - } -} - -impl ShlAssign for BigInt { - #[inline] - fn shl_assign(&mut self, rhs: usize) { - self.data <<= rhs; - } -} - -// Negative values need a rounding adjustment if there are any ones in the -// bits that are getting shifted out. -fn shr_round_down(i: &BigInt, rhs: usize) -> bool { - i.is_negative() - && biguint::trailing_zeros(&i.data) - .map(|n| n < rhs) - .unwrap_or(false) -} - -impl Shr for BigInt { - type Output = BigInt; - - #[inline] - fn shr(mut self, rhs: usize) -> BigInt { - self >>= rhs; - self - } -} - -impl<'a> Shr for &'a BigInt { - type Output = BigInt; - - #[inline] - fn shr(self, rhs: usize) -> BigInt { - let round_down = shr_round_down(self, rhs); - let data = &self.data >> rhs; - BigInt::from_biguint(self.sign, if round_down { data + 1u8 } else { data }) - } -} - -impl ShrAssign for BigInt { - #[inline] - fn shr_assign(&mut self, rhs: usize) { - let round_down = shr_round_down(self, rhs); - self.data >>= rhs; - if round_down { - self.data += 1u8; - } else if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -impl Zero for BigInt { - #[inline] - fn zero() -> BigInt { - BigInt::from_biguint(NoSign, Zero::zero()) - } - - #[inline] - fn set_zero(&mut self) { - self.data.set_zero(); - self.sign = NoSign; - } - - #[inline] - fn is_zero(&self) -> bool { - self.sign == NoSign - } -} - -impl One for BigInt { - #[inline] - fn one() -> BigInt { - BigInt::from_biguint(Plus, One::one()) - } - - #[inline] - fn set_one(&mut self) { - self.data.set_one(); - self.sign = Plus; - } - - #[inline] - fn is_one(&self) -> bool { - self.sign == Plus && self.data.is_one() - } -} - -impl Signed for BigInt { - #[inline] - fn abs(&self) -> BigInt { - match self.sign { - Plus | NoSign => self.clone(), - Minus => BigInt::from_biguint(Plus, self.data.clone()), - } - } - - #[inline] - fn abs_sub(&self, other: &BigInt) -> BigInt { - if *self <= *other { - Zero::zero() - } else { - self - other - } - } - - #[inline] - fn signum(&self) -> BigInt { - match self.sign { - Plus => BigInt::from_biguint(Plus, One::one()), - Minus => BigInt::from_biguint(Minus, One::one()), - NoSign => Zero::zero(), - } - } - - #[inline] - fn is_positive(&self) -> bool { - self.sign == Plus - } - - #[inline] - fn is_negative(&self) -> bool { - self.sign == Minus - } -} - -/// Help function for pow -/// -/// Computes the effect of the exponent on the sign. -#[inline] -fn powsign(sign: Sign, other: &T) -> Sign { - if other.is_zero() { - Plus - } else if sign != Minus { - sign - } else if other.is_odd() { - sign - } else { - -sign - } -} - -macro_rules! pow_impl { - ($T:ty) => { - impl<'a> Pow<$T> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn pow(self, rhs: $T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, &rhs), (&self.data).pow(rhs)) - } - } - - impl<'a, 'b> Pow<&'b $T> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn pow(self, rhs: &$T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, rhs), (&self.data).pow(rhs)) - } - } - }; -} - -pow_impl!(u8); -pow_impl!(u16); -pow_impl!(u32); -pow_impl!(u64); -pow_impl!(usize); -#[cfg(has_i128)] -pow_impl!(u128); -pow_impl!(BigUint); - -// A convenience method for getting the absolute value of an i32 in a u32. -#[inline] -fn i32_abs_as_u32(a: i32) -> u32 { - if a == i32::min_value() { - a as u32 - } else { - a.abs() as u32 - } -} - -// A convenience method for getting the absolute value of an i64 in a u64. -#[inline] -fn i64_abs_as_u64(a: i64) -> u64 { - if a == i64::min_value() { - a as u64 - } else { - a.abs() as u64 - } -} - -// A convenience method for getting the absolute value of an i128 in a u128. -#[cfg(has_i128)] -#[inline] -fn i128_abs_as_u128(a: i128) -> u128 { - if a == i128::min_value() { - a as u128 - } else { - a.abs() as u128 - } -} - -// We want to forward to BigUint::add, but it's not clear how that will go until -// we compare both sign and magnitude. So we duplicate this body for every -// val/ref combination, deferring that decision to BigUint's own forwarding. -macro_rules! bigint_add { - ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { - match ($a.sign, $b.sign) { - (_, NoSign) => $a_owned, - (NoSign, _) => $b_owned, - // same sign => keep the sign with the sum of magnitudes - (Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data), - // opposite signs => keep the sign of the larger with the difference of magnitudes - (Plus, Minus) | (Minus, Plus) => match $a.data.cmp(&$b.data) { - Less => BigInt::from_biguint($b.sign, $b_data - $a_data), - Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), - Equal => Zero::zero(), - }, - } - }; -} - -impl<'a, 'b> Add<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: &BigInt) -> BigInt { - bigint_add!( - self, - self.clone(), - &self.data, - other, - other.clone(), - &other.data - ) - } -} - -impl<'a> Add for &'a BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: BigInt) -> BigInt { - bigint_add!(self, self.clone(), &self.data, other, other, other.data) - } -} - -impl<'a> Add<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: &BigInt) -> BigInt { - bigint_add!(self, self, self.data, other, other.clone(), &other.data) - } -} - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: BigInt) -> BigInt { - bigint_add!(self, self, self.data, other, other, other.data) - } -} - -impl<'a> AddAssign<&'a BigInt> for BigInt { - #[inline] - fn add_assign(&mut self, other: &BigInt) { - let n = mem::replace(self, BigInt::zero()); - *self = n + other; - } -} -forward_val_assign!(impl AddAssign for BigInt, add_assign); - -promote_all_scalars!(impl Add for BigInt, add); -promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: u32) -> BigInt { - match self.sign { - NoSign => From::from(other), - Plus => BigInt::from_biguint(Plus, self.data + other), - Minus => match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Less => BigInt::from_biguint(Plus, other - self.data), - Greater => BigInt::from_biguint(Minus, self.data - other), - }, - } - } -} -impl AddAssign for BigInt { - #[inline] - fn add_assign(&mut self, other: u32) { - let n = mem::replace(self, BigInt::zero()); - *self = n + other; - } -} - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: u64) -> BigInt { - match self.sign { - NoSign => From::from(other), - Plus => BigInt::from_biguint(Plus, self.data + other), - Minus => match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Less => BigInt::from_biguint(Plus, other - self.data), - Greater => BigInt::from_biguint(Minus, self.data - other), - }, - } - } -} -impl AddAssign for BigInt { - #[inline] - fn add_assign(&mut self, other: u64) { - let n = mem::replace(self, BigInt::zero()); - *self = n + other; - } -} - -#[cfg(has_i128)] -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: u128) -> BigInt { - match self.sign { - NoSign => From::from(other), - Plus => BigInt::from_biguint(Plus, self.data + other), - Minus => match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Less => BigInt::from_biguint(Plus, other - self.data), - Greater => BigInt::from_biguint(Minus, self.data - other), - }, - } - } -} -#[cfg(has_i128)] -impl AddAssign for BigInt { - #[inline] - fn add_assign(&mut self, other: u128) { - let n = mem::replace(self, BigInt::zero()); - *self = n + other; - } -} - -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: i32) -> BigInt { - if other >= 0 { - self + other as u32 - } else { - self - i32_abs_as_u32(other) - } - } -} -impl AddAssign for BigInt { - #[inline] - fn add_assign(&mut self, other: i32) { - if other >= 0 { - *self += other as u32; - } else { - *self -= i32_abs_as_u32(other); - } - } -} - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: i64) -> BigInt { - if other >= 0 { - self + other as u64 - } else { - self - i64_abs_as_u64(other) - } - } -} -impl AddAssign for BigInt { - #[inline] - fn add_assign(&mut self, other: i64) { - if other >= 0 { - *self += other as u64; - } else { - *self -= i64_abs_as_u64(other); - } - } -} - -#[cfg(has_i128)] -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: i128) -> BigInt { - if other >= 0 { - self + other as u128 - } else { - self - i128_abs_as_u128(other) - } - } -} -#[cfg(has_i128)] -impl AddAssign for BigInt { - #[inline] - fn add_assign(&mut self, other: i128) { - if other >= 0 { - *self += other as u128; - } else { - *self -= i128_abs_as_u128(other); - } - } -} - -// We want to forward to BigUint::sub, but it's not clear how that will go until -// we compare both sign and magnitude. So we duplicate this body for every -// val/ref combination, deferring that decision to BigUint's own forwarding. -macro_rules! bigint_sub { - ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { - match ($a.sign, $b.sign) { - (_, NoSign) => $a_owned, - (NoSign, _) => -$b_owned, - // opposite signs => keep the sign of the left with the sum of magnitudes - (Plus, Minus) | (Minus, Plus) => BigInt::from_biguint($a.sign, $a_data + $b_data), - // same sign => keep or toggle the sign of the left with the difference of magnitudes - (Plus, Plus) | (Minus, Minus) => match $a.data.cmp(&$b.data) { - Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data), - Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), - Equal => Zero::zero(), - }, - } - }; -} - -impl<'a, 'b> Sub<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: &BigInt) -> BigInt { - bigint_sub!( - self, - self.clone(), - &self.data, - other, - other.clone(), - &other.data - ) - } -} - -impl<'a> Sub for &'a BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - bigint_sub!(self, self.clone(), &self.data, other, other, other.data) - } -} - -impl<'a> Sub<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: &BigInt) -> BigInt { - bigint_sub!(self, self, self.data, other, other.clone(), &other.data) - } -} - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - bigint_sub!(self, self, self.data, other, other, other.data) - } -} - -impl<'a> SubAssign<&'a BigInt> for BigInt { - #[inline] - fn sub_assign(&mut self, other: &BigInt) { - let n = mem::replace(self, BigInt::zero()); - *self = n - other; - } -} -forward_val_assign!(impl SubAssign for BigInt, sub_assign); - -promote_all_scalars!(impl Sub for BigInt, sub); -promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign); -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: u32) -> BigInt { - match self.sign { - NoSign => BigInt::from_biguint(Minus, From::from(other)), - Minus => BigInt::from_biguint(Minus, self.data + other), - Plus => match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Greater => BigInt::from_biguint(Plus, self.data - other), - Less => BigInt::from_biguint(Minus, other - self.data), - }, - } - } -} -impl SubAssign for BigInt { - #[inline] - fn sub_assign(&mut self, other: u32) { - let n = mem::replace(self, BigInt::zero()); - *self = n - other; - } -} - -impl Sub for u32 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - -(other - self) - } -} - -impl Sub for u64 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - -(other - self) - } -} -#[cfg(has_i128)] -impl Sub for u128 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - -(other - self) - } -} - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: u64) -> BigInt { - match self.sign { - NoSign => BigInt::from_biguint(Minus, From::from(other)), - Minus => BigInt::from_biguint(Minus, self.data + other), - Plus => match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Greater => BigInt::from_biguint(Plus, self.data - other), - Less => BigInt::from_biguint(Minus, other - self.data), - }, - } - } -} -impl SubAssign for BigInt { - #[inline] - fn sub_assign(&mut self, other: u64) { - let n = mem::replace(self, BigInt::zero()); - *self = n - other; - } -} - -#[cfg(has_i128)] -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: u128) -> BigInt { - match self.sign { - NoSign => BigInt::from_biguint(Minus, From::from(other)), - Minus => BigInt::from_biguint(Minus, self.data + other), - Plus => match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Greater => BigInt::from_biguint(Plus, self.data - other), - Less => BigInt::from_biguint(Minus, other - self.data), - }, - } - } -} -#[cfg(has_i128)] -impl SubAssign for BigInt { - #[inline] - fn sub_assign(&mut self, other: u128) { - let n = mem::replace(self, BigInt::zero()); - *self = n - other; - } -} - -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: i32) -> BigInt { - if other >= 0 { - self - other as u32 - } else { - self + i32_abs_as_u32(other) - } - } -} -impl SubAssign for BigInt { - #[inline] - fn sub_assign(&mut self, other: i32) { - if other >= 0 { - *self -= other as u32; - } else { - *self += i32_abs_as_u32(other); - } - } -} - -impl Sub for i32 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u32 - other - } else { - -other - i32_abs_as_u32(self) - } - } -} - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: i64) -> BigInt { - if other >= 0 { - self - other as u64 - } else { - self + i64_abs_as_u64(other) - } - } -} -impl SubAssign for BigInt { - #[inline] - fn sub_assign(&mut self, other: i64) { - if other >= 0 { - *self -= other as u64; - } else { - *self += i64_abs_as_u64(other); - } - } -} - -impl Sub for i64 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u64 - other - } else { - -other - i64_abs_as_u64(self) - } - } -} - -#[cfg(has_i128)] -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: i128) -> BigInt { - if other >= 0 { - self - other as u128 - } else { - self + i128_abs_as_u128(other) - } - } -} -#[cfg(has_i128)] -impl SubAssign for BigInt { - #[inline] - fn sub_assign(&mut self, other: i128) { - if other >= 0 { - *self -= other as u128; - } else { - *self += i128_abs_as_u128(other); - } - } -} -#[cfg(has_i128)] -impl Sub for i128 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u128 - other - } else { - -other - i128_abs_as_u128(self) - } - } -} - -forward_all_binop_to_ref_ref!(impl Mul for BigInt, mul); - -impl<'a, 'b> Mul<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: &BigInt) -> BigInt { - BigInt::from_biguint(self.sign * other.sign, &self.data * &other.data) - } -} - -impl<'a> MulAssign<&'a BigInt> for BigInt { - #[inline] - fn mul_assign(&mut self, other: &BigInt) { - *self = &*self * other; - } -} -forward_val_assign!(impl MulAssign for BigInt, mul_assign); - -promote_all_scalars!(impl Mul for BigInt, mul); -promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: u32) -> BigInt { - BigInt::from_biguint(self.sign, self.data * other) - } -} - -impl MulAssign for BigInt { - #[inline] - fn mul_assign(&mut self, other: u32) { - self.data *= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: u64) -> BigInt { - BigInt::from_biguint(self.sign, self.data * other) - } -} - -impl MulAssign for BigInt { - #[inline] - fn mul_assign(&mut self, other: u64) { - self.data *= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} -#[cfg(has_i128)] -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: u128) -> BigInt { - BigInt::from_biguint(self.sign, self.data * other) - } -} -#[cfg(has_i128)] -impl MulAssign for BigInt { - #[inline] - fn mul_assign(&mut self, other: u128) { - self.data *= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: i32) -> BigInt { - if other >= 0 { - self * other as u32 - } else { - -(self * i32_abs_as_u32(other)) - } - } -} - -impl MulAssign for BigInt { - #[inline] - fn mul_assign(&mut self, other: i32) { - if other >= 0 { - *self *= other as u32; - } else { - self.sign = -self.sign; - *self *= i32_abs_as_u32(other); - } - } -} - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: i64) -> BigInt { - if other >= 0 { - self * other as u64 - } else { - -(self * i64_abs_as_u64(other)) - } - } -} - -impl MulAssign for BigInt { - #[inline] - fn mul_assign(&mut self, other: i64) { - if other >= 0 { - *self *= other as u64; - } else { - self.sign = -self.sign; - *self *= i64_abs_as_u64(other); - } - } -} -#[cfg(has_i128)] -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: i128) -> BigInt { - if other >= 0 { - self * other as u128 - } else { - -(self * i128_abs_as_u128(other)) - } - } -} -#[cfg(has_i128)] -impl MulAssign for BigInt { - #[inline] - fn mul_assign(&mut self, other: i128) { - if other >= 0 { - *self *= other as u128; - } else { - self.sign = -self.sign; - *self *= i128_abs_as_u128(other); - } - } -} - -forward_all_binop_to_ref_ref!(impl Div for BigInt, div); - -impl<'a, 'b> Div<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: &BigInt) -> BigInt { - let (q, _) = self.div_rem(other); - q - } -} - -impl<'a> DivAssign<&'a BigInt> for BigInt { - #[inline] - fn div_assign(&mut self, other: &BigInt) { - *self = &*self / other; - } -} -forward_val_assign!(impl DivAssign for BigInt, div_assign); - -promote_all_scalars!(impl Div for BigInt, div); -promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign); -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: u32) -> BigInt { - BigInt::from_biguint(self.sign, self.data / other) - } -} - -impl DivAssign for BigInt { - #[inline] - fn div_assign(&mut self, other: u32) { - self.data /= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -impl Div for u32 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - BigInt::from_biguint(other.sign, self / other.data) - } -} - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: u64) -> BigInt { - BigInt::from_biguint(self.sign, self.data / other) - } -} - -impl DivAssign for BigInt { - #[inline] - fn div_assign(&mut self, other: u64) { - self.data /= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -impl Div for u64 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - BigInt::from_biguint(other.sign, self / other.data) - } -} - -#[cfg(has_i128)] -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: u128) -> BigInt { - BigInt::from_biguint(self.sign, self.data / other) - } -} - -#[cfg(has_i128)] -impl DivAssign for BigInt { - #[inline] - fn div_assign(&mut self, other: u128) { - self.data /= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -#[cfg(has_i128)] -impl Div for u128 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - BigInt::from_biguint(other.sign, self / other.data) - } -} - -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: i32) -> BigInt { - if other >= 0 { - self / other as u32 - } else { - -(self / i32_abs_as_u32(other)) - } - } -} - -impl DivAssign for BigInt { - #[inline] - fn div_assign(&mut self, other: i32) { - if other >= 0 { - *self /= other as u32; - } else { - self.sign = -self.sign; - *self /= i32_abs_as_u32(other); - } - } -} - -impl Div for i32 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u32 / other - } else { - -(i32_abs_as_u32(self) / other) - } - } -} - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: i64) -> BigInt { - if other >= 0 { - self / other as u64 - } else { - -(self / i64_abs_as_u64(other)) - } - } -} - -impl DivAssign for BigInt { - #[inline] - fn div_assign(&mut self, other: i64) { - if other >= 0 { - *self /= other as u64; - } else { - self.sign = -self.sign; - *self /= i64_abs_as_u64(other); - } - } -} - -impl Div for i64 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u64 / other - } else { - -(i64_abs_as_u64(self) / other) - } - } -} - -#[cfg(has_i128)] -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: i128) -> BigInt { - if other >= 0 { - self / other as u128 - } else { - -(self / i128_abs_as_u128(other)) - } - } -} - -#[cfg(has_i128)] -impl DivAssign for BigInt { - #[inline] - fn div_assign(&mut self, other: i128) { - if other >= 0 { - *self /= other as u128; - } else { - self.sign = -self.sign; - *self /= i128_abs_as_u128(other); - } - } -} - -#[cfg(has_i128)] -impl Div for i128 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u128 / other - } else { - -(i128_abs_as_u128(self) / other) - } - } -} - -forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); - -impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: &BigInt) -> BigInt { - let (_, r) = self.div_rem(other); - r - } -} - -impl<'a> RemAssign<&'a BigInt> for BigInt { - #[inline] - fn rem_assign(&mut self, other: &BigInt) { - *self = &*self % other; - } -} -forward_val_assign!(impl RemAssign for BigInt, rem_assign); - -promote_all_scalars!(impl Rem for BigInt, rem); -promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign); -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: u32) -> BigInt { - BigInt::from_biguint(self.sign, self.data % other) - } -} - -impl RemAssign for BigInt { - #[inline] - fn rem_assign(&mut self, other: u32) { - self.data %= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -impl Rem for u32 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - BigInt::from_biguint(Plus, self % other.data) - } -} - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: u64) -> BigInt { - BigInt::from_biguint(self.sign, self.data % other) - } -} - -impl RemAssign for BigInt { - #[inline] - fn rem_assign(&mut self, other: u64) { - self.data %= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -impl Rem for u64 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - BigInt::from_biguint(Plus, self % other.data) - } -} - -#[cfg(has_i128)] -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: u128) -> BigInt { - BigInt::from_biguint(self.sign, self.data % other) - } -} - -#[cfg(has_i128)] -impl RemAssign for BigInt { - #[inline] - fn rem_assign(&mut self, other: u128) { - self.data %= other; - if self.data.is_zero() { - self.sign = NoSign; - } - } -} - -#[cfg(has_i128)] -impl Rem for u128 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - BigInt::from_biguint(Plus, self % other.data) - } -} - -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: i32) -> BigInt { - if other >= 0 { - self % other as u32 - } else { - self % i32_abs_as_u32(other) - } - } -} - -impl RemAssign for BigInt { - #[inline] - fn rem_assign(&mut self, other: i32) { - if other >= 0 { - *self %= other as u32; - } else { - *self %= i32_abs_as_u32(other); - } - } -} - -impl Rem for i32 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u32 % other - } else { - -(i32_abs_as_u32(self) % other) - } - } -} - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: i64) -> BigInt { - if other >= 0 { - self % other as u64 - } else { - self % i64_abs_as_u64(other) - } - } -} - -impl RemAssign for BigInt { - #[inline] - fn rem_assign(&mut self, other: i64) { - if other >= 0 { - *self %= other as u64; - } else { - *self %= i64_abs_as_u64(other); - } - } -} - -impl Rem for i64 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u64 % other - } else { - -(i64_abs_as_u64(self) % other) - } - } -} - -#[cfg(has_i128)] -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: i128) -> BigInt { - if other >= 0 { - self % other as u128 - } else { - self % i128_abs_as_u128(other) - } - } -} -#[cfg(has_i128)] -impl RemAssign for BigInt { - #[inline] - fn rem_assign(&mut self, other: i128) { - if other >= 0 { - *self %= other as u128; - } else { - *self %= i128_abs_as_u128(other); - } - } -} -#[cfg(has_i128)] -impl Rem for i128 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u128 % other - } else { - -(i128_abs_as_u128(self) % other) - } - } -} - -impl Neg for BigInt { - type Output = BigInt; - - #[inline] - fn neg(mut self) -> BigInt { - self.sign = -self.sign; - self - } -} - -impl<'a> Neg for &'a BigInt { - type Output = BigInt; - - #[inline] - fn neg(self) -> BigInt { - -self.clone() - } -} - -impl CheckedAdd for BigInt { - #[inline] - fn checked_add(&self, v: &BigInt) -> Option { - return Some(self.add(v)); - } -} - -impl CheckedSub for BigInt { - #[inline] - fn checked_sub(&self, v: &BigInt) -> Option { - return Some(self.sub(v)); - } -} - -impl CheckedMul for BigInt { - #[inline] - fn checked_mul(&self, v: &BigInt) -> Option { - return Some(self.mul(v)); - } -} - -impl CheckedDiv for BigInt { - #[inline] - fn checked_div(&self, v: &BigInt) -> Option { - if v.is_zero() { - return None; - } - return Some(self.div(v)); - } -} - -impl Integer for BigInt { - #[inline] - fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { - // r.sign == self.sign - let (d_ui, r_ui) = self.data.div_mod_floor(&other.data); - let d = BigInt::from_biguint(self.sign, d_ui); - let r = BigInt::from_biguint(self.sign, r_ui); - if other.is_negative() { - (-d, r) - } else { - (d, r) - } - } - - #[inline] - fn div_floor(&self, other: &BigInt) -> BigInt { - let (d, _) = self.div_mod_floor(other); - d - } - - #[inline] - fn mod_floor(&self, other: &BigInt) -> BigInt { - let (_, m) = self.div_mod_floor(other); - m - } - - fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { - // m.sign == other.sign - let (d_ui, m_ui) = self.data.div_rem(&other.data); - let d = BigInt::from_biguint(Plus, d_ui); - let m = BigInt::from_biguint(Plus, m_ui); - let one: BigInt = One::one(); - match (self.sign, other.sign) { - (_, NoSign) => panic!(), - (Plus, Plus) | (NoSign, Plus) => (d, m), - (Plus, Minus) | (NoSign, Minus) => { - if m.is_zero() { - (-d, Zero::zero()) - } else { - (-d - one, m + other) - } - } - (Minus, Plus) => { - if m.is_zero() { - (-d, Zero::zero()) - } else { - (-d - one, other - m) - } - } - (Minus, Minus) => (d, -m), - } - } - - /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. - /// - /// The result is always positive. - #[inline] - fn gcd(&self, other: &BigInt) -> BigInt { - BigInt::from_biguint(Plus, self.data.gcd(&other.data)) - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. - #[inline] - fn lcm(&self, other: &BigInt) -> BigInt { - BigInt::from_biguint(Plus, self.data.lcm(&other.data)) - } - - /// Deprecated, use `is_multiple_of` instead. - #[inline] - fn divides(&self, other: &BigInt) -> bool { - return self.is_multiple_of(other); - } - - /// Returns `true` if the number is a multiple of `other`. - #[inline] - fn is_multiple_of(&self, other: &BigInt) -> bool { - self.data.is_multiple_of(&other.data) - } - - /// Returns `true` if the number is divisible by `2`. - #[inline] - fn is_even(&self) -> bool { - self.data.is_even() - } - - /// Returns `true` if the number is not divisible by `2`. - #[inline] - fn is_odd(&self) -> bool { - self.data.is_odd() - } -} - -impl Roots for BigInt { - fn nth_root(&self, n: u32) -> Self { - assert!( - !(self.is_negative() && n.is_even()), - "root of degree {} is imaginary", - n - ); - - BigInt::from_biguint(self.sign, self.data.nth_root(n)) - } - - fn sqrt(&self) -> Self { - assert!(!self.is_negative(), "square root is imaginary"); - - BigInt::from_biguint(self.sign, self.data.sqrt()) - } - - fn cbrt(&self) -> Self { - BigInt::from_biguint(self.sign, self.data.cbrt()) - } -} - -impl ToPrimitive for BigInt { - #[inline] - fn to_i64(&self) -> Option { - match self.sign { - Plus => self.data.to_i64(), - NoSign => Some(0), - Minus => self.data.to_u64().and_then(|n| { - let m: u64 = 1 << 63; - if n < m { - Some(-(n as i64)) - } else if n == m { - Some(i64::MIN) - } else { - None - } - }), - } - } - - #[inline] - #[cfg(has_i128)] - fn to_i128(&self) -> Option { - match self.sign { - Plus => self.data.to_i128(), - NoSign => Some(0), - Minus => self.data.to_u128().and_then(|n| { - let m: u128 = 1 << 127; - if n < m { - Some(-(n as i128)) - } else if n == m { - Some(i128::MIN) - } else { - None - } - }), - } - } - - #[inline] - fn to_u64(&self) -> Option { - match self.sign { - Plus => self.data.to_u64(), - NoSign => Some(0), - Minus => None, - } - } - - #[inline] - #[cfg(has_i128)] - fn to_u128(&self) -> Option { - match self.sign { - Plus => self.data.to_u128(), - NoSign => Some(0), - Minus => None, - } - } - - #[inline] - fn to_f32(&self) -> Option { - self.data - .to_f32() - .map(|n| if self.sign == Minus { -n } else { n }) - } - - #[inline] - fn to_f64(&self) -> Option { - self.data - .to_f64() - .map(|n| if self.sign == Minus { -n } else { n }) - } -} - -impl FromPrimitive for BigInt { - #[inline] - fn from_i64(n: i64) -> Option { - Some(BigInt::from(n)) - } - - #[inline] - #[cfg(has_i128)] - fn from_i128(n: i128) -> Option { - Some(BigInt::from(n)) - } - - #[inline] - fn from_u64(n: u64) -> Option { - Some(BigInt::from(n)) - } - - #[inline] - #[cfg(has_i128)] - fn from_u128(n: u128) -> Option { - Some(BigInt::from(n)) - } - - #[inline] - fn from_f64(n: f64) -> Option { - if n >= 0.0 { - BigUint::from_f64(n).map(|x| BigInt::from_biguint(Plus, x)) - } else { - BigUint::from_f64(-n).map(|x| BigInt::from_biguint(Minus, x)) - } - } -} - -impl From for BigInt { - #[inline] - fn from(n: i64) -> Self { - if n >= 0 { - BigInt::from(n as u64) - } else { - let u = u64::MAX - (n as u64) + 1; - BigInt { - sign: Minus, - data: BigUint::from(u), - } - } - } -} - -#[cfg(has_i128)] -impl From for BigInt { - #[inline] - fn from(n: i128) -> Self { - if n >= 0 { - BigInt::from(n as u128) - } else { - let u = u128::MAX - (n as u128) + 1; - BigInt { - sign: Minus, - data: BigUint::from(u), - } - } - } -} - -macro_rules! impl_bigint_from_int { - ($T:ty) => { - impl From<$T> for BigInt { - #[inline] - fn from(n: $T) -> Self { - BigInt::from(n as i64) - } - } - }; -} - -impl_bigint_from_int!(i8); -impl_bigint_from_int!(i16); -impl_bigint_from_int!(i32); -impl_bigint_from_int!(isize); - -impl From for BigInt { - #[inline] - fn from(n: u64) -> Self { - if n > 0 { - BigInt { - sign: Plus, - data: BigUint::from(n), - } - } else { - BigInt::zero() - } - } -} - -#[cfg(has_i128)] -impl From for BigInt { - #[inline] - fn from(n: u128) -> Self { - if n > 0 { - BigInt { - sign: Plus, - data: BigUint::from(n), - } - } else { - BigInt::zero() - } - } -} - -macro_rules! impl_bigint_from_uint { - ($T:ty) => { - impl From<$T> for BigInt { - #[inline] - fn from(n: $T) -> Self { - BigInt::from(n as u64) - } - } - }; -} - -impl_bigint_from_uint!(u8); -impl_bigint_from_uint!(u16); -impl_bigint_from_uint!(u32); -impl_bigint_from_uint!(usize); - -impl From for BigInt { - #[inline] - fn from(n: BigUint) -> Self { - if n.is_zero() { - BigInt::zero() - } else { - BigInt { - sign: Plus, - data: n, - } - } - } -} - -impl IntDigits for BigInt { - #[inline] - fn digits(&self) -> &[BigDigit] { - self.data.digits() - } - #[inline] - fn digits_mut(&mut self) -> &mut Vec { - self.data.digits_mut() - } - #[inline] - fn normalize(&mut self) { - self.data.normalize(); - if self.data.is_zero() { - self.sign = NoSign; - } - } - #[inline] - fn capacity(&self) -> usize { - self.data.capacity() - } - #[inline] - fn len(&self) -> usize { - self.data.len() - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for BigInt { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - // Note: do not change the serialization format, or it may break - // forward and backward compatibility of serialized data! - (self.sign, &self.data).serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for BigInt { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let (sign, data) = serde::Deserialize::deserialize(deserializer)?; - Ok(BigInt::from_biguint(sign, data)) - } -} - -/// A generic trait for converting a value to a `BigInt`. This may return -/// `None` when converting from `f32` or `f64`, and will always succeed -/// when converting from any integer or unsigned primitive, or `BigUint`. -pub trait ToBigInt { - /// Converts the value of `self` to a `BigInt`. - fn to_bigint(&self) -> Option; -} - -impl ToBigInt for BigInt { - #[inline] - fn to_bigint(&self) -> Option { - Some(self.clone()) - } -} - -impl ToBigInt for BigUint { - #[inline] - fn to_bigint(&self) -> Option { - if self.is_zero() { - Some(Zero::zero()) - } else { - Some(BigInt { - sign: Plus, - data: self.clone(), - }) - } - } -} - -impl biguint::ToBigUint for BigInt { - #[inline] - fn to_biguint(&self) -> Option { - match self.sign() { - Plus => Some(self.data.clone()), - NoSign => Some(Zero::zero()), - Minus => None, - } - } -} - -macro_rules! impl_to_bigint { - ($T:ty, $from_ty:path) => { - impl ToBigInt for $T { - #[inline] - fn to_bigint(&self) -> Option { - $from_ty(*self) - } - } - }; -} - -impl_to_bigint!(isize, FromPrimitive::from_isize); -impl_to_bigint!(i8, FromPrimitive::from_i8); -impl_to_bigint!(i16, FromPrimitive::from_i16); -impl_to_bigint!(i32, FromPrimitive::from_i32); -impl_to_bigint!(i64, FromPrimitive::from_i64); -#[cfg(has_i128)] -impl_to_bigint!(i128, FromPrimitive::from_i128); - -impl_to_bigint!(usize, FromPrimitive::from_usize); -impl_to_bigint!(u8, FromPrimitive::from_u8); -impl_to_bigint!(u16, FromPrimitive::from_u16); -impl_to_bigint!(u32, FromPrimitive::from_u32); -impl_to_bigint!(u64, FromPrimitive::from_u64); -#[cfg(has_i128)] -impl_to_bigint!(u128, FromPrimitive::from_u128); - -impl_to_bigint!(f32, FromPrimitive::from_f32); -impl_to_bigint!(f64, FromPrimitive::from_f64); - -impl BigInt { - /// Creates and initializes a BigInt. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn new(sign: Sign, digits: Vec) -> BigInt { - BigInt::from_biguint(sign, BigUint::new(digits)) - } - - /// Creates and initializes a `BigInt`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { - if sign == NoSign { - data.assign_from_slice(&[]); - } else if data.is_zero() { - sign = NoSign; - } - - BigInt { - sign: sign, - data: data, - } - } - - /// Creates and initializes a `BigInt`. - #[inline] - pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt { - BigInt::from_biguint(sign, BigUint::from_slice(slice)) - } - - /// Reinitializes a `BigInt`. - #[inline] - pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) { - if sign == NoSign { - self.data.assign_from_slice(&[]); - self.sign = NoSign; - } else { - self.data.assign_from_slice(slice); - self.sign = match self.data.is_zero() { - true => NoSign, - false => sign, - } - } - } - - /// Creates and initializes a `BigInt`. - /// - /// The bytes are in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"A"), - /// BigInt::parse_bytes(b"65", 10).unwrap()); - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AA"), - /// BigInt::parse_bytes(b"16705", 10).unwrap()); - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AB"), - /// BigInt::parse_bytes(b"16706", 10).unwrap()); - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"Hello world!"), - /// BigInt::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); - /// ``` - #[inline] - pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt { - BigInt::from_biguint(sign, BigUint::from_bytes_be(bytes)) - } - - /// Creates and initializes a `BigInt`. - /// - /// The bytes are in little-endian byte order. - #[inline] - pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> BigInt { - BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes)) - } - - /// Creates and initializes a `BigInt` from an array of bytes in - /// two's complement binary representation. - /// - /// The digits are in big-endian base 28. - #[inline] - pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt { - let sign = match digits.first() { - Some(v) if *v > 0x7f => Sign::Minus, - Some(_) => Sign::Plus, - None => return BigInt::zero(), - }; - - if sign == Sign::Minus { - // two's-complement the content to retrieve the magnitude - let mut digits = Vec::from(digits); - twos_complement_be(&mut digits); - BigInt::from_biguint(sign, BigUint::from_bytes_be(&*digits)) - } else { - BigInt::from_biguint(sign, BigUint::from_bytes_be(digits)) - } - } - - /// Creates and initializes a `BigInt` from an array of bytes in two's complement. - /// - /// The digits are in little-endian base 28. - #[inline] - pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt { - let sign = match digits.last() { - Some(v) if *v > 0x7f => Sign::Minus, - Some(_) => Sign::Plus, - None => return BigInt::zero(), - }; - - if sign == Sign::Minus { - // two's-complement the content to retrieve the magnitude - let mut digits = Vec::from(digits); - twos_complement_le(&mut digits); - BigInt::from_biguint(sign, BigUint::from_bytes_le(&*digits)) - } else { - BigInt::from_biguint(sign, BigUint::from_bytes_le(digits)) - } - } - - /// Creates and initializes a `BigInt`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, ToBigInt}; - /// - /// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234)); - /// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD)); - /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); - /// ``` - #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - str::from_utf8(buf) - .ok() - .and_then(|s| BigInt::from_str_radix(s, radix).ok()) - } - - /// Creates and initializes a `BigInt`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in big-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// let inbase190 = vec![15, 33, 125, 12, 14]; - /// let a = BigInt::from_radix_be(Sign::Minus, &inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), (Sign:: Minus, inbase190)); - /// ``` - pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option { - BigUint::from_radix_be(buf, radix).map(|u| BigInt::from_biguint(sign, u)) - } - - /// Creates and initializes a `BigInt`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in little-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// let inbase190 = vec![14, 12, 125, 33, 15]; - /// let a = BigInt::from_radix_be(Sign::Minus, &inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), (Sign::Minus, inbase190)); - /// ``` - pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option { - BigUint::from_radix_le(buf, radix).map(|u| BigInt::from_biguint(sign, u)) - } - - /// Returns the sign and the byte representation of the `BigInt` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_bytes_be(), (Sign::Minus, vec![4, 101])); - /// ``` - #[inline] - pub fn to_bytes_be(&self) -> (Sign, Vec) { - (self.sign, self.data.to_bytes_be()) - } - - /// Returns the sign and the byte representation of the `BigInt` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4])); - /// ``` - #[inline] - pub fn to_bytes_le(&self) -> (Sign, Vec) { - (self.sign, self.data.to_bytes_le()) - } - - /// Returns the two's complement byte representation of the `BigInt` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::ToBigInt; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_signed_bytes_be(), vec![251, 155]); - /// ``` - #[inline] - pub fn to_signed_bytes_be(&self) -> Vec { - let mut bytes = self.data.to_bytes_be(); - let first_byte = bytes.first().map(|v| *v).unwrap_or(0); - if first_byte > 0x7f - && !(first_byte == 0x80 - && bytes.iter().skip(1).all(Zero::is_zero) - && self.sign == Sign::Minus) - { - // msb used by magnitude, extend by 1 byte - bytes.insert(0, 0); - } - if self.sign == Sign::Minus { - twos_complement_be(&mut bytes); - } - bytes - } - - /// Returns the two's complement byte representation of the `BigInt` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::ToBigInt; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]); - /// ``` - #[inline] - pub fn to_signed_bytes_le(&self) -> Vec { - let mut bytes = self.data.to_bytes_le(); - let last_byte = bytes.last().map(|v| *v).unwrap_or(0); - if last_byte > 0x7f - && !(last_byte == 0x80 - && bytes.iter().rev().skip(1).all(Zero::is_zero) - && self.sign == Sign::Minus) - { - // msb used by magnitude, extend by 1 byte - bytes.push(0); - } - if self.sign == Sign::Minus { - twos_complement_le(&mut bytes); - } - bytes - } - - /// Returns the integer formatted as a string in the given radix. - /// `radix` must be in the range `2...36`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigInt; - /// - /// let i = BigInt::parse_bytes(b"ff", 16).unwrap(); - /// assert_eq!(i.to_str_radix(16), "ff"); - /// ``` - #[inline] - pub fn to_str_radix(&self, radix: u32) -> String { - let mut v = to_str_radix_reversed(&self.data, radix); - - if self.is_negative() { - v.push(b'-'); - } - - v.reverse(); - unsafe { String::from_utf8_unchecked(v) } - } - - /// Returns the integer in the requested base in big-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from(-0xFFFFi64).to_radix_be(159), - /// (Sign::Minus, vec![2, 94, 27])); - /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 - /// ``` - #[inline] - pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec) { - (self.sign, self.data.to_radix_be(radix)) - } - - /// Returns the integer in the requested base in little-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from(-0xFFFFi64).to_radix_le(159), - /// (Sign::Minus, vec![27, 94, 2])); - /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) - /// ``` - #[inline] - pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec) { - (self.sign, self.data.to_radix_le(radix)) - } - - /// Returns the sign of the `BigInt` as a `Sign`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// assert_eq!(ToBigInt::to_bigint(&1234).unwrap().sign(), Sign::Plus); - /// assert_eq!(ToBigInt::to_bigint(&-4321).unwrap().sign(), Sign::Minus); - /// assert_eq!(ToBigInt::to_bigint(&0).unwrap().sign(), Sign::NoSign); - /// ``` - #[inline] - pub fn sign(&self) -> Sign { - self.sign - } - - /// Determines the fewest bits necessary to express the `BigInt`, - /// not including the sign. - #[inline] - pub fn bits(&self) -> usize { - self.data.bits() - } - - /// Converts this `BigInt` into a `BigUint`, if it's not negative. - #[inline] - pub fn to_biguint(&self) -> Option { - match self.sign { - Plus => Some(self.data.clone()), - NoSign => Some(Zero::zero()), - Minus => None, - } - } - - #[inline] - pub fn checked_add(&self, v: &BigInt) -> Option { - return Some(self.add(v)); - } - - #[inline] - pub fn checked_sub(&self, v: &BigInt) -> Option { - return Some(self.sub(v)); - } - - #[inline] - pub fn checked_mul(&self, v: &BigInt) -> Option { - return Some(self.mul(v)); - } - - #[inline] - pub fn checked_div(&self, v: &BigInt) -> Option { - if v.is_zero() { - return None; - } - return Some(self.div(v)); - } - - /// Returns `(self ^ exponent) mod modulus` - /// - /// Note that this rounds like `mod_floor`, not like the `%` operator, - /// which makes a difference when given a negative `self` or `modulus`. - /// The result will be in the interval `[0, modulus)` for `modulus > 0`, - /// or in the interval `(modulus, 0]` for `modulus < 0` - /// - /// Panics if the exponent is negative or the modulus is zero. - pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { - assert!( - !exponent.is_negative(), - "negative exponentiation is not supported!" - ); - assert!(!modulus.is_zero(), "divide by zero!"); - - let result = self.data.modpow(&exponent.data, &modulus.data); - if result.is_zero() { - return BigInt::zero(); - } - - // The sign of the result follows the modulus, like `mod_floor`. - let (sign, mag) = match (self.is_negative(), modulus.is_negative()) { - (false, false) => (Plus, result), - (true, false) => (Plus, &modulus.data - result), - (false, true) => (Minus, &modulus.data - result), - (true, true) => (Minus, result), - }; - BigInt::from_biguint(sign, mag) - } - - /// Returns the truncated principal square root of `self` -- - /// see [Roots::sqrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.sqrt). - pub fn sqrt(&self) -> Self { - Roots::sqrt(self) - } - - /// Returns the truncated principal cube root of `self` -- - /// see [Roots::cbrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.cbrt). - pub fn cbrt(&self) -> Self { - Roots::cbrt(self) - } - - /// Returns the truncated principal `n`th root of `self` -- - /// See [Roots::nth_root](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#tymethod.nth_root). - pub fn nth_root(&self, n: u32) -> Self { - Roots::nth_root(self, n) - } -} - -impl_sum_iter_type!(BigInt); -impl_product_iter_type!(BigInt); - -/// Perform in-place two's complement of the given binary representation, -/// in little-endian byte order. -#[inline] -fn twos_complement_le(digits: &mut [u8]) { - twos_complement(digits) -} - -/// Perform in-place two's complement of the given binary representation -/// in big-endian byte order. -#[inline] -fn twos_complement_be(digits: &mut [u8]) { - twos_complement(digits.iter_mut().rev()) -} - -/// Perform in-place two's complement of the given digit iterator -/// starting from the least significant byte. -#[inline] -fn twos_complement<'a, I>(digits: I) -where - I: IntoIterator, -{ - let mut carry = true; - for d in digits { - *d = d.not(); - if carry { - *d = d.wrapping_add(1); - carry = d.is_zero(); - } - } -} - -#[test] -fn test_from_biguint() { - fn check(inp_s: Sign, inp_n: usize, ans_s: Sign, ans_n: usize) { - let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_usize(inp_n).unwrap()); - let ans = BigInt { - sign: ans_s, - data: FromPrimitive::from_usize(ans_n).unwrap(), - }; - assert_eq!(inp, ans); - } - check(Plus, 1, Plus, 1); - check(Plus, 0, NoSign, 0); - check(Minus, 1, Minus, 1); - check(NoSign, 1, NoSign, 0); -} - -#[test] -fn test_from_slice() { - fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) { - let inp = BigInt::from_slice(inp_s, &[inp_n]); - let ans = BigInt { - sign: ans_s, - data: FromPrimitive::from_u32(ans_n).unwrap(), - }; - assert_eq!(inp, ans); - } - check(Plus, 1, Plus, 1); - check(Plus, 0, NoSign, 0); - check(Minus, 1, Minus, 1); - check(NoSign, 1, NoSign, 0); -} - -#[test] -fn test_assign_from_slice() { - fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) { - let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]); - inp.assign_from_slice(inp_s, &[inp_n]); - let ans = BigInt { - sign: ans_s, - data: FromPrimitive::from_u32(ans_n).unwrap(), - }; - assert_eq!(inp, ans); - } - check(Plus, 1, Plus, 1); - check(Plus, 0, NoSign, 0); - check(Minus, 1, Minus, 1); - check(NoSign, 1, NoSign, 0); -} diff --git a/third_party/rust/num-bigint-0.2.3/src/bigrand.rs b/third_party/rust/num-bigint-0.2.3/src/bigrand.rs deleted file mode 100644 index 4a13b29df48b..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/bigrand.rs +++ /dev/null @@ -1,218 +0,0 @@ -//! Randomization of big integers - -use rand::distributions::uniform::{SampleUniform, UniformSampler}; -use rand::prelude::*; -use rand::AsByteSliceMut; - -use BigInt; -use BigUint; -use Sign::*; - -use big_digit::BigDigit; -use bigint::{into_magnitude, magnitude}; - -use integer::Integer; -use traits::Zero; - -pub trait RandBigInt { - /// Generate a random `BigUint` of the given bit size. - fn gen_biguint(&mut self, bit_size: usize) -> BigUint; - - /// Generate a random BigInt of the given bit size. - fn gen_bigint(&mut self, bit_size: usize) -> BigInt; - - /// Generate a random `BigUint` less than the given bound. Fails - /// when the bound is zero. - fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint; - - /// Generate a random `BigUint` within the given range. The lower - /// bound is inclusive; the upper bound is exclusive. Fails when - /// the upper bound is not greater than the lower bound. - fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint; - - /// Generate a random `BigInt` within the given range. The lower - /// bound is inclusive; the upper bound is exclusive. Fails when - /// the upper bound is not greater than the lower bound. - fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt; -} - -impl RandBigInt for R { - fn gen_biguint(&mut self, bit_size: usize) -> BigUint { - use super::big_digit::BITS; - let (digits, rem) = bit_size.div_rem(&BITS); - let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize]; - // `fill_bytes` is faster than many `gen::` calls - self.fill_bytes(data[..].as_byte_slice_mut()); - // Swap bytes per the `Rng::fill` source. This might be - // unnecessary if reproducibility across architectures is not - // desired. - data.to_le(); - if rem > 0 { - data[digits] >>= BITS - rem; - } - BigUint::new(data) - } - - fn gen_bigint(&mut self, bit_size: usize) -> BigInt { - loop { - // Generate a random BigUint... - let biguint = self.gen_biguint(bit_size); - // ...and then randomly assign it a Sign... - let sign = if biguint.is_zero() { - // ...except that if the BigUint is zero, we need to try - // again with probability 0.5. This is because otherwise, - // the probability of generating a zero BigInt would be - // double that of any other number. - if self.gen() { - continue; - } else { - NoSign - } - } else if self.gen() { - Plus - } else { - Minus - }; - return BigInt::from_biguint(sign, biguint); - } - } - - fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint { - assert!(!bound.is_zero()); - let bits = bound.bits(); - loop { - let n = self.gen_biguint(bits); - if n < *bound { - return n; - } - } - } - - fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint { - assert!(*lbound < *ubound); - if lbound.is_zero() { - self.gen_biguint_below(ubound) - } else { - lbound + self.gen_biguint_below(&(ubound - lbound)) - } - } - - fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt { - assert!(*lbound < *ubound); - if lbound.is_zero() { - BigInt::from(self.gen_biguint_below(magnitude(&ubound))) - } else if ubound.is_zero() { - lbound + BigInt::from(self.gen_biguint_below(magnitude(&lbound))) - } else { - let delta = ubound - lbound; - lbound + BigInt::from(self.gen_biguint_below(magnitude(&delta))) - } - } -} - -/// The back-end implementing rand's `UniformSampler` for `BigUint`. -#[derive(Clone, Debug)] -pub struct UniformBigUint { - base: BigUint, - len: BigUint, -} - -impl UniformSampler for UniformBigUint { - type X = BigUint; - - #[inline] - fn new(low: Self::X, high: Self::X) -> Self { - assert!(low < high); - UniformBigUint { - len: high - &low, - base: low, - } - } - - #[inline] - fn new_inclusive(low: Self::X, high: Self::X) -> Self { - assert!(low <= high); - Self::new(low, high + 1u32) - } - - #[inline] - fn sample(&self, rng: &mut R) -> Self::X { - &self.base + rng.gen_biguint_below(&self.len) - } - - #[inline] - fn sample_single(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { - rng.gen_biguint_range(&low, &high) - } -} - -impl SampleUniform for BigUint { - type Sampler = UniformBigUint; -} - -/// The back-end implementing rand's `UniformSampler` for `BigInt`. -#[derive(Clone, Debug)] -pub struct UniformBigInt { - base: BigInt, - len: BigUint, -} - -impl UniformSampler for UniformBigInt { - type X = BigInt; - - #[inline] - fn new(low: Self::X, high: Self::X) -> Self { - assert!(low < high); - UniformBigInt { - len: into_magnitude(high - &low), - base: low, - } - } - - #[inline] - fn new_inclusive(low: Self::X, high: Self::X) -> Self { - assert!(low <= high); - Self::new(low, high + 1u32) - } - - #[inline] - fn sample(&self, rng: &mut R) -> Self::X { - &self.base + BigInt::from(rng.gen_biguint_below(&self.len)) - } - - #[inline] - fn sample_single(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { - rng.gen_bigint_range(&low, &high) - } -} - -impl SampleUniform for BigInt { - type Sampler = UniformBigInt; -} - -/// A random distribution for `BigUint` and `BigInt` values of a particular bit size. -#[derive(Clone, Copy, Debug)] -pub struct RandomBits { - bits: usize, -} - -impl RandomBits { - #[inline] - pub fn new(bits: usize) -> RandomBits { - RandomBits { bits } - } -} - -impl Distribution for RandomBits { - #[inline] - fn sample(&self, rng: &mut R) -> BigUint { - rng.gen_biguint(self.bits) - } -} - -impl Distribution for RandomBits { - #[inline] - fn sample(&self, rng: &mut R) -> BigInt { - rng.gen_bigint(self.bits) - } -} diff --git a/third_party/rust/num-bigint-0.2.3/src/biguint.rs b/third_party/rust/num-bigint-0.2.3/src/biguint.rs deleted file mode 100644 index e6e9fbcce5ab..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/biguint.rs +++ /dev/null @@ -1,3088 +0,0 @@ -#[allow(deprecated, unused_imports)] -use std::ascii::AsciiExt; -use std::borrow::Cow; -use std::cmp; -use std::cmp::Ordering::{self, Equal, Greater, Less}; -use std::default::Default; -use std::fmt; -use std::iter::{Product, Sum}; -use std::mem; -use std::ops::{ - Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, - Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, -}; -use std::str::{self, FromStr}; -use std::{f32, f64}; -use std::{u64, u8}; - -#[cfg(feature = "serde")] -use serde; - -use integer::{Integer, Roots}; -use traits::{ - CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Float, FromPrimitive, Num, One, Pow, - ToPrimitive, Unsigned, Zero, -}; - -use big_digit::{self, BigDigit}; - -#[path = "algorithms.rs"] -mod algorithms; -#[path = "monty.rs"] -mod monty; - -use self::algorithms::{__add2, __sub2rev, add2, sub2, sub2rev}; -use self::algorithms::{biguint_shl, biguint_shr}; -use self::algorithms::{cmp_slice, fls, ilog2}; -use self::algorithms::{div_rem, div_rem_digit, div_rem_ref, rem_digit}; -use self::algorithms::{mac_with_carry, mul3, scalar_mul}; -use self::monty::monty_modpow; - -use UsizePromotion; - -use ParseBigIntError; - -#[cfg(feature = "quickcheck")] -use quickcheck::{Arbitrary, Gen}; - -/// A big unsigned integer type. -#[derive(Clone, Debug, Hash)] -pub struct BigUint { - data: Vec, -} - -#[cfg(feature = "quickcheck")] -impl Arbitrary for BigUint { - fn arbitrary(g: &mut G) -> Self { - // Use arbitrary from Vec - Self::new(Vec::::arbitrary(g)) - } - - #[allow(bare_trait_objects)] // `dyn` needs Rust 1.27 to parse, even when cfg-disabled - fn shrink(&self) -> Box> { - // Use shrinker from Vec - Box::new(self.data.shrink().map(|x| BigUint::new(x))) - } -} - -impl PartialEq for BigUint { - #[inline] - fn eq(&self, other: &BigUint) -> bool { - match self.cmp(other) { - Equal => true, - _ => false, - } - } -} -impl Eq for BigUint {} - -impl PartialOrd for BigUint { - #[inline] - fn partial_cmp(&self, other: &BigUint) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for BigUint { - #[inline] - fn cmp(&self, other: &BigUint) -> Ordering { - cmp_slice(&self.data[..], &other.data[..]) - } -} - -impl Default for BigUint { - #[inline] - fn default() -> BigUint { - Zero::zero() - } -} - -impl fmt::Display for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "", &self.to_str_radix(10)) - } -} - -impl fmt::LowerHex for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0x", &self.to_str_radix(16)) - } -} - -impl fmt::UpperHex for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut s = self.to_str_radix(16); - s.make_ascii_uppercase(); - f.pad_integral(true, "0x", &s) - } -} - -impl fmt::Binary for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0b", &self.to_str_radix(2)) - } -} - -impl fmt::Octal for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0o", &self.to_str_radix(8)) - } -} - -impl FromStr for BigUint { - type Err = ParseBigIntError; - - #[inline] - fn from_str(s: &str) -> Result { - BigUint::from_str_radix(s, 10) - } -} - -// Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides -// BigDigit::BITS -fn from_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { - debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); - debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); - - let digits_per_big_digit = big_digit::BITS / bits; - - let data = v - .chunks(digits_per_big_digit) - .map(|chunk| { - chunk - .iter() - .rev() - .fold(0, |acc, &c| (acc << bits) | BigDigit::from(c)) - }) - .collect(); - - BigUint::new(data) -} - -// Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide -// BigDigit::BITS -fn from_inexact_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { - debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); - debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); - - let big_digits = (v.len() * bits + big_digit::BITS - 1) / big_digit::BITS; - let mut data = Vec::with_capacity(big_digits); - - let mut d = 0; - let mut dbits = 0; // number of bits we currently have in d - - // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a - // big_digit: - for &c in v { - d |= BigDigit::from(c) << dbits; - dbits += bits; - - if dbits >= big_digit::BITS { - data.push(d); - dbits -= big_digit::BITS; - // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit - // in d) - grab the bits we lost here: - d = BigDigit::from(c) >> (bits - dbits); - } - } - - if dbits > 0 { - debug_assert!(dbits < big_digit::BITS); - data.push(d as BigDigit); - } - - BigUint::new(data) -} - -// Read little-endian radix digits -fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { - debug_assert!(!v.is_empty() && !radix.is_power_of_two()); - debug_assert!(v.iter().all(|&c| u32::from(c) < radix)); - - // Estimate how big the result will be, so we can pre-allocate it. - let bits = f64::from(radix).log2() * v.len() as f64; - let big_digits = (bits / big_digit::BITS as f64).ceil(); - let mut data = Vec::with_capacity(big_digits as usize); - - let (base, power) = get_radix_base(radix); - let radix = radix as BigDigit; - - let r = v.len() % power; - let i = if r == 0 { power } else { r }; - let (head, tail) = v.split_at(i); - - let first = head - .iter() - .fold(0, |acc, &d| acc * radix + BigDigit::from(d)); - data.push(first); - - debug_assert!(tail.len() % power == 0); - for chunk in tail.chunks(power) { - if data.last() != Some(&0) { - data.push(0); - } - - let mut carry = 0; - for d in data.iter_mut() { - *d = mac_with_carry(0, *d, base, &mut carry); - } - debug_assert!(carry == 0); - - let n = chunk - .iter() - .fold(0, |acc, &d| acc * radix + BigDigit::from(d)); - add2(&mut data, &[n]); - } - - BigUint::new(data) -} - -impl Num for BigUint { - type FromStrRadixErr = ParseBigIntError; - - /// Creates and initializes a `BigUint`. - fn from_str_radix(s: &str, radix: u32) -> Result { - assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); - let mut s = s; - if s.starts_with('+') { - let tail = &s[1..]; - if !tail.starts_with('+') { - s = tail - } - } - - if s.is_empty() { - return Err(ParseBigIntError::empty()); - } - - if s.starts_with('_') { - // Must lead with a real digit! - return Err(ParseBigIntError::invalid()); - } - - // First normalize all characters to plain digit values - let mut v = Vec::with_capacity(s.len()); - for b in s.bytes() { - #[allow(unknown_lints, ellipsis_inclusive_range_patterns)] - let d = match b { - b'0'...b'9' => b - b'0', - b'a'...b'z' => b - b'a' + 10, - b'A'...b'Z' => b - b'A' + 10, - b'_' => continue, - _ => u8::MAX, - }; - if d < radix as u8 { - v.push(d); - } else { - return Err(ParseBigIntError::invalid()); - } - } - - let res = if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of multiplication - let bits = ilog2(radix); - v.reverse(); - if big_digit::BITS % bits == 0 { - from_bitwise_digits_le(&v, bits) - } else { - from_inexact_bitwise_digits_le(&v, bits) - } - } else { - from_radix_digits_be(&v, radix) - }; - Ok(res) - } -} - -forward_val_val_binop!(impl BitAnd for BigUint, bitand); -forward_ref_val_binop!(impl BitAnd for BigUint, bitand); - -// do not use forward_ref_ref_binop_commutative! for bitand so that we can -// clone the smaller value rather than the larger, avoiding over-allocation -impl<'a, 'b> BitAnd<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn bitand(self, other: &BigUint) -> BigUint { - // forward to val-ref, choosing the smaller to clone - if self.data.len() <= other.data.len() { - self.clone() & other - } else { - other.clone() & self - } - } -} - -forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign); - -impl<'a> BitAnd<&'a BigUint> for BigUint { - type Output = BigUint; - - #[inline] - fn bitand(mut self, other: &BigUint) -> BigUint { - self &= other; - self - } -} -impl<'a> BitAndAssign<&'a BigUint> for BigUint { - #[inline] - fn bitand_assign(&mut self, other: &BigUint) { - for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { - *ai &= bi; - } - self.data.truncate(other.data.len()); - self.normalize(); - } -} - -forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor); -forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign); - -impl<'a> BitOr<&'a BigUint> for BigUint { - type Output = BigUint; - - fn bitor(mut self, other: &BigUint) -> BigUint { - self |= other; - self - } -} -impl<'a> BitOrAssign<&'a BigUint> for BigUint { - #[inline] - fn bitor_assign(&mut self, other: &BigUint) { - for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { - *ai |= bi; - } - if other.data.len() > self.data.len() { - let extra = &other.data[self.data.len()..]; - self.data.extend(extra.iter().cloned()); - } - } -} - -forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor); -forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign); - -impl<'a> BitXor<&'a BigUint> for BigUint { - type Output = BigUint; - - fn bitxor(mut self, other: &BigUint) -> BigUint { - self ^= other; - self - } -} -impl<'a> BitXorAssign<&'a BigUint> for BigUint { - #[inline] - fn bitxor_assign(&mut self, other: &BigUint) { - for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { - *ai ^= bi; - } - if other.data.len() > self.data.len() { - let extra = &other.data[self.data.len()..]; - self.data.extend(extra.iter().cloned()); - } - self.normalize(); - } -} - -impl Shl for BigUint { - type Output = BigUint; - - #[inline] - fn shl(self, rhs: usize) -> BigUint { - biguint_shl(Cow::Owned(self), rhs) - } -} -impl<'a> Shl for &'a BigUint { - type Output = BigUint; - - #[inline] - fn shl(self, rhs: usize) -> BigUint { - biguint_shl(Cow::Borrowed(self), rhs) - } -} - -impl ShlAssign for BigUint { - #[inline] - fn shl_assign(&mut self, rhs: usize) { - let n = mem::replace(self, BigUint::zero()); - *self = n << rhs; - } -} - -impl Shr for BigUint { - type Output = BigUint; - - #[inline] - fn shr(self, rhs: usize) -> BigUint { - biguint_shr(Cow::Owned(self), rhs) - } -} -impl<'a> Shr for &'a BigUint { - type Output = BigUint; - - #[inline] - fn shr(self, rhs: usize) -> BigUint { - biguint_shr(Cow::Borrowed(self), rhs) - } -} - -impl ShrAssign for BigUint { - #[inline] - fn shr_assign(&mut self, rhs: usize) { - let n = mem::replace(self, BigUint::zero()); - *self = n >> rhs; - } -} - -impl Zero for BigUint { - #[inline] - fn zero() -> BigUint { - BigUint::new(Vec::new()) - } - - #[inline] - fn set_zero(&mut self) { - self.data.clear(); - } - - #[inline] - fn is_zero(&self) -> bool { - self.data.is_empty() - } -} - -impl One for BigUint { - #[inline] - fn one() -> BigUint { - BigUint::new(vec![1]) - } - - #[inline] - fn set_one(&mut self) { - self.data.clear(); - self.data.push(1); - } - - #[inline] - fn is_one(&self) -> bool { - self.data[..] == [1] - } -} - -impl Unsigned for BigUint {} - -impl<'a> Pow for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: BigUint) -> Self::Output { - self.pow(&exp) - } -} - -impl<'a, 'b> Pow<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: &BigUint) -> Self::Output { - if self.is_one() || exp.is_zero() { - BigUint::one() - } else if self.is_zero() { - BigUint::zero() - } else if let Some(exp) = exp.to_u64() { - self.pow(exp) - } else { - // At this point, `self >= 2` and `exp >= 2⁶⁴`. The smallest possible result - // given `2.pow(2⁶⁴)` would take 2.3 exabytes of memory! - panic!("memory overflow") - } - } -} - -macro_rules! pow_impl { - ($T:ty) => { - impl<'a> Pow<$T> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, mut exp: $T) -> Self::Output { - if exp == 0 { - return BigUint::one(); - } - let mut base = self.clone(); - - while exp & 1 == 0 { - base = &base * &base; - exp >>= 1; - } - - if exp == 1 { - return base; - } - - let mut acc = base.clone(); - while exp > 1 { - exp >>= 1; - base = &base * &base; - if exp & 1 == 1 { - acc = &acc * &base; - } - } - acc - } - } - - impl<'a, 'b> Pow<&'b $T> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: &$T) -> Self::Output { - self.pow(*exp) - } - } - }; -} - -pow_impl!(u8); -pow_impl!(u16); -pow_impl!(u32); -pow_impl!(u64); -pow_impl!(usize); -#[cfg(has_i128)] -pow_impl!(u128); - -forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); -forward_val_assign!(impl AddAssign for BigUint, add_assign); - -impl<'a> Add<&'a BigUint> for BigUint { - type Output = BigUint; - - fn add(mut self, other: &BigUint) -> BigUint { - self += other; - self - } -} -impl<'a> AddAssign<&'a BigUint> for BigUint { - #[inline] - fn add_assign(&mut self, other: &BigUint) { - let self_len = self.data.len(); - let carry = if self_len < other.data.len() { - let lo_carry = __add2(&mut self.data[..], &other.data[..self_len]); - self.data.extend_from_slice(&other.data[self_len..]); - __add2(&mut self.data[self_len..], &[lo_carry]) - } else { - __add2(&mut self.data[..], &other.data[..]) - }; - if carry != 0 { - self.data.push(carry); - } - } -} - -promote_unsigned_scalars!(impl Add for BigUint, add); -promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); - -impl Add for BigUint { - type Output = BigUint; - - #[inline] - fn add(mut self, other: u32) -> BigUint { - self += other; - self - } -} - -impl AddAssign for BigUint { - #[inline] - fn add_assign(&mut self, other: u32) { - if other != 0 { - if self.data.len() == 0 { - self.data.push(0); - } - - let carry = __add2(&mut self.data, &[other as BigDigit]); - if carry != 0 { - self.data.push(carry); - } - } - } -} - -impl Add for BigUint { - type Output = BigUint; - - #[inline] - fn add(mut self, other: u64) -> BigUint { - self += other; - self - } -} - -impl AddAssign for BigUint { - #[inline] - fn add_assign(&mut self, other: u64) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - if hi == 0 { - *self += lo; - } else { - while self.data.len() < 2 { - self.data.push(0); - } - - let carry = __add2(&mut self.data, &[lo, hi]); - if carry != 0 { - self.data.push(carry); - } - } - } -} - -#[cfg(has_i128)] -impl Add for BigUint { - type Output = BigUint; - - #[inline] - fn add(mut self, other: u128) -> BigUint { - self += other; - self - } -} - -#[cfg(has_i128)] -impl AddAssign for BigUint { - #[inline] - fn add_assign(&mut self, other: u128) { - if other <= u128::from(u64::max_value()) { - *self += other as u64 - } else { - let (a, b, c, d) = u32_from_u128(other); - let carry = if a > 0 { - while self.data.len() < 4 { - self.data.push(0); - } - __add2(&mut self.data, &[d, c, b, a]) - } else { - debug_assert!(b > 0); - while self.data.len() < 3 { - self.data.push(0); - } - __add2(&mut self.data, &[d, c, b]) - }; - - if carry != 0 { - self.data.push(carry); - } - } - } -} - -forward_val_val_binop!(impl Sub for BigUint, sub); -forward_ref_ref_binop!(impl Sub for BigUint, sub); -forward_val_assign!(impl SubAssign for BigUint, sub_assign); - -impl<'a> Sub<&'a BigUint> for BigUint { - type Output = BigUint; - - fn sub(mut self, other: &BigUint) -> BigUint { - self -= other; - self - } -} -impl<'a> SubAssign<&'a BigUint> for BigUint { - fn sub_assign(&mut self, other: &'a BigUint) { - sub2(&mut self.data[..], &other.data[..]); - self.normalize(); - } -} - -impl<'a> Sub for &'a BigUint { - type Output = BigUint; - - fn sub(self, mut other: BigUint) -> BigUint { - let other_len = other.data.len(); - if other_len < self.data.len() { - let lo_borrow = __sub2rev(&self.data[..other_len], &mut other.data); - other.data.extend_from_slice(&self.data[other_len..]); - if lo_borrow != 0 { - sub2(&mut other.data[other_len..], &[1]) - } - } else { - sub2rev(&self.data[..], &mut other.data[..]); - } - other.normalized() - } -} - -promote_unsigned_scalars!(impl Sub for BigUint, sub); -promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign); -forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); - -impl Sub for BigUint { - type Output = BigUint; - - #[inline] - fn sub(mut self, other: u32) -> BigUint { - self -= other; - self - } -} -impl SubAssign for BigUint { - fn sub_assign(&mut self, other: u32) { - sub2(&mut self.data[..], &[other as BigDigit]); - self.normalize(); - } -} - -impl Sub for u32 { - type Output = BigUint; - - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.len() == 0 { - other.data.push(self as BigDigit); - } else { - sub2rev(&[self as BigDigit], &mut other.data[..]); - } - other.normalized() - } -} - -impl Sub for BigUint { - type Output = BigUint; - - #[inline] - fn sub(mut self, other: u64) -> BigUint { - self -= other; - self - } -} - -impl SubAssign for BigUint { - #[inline] - fn sub_assign(&mut self, other: u64) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - sub2(&mut self.data[..], &[lo, hi]); - self.normalize(); - } -} - -impl Sub for u64 { - type Output = BigUint; - - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 2 { - other.data.push(0); - } - - let (hi, lo) = big_digit::from_doublebigdigit(self); - sub2rev(&[lo, hi], &mut other.data[..]); - other.normalized() - } -} - -#[cfg(has_i128)] -impl Sub for BigUint { - type Output = BigUint; - - #[inline] - fn sub(mut self, other: u128) -> BigUint { - self -= other; - self - } -} -#[cfg(has_i128)] -impl SubAssign for BigUint { - fn sub_assign(&mut self, other: u128) { - let (a, b, c, d) = u32_from_u128(other); - sub2(&mut self.data[..], &[d, c, b, a]); - self.normalize(); - } -} - -#[cfg(has_i128)] -impl Sub for u128 { - type Output = BigUint; - - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 4 { - other.data.push(0); - } - - let (a, b, c, d) = u32_from_u128(self); - sub2rev(&[d, c, b, a], &mut other.data[..]); - other.normalized() - } -} - -forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul); -forward_val_assign!(impl MulAssign for BigUint, mul_assign); - -impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn mul(self, other: &BigUint) -> BigUint { - mul3(&self.data[..], &other.data[..]) - } -} -impl<'a> MulAssign<&'a BigUint> for BigUint { - #[inline] - fn mul_assign(&mut self, other: &'a BigUint) { - *self = &*self * other - } -} - -promote_unsigned_scalars!(impl Mul for BigUint, mul); -promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); - -impl Mul for BigUint { - type Output = BigUint; - - #[inline] - fn mul(mut self, other: u32) -> BigUint { - self *= other; - self - } -} -impl MulAssign for BigUint { - #[inline] - fn mul_assign(&mut self, other: u32) { - if other == 0 { - self.data.clear(); - } else { - let carry = scalar_mul(&mut self.data[..], other as BigDigit); - if carry != 0 { - self.data.push(carry); - } - } - } -} - -impl Mul for BigUint { - type Output = BigUint; - - #[inline] - fn mul(mut self, other: u64) -> BigUint { - self *= other; - self - } -} -impl MulAssign for BigUint { - #[inline] - fn mul_assign(&mut self, other: u64) { - if other == 0 { - self.data.clear(); - } else if other <= u64::from(BigDigit::max_value()) { - *self *= other as BigDigit - } else { - let (hi, lo) = big_digit::from_doublebigdigit(other); - *self = mul3(&self.data[..], &[lo, hi]) - } - } -} - -#[cfg(has_i128)] -impl Mul for BigUint { - type Output = BigUint; - - #[inline] - fn mul(mut self, other: u128) -> BigUint { - self *= other; - self - } -} -#[cfg(has_i128)] -impl MulAssign for BigUint { - #[inline] - fn mul_assign(&mut self, other: u128) { - if other == 0 { - self.data.clear(); - } else if other <= u128::from(BigDigit::max_value()) { - *self *= other as BigDigit - } else { - let (a, b, c, d) = u32_from_u128(other); - *self = mul3(&self.data[..], &[d, c, b, a]) - } - } -} - -forward_val_ref_binop!(impl Div for BigUint, div); -forward_ref_val_binop!(impl Div for BigUint, div); -forward_val_assign!(impl DivAssign for BigUint, div_assign); - -impl Div for BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: BigUint) -> BigUint { - let (q, _) = div_rem(self, other); - q - } -} - -impl<'a, 'b> Div<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: &BigUint) -> BigUint { - let (q, _) = self.div_rem(other); - q - } -} -impl<'a> DivAssign<&'a BigUint> for BigUint { - #[inline] - fn div_assign(&mut self, other: &'a BigUint) { - *self = &*self / other; - } -} - -promote_unsigned_scalars!(impl Div for BigUint, div); -promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign); -forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); - -impl Div for BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: u32) -> BigUint { - let (q, _) = div_rem_digit(self, other as BigDigit); - q - } -} -impl DivAssign for BigUint { - #[inline] - fn div_assign(&mut self, other: u32) { - *self = &*self / other; - } -} - -impl Div for u32 { - type Output = BigUint; - - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!(), - 1 => From::from(self as BigDigit / other.data[0]), - _ => Zero::zero(), - } - } -} - -impl Div for BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: u64) -> BigUint { - let (q, _) = div_rem(self, From::from(other)); - q - } -} -impl DivAssign for BigUint { - #[inline] - fn div_assign(&mut self, other: u64) { - // a vec of size 0 does not allocate, so this is fairly cheap - let temp = mem::replace(self, Zero::zero()); - *self = temp / other; - } -} - -impl Div for u64 { - type Output = BigUint; - - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!(), - 1 => From::from(self / u64::from(other.data[0])), - 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => Zero::zero(), - } - } -} - -#[cfg(has_i128)] -impl Div for BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: u128) -> BigUint { - let (q, _) = div_rem(self, From::from(other)); - q - } -} -#[cfg(has_i128)] -impl DivAssign for BigUint { - #[inline] - fn div_assign(&mut self, other: u128) { - *self = &*self / other; - } -} - -#[cfg(has_i128)] -impl Div for u128 { - type Output = BigUint; - - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!(), - 1 => From::from(self / u128::from(other.data[0])), - 2 => From::from( - self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])), - ), - 3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])), - 4 => From::from( - self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]), - ), - _ => Zero::zero(), - } - } -} - -forward_val_ref_binop!(impl Rem for BigUint, rem); -forward_ref_val_binop!(impl Rem for BigUint, rem); -forward_val_assign!(impl RemAssign for BigUint, rem_assign); - -impl Rem for BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: BigUint) -> BigUint { - let (_, r) = div_rem(self, other); - r - } -} - -impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: &BigUint) -> BigUint { - let (_, r) = self.div_rem(other); - r - } -} -impl<'a> RemAssign<&'a BigUint> for BigUint { - #[inline] - fn rem_assign(&mut self, other: &BigUint) { - *self = &*self % other; - } -} - -promote_unsigned_scalars!(impl Rem for BigUint, rem); -promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign); -forward_all_scalar_binop_to_ref_val!(impl Rem for BigUint, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); -#[cfg(has_i128)] -forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); - -impl<'a> Rem for &'a BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: u32) -> BigUint { - From::from(rem_digit(self, other as BigDigit)) - } -} -impl RemAssign for BigUint { - #[inline] - fn rem_assign(&mut self, other: u32) { - *self = &*self % other; - } -} - -impl<'a> Rem<&'a BigUint> for u32 { - type Output = BigUint; - - #[inline] - fn rem(mut self, other: &'a BigUint) -> BigUint { - self %= other; - From::from(self) - } -} - -macro_rules! impl_rem_assign_scalar { - ($scalar:ty, $to_scalar:ident) => { - forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign); - impl<'a> RemAssign<&'a BigUint> for $scalar { - #[inline] - fn rem_assign(&mut self, other: &BigUint) { - *self = match other.$to_scalar() { - None => *self, - Some(0) => panic!(), - Some(v) => *self % v - }; - } - } - } -} -// we can scalar %= BigUint for any scalar, including signed types -#[cfg(has_i128)] -impl_rem_assign_scalar!(u128, to_u128); -impl_rem_assign_scalar!(usize, to_usize); -impl_rem_assign_scalar!(u64, to_u64); -impl_rem_assign_scalar!(u32, to_u32); -impl_rem_assign_scalar!(u16, to_u16); -impl_rem_assign_scalar!(u8, to_u8); -#[cfg(has_i128)] -impl_rem_assign_scalar!(i128, to_i128); -impl_rem_assign_scalar!(isize, to_isize); -impl_rem_assign_scalar!(i64, to_i64); -impl_rem_assign_scalar!(i32, to_i32); -impl_rem_assign_scalar!(i16, to_i16); -impl_rem_assign_scalar!(i8, to_i8); - -impl Rem for BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: u64) -> BigUint { - let (_, r) = div_rem(self, From::from(other)); - r - } -} -impl RemAssign for BigUint { - #[inline] - fn rem_assign(&mut self, other: u64) { - *self = &*self % other; - } -} - -impl Rem for u64 { - type Output = BigUint; - - #[inline] - fn rem(mut self, other: BigUint) -> BigUint { - self %= other; - From::from(self) - } -} - -#[cfg(has_i128)] -impl Rem for BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: u128) -> BigUint { - let (_, r) = div_rem(self, From::from(other)); - r - } -} -#[cfg(has_i128)] -impl RemAssign for BigUint { - #[inline] - fn rem_assign(&mut self, other: u128) { - *self = &*self % other; - } -} - -#[cfg(has_i128)] -impl Rem for u128 { - type Output = BigUint; - - #[inline] - fn rem(mut self, other: BigUint) -> BigUint { - self %= other; - From::from(self) - } -} - -impl Neg for BigUint { - type Output = BigUint; - - #[inline] - fn neg(self) -> BigUint { - panic!() - } -} - -impl<'a> Neg for &'a BigUint { - type Output = BigUint; - - #[inline] - fn neg(self) -> BigUint { - panic!() - } -} - -impl CheckedAdd for BigUint { - #[inline] - fn checked_add(&self, v: &BigUint) -> Option { - return Some(self.add(v)); - } -} - -impl CheckedSub for BigUint { - #[inline] - fn checked_sub(&self, v: &BigUint) -> Option { - match self.cmp(v) { - Less => None, - Equal => Some(Zero::zero()), - Greater => Some(self.sub(v)), - } - } -} - -impl CheckedMul for BigUint { - #[inline] - fn checked_mul(&self, v: &BigUint) -> Option { - return Some(self.mul(v)); - } -} - -impl CheckedDiv for BigUint { - #[inline] - fn checked_div(&self, v: &BigUint) -> Option { - if v.is_zero() { - return None; - } - return Some(self.div(v)); - } -} - -impl Integer for BigUint { - #[inline] - fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { - div_rem_ref(self, other) - } - - #[inline] - fn div_floor(&self, other: &BigUint) -> BigUint { - let (d, _) = div_rem_ref(self, other); - d - } - - #[inline] - fn mod_floor(&self, other: &BigUint) -> BigUint { - let (_, m) = div_rem_ref(self, other); - m - } - - #[inline] - fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { - div_rem_ref(self, other) - } - - /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. - /// - /// The result is always positive. - #[inline] - fn gcd(&self, other: &Self) -> Self { - #[inline] - fn twos(x: &BigUint) -> usize { - trailing_zeros(x).unwrap_or(0) - } - - // Stein's algorithm - if self.is_zero() { - return other.clone(); - } - if other.is_zero() { - return self.clone(); - } - let mut m = self.clone(); - let mut n = other.clone(); - - // find common factors of 2 - let shift = cmp::min(twos(&n), twos(&m)); - - // divide m and n by 2 until odd - // m inside loop - n >>= twos(&n); - - while !m.is_zero() { - m >>= twos(&m); - if n > m { - mem::swap(&mut n, &mut m) - } - m -= &n; - } - - n << shift - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. - #[inline] - fn lcm(&self, other: &BigUint) -> BigUint { - if self.is_zero() && other.is_zero() { - Self::zero() - } else { - self / self.gcd(other) * other - } - } - - /// Deprecated, use `is_multiple_of` instead. - #[inline] - fn divides(&self, other: &BigUint) -> bool { - self.is_multiple_of(other) - } - - /// Returns `true` if the number is a multiple of `other`. - #[inline] - fn is_multiple_of(&self, other: &BigUint) -> bool { - (self % other).is_zero() - } - - /// Returns `true` if the number is divisible by `2`. - #[inline] - fn is_even(&self) -> bool { - // Considering only the last digit. - match self.data.first() { - Some(x) => x.is_even(), - None => true, - } - } - - /// Returns `true` if the number is not divisible by `2`. - #[inline] - fn is_odd(&self) -> bool { - !self.is_even() - } -} - -#[inline] -fn fixpoint(mut x: BigUint, max_bits: usize, f: F) -> BigUint -where - F: Fn(&BigUint) -> BigUint, -{ - let mut xn = f(&x); - - // If the value increased, then the initial guess must have been low. - // Repeat until we reverse course. - while x < xn { - // Sometimes an increase will go way too far, especially with large - // powers, and then take a long time to walk back. We know an upper - // bound based on bit size, so saturate on that. - x = if xn.bits() > max_bits { - BigUint::one() << max_bits - } else { - xn - }; - xn = f(&x); - } - - // Now keep repeating while the estimate is decreasing. - while x > xn { - x = xn; - xn = f(&x); - } - x -} - -impl Roots for BigUint { - // nth_root, sqrt and cbrt use Newton's method to compute - // principal root of a given degree for a given integer. - - // Reference: - // Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.14 - fn nth_root(&self, n: u32) -> Self { - assert!(n > 0, "root degree n must be at least 1"); - - if self.is_zero() || self.is_one() { - return self.clone(); - } - - match n { - // Optimize for small n - 1 => return self.clone(), - 2 => return self.sqrt(), - 3 => return self.cbrt(), - _ => (), - } - - // The root of non-zero values less than 2ⁿ can only be 1. - let bits = self.bits(); - if bits <= n as usize { - return BigUint::one(); - } - - // If we fit in `u64`, compute the root that way. - if let Some(x) = self.to_u64() { - return x.nth_root(n).into(); - } - - let max_bits = bits / n as usize + 1; - - let guess = if let Some(f) = self.to_f64() { - // We fit in `f64` (lossy), so get a better initial guess from that. - BigUint::from_f64((f.ln() / f64::from(n)).exp()).unwrap() - } else { - // Try to guess by scaling down such that it does fit in `f64`. - // With some (x * 2ⁿᵏ), its nth root ≈ (ⁿ√x * 2ᵏ) - let nsz = n as usize; - let extra_bits = bits - (f64::MAX_EXP as usize - 1); - let root_scale = (extra_bits + (nsz - 1)) / nsz; - let scale = root_scale * nsz; - if scale < bits && bits - scale > nsz { - (self >> scale).nth_root(n) << root_scale - } else { - BigUint::one() << max_bits - } - }; - - let n_min_1 = n - 1; - fixpoint(guess, max_bits, move |s| { - let q = self / s.pow(n_min_1); - let t = n_min_1 * s + q; - t / n - }) - } - - // Reference: - // Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.13 - fn sqrt(&self) -> Self { - if self.is_zero() || self.is_one() { - return self.clone(); - } - - // If we fit in `u64`, compute the root that way. - if let Some(x) = self.to_u64() { - return x.sqrt().into(); - } - - let bits = self.bits(); - let max_bits = bits / 2 as usize + 1; - - let guess = if let Some(f) = self.to_f64() { - // We fit in `f64` (lossy), so get a better initial guess from that. - BigUint::from_f64(f.sqrt()).unwrap() - } else { - // Try to guess by scaling down such that it does fit in `f64`. - // With some (x * 2²ᵏ), its sqrt ≈ (√x * 2ᵏ) - let extra_bits = bits - (f64::MAX_EXP as usize - 1); - let root_scale = (extra_bits + 1) / 2; - let scale = root_scale * 2; - (self >> scale).sqrt() << root_scale - }; - - fixpoint(guess, max_bits, move |s| { - let q = self / s; - let t = s + q; - t >> 1 - }) - } - - fn cbrt(&self) -> Self { - if self.is_zero() || self.is_one() { - return self.clone(); - } - - // If we fit in `u64`, compute the root that way. - if let Some(x) = self.to_u64() { - return x.cbrt().into(); - } - - let bits = self.bits(); - let max_bits = bits / 3 as usize + 1; - - let guess = if let Some(f) = self.to_f64() { - // We fit in `f64` (lossy), so get a better initial guess from that. - BigUint::from_f64(f.cbrt()).unwrap() - } else { - // Try to guess by scaling down such that it does fit in `f64`. - // With some (x * 2³ᵏ), its cbrt ≈ (∛x * 2ᵏ) - let extra_bits = bits - (f64::MAX_EXP as usize - 1); - let root_scale = (extra_bits + 2) / 3; - let scale = root_scale * 3; - (self >> scale).cbrt() << root_scale - }; - - fixpoint(guess, max_bits, move |s| { - let q = self / (s * s); - let t = (s << 1) + q; - t / 3u32 - }) - } -} - -fn high_bits_to_u64(v: &BigUint) -> u64 { - match v.data.len() { - 0 => 0, - 1 => u64::from(v.data[0]), - _ => { - let mut bits = v.bits(); - let mut ret = 0u64; - let mut ret_bits = 0; - - for d in v.data.iter().rev() { - let digit_bits = (bits - 1) % big_digit::BITS + 1; - let bits_want = cmp::min(64 - ret_bits, digit_bits); - - if bits_want != 64 { - ret <<= bits_want; - } - ret |= u64::from(*d) >> (digit_bits - bits_want); - ret_bits += bits_want; - bits -= bits_want; - - if ret_bits == 64 { - break; - } - } - - ret - } - } -} - -impl ToPrimitive for BigUint { - #[inline] - fn to_i64(&self) -> Option { - self.to_u64().as_ref().and_then(u64::to_i64) - } - - #[inline] - #[cfg(has_i128)] - fn to_i128(&self) -> Option { - self.to_u128().as_ref().and_then(u128::to_i128) - } - - #[inline] - fn to_u64(&self) -> Option { - let mut ret: u64 = 0; - let mut bits = 0; - - for i in self.data.iter() { - if bits >= 64 { - return None; - } - - ret += u64::from(*i) << bits; - bits += big_digit::BITS; - } - - Some(ret) - } - - #[inline] - #[cfg(has_i128)] - fn to_u128(&self) -> Option { - let mut ret: u128 = 0; - let mut bits = 0; - - for i in self.data.iter() { - if bits >= 128 { - return None; - } - - ret |= u128::from(*i) << bits; - bits += big_digit::BITS; - } - - Some(ret) - } - - #[inline] - fn to_f32(&self) -> Option { - let mantissa = high_bits_to_u64(self); - let exponent = self.bits() - fls(mantissa); - - if exponent > f32::MAX_EXP as usize { - None - } else { - let ret = (mantissa as f32) * 2.0f32.powi(exponent as i32); - if ret.is_infinite() { - None - } else { - Some(ret) - } - } - } - - #[inline] - fn to_f64(&self) -> Option { - let mantissa = high_bits_to_u64(self); - let exponent = self.bits() - fls(mantissa); - - if exponent > f64::MAX_EXP as usize { - None - } else { - let ret = (mantissa as f64) * 2.0f64.powi(exponent as i32); - if ret.is_infinite() { - None - } else { - Some(ret) - } - } - } -} - -impl FromPrimitive for BigUint { - #[inline] - fn from_i64(n: i64) -> Option { - if n >= 0 { - Some(BigUint::from(n as u64)) - } else { - None - } - } - - #[inline] - #[cfg(has_i128)] - fn from_i128(n: i128) -> Option { - if n >= 0 { - Some(BigUint::from(n as u128)) - } else { - None - } - } - - #[inline] - fn from_u64(n: u64) -> Option { - Some(BigUint::from(n)) - } - - #[inline] - #[cfg(has_i128)] - fn from_u128(n: u128) -> Option { - Some(BigUint::from(n)) - } - - #[inline] - fn from_f64(mut n: f64) -> Option { - // handle NAN, INFINITY, NEG_INFINITY - if !n.is_finite() { - return None; - } - - // match the rounding of casting from float to int - n = n.trunc(); - - // handle 0.x, -0.x - if n.is_zero() { - return Some(BigUint::zero()); - } - - let (mantissa, exponent, sign) = Float::integer_decode(n); - - if sign == -1 { - return None; - } - - let mut ret = BigUint::from(mantissa); - if exponent > 0 { - ret = ret << exponent as usize; - } else if exponent < 0 { - ret = ret >> (-exponent) as usize; - } - Some(ret) - } -} - -impl From for BigUint { - #[inline] - fn from(mut n: u64) -> Self { - let mut ret: BigUint = Zero::zero(); - - while n != 0 { - ret.data.push(n as BigDigit); - // don't overflow if BITS is 64: - n = (n >> 1) >> (big_digit::BITS - 1); - } - - ret - } -} - -#[cfg(has_i128)] -impl From for BigUint { - #[inline] - fn from(mut n: u128) -> Self { - let mut ret: BigUint = Zero::zero(); - - while n != 0 { - ret.data.push(n as BigDigit); - n >>= big_digit::BITS; - } - - ret - } -} - -macro_rules! impl_biguint_from_uint { - ($T:ty) => { - impl From<$T> for BigUint { - #[inline] - fn from(n: $T) -> Self { - BigUint::from(n as u64) - } - } - }; -} - -impl_biguint_from_uint!(u8); -impl_biguint_from_uint!(u16); -impl_biguint_from_uint!(u32); -impl_biguint_from_uint!(usize); - -/// A generic trait for converting a value to a `BigUint`. -pub trait ToBigUint { - /// Converts the value of `self` to a `BigUint`. - fn to_biguint(&self) -> Option; -} - -impl ToBigUint for BigUint { - #[inline] - fn to_biguint(&self) -> Option { - Some(self.clone()) - } -} - -macro_rules! impl_to_biguint { - ($T:ty, $from_ty:path) => { - impl ToBigUint for $T { - #[inline] - fn to_biguint(&self) -> Option { - $from_ty(*self) - } - } - }; -} - -impl_to_biguint!(isize, FromPrimitive::from_isize); -impl_to_biguint!(i8, FromPrimitive::from_i8); -impl_to_biguint!(i16, FromPrimitive::from_i16); -impl_to_biguint!(i32, FromPrimitive::from_i32); -impl_to_biguint!(i64, FromPrimitive::from_i64); -#[cfg(has_i128)] -impl_to_biguint!(i128, FromPrimitive::from_i128); - -impl_to_biguint!(usize, FromPrimitive::from_usize); -impl_to_biguint!(u8, FromPrimitive::from_u8); -impl_to_biguint!(u16, FromPrimitive::from_u16); -impl_to_biguint!(u32, FromPrimitive::from_u32); -impl_to_biguint!(u64, FromPrimitive::from_u64); -#[cfg(has_i128)] -impl_to_biguint!(u128, FromPrimitive::from_u128); - -impl_to_biguint!(f32, FromPrimitive::from_f32); -impl_to_biguint!(f64, FromPrimitive::from_f64); - -// Extract bitwise digits that evenly divide BigDigit -fn to_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { - debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); - - let last_i = u.data.len() - 1; - let mask: BigDigit = (1 << bits) - 1; - let digits_per_big_digit = big_digit::BITS / bits; - let digits = (u.bits() + bits - 1) / bits; - let mut res = Vec::with_capacity(digits); - - for mut r in u.data[..last_i].iter().cloned() { - for _ in 0..digits_per_big_digit { - res.push((r & mask) as u8); - r >>= bits; - } - } - - let mut r = u.data[last_i]; - while r != 0 { - res.push((r & mask) as u8); - r >>= bits; - } - - res -} - -// Extract bitwise digits that don't evenly divide BigDigit -fn to_inexact_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { - debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); - - let mask: BigDigit = (1 << bits) - 1; - let digits = (u.bits() + bits - 1) / bits; - let mut res = Vec::with_capacity(digits); - - let mut r = 0; - let mut rbits = 0; - - for c in &u.data { - r |= *c << rbits; - rbits += big_digit::BITS; - - while rbits >= bits { - res.push((r & mask) as u8); - r >>= bits; - - // r had more bits than it could fit - grab the bits we lost - if rbits > big_digit::BITS { - r = *c >> (big_digit::BITS - (rbits - bits)); - } - - rbits -= bits; - } - } - - if rbits != 0 { - res.push(r as u8); - } - - while let Some(&0) = res.last() { - res.pop(); - } - - res -} - -// Extract little-endian radix digits -#[inline(always)] // forced inline to get const-prop for radix=10 -fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { - debug_assert!(!u.is_zero() && !radix.is_power_of_two()); - - // Estimate how big the result will be, so we can pre-allocate it. - let radix_digits = ((u.bits() as f64) / f64::from(radix).log2()).ceil(); - let mut res = Vec::with_capacity(radix_digits as usize); - let mut digits = u.clone(); - - let (base, power) = get_radix_base(radix); - let radix = radix as BigDigit; - - while digits.data.len() > 1 { - let (q, mut r) = div_rem_digit(digits, base); - for _ in 0..power { - res.push((r % radix) as u8); - r /= radix; - } - digits = q; - } - - let mut r = digits.data[0]; - while r != 0 { - res.push((r % radix) as u8); - r /= radix; - } - - res -} - -pub fn to_radix_le(u: &BigUint, radix: u32) -> Vec { - if u.is_zero() { - vec![0] - } else if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of division - let bits = ilog2(radix); - if big_digit::BITS % bits == 0 { - to_bitwise_digits_le(u, bits) - } else { - to_inexact_bitwise_digits_le(u, bits) - } - } else if radix == 10 { - // 10 is so common that it's worth separating out for const-propagation. - // Optimizers can often turn constant division into a faster multiplication. - to_radix_digits_le(u, 10) - } else { - to_radix_digits_le(u, radix) - } -} - -pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { - assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); - - if u.is_zero() { - return vec![b'0']; - } - - let mut res = to_radix_le(u, radix); - - // Now convert everything to ASCII digits. - for r in &mut res { - debug_assert!(u32::from(*r) < radix); - if *r < 10 { - *r += b'0'; - } else { - *r += b'a' - 10; - } - } - res -} - -impl BigUint { - /// Creates and initializes a `BigUint`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn new(digits: Vec) -> BigUint { - BigUint { data: digits }.normalized() - } - - /// Creates and initializes a `BigUint`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn from_slice(slice: &[u32]) -> BigUint { - BigUint::new(slice.to_vec()) - } - - /// Assign a value to a `BigUint`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn assign_from_slice(&mut self, slice: &[u32]) { - self.data.resize(slice.len(), 0); - self.data.clone_from_slice(slice); - self.normalize(); - } - - /// Creates and initializes a `BigUint`. - /// - /// The bytes are in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from_bytes_be(b"A"), - /// BigUint::parse_bytes(b"65", 10).unwrap()); - /// assert_eq!(BigUint::from_bytes_be(b"AA"), - /// BigUint::parse_bytes(b"16705", 10).unwrap()); - /// assert_eq!(BigUint::from_bytes_be(b"AB"), - /// BigUint::parse_bytes(b"16706", 10).unwrap()); - /// assert_eq!(BigUint::from_bytes_be(b"Hello world!"), - /// BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); - /// ``` - #[inline] - pub fn from_bytes_be(bytes: &[u8]) -> BigUint { - if bytes.is_empty() { - Zero::zero() - } else { - let mut v = bytes.to_vec(); - v.reverse(); - BigUint::from_bytes_le(&*v) - } - } - - /// Creates and initializes a `BigUint`. - /// - /// The bytes are in little-endian byte order. - #[inline] - pub fn from_bytes_le(bytes: &[u8]) -> BigUint { - if bytes.is_empty() { - Zero::zero() - } else { - from_bitwise_digits_le(bytes, 8) - } - } - - /// Creates and initializes a `BigUint`. The input slice must contain - /// ascii/utf8 characters in [0-9a-zA-Z]. - /// `radix` must be in the range `2...36`. - /// - /// The function `from_str_radix` from the `Num` trait provides the same logic - /// for `&str` buffers. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigUint, ToBigUint}; - /// - /// assert_eq!(BigUint::parse_bytes(b"1234", 10), ToBigUint::to_biguint(&1234)); - /// assert_eq!(BigUint::parse_bytes(b"ABCD", 16), ToBigUint::to_biguint(&0xABCD)); - /// assert_eq!(BigUint::parse_bytes(b"G", 16), None); - /// ``` - #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - str::from_utf8(buf) - .ok() - .and_then(|s| BigUint::from_str_radix(s, radix).ok()) - } - - /// Creates and initializes a `BigUint`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in big-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigUint}; - /// - /// let inbase190 = &[15, 33, 125, 12, 14]; - /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), inbase190); - /// ``` - pub fn from_radix_be(buf: &[u8], radix: u32) -> Option { - assert!( - 2 <= radix && radix <= 256, - "The radix must be within 2...256" - ); - - if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { - return None; - } - - let res = if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of multiplication - let bits = ilog2(radix); - let mut v = Vec::from(buf); - v.reverse(); - if big_digit::BITS % bits == 0 { - from_bitwise_digits_le(&v, bits) - } else { - from_inexact_bitwise_digits_le(&v, bits) - } - } else { - from_radix_digits_be(buf, radix) - }; - - Some(res) - } - - /// Creates and initializes a `BigUint`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in little-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigUint}; - /// - /// let inbase190 = &[14, 12, 125, 33, 15]; - /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), inbase190); - /// ``` - pub fn from_radix_le(buf: &[u8], radix: u32) -> Option { - assert!( - 2 <= radix && radix <= 256, - "The radix must be within 2...256" - ); - - if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { - return None; - } - - let res = if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of multiplication - let bits = ilog2(radix); - if big_digit::BITS % bits == 0 { - from_bitwise_digits_le(buf, bits) - } else { - from_inexact_bitwise_digits_le(buf, bits) - } - } else { - let mut v = Vec::from(buf); - v.reverse(); - from_radix_digits_be(&v, radix) - }; - - Some(res) - } - - /// Returns the byte representation of the `BigUint` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); - /// assert_eq!(i.to_bytes_be(), vec![4, 101]); - /// ``` - #[inline] - pub fn to_bytes_be(&self) -> Vec { - let mut v = self.to_bytes_le(); - v.reverse(); - v - } - - /// Returns the byte representation of the `BigUint` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); - /// assert_eq!(i.to_bytes_le(), vec![101, 4]); - /// ``` - #[inline] - pub fn to_bytes_le(&self) -> Vec { - if self.is_zero() { - vec![0] - } else { - to_bitwise_digits_le(self, 8) - } - } - - /// Returns the integer formatted as a string in the given radix. - /// `radix` must be in the range `2...36`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"ff", 16).unwrap(); - /// assert_eq!(i.to_str_radix(16), "ff"); - /// ``` - #[inline] - pub fn to_str_radix(&self, radix: u32) -> String { - let mut v = to_str_radix_reversed(self, radix); - v.reverse(); - unsafe { String::from_utf8_unchecked(v) } - } - - /// Returns the integer in the requested base in big-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_be(159), - /// vec![2, 94, 27]); - /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 - /// ``` - #[inline] - pub fn to_radix_be(&self, radix: u32) -> Vec { - let mut v = to_radix_le(self, radix); - v.reverse(); - v - } - - /// Returns the integer in the requested base in little-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159), - /// vec![27, 94, 2]); - /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) - /// ``` - #[inline] - pub fn to_radix_le(&self, radix: u32) -> Vec { - to_radix_le(self, radix) - } - - /// Determines the fewest bits necessary to express the `BigUint`. - #[inline] - pub fn bits(&self) -> usize { - if self.is_zero() { - return 0; - } - let zeros = self.data.last().unwrap().leading_zeros(); - return self.data.len() * big_digit::BITS - zeros as usize; - } - - /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to - /// be nonzero. - #[inline] - fn normalize(&mut self) { - while let Some(&0) = self.data.last() { - self.data.pop(); - } - } - - /// Returns a normalized `BigUint`. - #[inline] - fn normalized(mut self) -> BigUint { - self.normalize(); - self - } - - /// Returns `(self ^ exponent) % modulus`. - /// - /// Panics if the modulus is zero. - pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { - assert!(!modulus.is_zero(), "divide by zero!"); - - if modulus.is_odd() { - // For an odd modulus, we can use Montgomery multiplication in base 2^32. - monty_modpow(self, exponent, modulus) - } else { - // Otherwise do basically the same as `num::pow`, but with a modulus. - plain_modpow(self, &exponent.data, modulus) - } - } - - /// Returns the truncated principal square root of `self` -- - /// see [Roots::sqrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.sqrt) - pub fn sqrt(&self) -> Self { - Roots::sqrt(self) - } - - /// Returns the truncated principal cube root of `self` -- - /// see [Roots::cbrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.cbrt). - pub fn cbrt(&self) -> Self { - Roots::cbrt(self) - } - - /// Returns the truncated principal `n`th root of `self` -- - /// see [Roots::nth_root](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#tymethod.nth_root). - pub fn nth_root(&self, n: u32) -> Self { - Roots::nth_root(self, n) - } -} - -fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> BigUint { - assert!(!modulus.is_zero(), "divide by zero!"); - - let i = match exp_data.iter().position(|&r| r != 0) { - None => return BigUint::one(), - Some(i) => i, - }; - - let mut base = base.clone(); - for _ in 0..i { - for _ in 0..big_digit::BITS { - base = &base * &base % modulus; - } - } - - let mut r = exp_data[i]; - let mut b = 0usize; - while r.is_even() { - base = &base * &base % modulus; - r >>= 1; - b += 1; - } - - let mut exp_iter = exp_data[i + 1..].iter(); - if exp_iter.len() == 0 && r.is_one() { - return base; - } - - let mut acc = base.clone(); - r >>= 1; - b += 1; - - { - let mut unit = |exp_is_odd| { - base = &base * &base % modulus; - if exp_is_odd { - acc = &acc * &base % modulus; - } - }; - - if let Some(&last) = exp_iter.next_back() { - // consume exp_data[i] - for _ in b..big_digit::BITS { - unit(r.is_odd()); - r >>= 1; - } - - // consume all other digits before the last - for &r in exp_iter { - let mut r = r; - for _ in 0..big_digit::BITS { - unit(r.is_odd()); - r >>= 1; - } - } - r = last; - } - - debug_assert_ne!(r, 0); - while !r.is_zero() { - unit(r.is_odd()); - r >>= 1; - } - } - acc -} - -#[test] -fn test_plain_modpow() { - let two = BigUint::from(2u32); - let modulus = BigUint::from(0x1100u32); - - let exp = vec![0, 0b1]; - assert_eq!( - two.pow(0b1_00000000_u32) % &modulus, - plain_modpow(&two, &exp, &modulus) - ); - let exp = vec![0, 0b10]; - assert_eq!( - two.pow(0b10_00000000_u32) % &modulus, - plain_modpow(&two, &exp, &modulus) - ); - let exp = vec![0, 0b110010]; - assert_eq!( - two.pow(0b110010_00000000_u32) % &modulus, - plain_modpow(&two, &exp, &modulus) - ); - let exp = vec![0b1, 0b1]; - assert_eq!( - two.pow(0b1_00000001_u32) % &modulus, - plain_modpow(&two, &exp, &modulus) - ); - let exp = vec![0b1100, 0, 0b1]; - assert_eq!( - two.pow(0b1_00000000_00001100_u32) % &modulus, - plain_modpow(&two, &exp, &modulus) - ); -} - -/// Returns the number of least-significant bits that are zero, -/// or `None` if the entire number is zero. -pub fn trailing_zeros(u: &BigUint) -> Option { - u.data - .iter() - .enumerate() - .find(|&(_, &digit)| digit != 0) - .map(|(i, digit)| i * big_digit::BITS + digit.trailing_zeros() as usize) -} - -impl_sum_iter_type!(BigUint); -impl_product_iter_type!(BigUint); - -pub trait IntDigits { - fn digits(&self) -> &[BigDigit]; - fn digits_mut(&mut self) -> &mut Vec; - fn normalize(&mut self); - fn capacity(&self) -> usize; - fn len(&self) -> usize; -} - -impl IntDigits for BigUint { - #[inline] - fn digits(&self) -> &[BigDigit] { - &self.data - } - #[inline] - fn digits_mut(&mut self) -> &mut Vec { - &mut self.data - } - #[inline] - fn normalize(&mut self) { - self.normalize(); - } - #[inline] - fn capacity(&self) -> usize { - self.data.capacity() - } - #[inline] - fn len(&self) -> usize { - self.data.len() - } -} - -/// Combine four `u32`s into a single `u128`. -#[cfg(has_i128)] -#[inline] -fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 { - u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96) -} - -/// Split a single `u128` into four `u32`. -#[cfg(has_i128)] -#[inline] -fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { - ( - (n >> 96) as u32, - (n >> 64) as u32, - (n >> 32) as u32, - n as u32, - ) -} - -#[cfg(feature = "serde")] -impl serde::Serialize for BigUint { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - // Note: do not change the serialization format, or it may break forward - // and backward compatibility of serialized data! If we ever change the - // internal representation, we should still serialize in base-`u32`. - let data: &Vec = &self.data; - data.serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for BigUint { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let data: Vec = Vec::deserialize(deserializer)?; - Ok(BigUint::new(data)) - } -} - -/// Returns the greatest power of the radix <= big_digit::BASE -#[inline] -fn get_radix_base(radix: u32) -> (BigDigit, usize) { - debug_assert!( - 2 <= radix && radix <= 256, - "The radix must be within 2...256" - ); - debug_assert!(!radix.is_power_of_two()); - - // To generate this table: - // for radix in 2u64..257 { - // let mut power = big_digit::BITS / fls(radix as u64); - // let mut base = radix.pow(power as u32); - // - // while let Some(b) = base.checked_mul(radix) { - // if b > big_digit::MAX { - // break; - // } - // base = b; - // power += 1; - // } - // - // println!("({:10}, {:2}), // {:2}", base, power, radix); - // } - // and - // for radix in 2u64..257 { - // let mut power = 64 / fls(radix as u64); - // let mut base = radix.pow(power as u32); - // - // while let Some(b) = base.checked_mul(radix) { - // base = b; - // power += 1; - // } - // - // println!("({:20}, {:2}), // {:2}", base, power, radix); - // } - match big_digit::BITS { - 32 => { - const BASES: [(u32, usize); 257] = [ - (0, 0), - (0, 0), - (0, 0), // 2 - (3486784401, 20), // 3 - (0, 0), // 4 - (1220703125, 13), // 5 - (2176782336, 12), // 6 - (1977326743, 11), // 7 - (0, 0), // 8 - (3486784401, 10), // 9 - (1000000000, 9), // 10 - (2357947691, 9), // 11 - (429981696, 8), // 12 - (815730721, 8), // 13 - (1475789056, 8), // 14 - (2562890625, 8), // 15 - (0, 0), // 16 - (410338673, 7), // 17 - (612220032, 7), // 18 - (893871739, 7), // 19 - (1280000000, 7), // 20 - (1801088541, 7), // 21 - (2494357888, 7), // 22 - (3404825447, 7), // 23 - (191102976, 6), // 24 - (244140625, 6), // 25 - (308915776, 6), // 26 - (387420489, 6), // 27 - (481890304, 6), // 28 - (594823321, 6), // 29 - (729000000, 6), // 30 - (887503681, 6), // 31 - (0, 0), // 32 - (1291467969, 6), // 33 - (1544804416, 6), // 34 - (1838265625, 6), // 35 - (2176782336, 6), // 36 - (2565726409, 6), // 37 - (3010936384, 6), // 38 - (3518743761, 6), // 39 - (4096000000, 6), // 40 - (115856201, 5), // 41 - (130691232, 5), // 42 - (147008443, 5), // 43 - (164916224, 5), // 44 - (184528125, 5), // 45 - (205962976, 5), // 46 - (229345007, 5), // 47 - (254803968, 5), // 48 - (282475249, 5), // 49 - (312500000, 5), // 50 - (345025251, 5), // 51 - (380204032, 5), // 52 - (418195493, 5), // 53 - (459165024, 5), // 54 - (503284375, 5), // 55 - (550731776, 5), // 56 - (601692057, 5), // 57 - (656356768, 5), // 58 - (714924299, 5), // 59 - (777600000, 5), // 60 - (844596301, 5), // 61 - (916132832, 5), // 62 - (992436543, 5), // 63 - (0, 0), // 64 - (1160290625, 5), // 65 - (1252332576, 5), // 66 - (1350125107, 5), // 67 - (1453933568, 5), // 68 - (1564031349, 5), // 69 - (1680700000, 5), // 70 - (1804229351, 5), // 71 - (1934917632, 5), // 72 - (2073071593, 5), // 73 - (2219006624, 5), // 74 - (2373046875, 5), // 75 - (2535525376, 5), // 76 - (2706784157, 5), // 77 - (2887174368, 5), // 78 - (3077056399, 5), // 79 - (3276800000, 5), // 80 - (3486784401, 5), // 81 - (3707398432, 5), // 82 - (3939040643, 5), // 83 - (4182119424, 5), // 84 - (52200625, 4), // 85 - (54700816, 4), // 86 - (57289761, 4), // 87 - (59969536, 4), // 88 - (62742241, 4), // 89 - (65610000, 4), // 90 - (68574961, 4), // 91 - (71639296, 4), // 92 - (74805201, 4), // 93 - (78074896, 4), // 94 - (81450625, 4), // 95 - (84934656, 4), // 96 - (88529281, 4), // 97 - (92236816, 4), // 98 - (96059601, 4), // 99 - (100000000, 4), // 100 - (104060401, 4), // 101 - (108243216, 4), // 102 - (112550881, 4), // 103 - (116985856, 4), // 104 - (121550625, 4), // 105 - (126247696, 4), // 106 - (131079601, 4), // 107 - (136048896, 4), // 108 - (141158161, 4), // 109 - (146410000, 4), // 110 - (151807041, 4), // 111 - (157351936, 4), // 112 - (163047361, 4), // 113 - (168896016, 4), // 114 - (174900625, 4), // 115 - (181063936, 4), // 116 - (187388721, 4), // 117 - (193877776, 4), // 118 - (200533921, 4), // 119 - (207360000, 4), // 120 - (214358881, 4), // 121 - (221533456, 4), // 122 - (228886641, 4), // 123 - (236421376, 4), // 124 - (244140625, 4), // 125 - (252047376, 4), // 126 - (260144641, 4), // 127 - (0, 0), // 128 - (276922881, 4), // 129 - (285610000, 4), // 130 - (294499921, 4), // 131 - (303595776, 4), // 132 - (312900721, 4), // 133 - (322417936, 4), // 134 - (332150625, 4), // 135 - (342102016, 4), // 136 - (352275361, 4), // 137 - (362673936, 4), // 138 - (373301041, 4), // 139 - (384160000, 4), // 140 - (395254161, 4), // 141 - (406586896, 4), // 142 - (418161601, 4), // 143 - (429981696, 4), // 144 - (442050625, 4), // 145 - (454371856, 4), // 146 - (466948881, 4), // 147 - (479785216, 4), // 148 - (492884401, 4), // 149 - (506250000, 4), // 150 - (519885601, 4), // 151 - (533794816, 4), // 152 - (547981281, 4), // 153 - (562448656, 4), // 154 - (577200625, 4), // 155 - (592240896, 4), // 156 - (607573201, 4), // 157 - (623201296, 4), // 158 - (639128961, 4), // 159 - (655360000, 4), // 160 - (671898241, 4), // 161 - (688747536, 4), // 162 - (705911761, 4), // 163 - (723394816, 4), // 164 - (741200625, 4), // 165 - (759333136, 4), // 166 - (777796321, 4), // 167 - (796594176, 4), // 168 - (815730721, 4), // 169 - (835210000, 4), // 170 - (855036081, 4), // 171 - (875213056, 4), // 172 - (895745041, 4), // 173 - (916636176, 4), // 174 - (937890625, 4), // 175 - (959512576, 4), // 176 - (981506241, 4), // 177 - (1003875856, 4), // 178 - (1026625681, 4), // 179 - (1049760000, 4), // 180 - (1073283121, 4), // 181 - (1097199376, 4), // 182 - (1121513121, 4), // 183 - (1146228736, 4), // 184 - (1171350625, 4), // 185 - (1196883216, 4), // 186 - (1222830961, 4), // 187 - (1249198336, 4), // 188 - (1275989841, 4), // 189 - (1303210000, 4), // 190 - (1330863361, 4), // 191 - (1358954496, 4), // 192 - (1387488001, 4), // 193 - (1416468496, 4), // 194 - (1445900625, 4), // 195 - (1475789056, 4), // 196 - (1506138481, 4), // 197 - (1536953616, 4), // 198 - (1568239201, 4), // 199 - (1600000000, 4), // 200 - (1632240801, 4), // 201 - (1664966416, 4), // 202 - (1698181681, 4), // 203 - (1731891456, 4), // 204 - (1766100625, 4), // 205 - (1800814096, 4), // 206 - (1836036801, 4), // 207 - (1871773696, 4), // 208 - (1908029761, 4), // 209 - (1944810000, 4), // 210 - (1982119441, 4), // 211 - (2019963136, 4), // 212 - (2058346161, 4), // 213 - (2097273616, 4), // 214 - (2136750625, 4), // 215 - (2176782336, 4), // 216 - (2217373921, 4), // 217 - (2258530576, 4), // 218 - (2300257521, 4), // 219 - (2342560000, 4), // 220 - (2385443281, 4), // 221 - (2428912656, 4), // 222 - (2472973441, 4), // 223 - (2517630976, 4), // 224 - (2562890625, 4), // 225 - (2608757776, 4), // 226 - (2655237841, 4), // 227 - (2702336256, 4), // 228 - (2750058481, 4), // 229 - (2798410000, 4), // 230 - (2847396321, 4), // 231 - (2897022976, 4), // 232 - (2947295521, 4), // 233 - (2998219536, 4), // 234 - (3049800625, 4), // 235 - (3102044416, 4), // 236 - (3154956561, 4), // 237 - (3208542736, 4), // 238 - (3262808641, 4), // 239 - (3317760000, 4), // 240 - (3373402561, 4), // 241 - (3429742096, 4), // 242 - (3486784401, 4), // 243 - (3544535296, 4), // 244 - (3603000625, 4), // 245 - (3662186256, 4), // 246 - (3722098081, 4), // 247 - (3782742016, 4), // 248 - (3844124001, 4), // 249 - (3906250000, 4), // 250 - (3969126001, 4), // 251 - (4032758016, 4), // 252 - (4097152081, 4), // 253 - (4162314256, 4), // 254 - (4228250625, 4), // 255 - (0, 0), // 256 - ]; - - let (base, power) = BASES[radix as usize]; - (base as BigDigit, power) - } - 64 => { - const BASES: [(u64, usize); 257] = [ - (0, 0), - (0, 0), - (9223372036854775808, 63), // 2 - (12157665459056928801, 40), // 3 - (4611686018427387904, 31), // 4 - (7450580596923828125, 27), // 5 - (4738381338321616896, 24), // 6 - (3909821048582988049, 22), // 7 - (9223372036854775808, 21), // 8 - (12157665459056928801, 20), // 9 - (10000000000000000000, 19), // 10 - (5559917313492231481, 18), // 11 - (2218611106740436992, 17), // 12 - (8650415919381337933, 17), // 13 - (2177953337809371136, 16), // 14 - (6568408355712890625, 16), // 15 - (1152921504606846976, 15), // 16 - (2862423051509815793, 15), // 17 - (6746640616477458432, 15), // 18 - (15181127029874798299, 15), // 19 - (1638400000000000000, 14), // 20 - (3243919932521508681, 14), // 21 - (6221821273427820544, 14), // 22 - (11592836324538749809, 14), // 23 - (876488338465357824, 13), // 24 - (1490116119384765625, 13), // 25 - (2481152873203736576, 13), // 26 - (4052555153018976267, 13), // 27 - (6502111422497947648, 13), // 28 - (10260628712958602189, 13), // 29 - (15943230000000000000, 13), // 30 - (787662783788549761, 12), // 31 - (1152921504606846976, 12), // 32 - (1667889514952984961, 12), // 33 - (2386420683693101056, 12), // 34 - (3379220508056640625, 12), // 35 - (4738381338321616896, 12), // 36 - (6582952005840035281, 12), // 37 - (9065737908494995456, 12), // 38 - (12381557655576425121, 12), // 39 - (16777216000000000000, 12), // 40 - (550329031716248441, 11), // 41 - (717368321110468608, 11), // 42 - (929293739471222707, 11), // 43 - (1196683881290399744, 11), // 44 - (1532278301220703125, 11), // 45 - (1951354384207722496, 11), // 46 - (2472159215084012303, 11), // 47 - (3116402981210161152, 11), // 48 - (3909821048582988049, 11), // 49 - (4882812500000000000, 11), // 50 - (6071163615208263051, 11), // 51 - (7516865509350965248, 11), // 52 - (9269035929372191597, 11), // 53 - (11384956040305711104, 11), // 54 - (13931233916552734375, 11), // 55 - (16985107389382393856, 11), // 56 - (362033331456891249, 10), // 57 - (430804206899405824, 10), // 58 - (511116753300641401, 10), // 59 - (604661760000000000, 10), // 60 - (713342911662882601, 10), // 61 - (839299365868340224, 10), // 62 - (984930291881790849, 10), // 63 - (1152921504606846976, 10), // 64 - (1346274334462890625, 10), // 65 - (1568336880910795776, 10), // 66 - (1822837804551761449, 10), // 67 - (2113922820157210624, 10), // 68 - (2446194060654759801, 10), // 69 - (2824752490000000000, 10), // 70 - (3255243551009881201, 10), // 71 - (3743906242624487424, 10), // 72 - (4297625829703557649, 10), // 73 - (4923990397355877376, 10), // 74 - (5631351470947265625, 10), // 75 - (6428888932339941376, 10), // 76 - (7326680472586200649, 10), // 77 - (8335775831236199424, 10), // 78 - (9468276082626847201, 10), // 79 - (10737418240000000000, 10), // 80 - (12157665459056928801, 10), // 81 - (13744803133596058624, 10), // 82 - (15516041187205853449, 10), // 83 - (17490122876598091776, 10), // 84 - (231616946283203125, 9), // 85 - (257327417311663616, 9), // 86 - (285544154243029527, 9), // 87 - (316478381828866048, 9), // 88 - (350356403707485209, 9), // 89 - (387420489000000000, 9), // 90 - (427929800129788411, 9), // 91 - (472161363286556672, 9), // 92 - (520411082988487293, 9), // 93 - (572994802228616704, 9), // 94 - (630249409724609375, 9), // 95 - (692533995824480256, 9), // 96 - (760231058654565217, 9), // 97 - (833747762130149888, 9), // 98 - (913517247483640899, 9), // 99 - (1000000000000000000, 9), // 100 - (1093685272684360901, 9), // 101 - (1195092568622310912, 9), // 102 - (1304773183829244583, 9), // 103 - (1423311812421484544, 9), // 104 - (1551328215978515625, 9), // 105 - (1689478959002692096, 9), // 106 - (1838459212420154507, 9), // 107 - (1999004627104432128, 9), // 108 - (2171893279442309389, 9), // 109 - (2357947691000000000, 9), // 110 - (2558036924386500591, 9), // 111 - (2773078757450186752, 9), // 112 - (3004041937984268273, 9), // 113 - (3251948521156637184, 9), // 114 - (3517876291919921875, 9), // 115 - (3802961274698203136, 9), // 116 - (4108400332687853397, 9), // 117 - (4435453859151328768, 9), // 118 - (4785448563124474679, 9), // 119 - (5159780352000000000, 9), // 120 - (5559917313492231481, 9), // 121 - (5987402799531080192, 9), // 122 - (6443858614676334363, 9), // 123 - (6930988311686938624, 9), // 124 - (7450580596923828125, 9), // 125 - (8004512848309157376, 9), // 126 - (8594754748609397887, 9), // 127 - (9223372036854775808, 9), // 128 - (9892530380752880769, 9), // 129 - (10604499373000000000, 9), // 130 - (11361656654439817571, 9), // 131 - (12166492167065567232, 9), // 132 - (13021612539908538853, 9), // 133 - (13929745610903012864, 9), // 134 - (14893745087865234375, 9), // 135 - (15916595351771938816, 9), // 136 - (17001416405572203977, 9), // 137 - (18151468971815029248, 9), // 138 - (139353667211683681, 8), // 139 - (147578905600000000, 8), // 140 - (156225851787813921, 8), // 141 - (165312903998914816, 8), // 142 - (174859124550883201, 8), // 143 - (184884258895036416, 8), // 144 - (195408755062890625, 8), // 145 - (206453783524884736, 8), // 146 - (218041257467152161, 8), // 147 - (230193853492166656, 8), // 148 - (242935032749128801, 8), // 149 - (256289062500000000, 8), // 150 - (270281038127131201, 8), // 151 - (284936905588473856, 8), // 152 - (300283484326400961, 8), // 153 - (316348490636206336, 8), // 154 - (333160561500390625, 8), // 155 - (350749278894882816, 8), // 156 - (369145194573386401, 8), // 157 - (388379855336079616, 8), // 158 - (408485828788939521, 8), // 159 - (429496729600000000, 8), // 160 - (451447246258894081, 8), // 161 - (474373168346071296, 8), // 162 - (498311414318121121, 8), // 163 - (523300059815673856, 8), // 164 - (549378366500390625, 8), // 165 - (576586811427594496, 8), // 166 - (604967116961135041, 8), // 167 - (634562281237118976, 8), // 168 - (665416609183179841, 8), // 169 - (697575744100000000, 8), // 170 - (731086699811838561, 8), // 171 - (765997893392859136, 8), // 172 - (802359178476091681, 8), // 173 - (840221879151902976, 8), // 174 - (879638824462890625, 8), // 175 - (920664383502155776, 8), // 176 - (963354501121950081, 8), // 177 - (1007766734259732736, 8), // 178 - (1053960288888713761, 8), // 179 - (1101996057600000000, 8), // 180 - (1151936657823500641, 8), // 181 - (1203846470694789376, 8), // 182 - (1257791680575160641, 8), // 183 - (1313840315232157696, 8), // 184 - (1372062286687890625, 8), // 185 - (1432529432742502656, 8), // 186 - (1495315559180183521, 8), // 187 - (1560496482665168896, 8), // 188 - (1628150074335205281, 8), // 189 - (1698356304100000000, 8), // 190 - (1771197285652216321, 8), // 191 - (1846757322198614016, 8), // 192 - (1925122952918976001, 8), // 193 - (2006383000160502016, 8), // 194 - (2090628617375390625, 8), // 195 - (2177953337809371136, 8), // 196 - (2268453123948987361, 8), // 197 - (2362226417735475456, 8), // 198 - (2459374191553118401, 8), // 199 - (2560000000000000000, 8), // 200 - (2664210032449121601, 8), // 201 - (2772113166407885056, 8), // 202 - (2883821021683985761, 8), // 203 - (2999448015365799936, 8), // 204 - (3119111417625390625, 8), // 205 - (3242931408352297216, 8), // 206 - (3371031134626313601, 8), // 207 - (3503536769037500416, 8), // 208 - (3640577568861717121, 8), // 209 - (3782285936100000000, 8), // 210 - (3928797478390152481, 8), // 211 - (4080251070798954496, 8), // 212 - (4236788918503437921, 8), // 213 - (4398556620369715456, 8), // 214 - (4565703233437890625, 8), // 215 - (4738381338321616896, 8), // 216 - (4916747105530914241, 8), // 217 - (5100960362726891776, 8), // 218 - (5291184662917065441, 8), // 219 - (5487587353600000000, 8), // 220 - (5690339646868044961, 8), // 221 - (5899616690476974336, 8), // 222 - (6115597639891380481, 8), // 223 - (6338465731314712576, 8), // 224 - (6568408355712890625, 8), // 225 - (6805617133840466176, 8), // 226 - (7050287992278341281, 8), // 227 - (7302621240492097536, 8), // 228 - (7562821648920027361, 8), // 229 - (7831098528100000000, 8), // 230 - (8107665808844335041, 8), // 231 - (8392742123471896576, 8), // 232 - (8686550888106661441, 8), // 233 - (8989320386052055296, 8), // 234 - (9301283852250390625, 8), // 235 - (9622679558836781056, 8), // 236 - (9953750901796946721, 8), // 237 - (10294746488738365696, 8), // 238 - (10645920227784266881, 8), // 239 - (11007531417600000000, 8), // 240 - (11379844838561358721, 8), // 241 - (11763130845074473216, 8), // 242 - (12157665459056928801, 8), // 243 - (12563730464589807616, 8), // 244 - (12981613503750390625, 8), // 245 - (13411608173635297536, 8), // 246 - (13854014124583882561, 8), // 247 - (14309137159611744256, 8), // 248 - (14777289335064248001, 8), // 249 - (15258789062500000000, 8), // 250 - (15753961211814252001, 8), // 251 - (16263137215612256256, 8), // 252 - (16786655174842630561, 8), // 253 - (17324859965700833536, 8), // 254 - (17878103347812890625, 8), // 255 - (72057594037927936, 7), // 256 - ]; - - let (base, power) = BASES[radix as usize]; - (base as BigDigit, power) - } - _ => panic!("Invalid bigdigit size"), - } -} - -#[test] -fn test_from_slice() { - fn check(slice: &[BigDigit], data: &[BigDigit]) { - assert!(BigUint::from_slice(slice).data == data); - } - check(&[1], &[1]); - check(&[0, 0, 0], &[]); - check(&[1, 2, 0, 0], &[1, 2]); - check(&[0, 0, 1, 2], &[0, 0, 1, 2]); - check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); - check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); -} - -#[test] -fn test_assign_from_slice() { - fn check(slice: &[BigDigit], data: &[BigDigit]) { - let mut p = BigUint::from_slice(&[2627_u32, 0_u32, 9182_u32, 42_u32]); - p.assign_from_slice(slice); - assert!(p.data == data); - } - check(&[1], &[1]); - check(&[0, 0, 0], &[]); - check(&[1, 2, 0, 0], &[1, 2]); - check(&[0, 0, 1, 2], &[0, 0, 1, 2]); - check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); - check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); -} - -#[cfg(has_i128)] -#[test] -fn test_u32_u128() { - assert_eq!(u32_from_u128(0u128), (0, 0, 0, 0)); - assert_eq!( - u32_from_u128(u128::max_value()), - ( - u32::max_value(), - u32::max_value(), - u32::max_value(), - u32::max_value() - ) - ); - - assert_eq!( - u32_from_u128(u32::max_value() as u128), - (0, 0, 0, u32::max_value()) - ); - - assert_eq!( - u32_from_u128(u64::max_value() as u128), - (0, 0, u32::max_value(), u32::max_value()) - ); - - assert_eq!( - u32_from_u128((u64::max_value() as u128) + u32::max_value() as u128), - (0, 1, 0, u32::max_value() - 1) - ); - - assert_eq!(u32_from_u128(36_893_488_151_714_070_528), (0, 2, 1, 0)); -} - -#[cfg(has_i128)] -#[test] -fn test_u128_u32_roundtrip() { - // roundtrips - let values = vec![ - 0u128, - 1u128, - u64::max_value() as u128 * 3, - u32::max_value() as u128, - u64::max_value() as u128, - (u64::max_value() as u128) + u32::max_value() as u128, - u128::max_value(), - ]; - - for val in &values { - let (a, b, c, d) = u32_from_u128(*val); - assert_eq!(u32_to_u128(a, b, c, d), *val); - } -} - -#[test] -fn test_pow_biguint() { - let base = BigUint::from(5u8); - let exponent = BigUint::from(3u8); - - assert_eq!(BigUint::from(125u8), base.pow(exponent)); -} diff --git a/third_party/rust/num-bigint-0.2.3/src/lib.rs b/third_party/rust/num-bigint-0.2.3/src/lib.rs deleted file mode 100644 index dece7bab0070..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/lib.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A Big integer (signed version: `BigInt`, unsigned version: `BigUint`). -//! -//! A `BigUint` is represented as a vector of `BigDigit`s. -//! A `BigInt` is a combination of `BigUint` and `Sign`. -//! -//! Common numerical operations are overloaded, so we can treat them -//! the same way we treat other numbers. -//! -//! ## Example -//! -//! ```rust -//! extern crate num_bigint; -//! extern crate num_traits; -//! -//! # fn main() { -//! use num_bigint::BigUint; -//! use num_traits::{Zero, One}; -//! use std::mem::replace; -//! -//! // Calculate large fibonacci numbers. -//! fn fib(n: usize) -> BigUint { -//! let mut f0: BigUint = Zero::zero(); -//! let mut f1: BigUint = One::one(); -//! for _ in 0..n { -//! let f2 = f0 + &f1; -//! // This is a low cost way of swapping f0 with f1 and f1 with f2. -//! f0 = replace(&mut f1, f2); -//! } -//! f0 -//! } -//! -//! // This is a very large number. -//! println!("fib(1000) = {}", fib(1000)); -//! # } -//! ``` -//! -//! It's easy to generate large random numbers: -//! -//! ```rust -//! # #[cfg(feature = "rand")] -//! extern crate rand; -//! extern crate num_bigint as bigint; -//! -//! # #[cfg(feature = "rand")] -//! # fn main() { -//! use bigint::{ToBigInt, RandBigInt}; -//! -//! let mut rng = rand::thread_rng(); -//! let a = rng.gen_bigint(1000); -//! -//! let low = -10000.to_bigint().unwrap(); -//! let high = 10000.to_bigint().unwrap(); -//! let b = rng.gen_bigint_range(&low, &high); -//! -//! // Probably an even larger number. -//! println!("{}", a * b); -//! # } -//! -//! # #[cfg(not(feature = "rand"))] -//! # fn main() { -//! # } -//! ``` -//! -//! ## Compatibility -//! -//! The `num-bigint` crate is tested for rustc 1.15 and greater. - -#![doc(html_root_url = "https://docs.rs/num-bigint/0.2")] -// We don't actually support `no_std` yet, and probably won't until `alloc` is stable. We're just -// reserving this ability with the "std" feature now, and compilation will fail without. -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "rand")] -extern crate rand; -#[cfg(feature = "serde")] -extern crate serde; - -extern crate num_integer as integer; -extern crate num_traits as traits; -#[cfg(feature = "quickcheck")] -extern crate quickcheck; - -use std::error::Error; -use std::fmt; - -#[macro_use] -mod macros; - -mod bigint; -mod biguint; - -#[cfg(feature = "rand")] -mod bigrand; - -#[cfg(target_pointer_width = "32")] -type UsizePromotion = u32; -#[cfg(target_pointer_width = "64")] -type UsizePromotion = u64; - -#[cfg(target_pointer_width = "32")] -type IsizePromotion = i32; -#[cfg(target_pointer_width = "64")] -type IsizePromotion = i64; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ParseBigIntError { - kind: BigIntErrorKind, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -enum BigIntErrorKind { - Empty, - InvalidDigit, -} - -impl ParseBigIntError { - fn __description(&self) -> &str { - use BigIntErrorKind::*; - match self.kind { - Empty => "cannot parse integer from empty string", - InvalidDigit => "invalid digit found in string", - } - } - - fn empty() -> Self { - ParseBigIntError { - kind: BigIntErrorKind::Empty, - } - } - - fn invalid() -> Self { - ParseBigIntError { - kind: BigIntErrorKind::InvalidDigit, - } - } -} - -impl fmt::Display for ParseBigIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.__description().fmt(f) - } -} - -impl Error for ParseBigIntError { - fn description(&self) -> &str { - self.__description() - } -} - -pub use biguint::BigUint; -pub use biguint::ToBigUint; - -pub use bigint::BigInt; -pub use bigint::Sign; -pub use bigint::ToBigInt; - -#[cfg(feature = "rand")] -pub use bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint}; - -mod big_digit { - /// A `BigDigit` is a `BigUint`'s composing element. - pub type BigDigit = u32; - - /// A `DoubleBigDigit` is the internal type used to do the computations. Its - /// size is the double of the size of `BigDigit`. - pub type DoubleBigDigit = u64; - - /// A `SignedDoubleBigDigit` is the signed version of `DoubleBigDigit`. - pub type SignedDoubleBigDigit = i64; - - // `DoubleBigDigit` size dependent - pub const BITS: usize = 32; - - const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS; - - #[inline] - fn get_hi(n: DoubleBigDigit) -> BigDigit { - (n >> BITS) as BigDigit - } - #[inline] - fn get_lo(n: DoubleBigDigit) -> BigDigit { - (n & LO_MASK) as BigDigit - } - - /// Split one `DoubleBigDigit` into two `BigDigit`s. - #[inline] - pub fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { - (get_hi(n), get_lo(n)) - } - - /// Join two `BigDigit`s into one `DoubleBigDigit` - #[inline] - pub fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { - DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS) - } -} diff --git a/third_party/rust/num-bigint-0.2.3/src/macros.rs b/third_party/rust/num-bigint-0.2.3/src/macros.rs deleted file mode 100644 index 0ba6e48c72fe..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/macros.rs +++ /dev/null @@ -1,445 +0,0 @@ -#![allow(unknown_lints)] // older rustc doesn't know `unused_macros` -#![allow(unused_macros)] - -macro_rules! forward_val_val_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // forward to val-ref - $imp::$method(self, &other) - } - } - }; -} - -macro_rules! forward_val_val_binop_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // forward to val-ref, with the larger capacity as val - if self.capacity() >= other.capacity() { - $imp::$method(self, &other) - } else { - $imp::$method(other, &self) - } - } - } - }; -} - -macro_rules! forward_ref_val_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<$res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // forward to ref-ref - $imp::$method(self, &other) - } - } - }; -} - -macro_rules! forward_ref_val_binop_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<$res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // reverse, forward to val-ref - $imp::$method(other, self) - } - } - }; -} - -macro_rules! forward_val_ref_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<&'a $res> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - // forward to ref-ref - $imp::$method(&self, other) - } - } - }; -} - -macro_rules! forward_ref_ref_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - // forward to val-ref - $imp::$method(self.clone(), other) - } - } - }; -} - -macro_rules! forward_ref_ref_binop_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - // forward to val-ref, choosing the larger to clone - if self.len() >= other.len() { - $imp::$method(self.clone(), other) - } else { - $imp::$method(other.clone(), self) - } - } - } - }; -} - -macro_rules! forward_val_assign { - (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { - #[inline] - fn $method(&mut self, other: $res) { - self.$method(&other); - } - } - }; -} - -macro_rules! forward_val_assign_scalar { - (impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => { - impl $imp<$res> for $scalar { - #[inline] - fn $method(&mut self, other: $res) { - self.$method(&other); - } - } - }; -} - -/// use this if val_val_binop is already implemented and the reversed order is required -macro_rules! forward_scalar_val_val_binop_commutative { - (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => { - impl $imp<$res> for $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(other, self) - } - } - }; -} - -// Forward scalar to ref-val, when reusing storage is not helpful -macro_rules! forward_scalar_val_val_binop_to_ref_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl $imp<$scalar> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: $scalar) -> $res { - $imp::$method(&self, other) - } - } - - impl $imp<$res> for $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(self, &other) - } - } - }; -} - -macro_rules! forward_scalar_ref_ref_binop_to_ref_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $scalar> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$scalar) -> $res { - $imp::$method(self, *other) - } - } - - impl<'a, 'b> $imp<&'a $res> for &'b $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - $imp::$method(*self, other) - } - } - }; -} - -macro_rules! forward_scalar_val_ref_binop_to_ref_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a> $imp<&'a $scalar> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$scalar) -> $res { - $imp::$method(&self, *other) - } - } - - impl<'a> $imp<$res> for &'a $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(*self, &other) - } - } - }; -} - -macro_rules! forward_scalar_val_ref_binop_to_val_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a> $imp<&'a $scalar> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$scalar) -> $res { - $imp::$method(self, *other) - } - } - - impl<'a> $imp<$res> for &'a $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(*self, other) - } - } - }; -} - -macro_rules! forward_scalar_ref_val_binop_to_val_val { - (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => { - impl<'a> $imp<$scalar> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: $scalar) -> $res { - $imp::$method(self.clone(), other) - } - } - - impl<'a> $imp<&'a $res> for $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - $imp::$method(self, other.clone()) - } - } - }; -} - -macro_rules! forward_scalar_ref_ref_binop_to_val_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $scalar> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$scalar) -> $res { - $imp::$method(self.clone(), *other) - } - } - - impl<'a, 'b> $imp<&'a $res> for &'b $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - $imp::$method(*self, other.clone()) - } - } - }; -} - -macro_rules! promote_scalars { - (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { - $( - forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - - impl $imp<$scalar> for $res { - type Output = $res; - - #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] - #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] - #[inline] - fn $method(self, other: $scalar) -> $res { - $imp::$method(self, other as $promo) - } - } - - impl $imp<$res> for $scalar { - type Output = $res; - - #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] - #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(self as $promo, other) - } - } - )* - } -} -macro_rules! promote_scalars_assign { - (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { - $( - impl $imp<$scalar> for $res { - #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] - #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] - #[inline] - fn $method(&mut self, other: $scalar) { - self.$method(other as $promo); - } - } - )* - } -} - -macro_rules! promote_unsigned_scalars { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars!(impl $imp for $res, $method, u8, u16); - promote_scalars!(impl $imp for $res, $method, usize); - } -} - -macro_rules! promote_unsigned_scalars_assign { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars_assign!(impl $imp for $res, $method, u8, u16); - promote_scalars_assign!(impl $imp for $res, $method, usize); - } -} - -macro_rules! promote_signed_scalars { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars!(impl $imp for $res, $method, i8, i16); - promote_scalars!(impl $imp for $res, $method, isize); - } -} - -macro_rules! promote_signed_scalars_assign { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars_assign!(impl $imp for $res, $method, i8, i16); - promote_scalars_assign!(impl $imp for $res, $method, isize); - } -} - -// Forward everything to ref-ref, when reusing storage is not helpful -macro_rules! forward_all_binop_to_ref_ref { - (impl $imp:ident for $res:ty, $method:ident) => { - forward_val_val_binop!(impl $imp for $res, $method); - forward_val_ref_binop!(impl $imp for $res, $method); - forward_ref_val_binop!(impl $imp for $res, $method); - }; -} - -// Forward everything to val-ref, so LHS storage can be reused -macro_rules! forward_all_binop_to_val_ref { - (impl $imp:ident for $res:ty, $method:ident) => { - forward_val_val_binop!(impl $imp for $res, $method); - forward_ref_val_binop!(impl $imp for $res, $method); - forward_ref_ref_binop!(impl $imp for $res, $method); - }; -} - -// Forward everything to val-ref, commutatively, so either LHS or RHS storage can be reused -macro_rules! forward_all_binop_to_val_ref_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - forward_val_val_binop_commutative!(impl $imp for $res, $method); - forward_ref_val_binop_commutative!(impl $imp for $res, $method); - forward_ref_ref_binop_commutative!(impl $imp for $res, $method); - }; -} - -macro_rules! forward_all_scalar_binop_to_ref_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - forward_scalar_val_val_binop_to_ref_val!(impl $imp<$scalar> for $res, $method); - forward_scalar_val_ref_binop_to_ref_val!(impl $imp<$scalar> for $res, $method); - forward_scalar_ref_ref_binop_to_ref_val!(impl $imp<$scalar> for $res, $method); - } -} - -macro_rules! forward_all_scalar_binop_to_val_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - forward_scalar_val_ref_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - forward_scalar_ref_val_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - forward_scalar_ref_ref_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - } -} - -macro_rules! forward_all_scalar_binop_to_val_val_commutative { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - forward_scalar_val_val_binop_commutative!(impl $imp<$scalar> for $res, $method); - forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - } -} - -macro_rules! promote_all_scalars { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_unsigned_scalars!(impl $imp for $res, $method); - promote_signed_scalars!(impl $imp for $res, $method); - } -} - -macro_rules! promote_all_scalars_assign { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_unsigned_scalars_assign!(impl $imp for $res, $method); - promote_signed_scalars_assign!(impl $imp for $res, $method); - } -} - -macro_rules! impl_sum_iter_type { - ($res:ty) => { - impl Sum for $res - where - $res: Add, - { - fn sum(iter: I) -> Self - where - I: Iterator, - { - iter.fold(Zero::zero(), <$res>::add) - } - } - }; -} - -macro_rules! impl_product_iter_type { - ($res:ty) => { - impl Product for $res - where - $res: Mul, - { - fn product(iter: I) -> Self - where - I: Iterator, - { - iter.fold(One::one(), <$res>::mul) - } - } - }; -} diff --git a/third_party/rust/num-bigint-0.2.3/src/monty.rs b/third_party/rust/num-bigint-0.2.3/src/monty.rs deleted file mode 100644 index 72a4ab53eb68..000000000000 --- a/third_party/rust/num-bigint-0.2.3/src/monty.rs +++ /dev/null @@ -1,129 +0,0 @@ -use integer::Integer; -use traits::Zero; - -use biguint::BigUint; - -struct MontyReducer<'a> { - n: &'a BigUint, - n0inv: u32, -} - -// Calculate the modular inverse of `num`, using Extended GCD. -// -// Reference: -// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20 -fn inv_mod_u32(num: u32) -> u32 { - // num needs to be relatively prime to 2**32 -- i.e. it must be odd. - assert!(num % 2 != 0); - - let mut a: i64 = i64::from(num); - let mut b: i64 = i64::from(u32::max_value()) + 1; - - // ExtendedGcd - // Input: positive integers a and b - // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb - // As we don't need v for modular inverse, we don't calculate it. - - // 1: (u, w) <- (1, 0) - let mut u = 1; - let mut w = 0; - // 3: while b != 0 - while b != 0 { - // 4: (q, r) <- DivRem(a, b) - let q = a / b; - let r = a % b; - // 5: (a, b) <- (b, r) - a = b; - b = r; - // 6: (u, w) <- (w, u - qw) - let m = u - w * q; - u = w; - w = m; - } - - assert!(a == 1); - // Downcasting acts like a mod 2^32 too. - u as u32 -} - -impl<'a> MontyReducer<'a> { - fn new(n: &'a BigUint) -> Self { - let n0inv = inv_mod_u32(n.data[0]); - MontyReducer { n: n, n0inv: n0inv } - } -} - -// Montgomery Reduction -// -// Reference: -// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6 -fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint { - let mut c = a.data; - let n = &mr.n.data; - let n_size = n.len(); - - // Allocate sufficient work space - c.resize(2 * n_size + 2, 0); - - // β is the size of a word, in this case 32 bits. So "a mod β" is - // equivalent to masking a to 32 bits. - // mu <- -N^(-1) mod β - let mu = 0u32.wrapping_sub(mr.n0inv); - - // 1: for i = 0 to (n-1) - for i in 0..n_size { - // 2: q_i <- mu*c_i mod β - let q_i = c[i].wrapping_mul(mu); - - // 3: C <- C + q_i * N * β^i - super::algorithms::mac_digit(&mut c[i..], n, q_i); - } - - // 4: R <- C * β^(-n) - // This is an n-word bitshift, equivalent to skipping n words. - let ret = BigUint::new(c[n_size..].to_vec()); - - // 5: if R >= β^n then return R-N else return R. - if &ret < mr.n { - ret - } else { - ret - mr.n - } -} - -// Montgomery Multiplication -fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint { - monty_redc(a * b, mr) -} - -// Montgomery Squaring -fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint { - // TODO: Replace with an optimised squaring function - monty_redc(&a * &a, mr) -} - -pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { - let mr = MontyReducer::new(modulus); - - // Calculate the Montgomery parameter - let mut v = vec![0; modulus.data.len()]; - v.push(1); - let r = BigUint::new(v); - - // Map the base to the Montgomery domain - let mut apri = a * &r % modulus; - - // Binary exponentiation - let mut ans = &r % modulus; - let mut e = exp.clone(); - while !e.is_zero() { - if e.is_odd() { - ans = monty_mult(ans, &apri, &mr); - } - apri = monty_sqr(apri, &mr); - e = e >> 1; - } - - // Map the result back to the residues domain - monty_redc(ans, &mr) -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/bigint.rs b/third_party/rust/num-bigint-0.2.3/tests/bigint.rs deleted file mode 100644 index 911bff0020a9..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/bigint.rs +++ /dev/null @@ -1,1193 +0,0 @@ -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; -#[cfg(feature = "rand")] -extern crate rand; - -use num_bigint::BigUint; -use num_bigint::Sign::{Minus, NoSign, Plus}; -use num_bigint::{BigInt, ToBigInt}; - -use std::cmp::Ordering::{Equal, Greater, Less}; -use std::collections::hash_map::RandomState; -use std::hash::{BuildHasher, Hash, Hasher}; -use std::iter::repeat; -use std::ops::Neg; -use std::{f32, f64}; -#[cfg(has_i128)] -use std::{i128, u128}; -use std::{i16, i32, i64, i8, isize}; -use std::{u16, u32, u64, u8, usize}; - -use num_integer::Integer; -use num_traits::{Float, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero}; - -mod consts; -use consts::*; - -#[macro_use] -mod macros; - -#[test] -fn test_from_bytes_be() { - fn check(s: &str, result: &str) { - assert_eq!( - BigInt::from_bytes_be(Plus, s.as_bytes()), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap() - ); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - assert_eq!(BigInt::from_bytes_be(Plus, &[]), Zero::zero()); - assert_eq!(BigInt::from_bytes_be(Minus, &[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_be() { - fn check(s: &str, result: &str) { - let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); - let (sign, v) = b.to_bytes_be(); - assert_eq!((Plus, s.as_bytes()), (sign, &*v)); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - let b: BigInt = Zero::zero(); - assert_eq!(b.to_bytes_be(), (NoSign, vec![0])); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_be(), (Plus, vec![1, 0, 0, 0, 0, 0, 0, 2, 0])); -} - -#[test] -fn test_from_bytes_le() { - fn check(s: &str, result: &str) { - assert_eq!( - BigInt::from_bytes_le(Plus, s.as_bytes()), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap() - ); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - assert_eq!(BigInt::from_bytes_le(Plus, &[]), Zero::zero()); - assert_eq!(BigInt::from_bytes_le(Minus, &[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_le() { - fn check(s: &str, result: &str) { - let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); - let (sign, v) = b.to_bytes_le(); - assert_eq!((Plus, s.as_bytes()), (sign, &*v)); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - let b: BigInt = Zero::zero(); - assert_eq!(b.to_bytes_le(), (NoSign, vec![0])); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_le(), (Plus, vec![0, 2, 0, 0, 0, 0, 0, 0, 1])); -} - -#[test] -fn test_to_signed_bytes_le() { - fn check(s: &str, result: Vec) { - assert_eq!( - BigInt::parse_bytes(s.as_bytes(), 10) - .unwrap() - .to_signed_bytes_le(), - result - ); - } - - check("0", vec![0]); - check("32767", vec![0xff, 0x7f]); - check("-1", vec![0xff]); - check("16777216", vec![0, 0, 0, 1]); - check("-100", vec![156]); - check("-8388608", vec![0, 0, 0x80]); - check("-192", vec![0x40, 0xff]); - check("128", vec![0x80, 0]) -} - -#[test] -fn test_from_signed_bytes_le() { - fn check(s: &[u8], result: &str) { - assert_eq!( - BigInt::from_signed_bytes_le(s), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap() - ); - } - - check(&[], "0"); - check(&[0], "0"); - check(&[0; 10], "0"); - check(&[0xff, 0x7f], "32767"); - check(&[0xff], "-1"); - check(&[0, 0, 0, 1], "16777216"); - check(&[156], "-100"); - check(&[0, 0, 0x80], "-8388608"); - check(&[0xff; 10], "-1"); - check(&[0x40, 0xff], "-192"); -} - -#[test] -fn test_to_signed_bytes_be() { - fn check(s: &str, result: Vec) { - assert_eq!( - BigInt::parse_bytes(s.as_bytes(), 10) - .unwrap() - .to_signed_bytes_be(), - result - ); - } - - check("0", vec![0]); - check("32767", vec![0x7f, 0xff]); - check("-1", vec![255]); - check("16777216", vec![1, 0, 0, 0]); - check("-100", vec![156]); - check("-8388608", vec![128, 0, 0]); - check("-192", vec![0xff, 0x40]); - check("128", vec![0, 0x80]); -} - -#[test] -fn test_from_signed_bytes_be() { - fn check(s: &[u8], result: &str) { - assert_eq!( - BigInt::from_signed_bytes_be(s), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap() - ); - } - - check(&[], "0"); - check(&[0], "0"); - check(&[0; 10], "0"); - check(&[127, 255], "32767"); - check(&[255], "-1"); - check(&[1, 0, 0, 0], "16777216"); - check(&[156], "-100"); - check(&[128, 0, 0], "-8388608"); - check(&[255; 10], "-1"); - check(&[0xff, 0x40], "-192"); -} - -#[test] -fn test_signed_bytes_be_round_trip() { - for i in -0x1FFFF..0x20000 { - let n = BigInt::from(i); - assert_eq!(n, BigInt::from_signed_bytes_be(&n.to_signed_bytes_be())); - } -} - -#[test] -fn test_signed_bytes_le_round_trip() { - for i in -0x1FFFF..0x20000 { - let n = BigInt::from(i); - assert_eq!(n, BigInt::from_signed_bytes_le(&n.to_signed_bytes_le())); - } -} - -#[test] -fn test_cmp() { - let vs: [&[u32]; 4] = [&[2 as u32], &[1, 1], &[2, 1], &[1, 1, 1]]; - let mut nums = Vec::new(); - for s in vs.iter().rev() { - nums.push(BigInt::from_slice(Minus, *s)); - } - nums.push(Zero::zero()); - nums.extend(vs.iter().map(|s| BigInt::from_slice(Plus, *s))); - - for (i, ni) in nums.iter().enumerate() { - for (j0, nj) in nums[i..].iter().enumerate() { - let j = i + j0; - if i == j { - assert_eq!(ni.cmp(nj), Equal); - assert_eq!(nj.cmp(ni), Equal); - assert_eq!(ni, nj); - assert!(!(ni != nj)); - assert!(ni <= nj); - assert!(ni >= nj); - assert!(!(ni < nj)); - assert!(!(ni > nj)); - } else { - assert_eq!(ni.cmp(nj), Less); - assert_eq!(nj.cmp(ni), Greater); - - assert!(!(ni == nj)); - assert!(ni != nj); - - assert!(ni <= nj); - assert!(!(ni >= nj)); - assert!(ni < nj); - assert!(!(ni > nj)); - - assert!(!(nj <= ni)); - assert!(nj >= ni); - assert!(!(nj < ni)); - assert!(nj > ni); - } - } - } -} - -fn hash(x: &T) -> u64 { - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[test] -fn test_hash() { - let a = BigInt::new(NoSign, vec![]); - let b = BigInt::new(NoSign, vec![0]); - let c = BigInt::new(Plus, vec![1]); - let d = BigInt::new(Plus, vec![1, 0, 0, 0, 0, 0]); - let e = BigInt::new(Plus, vec![0, 0, 0, 0, 0, 1]); - let f = BigInt::new(Minus, vec![1]); - assert!(hash(&a) == hash(&b)); - assert!(hash(&b) != hash(&c)); - assert!(hash(&c) == hash(&d)); - assert!(hash(&d) != hash(&e)); - assert!(hash(&c) != hash(&f)); -} - -#[test] -fn test_convert_i64() { - fn check(b1: BigInt, i: i64) { - let b2: BigInt = FromPrimitive::from_i64(i).unwrap(); - assert!(b1 == b2); - assert!(b1.to_i64().unwrap() == i); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(i64::MIN.to_bigint().unwrap(), i64::MIN); - check(i64::MAX.to_bigint().unwrap(), i64::MAX); - - assert_eq!((i64::MAX as u64 + 1).to_bigint().unwrap().to_i64(), None); - - assert_eq!( - BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i64(), - None - ); - - assert_eq!( - BigInt::from_biguint(Minus, BigUint::new(vec![1, 0, 0, 1 << 31])).to_i64(), - None - ); - - assert_eq!( - BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i64(), - None - ); -} - -#[test] -#[cfg(has_i128)] -fn test_convert_i128() { - fn check(b1: BigInt, i: i128) { - let b2: BigInt = FromPrimitive::from_i128(i).unwrap(); - assert!(b1 == b2); - assert!(b1.to_i128().unwrap() == i); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(i128::MIN.to_bigint().unwrap(), i128::MIN); - check(i128::MAX.to_bigint().unwrap(), i128::MAX); - - assert_eq!((i128::MAX as u128 + 1).to_bigint().unwrap().to_i128(), None); - - assert_eq!( - BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i128(), - None - ); - - assert_eq!( - BigInt::from_biguint(Minus, BigUint::new(vec![1, 0, 0, 1 << 31])).to_i128(), - None - ); - - assert_eq!( - BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_i128(), - None - ); -} - -#[test] -fn test_convert_u64() { - fn check(b1: BigInt, u: u64) { - let b2: BigInt = FromPrimitive::from_u64(u).unwrap(); - assert!(b1 == b2); - assert!(b1.to_u64().unwrap() == u); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(u64::MIN.to_bigint().unwrap(), u64::MIN); - check(u64::MAX.to_bigint().unwrap(), u64::MAX); - - assert_eq!( - BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u64(), - None - ); - - let max_value: BigUint = FromPrimitive::from_u64(u64::MAX).unwrap(); - assert_eq!(BigInt::from_biguint(Minus, max_value).to_u64(), None); - assert_eq!( - BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u64(), - None - ); -} - -#[test] -#[cfg(has_i128)] -fn test_convert_u128() { - fn check(b1: BigInt, u: u128) { - let b2: BigInt = FromPrimitive::from_u128(u).unwrap(); - assert!(b1 == b2); - assert!(b1.to_u128().unwrap() == u); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(u128::MIN.to_bigint().unwrap(), u128::MIN); - check(u128::MAX.to_bigint().unwrap(), u128::MAX); - - assert_eq!( - BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u128(), - None - ); - - let max_value: BigUint = FromPrimitive::from_u128(u128::MAX).unwrap(); - assert_eq!(BigInt::from_biguint(Minus, max_value).to_u128(), None); - assert_eq!( - BigInt::from_biguint(Minus, BigUint::new(vec![1, 2, 3, 4, 5])).to_u128(), - None - ); -} - -#[test] -fn test_convert_f32() { - fn check(b1: &BigInt, f: f32) { - let b2 = BigInt::from_f32(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f32().unwrap(), f); - let neg_b1 = -b1; - let neg_b2 = BigInt::from_f32(-f).unwrap(); - assert_eq!(neg_b1, neg_b2); - assert_eq!(neg_b1.to_f32().unwrap(), -f); - } - - check(&BigInt::zero(), 0.0); - check(&BigInt::one(), 1.0); - check(&BigInt::from(u16::MAX), 2.0.powi(16) - 1.0); - check(&BigInt::from(1u64 << 32), 2.0.powi(32)); - check(&BigInt::from_slice(Plus, &[0, 0, 1]), 2.0.powi(64)); - check( - &((BigInt::one() << 100) + (BigInt::one() << 123)), - 2.0.powi(100) + 2.0.powi(123), - ); - check(&(BigInt::one() << 127), 2.0.powi(127)); - check(&(BigInt::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); - - // keeping all 24 digits with the bits at different offsets to the BigDigits - let x: u32 = 0b00000000101111011111011011011101; - let mut f = x as f32; - let mut b = BigInt::from(x); - for _ in 0..64 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 - let mut n: i64 = 0b0000000000111111111111111111111111011111111111111111111111111111; - assert!((n as f64) as f32 != n as f32); - assert_eq!(BigInt::from(n).to_f32(), Some(n as f32)); - n = -n; - assert!((n as f64) as f32 != n as f32); - assert_eq!(BigInt::from(n).to_f32(), Some(n as f32)); - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 25) - 1) as f32; - let mut b = BigInt::from(1u64 << 25); - for _ in 0..64 { - assert_eq!(b.to_f32(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!( - BigInt::from_f32(-f32::consts::PI), - Some(BigInt::from(-3i32)) - ); - assert_eq!(BigInt::from_f32(-f32::consts::E), Some(BigInt::from(-2i32))); - assert_eq!(BigInt::from_f32(-0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(-0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(-0.0), Some(BigInt::zero())); - assert_eq!( - BigInt::from_f32(f32::MIN_POSITIVE / 2.0), - Some(BigInt::zero()) - ); - assert_eq!(BigInt::from_f32(f32::MIN_POSITIVE), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(f32::consts::E), Some(BigInt::from(2u32))); - assert_eq!(BigInt::from_f32(f32::consts::PI), Some(BigInt::from(3u32))); - - // special float values - assert_eq!(BigInt::from_f32(f32::NAN), None); - assert_eq!(BigInt::from_f32(f32::INFINITY), None); - assert_eq!(BigInt::from_f32(f32::NEG_INFINITY), None); - - // largest BigInt that will round to a finite f32 value - let big_num = (BigInt::one() << 128) - BigInt::one() - (BigInt::one() << (128 - 25)); - assert_eq!(big_num.to_f32(), Some(f32::MAX)); - assert_eq!((&big_num + BigInt::one()).to_f32(), None); - assert_eq!((-&big_num).to_f32(), Some(f32::MIN)); - assert_eq!(((-&big_num) - BigInt::one()).to_f32(), None); - - assert_eq!(((BigInt::one() << 128) - BigInt::one()).to_f32(), None); - assert_eq!((BigInt::one() << 128).to_f32(), None); - assert_eq!((-((BigInt::one() << 128) - BigInt::one())).to_f32(), None); - assert_eq!((-(BigInt::one() << 128)).to_f32(), None); -} - -#[test] -fn test_convert_f64() { - fn check(b1: &BigInt, f: f64) { - let b2 = BigInt::from_f64(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f64().unwrap(), f); - let neg_b1 = -b1; - let neg_b2 = BigInt::from_f64(-f).unwrap(); - assert_eq!(neg_b1, neg_b2); - assert_eq!(neg_b1.to_f64().unwrap(), -f); - } - - check(&BigInt::zero(), 0.0); - check(&BigInt::one(), 1.0); - check(&BigInt::from(u32::MAX), 2.0.powi(32) - 1.0); - check(&BigInt::from(1u64 << 32), 2.0.powi(32)); - check(&BigInt::from_slice(Plus, &[0, 0, 1]), 2.0.powi(64)); - check( - &((BigInt::one() << 100) + (BigInt::one() << 152)), - 2.0.powi(100) + 2.0.powi(152), - ); - check(&(BigInt::one() << 1023), 2.0.powi(1023)); - check(&(BigInt::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); - - // keeping all 53 digits with the bits at different offsets to the BigDigits - let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; - let mut f = x as f64; - let mut b = BigInt::from(x); - for _ in 0..128 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 54) - 1) as f64; - let mut b = BigInt::from(1u64 << 54); - for _ in 0..128 { - assert_eq!(b.to_f64(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!( - BigInt::from_f64(-f64::consts::PI), - Some(BigInt::from(-3i32)) - ); - assert_eq!(BigInt::from_f64(-f64::consts::E), Some(BigInt::from(-2i32))); - assert_eq!(BigInt::from_f64(-0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(-0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(-0.0), Some(BigInt::zero())); - assert_eq!( - BigInt::from_f64(f64::MIN_POSITIVE / 2.0), - Some(BigInt::zero()) - ); - assert_eq!(BigInt::from_f64(f64::MIN_POSITIVE), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(f64::consts::E), Some(BigInt::from(2u32))); - assert_eq!(BigInt::from_f64(f64::consts::PI), Some(BigInt::from(3u32))); - - // special float values - assert_eq!(BigInt::from_f64(f64::NAN), None); - assert_eq!(BigInt::from_f64(f64::INFINITY), None); - assert_eq!(BigInt::from_f64(f64::NEG_INFINITY), None); - - // largest BigInt that will round to a finite f64 value - let big_num = (BigInt::one() << 1024) - BigInt::one() - (BigInt::one() << (1024 - 54)); - assert_eq!(big_num.to_f64(), Some(f64::MAX)); - assert_eq!((&big_num + BigInt::one()).to_f64(), None); - assert_eq!((-&big_num).to_f64(), Some(f64::MIN)); - assert_eq!(((-&big_num) - BigInt::one()).to_f64(), None); - - assert_eq!(((BigInt::one() << 1024) - BigInt::one()).to_f64(), None); - assert_eq!((BigInt::one() << 1024).to_f64(), None); - assert_eq!((-((BigInt::one() << 1024) - BigInt::one())).to_f64(), None); - assert_eq!((-(BigInt::one() << 1024)).to_f64(), None); -} - -#[test] -fn test_convert_to_biguint() { - fn check(n: BigInt, ans_1: BigUint) { - assert_eq!(n.to_biguint().unwrap(), ans_1); - assert_eq!(n.to_biguint().unwrap().to_bigint().unwrap(), n); - } - let zero: BigInt = Zero::zero(); - let unsigned_zero: BigUint = Zero::zero(); - let positive = BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3])); - let negative = -&positive; - - check(zero, unsigned_zero); - check(positive, BigUint::new(vec![1, 2, 3])); - - assert_eq!(negative.to_biguint(), None); -} - -#[test] -fn test_convert_from_uint() { - macro_rules! check { - ($ty:ident, $max:expr) => { - assert_eq!(BigInt::from($ty::zero()), BigInt::zero()); - assert_eq!(BigInt::from($ty::one()), BigInt::one()); - assert_eq!(BigInt::from($ty::MAX - $ty::one()), $max - BigInt::one()); - assert_eq!(BigInt::from($ty::MAX), $max); - }; - } - - check!(u8, BigInt::from_slice(Plus, &[u8::MAX as u32])); - check!(u16, BigInt::from_slice(Plus, &[u16::MAX as u32])); - check!(u32, BigInt::from_slice(Plus, &[u32::MAX])); - check!(u64, BigInt::from_slice(Plus, &[u32::MAX, u32::MAX])); - #[cfg(has_i128)] - check!( - u128, - BigInt::from_slice(Plus, &[u32::MAX, u32::MAX, u32::MAX, u32::MAX]) - ); - check!(usize, BigInt::from(usize::MAX as u64)); -} - -#[test] -fn test_convert_from_int() { - macro_rules! check { - ($ty:ident, $min:expr, $max:expr) => { - assert_eq!(BigInt::from($ty::MIN), $min); - assert_eq!(BigInt::from($ty::MIN + $ty::one()), $min + BigInt::one()); - assert_eq!(BigInt::from(-$ty::one()), -BigInt::one()); - assert_eq!(BigInt::from($ty::zero()), BigInt::zero()); - assert_eq!(BigInt::from($ty::one()), BigInt::one()); - assert_eq!(BigInt::from($ty::MAX - $ty::one()), $max - BigInt::one()); - assert_eq!(BigInt::from($ty::MAX), $max); - }; - } - - check!( - i8, - BigInt::from_slice(Minus, &[1 << 7]), - BigInt::from_slice(Plus, &[i8::MAX as u32]) - ); - check!( - i16, - BigInt::from_slice(Minus, &[1 << 15]), - BigInt::from_slice(Plus, &[i16::MAX as u32]) - ); - check!( - i32, - BigInt::from_slice(Minus, &[1 << 31]), - BigInt::from_slice(Plus, &[i32::MAX as u32]) - ); - check!( - i64, - BigInt::from_slice(Minus, &[0, 1 << 31]), - BigInt::from_slice(Plus, &[u32::MAX, i32::MAX as u32]) - ); - #[cfg(has_i128)] - check!( - i128, - BigInt::from_slice(Minus, &[0, 0, 0, 1 << 31]), - BigInt::from_slice(Plus, &[u32::MAX, u32::MAX, u32::MAX, i32::MAX as u32]) - ); - check!( - isize, - BigInt::from(isize::MIN as i64), - BigInt::from(isize::MAX as i64) - ); -} - -#[test] -fn test_convert_from_biguint() { - assert_eq!(BigInt::from(BigUint::zero()), BigInt::zero()); - assert_eq!(BigInt::from(BigUint::one()), BigInt::one()); - assert_eq!( - BigInt::from(BigUint::from_slice(&[1, 2, 3])), - BigInt::from_slice(Plus, &[1, 2, 3]) - ); -} - -#[test] -fn test_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_op!(a + b == c); - assert_op!(b + a == c); - assert_op!(c + na == b); - assert_op!(c + nb == a); - assert_op!(a + nc == nb); - assert_op!(b + nc == na); - assert_op!(na + nb == nc); - assert_op!(a + na == Zero::zero()); - - assert_assign_op!(a += b == c); - assert_assign_op!(b += a == c); - assert_assign_op!(c += na == b); - assert_assign_op!(c += nb == a); - assert_assign_op!(a += nc == nb); - assert_assign_op!(b += nc == na); - assert_assign_op!(na += nb == nc); - assert_assign_op!(a += na == Zero::zero()); - } -} - -#[test] -fn test_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_op!(c - a == b); - assert_op!(c - b == a); - assert_op!(nb - a == nc); - assert_op!(na - b == nc); - assert_op!(b - na == c); - assert_op!(a - nb == c); - assert_op!(nc - na == nb); - assert_op!(a - a == Zero::zero()); - - assert_assign_op!(c -= a == b); - assert_assign_op!(c -= b == a); - assert_assign_op!(nb -= a == nc); - assert_assign_op!(na -= b == nc); - assert_assign_op!(b -= na == c); - assert_assign_op!(a -= nb == c); - assert_assign_op!(nc -= na == nb); - assert_assign_op!(a -= a == Zero::zero()); - } -} - -#[test] -fn test_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_op!(a * b == c); - assert_op!(b * a == c); - assert_op!(na * nb == c); - - assert_op!(na * b == nc); - assert_op!(nb * a == nc); - - assert_assign_op!(a *= b == c); - assert_assign_op!(b *= a == c); - assert_assign_op!(na *= nb == c); - - assert_assign_op!(na *= b == nc); - assert_assign_op!(nb *= a == nc); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - assert!(a == &b * &c + &d); - assert!(a == &c * &b + &d); - } -} - -#[test] -fn test_div_mod_floor() { - fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { - let (d, m) = a.div_mod_floor(b); - if !m.is_zero() { - assert_eq!(m.sign(), b.sign()); - } - assert!(m.abs() <= b.abs()); - assert!(*a == b * &d + &m); - assert!(d == *ans_d); - assert!(m == *ans_m); - } - - fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) { - if m.is_zero() { - check_sub(a, b, d, m); - check_sub(a, &b.neg(), &d.neg(), m); - check_sub(&a.neg(), b, &d.neg(), m); - check_sub(&a.neg(), &b.neg(), d, m); - } else { - let one: BigInt = One::one(); - check_sub(a, b, d, m); - check_sub(a, &b.neg(), &(d.neg() - &one), &(m - b)); - check_sub(&a.neg(), b, &(d.neg() - &one), &(b - m)); - check_sub(&a.neg(), &b.neg(), d, &m.neg()); - } - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if !a.is_zero() { - check(&c, &a, &b, &Zero::zero()); - } - if !b.is_zero() { - check(&c, &b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - if !b.is_zero() { - check(&a, &b, &c, &d); - } - } -} - -#[test] -fn test_div_rem() { - fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) { - let (q, r) = a.div_rem(b); - if !r.is_zero() { - assert_eq!(r.sign(), a.sign()); - } - assert!(r.abs() <= b.abs()); - assert!(*a == b * &q + &r); - assert!(q == *ans_q); - assert!(r == *ans_r); - - let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone()); - assert_op!(a / b == ans_q); - assert_op!(a % b == ans_r); - assert_assign_op!(a /= b == ans_q); - assert_assign_op!(a %= b == ans_r); - } - - fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) { - check_sub(a, b, q, r); - check_sub(a, &b.neg(), &q.neg(), r); - check_sub(&a.neg(), b, &q.neg(), &r.neg()); - check_sub(&a.neg(), &b.neg(), q, &r.neg()); - } - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if !a.is_zero() { - check(&c, &a, &b, &Zero::zero()); - } - if !b.is_zero() { - check(&c, &b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - if !b.is_zero() { - check(&a, &b, &c, &d); - } - } -} - -#[test] -fn test_checked_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - assert!(a.checked_add(&b).unwrap() == c); - assert!(b.checked_add(&a).unwrap() == c); - assert!(c.checked_add(&(-&a)).unwrap() == b); - assert!(c.checked_add(&(-&b)).unwrap() == a); - assert!(a.checked_add(&(-&c)).unwrap() == (-&b)); - assert!(b.checked_add(&(-&c)).unwrap() == (-&a)); - assert!((-&a).checked_add(&(-&b)).unwrap() == (-&c)); - assert!(a.checked_add(&(-&a)).unwrap() == Zero::zero()); - } -} - -#[test] -fn test_checked_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - assert!(c.checked_sub(&a).unwrap() == b); - assert!(c.checked_sub(&b).unwrap() == a); - assert!((-&b).checked_sub(&a).unwrap() == (-&c)); - assert!((-&a).checked_sub(&b).unwrap() == (-&c)); - assert!(b.checked_sub(&(-&a)).unwrap() == c); - assert!(a.checked_sub(&(-&b)).unwrap() == c); - assert!((-&c).checked_sub(&(-&a)).unwrap() == (-&b)); - assert!(a.checked_sub(&a).unwrap() == Zero::zero()); - } -} - -#[test] -fn test_checked_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - assert!(a.checked_mul(&b).unwrap() == c); - assert!(b.checked_mul(&a).unwrap() == c); - - assert!((-&a).checked_mul(&b).unwrap() == -&c); - assert!((-&b).checked_mul(&a).unwrap() == -&c); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - assert!(a == b.checked_mul(&c).unwrap() + &d); - assert!(a == c.checked_mul(&b).unwrap() + &d); - } -} -#[test] -fn test_checked_div() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if !a.is_zero() { - assert!(c.checked_div(&a).unwrap() == b); - assert!((-&c).checked_div(&(-&a)).unwrap() == b); - assert!((-&c).checked_div(&a).unwrap() == -&b); - } - if !b.is_zero() { - assert!(c.checked_div(&b).unwrap() == a); - assert!((-&c).checked_div(&(-&b)).unwrap() == a); - assert!((-&c).checked_div(&b).unwrap() == -&a); - } - - assert!(c.checked_div(&Zero::zero()).is_none()); - assert!((-&c).checked_div(&Zero::zero()).is_none()); - } -} - -#[test] -fn test_gcd() { - fn check(a: isize, b: isize, c: isize) { - let big_a: BigInt = FromPrimitive::from_isize(a).unwrap(); - let big_b: BigInt = FromPrimitive::from_isize(b).unwrap(); - let big_c: BigInt = FromPrimitive::from_isize(c).unwrap(); - - assert_eq!(big_a.gcd(&big_b), big_c); - } - - check(10, 2, 2); - check(10, 3, 1); - check(0, 3, 3); - check(3, 3, 3); - check(56, 42, 14); - check(3, -3, 3); - check(-6, 3, 3); - check(-4, -2, 2); -} - -#[test] -fn test_lcm() { - fn check(a: isize, b: isize, c: isize) { - let big_a: BigInt = FromPrimitive::from_isize(a).unwrap(); - let big_b: BigInt = FromPrimitive::from_isize(b).unwrap(); - let big_c: BigInt = FromPrimitive::from_isize(c).unwrap(); - - assert_eq!(big_a.lcm(&big_b), big_c); - } - - check(0, 0, 0); - check(1, 0, 0); - check(0, 1, 0); - check(1, 1, 1); - check(-1, 1, 1); - check(1, -1, 1); - check(-1, -1, 1); - check(8, 9, 72); - check(11, 5, 55); -} - -#[test] -fn test_abs_sub() { - let zero: BigInt = Zero::zero(); - let one: BigInt = One::one(); - assert_eq!((-&one).abs_sub(&one), zero); - let one: BigInt = One::one(); - let zero: BigInt = Zero::zero(); - assert_eq!(one.abs_sub(&one), zero); - let one: BigInt = One::one(); - let zero: BigInt = Zero::zero(); - assert_eq!(one.abs_sub(&zero), one); - let one: BigInt = One::one(); - let two: BigInt = FromPrimitive::from_isize(2).unwrap(); - assert_eq!(one.abs_sub(&-&one), two); -} - -#[test] -fn test_from_str_radix() { - fn check(s: &str, ans: Option) { - let ans = ans.map(|n| { - let x: BigInt = FromPrimitive::from_isize(n).unwrap(); - x - }); - assert_eq!(BigInt::from_str_radix(s, 10).ok(), ans); - } - check("10", Some(10)); - check("1", Some(1)); - check("0", Some(0)); - check("-1", Some(-1)); - check("-10", Some(-10)); - check("+10", Some(10)); - check("--7", None); - check("++5", None); - check("+-9", None); - check("-+3", None); - check("Z", None); - check("_", None); - - // issue 10522, this hit an edge case that caused it to - // attempt to allocate a vector of size (-1u) == huge. - let x: BigInt = format!("1{}", repeat("0").take(36).collect::()) - .parse() - .unwrap(); - let _y = x.to_string(); -} - -#[test] -fn test_lower_hex() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:x}", a), "a"); - assert_eq!(format!("{:x}", hello), "-48656c6c6f20776f726c6421"); - assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); -} - -#[test] -fn test_upper_hex() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:X}", a), "A"); - assert_eq!(format!("{:X}", hello), "-48656C6C6F20776F726C6421"); - assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); -} - -#[test] -fn test_binary() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-224055342307539".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:b}", a), "1010"); - assert_eq!( - format!("{:b}", hello), - "-110010111100011011110011000101101001100011010011" - ); - assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); -} - -#[test] -fn test_octal() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:o}", a), "12"); - assert_eq!(format!("{:o}", hello), "-22062554330674403566756233062041"); - assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); -} - -#[test] -fn test_display() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{}", a), "10"); - assert_eq!(format!("{}", hello), "-22405534230753963835153736737"); - assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); -} - -#[test] -fn test_neg() { - assert!(-BigInt::new(Plus, vec![1, 1, 1]) == BigInt::new(Minus, vec![1, 1, 1])); - assert!(-BigInt::new(Minus, vec![1, 1, 1]) == BigInt::new(Plus, vec![1, 1, 1])); - let zero: BigInt = Zero::zero(); - assert_eq!(-&zero, zero); -} - -#[test] -fn test_negative_shr() { - assert_eq!(BigInt::from(-1) >> 1, BigInt::from(-1)); - assert_eq!(BigInt::from(-2) >> 1, BigInt::from(-1)); - assert_eq!(BigInt::from(-3) >> 1, BigInt::from(-2)); - assert_eq!(BigInt::from(-3) >> 2, BigInt::from(-1)); -} - -#[test] -#[cfg(feature = "rand")] -fn test_random_shr() { - use rand::distributions::Standard; - use rand::Rng; - let mut rng = rand::thread_rng(); - - for p in rng.sample_iter::(&Standard).take(1000) { - let big = BigInt::from(p); - let bigger = &big << 1000; - assert_eq!(&bigger >> 1000, big); - for i in 0..64 { - let answer = BigInt::from(p >> i); - assert_eq!(&big >> i, answer); - assert_eq!(&bigger >> (1000 + i), answer); - } - } -} - -#[test] -fn test_iter_sum() { - let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); - let data: Vec = vec![ - FromPrimitive::from_i32(-1000000).unwrap(), - FromPrimitive::from_i32(-200000).unwrap(), - FromPrimitive::from_i32(-30000).unwrap(), - FromPrimitive::from_i32(-4000).unwrap(), - FromPrimitive::from_i32(-500).unwrap(), - FromPrimitive::from_i32(-60).unwrap(), - FromPrimitive::from_i32(-7).unwrap(), - ]; - - assert_eq!(result, data.iter().sum()); - assert_eq!(result, data.into_iter().sum()); -} - -#[test] -fn test_iter_product() { - let data: Vec = vec![ - FromPrimitive::from_i32(1001).unwrap(), - FromPrimitive::from_i32(-1002).unwrap(), - FromPrimitive::from_i32(1003).unwrap(), - FromPrimitive::from_i32(-1004).unwrap(), - FromPrimitive::from_i32(1005).unwrap(), - ]; - let result = data.get(0).unwrap() - * data.get(1).unwrap() - * data.get(2).unwrap() - * data.get(3).unwrap() - * data.get(4).unwrap(); - - assert_eq!(result, data.iter().product()); - assert_eq!(result, data.into_iter().product()); -} - -#[test] -fn test_iter_sum_generic() { - let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); - let data = vec![-1000000, -200000, -30000, -4000, -500, -60, -7]; - - assert_eq!(result, data.iter().sum()); - assert_eq!(result, data.into_iter().sum()); -} - -#[test] -fn test_iter_product_generic() { - let data = vec![1001, -1002, 1003, -1004, 1005]; - let result = data[0].to_bigint().unwrap() - * data[1].to_bigint().unwrap() - * data[2].to_bigint().unwrap() - * data[3].to_bigint().unwrap() - * data[4].to_bigint().unwrap(); - - assert_eq!(result, data.iter().product()); - assert_eq!(result, data.into_iter().product()); -} - -#[test] -fn test_pow() { - let one = BigInt::from(1i32); - let two = BigInt::from(2i32); - let four = BigInt::from(4i32); - let eight = BigInt::from(8i32); - let minus_two = BigInt::from(-2i32); - macro_rules! check { - ($t:ty) => { - assert_eq!(two.pow(0 as $t), one); - assert_eq!(two.pow(1 as $t), two); - assert_eq!(two.pow(2 as $t), four); - assert_eq!(two.pow(3 as $t), eight); - assert_eq!(two.pow(&(3 as $t)), eight); - assert_eq!(minus_two.pow(0 as $t), one, "-2^0"); - assert_eq!(minus_two.pow(1 as $t), minus_two, "-2^1"); - assert_eq!(minus_two.pow(2 as $t), four, "-2^2"); - assert_eq!(minus_two.pow(3 as $t), -&eight, "-2^3"); - }; - } - check!(u8); - check!(u16); - check!(u32); - check!(u64); - check!(usize); -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/bigint_bitwise.rs b/third_party/rust/num-bigint-0.2.3/tests/bigint_bitwise.rs deleted file mode 100644 index cc0c493cb5e0..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/bigint_bitwise.rs +++ /dev/null @@ -1,181 +0,0 @@ -extern crate num_bigint; -extern crate num_traits; - -use num_bigint::{BigInt, Sign, ToBigInt}; -use num_traits::ToPrimitive; -use std::{i32, i64, u32}; - -enum ValueVec { - N, - P(&'static [u32]), - M(&'static [u32]), -} - -use ValueVec::*; - -impl ToBigInt for ValueVec { - fn to_bigint(&self) -> Option { - match self { - &N => Some(BigInt::from_slice(Sign::NoSign, &[])), - &P(s) => Some(BigInt::from_slice(Sign::Plus, s)), - &M(s) => Some(BigInt::from_slice(Sign::Minus, s)), - } - } -} - -// a, !a -const NOT_VALUES: &'static [(ValueVec, ValueVec)] = &[ - (N, M(&[1])), - (P(&[1]), M(&[2])), - (P(&[2]), M(&[3])), - (P(&[!0 - 2]), M(&[!0 - 1])), - (P(&[!0 - 1]), M(&[!0])), - (P(&[!0]), M(&[0, 1])), - (P(&[0, 1]), M(&[1, 1])), - (P(&[1, 1]), M(&[2, 1])), -]; - -// a, b, a & b, a | b, a ^ b -const BITWISE_VALUES: &'static [(ValueVec, ValueVec, ValueVec, ValueVec, ValueVec)] = &[ - (N, N, N, N, N), - (N, P(&[1]), N, P(&[1]), P(&[1])), - (N, P(&[!0]), N, P(&[!0]), P(&[!0])), - (N, P(&[0, 1]), N, P(&[0, 1]), P(&[0, 1])), - (N, M(&[1]), N, M(&[1]), M(&[1])), - (N, M(&[!0]), N, M(&[!0]), M(&[!0])), - (N, M(&[0, 1]), N, M(&[0, 1]), M(&[0, 1])), - (P(&[1]), P(&[!0]), P(&[1]), P(&[!0]), P(&[!0 - 1])), - (P(&[!0]), P(&[!0]), P(&[!0]), P(&[!0]), N), - (P(&[!0]), P(&[1, 1]), P(&[1]), P(&[!0, 1]), P(&[!0 - 1, 1])), - (P(&[1]), M(&[!0]), P(&[1]), M(&[!0]), M(&[0, 1])), - (P(&[!0]), M(&[1]), P(&[!0]), M(&[1]), M(&[0, 1])), - (P(&[!0]), M(&[!0]), P(&[1]), M(&[1]), M(&[2])), - (P(&[!0]), M(&[1, 1]), P(&[!0]), M(&[1, 1]), M(&[0, 2])), - (P(&[1, 1]), M(&[!0]), P(&[1, 1]), M(&[!0]), M(&[0, 2])), - (M(&[1]), M(&[!0]), M(&[!0]), M(&[1]), P(&[!0 - 1])), - (M(&[!0]), M(&[!0]), M(&[!0]), M(&[!0]), N), - (M(&[!0]), M(&[1, 1]), M(&[!0, 1]), M(&[1]), P(&[!0 - 1, 1])), -]; - -const I32_MIN: i64 = i32::MIN as i64; -const I32_MAX: i64 = i32::MAX as i64; -const U32_MAX: i64 = u32::MAX as i64; - -// some corner cases -const I64_VALUES: &'static [i64] = &[ - i64::MIN, - i64::MIN + 1, - i64::MIN + 2, - i64::MIN + 3, - -U32_MAX - 3, - -U32_MAX - 2, - -U32_MAX - 1, - -U32_MAX, - -U32_MAX + 1, - -U32_MAX + 2, - -U32_MAX + 3, - I32_MIN - 3, - I32_MIN - 2, - I32_MIN - 1, - I32_MIN, - I32_MIN + 1, - I32_MIN + 2, - I32_MIN + 3, - -3, - -2, - -1, - 0, - 1, - 2, - 3, - I32_MAX - 3, - I32_MAX - 2, - I32_MAX - 1, - I32_MAX, - I32_MAX + 1, - I32_MAX + 2, - I32_MAX + 3, - U32_MAX - 3, - U32_MAX - 2, - U32_MAX - 1, - U32_MAX, - U32_MAX + 1, - U32_MAX + 2, - U32_MAX + 3, - i64::MAX - 3, - i64::MAX - 2, - i64::MAX - 1, - i64::MAX, -]; - -#[test] -fn test_not() { - for &(ref a, ref not) in NOT_VALUES.iter() { - let a = a.to_bigint().unwrap(); - let not = not.to_bigint().unwrap(); - - // sanity check for tests that fit in i64 - if let (Some(prim_a), Some(prim_not)) = (a.to_i64(), not.to_i64()) { - assert_eq!(!prim_a, prim_not); - } - - assert_eq!(!a.clone(), not, "!{:x}", a); - assert_eq!(!not.clone(), a, "!{:x}", not); - } -} - -#[test] -fn test_not_i64() { - for &prim_a in I64_VALUES.iter() { - let a = prim_a.to_bigint().unwrap(); - let not = (!prim_a).to_bigint().unwrap(); - assert_eq!(!a.clone(), not, "!{:x}", a); - } -} - -#[test] -fn test_bitwise() { - for &(ref a, ref b, ref and, ref or, ref xor) in BITWISE_VALUES.iter() { - let a = a.to_bigint().unwrap(); - let b = b.to_bigint().unwrap(); - let and = and.to_bigint().unwrap(); - let or = or.to_bigint().unwrap(); - let xor = xor.to_bigint().unwrap(); - - // sanity check for tests that fit in i64 - if let (Some(prim_a), Some(prim_b)) = (a.to_i64(), b.to_i64()) { - if let Some(prim_and) = and.to_i64() { - assert_eq!(prim_a & prim_b, prim_and); - } - if let Some(prim_or) = or.to_i64() { - assert_eq!(prim_a | prim_b, prim_or); - } - if let Some(prim_xor) = xor.to_i64() { - assert_eq!(prim_a ^ prim_b, prim_xor); - } - } - - assert_eq!(a.clone() & &b, and, "{:x} & {:x}", a, b); - assert_eq!(b.clone() & &a, and, "{:x} & {:x}", b, a); - assert_eq!(a.clone() | &b, or, "{:x} | {:x}", a, b); - assert_eq!(b.clone() | &a, or, "{:x} | {:x}", b, a); - assert_eq!(a.clone() ^ &b, xor, "{:x} ^ {:x}", a, b); - assert_eq!(b.clone() ^ &a, xor, "{:x} ^ {:x}", b, a); - } -} - -#[test] -fn test_bitwise_i64() { - for &prim_a in I64_VALUES.iter() { - let a = prim_a.to_bigint().unwrap(); - for &prim_b in I64_VALUES.iter() { - let b = prim_b.to_bigint().unwrap(); - let and = (prim_a & prim_b).to_bigint().unwrap(); - let or = (prim_a | prim_b).to_bigint().unwrap(); - let xor = (prim_a ^ prim_b).to_bigint().unwrap(); - assert_eq!(a.clone() & &b, and, "{:x} & {:x}", a, b); - assert_eq!(a.clone() | &b, or, "{:x} | {:x}", a, b); - assert_eq!(a.clone() ^ &b, xor, "{:x} ^ {:x}", a, b); - } - } -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/bigint_scalar.rs b/third_party/rust/num-bigint-0.2.3/tests/bigint_scalar.rs deleted file mode 100644 index ae9a6d7aa22f..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/bigint_scalar.rs +++ /dev/null @@ -1,145 +0,0 @@ -extern crate num_bigint; -extern crate num_traits; - -use num_bigint::BigInt; -use num_bigint::Sign::Plus; -use num_traits::{Signed, ToPrimitive, Zero}; - -use std::ops::Neg; - -mod consts; -use consts::*; - -#[macro_use] -mod macros; - -#[test] -fn test_scalar_add() { - fn check(x: &BigInt, y: &BigInt, z: &BigInt) { - let (x, y, z) = (x.clone(), y.clone(), z.clone()); - assert_signed_scalar_op!(x + y == z); - } - - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - check(&a, &b, &c); - check(&b, &a, &c); - check(&c, &na, &b); - check(&c, &nb, &a); - check(&a, &nc, &nb); - check(&b, &nc, &na); - check(&na, &nb, &nc); - check(&a, &na, &Zero::zero()); - } -} - -#[test] -fn test_scalar_sub() { - fn check(x: &BigInt, y: &BigInt, z: &BigInt) { - let (x, y, z) = (x.clone(), y.clone(), z.clone()); - assert_signed_scalar_op!(x - y == z); - } - - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - check(&c, &a, &b); - check(&c, &b, &a); - check(&nb, &a, &nc); - check(&na, &b, &nc); - check(&b, &na, &c); - check(&a, &nb, &c); - check(&nc, &na, &nb); - check(&a, &a, &Zero::zero()); - } -} - -#[test] -fn test_scalar_mul() { - fn check(x: &BigInt, y: &BigInt, z: &BigInt) { - let (x, y, z) = (x.clone(), y.clone(), z.clone()); - assert_signed_scalar_op!(x * y == z); - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - check(&a, &b, &c); - check(&b, &a, &c); - check(&na, &nb, &c); - - check(&na, &b, &nc); - check(&nb, &a, &nc); - } -} - -#[test] -fn test_scalar_div_rem() { - fn check_sub(a: &BigInt, b: u32, ans_q: &BigInt, ans_r: &BigInt) { - let (q, r) = (a / b, a % b); - if !r.is_zero() { - assert_eq!(r.sign(), a.sign()); - } - assert!(r.abs() <= From::from(b)); - assert!(*a == b * &q + &r); - assert!(q == *ans_q); - assert!(r == *ans_r); - - let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone()); - assert_op!(a / b == ans_q); - assert_op!(a % b == ans_r); - - if b <= i32::max_value() as u32 { - let nb = -(b as i32); - assert_op!(a / nb == -ans_q.clone()); - assert_op!(a % nb == ans_r); - } - } - - fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) { - check_sub(a, b, q, r); - check_sub(&a.neg(), b, &q.neg(), &r.neg()); - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if a_vec.len() == 1 && a_vec[0] != 0 { - let a = a_vec[0]; - check(&c, a, &b, &Zero::zero()); - } - - if b_vec.len() == 1 && b_vec[0] != 0 { - let b = b_vec[0]; - check(&c, b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - if b_vec.len() == 1 && b_vec[0] != 0 { - let b = b_vec[0]; - check(&a, b, &c, &d); - } - } -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/biguint.rs b/third_party/rust/num-bigint-0.2.3/tests/biguint.rs deleted file mode 100644 index 1e23aa17f9e4..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/biguint.rs +++ /dev/null @@ -1,1713 +0,0 @@ -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; - -use num_bigint::Sign::Plus; -use num_bigint::{BigInt, ToBigInt}; -use num_bigint::{BigUint, ToBigUint}; -use num_integer::Integer; - -use std::cmp::Ordering::{Equal, Greater, Less}; -use std::collections::hash_map::RandomState; -use std::hash::{BuildHasher, Hash, Hasher}; -use std::i64; -use std::iter::repeat; -use std::str::FromStr; -use std::{f32, f64}; -#[cfg(has_i128)] -use std::{i128, u128}; -use std::{u16, u32, u64, u8, usize}; - -use num_traits::{ - CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Float, FromPrimitive, Num, One, Pow, - ToPrimitive, Zero, -}; - -mod consts; -use consts::*; - -#[macro_use] -mod macros; - -#[test] -fn test_from_bytes_be() { - fn check(s: &str, result: &str) { - assert_eq!( - BigUint::from_bytes_be(s.as_bytes()), - BigUint::parse_bytes(result.as_bytes(), 10).unwrap() - ); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - assert_eq!(BigUint::from_bytes_be(&[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_be() { - fn check(s: &str, result: &str) { - let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); - assert_eq!(b.to_bytes_be(), s.as_bytes()); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - let b: BigUint = Zero::zero(); - assert_eq!(b.to_bytes_be(), [0]); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_be(), [1, 0, 0, 0, 0, 0, 0, 2, 0]); -} - -#[test] -fn test_from_bytes_le() { - fn check(s: &str, result: &str) { - assert_eq!( - BigUint::from_bytes_le(s.as_bytes()), - BigUint::parse_bytes(result.as_bytes(), 10).unwrap() - ); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - assert_eq!(BigUint::from_bytes_le(&[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_le() { - fn check(s: &str, result: &str) { - let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); - assert_eq!(b.to_bytes_le(), s.as_bytes()); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - let b: BigUint = Zero::zero(); - assert_eq!(b.to_bytes_le(), [0]); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_le(), [0, 2, 0, 0, 0, 0, 0, 0, 1]); -} - -#[test] -fn test_cmp() { - let data: [&[_]; 7] = [&[], &[1], &[2], &[!0], &[0, 1], &[2, 1], &[1, 1, 1]]; - let data: Vec = data.iter().map(|v| BigUint::from_slice(*v)).collect(); - for (i, ni) in data.iter().enumerate() { - for (j0, nj) in data[i..].iter().enumerate() { - let j = j0 + i; - if i == j { - assert_eq!(ni.cmp(nj), Equal); - assert_eq!(nj.cmp(ni), Equal); - assert_eq!(ni, nj); - assert!(!(ni != nj)); - assert!(ni <= nj); - assert!(ni >= nj); - assert!(!(ni < nj)); - assert!(!(ni > nj)); - } else { - assert_eq!(ni.cmp(nj), Less); - assert_eq!(nj.cmp(ni), Greater); - - assert!(!(ni == nj)); - assert!(ni != nj); - - assert!(ni <= nj); - assert!(!(ni >= nj)); - assert!(ni < nj); - assert!(!(ni > nj)); - - assert!(!(nj <= ni)); - assert!(nj >= ni); - assert!(!(nj < ni)); - assert!(nj > ni); - } - } - } -} - -fn hash(x: &T) -> u64 { - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[test] -fn test_hash() { - use hash; - - let a = BigUint::new(vec![]); - let b = BigUint::new(vec![0]); - let c = BigUint::new(vec![1]); - let d = BigUint::new(vec![1, 0, 0, 0, 0, 0]); - let e = BigUint::new(vec![0, 0, 0, 0, 0, 1]); - assert!(hash(&a) == hash(&b)); - assert!(hash(&b) != hash(&c)); - assert!(hash(&c) == hash(&d)); - assert!(hash(&d) != hash(&e)); -} - -// LEFT, RIGHT, AND, OR, XOR -const BIT_TESTS: &'static [( - &'static [u32], - &'static [u32], - &'static [u32], - &'static [u32], - &'static [u32], -)] = &[ - (&[], &[], &[], &[], &[]), - (&[1, 0, 1], &[1, 1], &[1], &[1, 1, 1], &[0, 1, 1]), - (&[1, 0, 1], &[0, 1, 1], &[0, 0, 1], &[1, 1, 1], &[1, 1]), - ( - &[268, 482, 17], - &[964, 54], - &[260, 34], - &[972, 502, 17], - &[712, 468, 17], - ), -]; - -#[test] -fn test_bitand() { - for elm in BIT_TESTS { - let (a_vec, b_vec, c_vec, _, _) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a & b == c); - assert_op!(b & a == c); - assert_assign_op!(a &= b == c); - assert_assign_op!(b &= a == c); - } -} - -#[test] -fn test_bitor() { - for elm in BIT_TESTS { - let (a_vec, b_vec, _, c_vec, _) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a | b == c); - assert_op!(b | a == c); - assert_assign_op!(a |= b == c); - assert_assign_op!(b |= a == c); - } -} - -#[test] -fn test_bitxor() { - for elm in BIT_TESTS { - let (a_vec, b_vec, _, _, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a ^ b == c); - assert_op!(b ^ a == c); - assert_op!(a ^ c == b); - assert_op!(c ^ a == b); - assert_op!(b ^ c == a); - assert_op!(c ^ b == a); - assert_assign_op!(a ^= b == c); - assert_assign_op!(b ^= a == c); - assert_assign_op!(a ^= c == b); - assert_assign_op!(c ^= a == b); - assert_assign_op!(b ^= c == a); - assert_assign_op!(c ^= b == a); - } -} - -#[test] -fn test_shl() { - fn check(s: &str, shift: usize, ans: &str) { - let opt_biguint = BigUint::from_str_radix(s, 16).ok(); - let mut bu_assign = opt_biguint.unwrap(); - let bu = (bu_assign.clone() << shift).to_str_radix(16); - assert_eq!(bu, ans); - bu_assign <<= shift; - assert_eq!(bu_assign.to_str_radix(16), ans); - } - - check("0", 3, "0"); - check("1", 3, "8"); - - check( - "1\ - 0000\ - 0000\ - 0000\ - 0001\ - 0000\ - 0000\ - 0000\ - 0001", - 3, - "8\ - 0000\ - 0000\ - 0000\ - 0008\ - 0000\ - 0000\ - 0000\ - 0008", - ); - check( - "1\ - 0000\ - 0001\ - 0000\ - 0001", - 2, - "4\ - 0000\ - 0004\ - 0000\ - 0004", - ); - check( - "1\ - 0001\ - 0001", - 1, - "2\ - 0002\ - 0002", - ); - - check( - "\ - 4000\ - 0000\ - 0000\ - 0000", - 3, - "2\ - 0000\ - 0000\ - 0000\ - 0000", - ); - check( - "4000\ - 0000", - 2, - "1\ - 0000\ - 0000", - ); - check( - "4000", - 2, - "1\ - 0000", - ); - - check( - "4000\ - 0000\ - 0000\ - 0000", - 67, - "2\ - 0000\ - 0000\ - 0000\ - 0000\ - 0000\ - 0000\ - 0000\ - 0000", - ); - check( - "4000\ - 0000", - 35, - "2\ - 0000\ - 0000\ - 0000\ - 0000", - ); - check( - "4000", - 19, - "2\ - 0000\ - 0000", - ); - - check( - "fedc\ - ba98\ - 7654\ - 3210\ - fedc\ - ba98\ - 7654\ - 3210", - 4, - "f\ - edcb\ - a987\ - 6543\ - 210f\ - edcb\ - a987\ - 6543\ - 2100", - ); - check( - "88887777666655554444333322221111", - 16, - "888877776666555544443333222211110000", - ); -} - -#[test] -fn test_shr() { - fn check(s: &str, shift: usize, ans: &str) { - let opt_biguint = BigUint::from_str_radix(s, 16).ok(); - let mut bu_assign = opt_biguint.unwrap(); - let bu = (bu_assign.clone() >> shift).to_str_radix(16); - assert_eq!(bu, ans); - bu_assign >>= shift; - assert_eq!(bu_assign.to_str_radix(16), ans); - } - - check("0", 3, "0"); - check("f", 3, "1"); - - check( - "1\ - 0000\ - 0000\ - 0000\ - 0001\ - 0000\ - 0000\ - 0000\ - 0001", - 3, - "2000\ - 0000\ - 0000\ - 0000\ - 2000\ - 0000\ - 0000\ - 0000", - ); - check( - "1\ - 0000\ - 0001\ - 0000\ - 0001", - 2, - "4000\ - 0000\ - 4000\ - 0000", - ); - check( - "1\ - 0001\ - 0001", - 1, - "8000\ - 8000", - ); - - check( - "2\ - 0000\ - 0000\ - 0000\ - 0001\ - 0000\ - 0000\ - 0000\ - 0001", - 67, - "4000\ - 0000\ - 0000\ - 0000", - ); - check( - "2\ - 0000\ - 0001\ - 0000\ - 0001", - 35, - "4000\ - 0000", - ); - check( - "2\ - 0001\ - 0001", - 19, - "4000", - ); - - check( - "1\ - 0000\ - 0000\ - 0000\ - 0000", - 1, - "8000\ - 0000\ - 0000\ - 0000", - ); - check( - "1\ - 0000\ - 0000", - 1, - "8000\ - 0000", - ); - check( - "1\ - 0000", - 1, - "8000", - ); - check( - "f\ - edcb\ - a987\ - 6543\ - 210f\ - edcb\ - a987\ - 6543\ - 2100", - 4, - "fedc\ - ba98\ - 7654\ - 3210\ - fedc\ - ba98\ - 7654\ - 3210", - ); - - check( - "888877776666555544443333222211110000", - 16, - "88887777666655554444333322221111", - ); -} - -// `DoubleBigDigit` size dependent -#[test] -fn test_convert_i64() { - fn check(b1: BigUint, i: i64) { - let b2: BigUint = FromPrimitive::from_i64(i).unwrap(); - assert_eq!(b1, b2); - assert_eq!(b1.to_i64().unwrap(), i); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(i64::MAX.to_biguint().unwrap(), i64::MAX); - - check(BigUint::new(vec![]), 0); - check(BigUint::new(vec![1]), 1); - check(BigUint::new(vec![N1]), (1 << 32) - 1); - check(BigUint::new(vec![0, 1]), 1 << 32); - check(BigUint::new(vec![N1, N1 >> 1]), i64::MAX); - - assert_eq!(i64::MIN.to_biguint(), None); - assert_eq!(BigUint::new(vec![N1, N1]).to_i64(), None); - assert_eq!(BigUint::new(vec![0, 0, 1]).to_i64(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1]).to_i64(), None); -} - -#[test] -#[cfg(has_i128)] -fn test_convert_i128() { - fn check(b1: BigUint, i: i128) { - let b2: BigUint = FromPrimitive::from_i128(i).unwrap(); - assert_eq!(b1, b2); - assert_eq!(b1.to_i128().unwrap(), i); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(i128::MAX.to_biguint().unwrap(), i128::MAX); - - check(BigUint::new(vec![]), 0); - check(BigUint::new(vec![1]), 1); - check(BigUint::new(vec![N1]), (1 << 32) - 1); - check(BigUint::new(vec![0, 1]), 1 << 32); - check(BigUint::new(vec![N1, N1, N1, N1 >> 1]), i128::MAX); - - assert_eq!(i128::MIN.to_biguint(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1, N1]).to_i128(), None); - assert_eq!(BigUint::new(vec![0, 0, 0, 0, 1]).to_i128(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1, N1, N1]).to_i128(), None); -} - -// `DoubleBigDigit` size dependent -#[test] -fn test_convert_u64() { - fn check(b1: BigUint, u: u64) { - let b2: BigUint = FromPrimitive::from_u64(u).unwrap(); - assert_eq!(b1, b2); - assert_eq!(b1.to_u64().unwrap(), u); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(u64::MIN.to_biguint().unwrap(), u64::MIN); - check(u64::MAX.to_biguint().unwrap(), u64::MAX); - - check(BigUint::new(vec![]), 0); - check(BigUint::new(vec![1]), 1); - check(BigUint::new(vec![N1]), (1 << 32) - 1); - check(BigUint::new(vec![0, 1]), 1 << 32); - check(BigUint::new(vec![N1, N1]), u64::MAX); - - assert_eq!(BigUint::new(vec![0, 0, 1]).to_u64(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1]).to_u64(), None); -} - -#[test] -#[cfg(has_i128)] -fn test_convert_u128() { - fn check(b1: BigUint, u: u128) { - let b2: BigUint = FromPrimitive::from_u128(u).unwrap(); - assert_eq!(b1, b2); - assert_eq!(b1.to_u128().unwrap(), u); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(u128::MIN.to_biguint().unwrap(), u128::MIN); - check(u128::MAX.to_biguint().unwrap(), u128::MAX); - - check(BigUint::new(vec![]), 0); - check(BigUint::new(vec![1]), 1); - check(BigUint::new(vec![N1]), (1 << 32) - 1); - check(BigUint::new(vec![0, 1]), 1 << 32); - check(BigUint::new(vec![N1, N1, N1, N1]), u128::MAX); - - assert_eq!(BigUint::new(vec![0, 0, 0, 0, 1]).to_u128(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1, N1, N1]).to_u128(), None); -} - -#[test] -fn test_convert_f32() { - fn check(b1: &BigUint, f: f32) { - let b2 = BigUint::from_f32(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f32().unwrap(), f); - } - - check(&BigUint::zero(), 0.0); - check(&BigUint::one(), 1.0); - check(&BigUint::from(u16::MAX), 2.0.powi(16) - 1.0); - check(&BigUint::from(1u64 << 32), 2.0.powi(32)); - check(&BigUint::from_slice(&[0, 0, 1]), 2.0.powi(64)); - check( - &((BigUint::one() << 100) + (BigUint::one() << 123)), - 2.0.powi(100) + 2.0.powi(123), - ); - check(&(BigUint::one() << 127), 2.0.powi(127)); - check(&(BigUint::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); - - // keeping all 24 digits with the bits at different offsets to the BigDigits - let x: u32 = 0b00000000101111011111011011011101; - let mut f = x as f32; - let mut b = BigUint::from(x); - for _ in 0..64 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 - let n: u64 = 0b0000000000111111111111111111111111011111111111111111111111111111; - assert!((n as f64) as f32 != n as f32); - assert_eq!(BigUint::from(n).to_f32(), Some(n as f32)); - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 25) - 1) as f32; - let mut b = BigUint::from(1u64 << 25); - for _ in 0..64 { - assert_eq!(b.to_f32(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!(BigUint::from_f32(-1.0), None); - assert_eq!(BigUint::from_f32(-0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(-0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(-0.0), Some(BigUint::zero())); - assert_eq!( - BigUint::from_f32(f32::MIN_POSITIVE / 2.0), - Some(BigUint::zero()) - ); - assert_eq!(BigUint::from_f32(f32::MIN_POSITIVE), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(f32::consts::E), Some(BigUint::from(2u32))); - assert_eq!( - BigUint::from_f32(f32::consts::PI), - Some(BigUint::from(3u32)) - ); - - // special float values - assert_eq!(BigUint::from_f32(f32::NAN), None); - assert_eq!(BigUint::from_f32(f32::INFINITY), None); - assert_eq!(BigUint::from_f32(f32::NEG_INFINITY), None); - assert_eq!(BigUint::from_f32(f32::MIN), None); - - // largest BigUint that will round to a finite f32 value - let big_num = (BigUint::one() << 128) - BigUint::one() - (BigUint::one() << (128 - 25)); - assert_eq!(big_num.to_f32(), Some(f32::MAX)); - assert_eq!((big_num + BigUint::one()).to_f32(), None); - - assert_eq!(((BigUint::one() << 128) - BigUint::one()).to_f32(), None); - assert_eq!((BigUint::one() << 128).to_f32(), None); -} - -#[test] -fn test_convert_f64() { - fn check(b1: &BigUint, f: f64) { - let b2 = BigUint::from_f64(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f64().unwrap(), f); - } - - check(&BigUint::zero(), 0.0); - check(&BigUint::one(), 1.0); - check(&BigUint::from(u32::MAX), 2.0.powi(32) - 1.0); - check(&BigUint::from(1u64 << 32), 2.0.powi(32)); - check(&BigUint::from_slice(&[0, 0, 1]), 2.0.powi(64)); - check( - &((BigUint::one() << 100) + (BigUint::one() << 152)), - 2.0.powi(100) + 2.0.powi(152), - ); - check(&(BigUint::one() << 1023), 2.0.powi(1023)); - check(&(BigUint::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); - - // keeping all 53 digits with the bits at different offsets to the BigDigits - let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; - let mut f = x as f64; - let mut b = BigUint::from(x); - for _ in 0..128 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 54) - 1) as f64; - let mut b = BigUint::from(1u64 << 54); - for _ in 0..128 { - assert_eq!(b.to_f64(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!(BigUint::from_f64(-1.0), None); - assert_eq!(BigUint::from_f64(-0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(-0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(-0.0), Some(BigUint::zero())); - assert_eq!( - BigUint::from_f64(f64::MIN_POSITIVE / 2.0), - Some(BigUint::zero()) - ); - assert_eq!(BigUint::from_f64(f64::MIN_POSITIVE), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(f64::consts::E), Some(BigUint::from(2u32))); - assert_eq!( - BigUint::from_f64(f64::consts::PI), - Some(BigUint::from(3u32)) - ); - - // special float values - assert_eq!(BigUint::from_f64(f64::NAN), None); - assert_eq!(BigUint::from_f64(f64::INFINITY), None); - assert_eq!(BigUint::from_f64(f64::NEG_INFINITY), None); - assert_eq!(BigUint::from_f64(f64::MIN), None); - - // largest BigUint that will round to a finite f64 value - let big_num = (BigUint::one() << 1024) - BigUint::one() - (BigUint::one() << (1024 - 54)); - assert_eq!(big_num.to_f64(), Some(f64::MAX)); - assert_eq!((big_num + BigUint::one()).to_f64(), None); - - assert_eq!(((BigInt::one() << 1024) - BigInt::one()).to_f64(), None); - assert_eq!((BigUint::one() << 1024).to_f64(), None); -} - -#[test] -fn test_convert_to_bigint() { - fn check(n: BigUint, ans: BigInt) { - assert_eq!(n.to_bigint().unwrap(), ans); - assert_eq!(n.to_bigint().unwrap().to_biguint().unwrap(), n); - } - check(Zero::zero(), Zero::zero()); - check( - BigUint::new(vec![1, 2, 3]), - BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3])), - ); -} - -#[test] -fn test_convert_from_uint() { - macro_rules! check { - ($ty:ident, $max:expr) => { - assert_eq!(BigUint::from($ty::zero()), BigUint::zero()); - assert_eq!(BigUint::from($ty::one()), BigUint::one()); - assert_eq!(BigUint::from($ty::MAX - $ty::one()), $max - BigUint::one()); - assert_eq!(BigUint::from($ty::MAX), $max); - }; - } - - check!(u8, BigUint::from_slice(&[u8::MAX as u32])); - check!(u16, BigUint::from_slice(&[u16::MAX as u32])); - check!(u32, BigUint::from_slice(&[u32::MAX])); - check!(u64, BigUint::from_slice(&[u32::MAX, u32::MAX])); - #[cfg(has_i128)] - check!( - u128, - BigUint::from_slice(&[u32::MAX, u32::MAX, u32::MAX, u32::MAX]) - ); - check!(usize, BigUint::from(usize::MAX as u64)); -} - -#[test] -fn test_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a + b == c); - assert_op!(b + a == c); - assert_assign_op!(a += b == c); - assert_assign_op!(b += a == c); - } -} - -#[test] -fn test_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(c - a == b); - assert_op!(c - b == a); - assert_assign_op!(c -= a == b); - assert_assign_op!(c -= b == a); - } -} - -#[test] -#[should_panic] -fn test_sub_fail_on_underflow() { - let (a, b): (BigUint, BigUint) = (Zero::zero(), One::one()); - let _ = a - b; -} - -#[test] -fn test_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a * b == c); - assert_op!(b * a == c); - assert_assign_op!(a *= b == c); - assert_assign_op!(b *= a == c); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - assert!(a == &b * &c + &d); - assert!(a == &c * &b + &d); - } -} - -#[test] -fn test_div_rem() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - assert_op!(c / a == b); - assert_op!(c % a == Zero::zero()); - assert_assign_op!(c /= a == b); - assert_assign_op!(c %= a == Zero::zero()); - assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero())); - } - if !b.is_zero() { - assert_op!(c / b == a); - assert_op!(c % b == Zero::zero()); - assert_assign_op!(c /= b == a); - assert_assign_op!(c %= b == Zero::zero()); - assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero())); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - if !b.is_zero() { - assert_op!(a / b == c); - assert_op!(a % b == d); - assert_assign_op!(a /= b == c); - assert_assign_op!(a %= b == d); - assert!(a.div_rem(&b) == (c, d)); - } - } -} - -#[test] -fn test_checked_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert!(a.checked_add(&b).unwrap() == c); - assert!(b.checked_add(&a).unwrap() == c); - } -} - -#[test] -fn test_checked_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert!(c.checked_sub(&a).unwrap() == b); - assert!(c.checked_sub(&b).unwrap() == a); - - if a > c { - assert!(a.checked_sub(&c).is_none()); - } - if b > c { - assert!(b.checked_sub(&c).is_none()); - } - } -} - -#[test] -fn test_checked_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert!(a.checked_mul(&b).unwrap() == c); - assert!(b.checked_mul(&a).unwrap() == c); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - assert!(a == b.checked_mul(&c).unwrap() + &d); - assert!(a == c.checked_mul(&b).unwrap() + &d); - } -} - -#[test] -fn test_mul_overflow() { - /* Test for issue #187 - overflow due to mac3 incorrectly sizing temporary */ - let s = "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502232636710047537552105951370000796528760829212940754539968588340162273730474622005920097370111"; - let a: BigUint = s.parse().unwrap(); - let b = a.clone(); - let _ = a.checked_mul(&b); -} - -#[test] -fn test_checked_div() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - assert!(c.checked_div(&a).unwrap() == b); - } - if !b.is_zero() { - assert!(c.checked_div(&b).unwrap() == a); - } - - assert!(c.checked_div(&Zero::zero()).is_none()); - } -} - -#[test] -fn test_gcd() { - fn check(a: usize, b: usize, c: usize) { - let big_a: BigUint = FromPrimitive::from_usize(a).unwrap(); - let big_b: BigUint = FromPrimitive::from_usize(b).unwrap(); - let big_c: BigUint = FromPrimitive::from_usize(c).unwrap(); - - assert_eq!(big_a.gcd(&big_b), big_c); - } - - check(10, 2, 2); - check(10, 3, 1); - check(0, 3, 3); - check(3, 3, 3); - check(56, 42, 14); -} - -#[test] -fn test_lcm() { - fn check(a: usize, b: usize, c: usize) { - let big_a: BigUint = FromPrimitive::from_usize(a).unwrap(); - let big_b: BigUint = FromPrimitive::from_usize(b).unwrap(); - let big_c: BigUint = FromPrimitive::from_usize(c).unwrap(); - - assert_eq!(big_a.lcm(&big_b), big_c); - } - - check(0, 0, 0); - check(1, 0, 0); - check(0, 1, 0); - check(1, 1, 1); - check(8, 9, 72); - check(11, 5, 55); - check(99, 17, 1683); -} - -#[test] -fn test_is_even() { - let one: BigUint = FromStr::from_str("1").unwrap(); - let two: BigUint = FromStr::from_str("2").unwrap(); - let thousand: BigUint = FromStr::from_str("1000").unwrap(); - let big: BigUint = FromStr::from_str("1000000000000000000000").unwrap(); - let bigger: BigUint = FromStr::from_str("1000000000000000000001").unwrap(); - assert!(one.is_odd()); - assert!(two.is_even()); - assert!(thousand.is_even()); - assert!(big.is_even()); - assert!(bigger.is_odd()); - assert!((&one << 64).is_even()); - assert!(((&one << 64) + one).is_odd()); -} - -fn to_str_pairs() -> Vec<(BigUint, Vec<(u32, String)>)> { - let bits = 32; - vec![ - ( - Zero::zero(), - vec![(2, "0".to_string()), (3, "0".to_string())], - ), - ( - BigUint::from_slice(&[0xff]), - vec![ - (2, "11111111".to_string()), - (3, "100110".to_string()), - (4, "3333".to_string()), - (5, "2010".to_string()), - (6, "1103".to_string()), - (7, "513".to_string()), - (8, "377".to_string()), - (9, "313".to_string()), - (10, "255".to_string()), - (11, "212".to_string()), - (12, "193".to_string()), - (13, "168".to_string()), - (14, "143".to_string()), - (15, "120".to_string()), - (16, "ff".to_string()), - ], - ), - ( - BigUint::from_slice(&[0xfff]), - vec![ - (2, "111111111111".to_string()), - (4, "333333".to_string()), - (16, "fff".to_string()), - ], - ), - ( - BigUint::from_slice(&[1, 2]), - vec![ - ( - 2, - format!("10{}1", repeat("0").take(bits - 1).collect::()), - ), - ( - 4, - format!("2{}1", repeat("0").take(bits / 2 - 1).collect::()), - ), - ( - 10, - match bits { - 64 => "36893488147419103233".to_string(), - 32 => "8589934593".to_string(), - 16 => "131073".to_string(), - _ => panic!(), - }, - ), - ( - 16, - format!("2{}1", repeat("0").take(bits / 4 - 1).collect::()), - ), - ], - ), - ( - BigUint::from_slice(&[1, 2, 3]), - vec![ - ( - 2, - format!( - "11{}10{}1", - repeat("0").take(bits - 2).collect::(), - repeat("0").take(bits - 1).collect::() - ), - ), - ( - 4, - format!( - "3{}2{}1", - repeat("0").take(bits / 2 - 1).collect::(), - repeat("0").take(bits / 2 - 1).collect::() - ), - ), - ( - 8, - match bits { - 64 => "14000000000000000000004000000000000000000001".to_string(), - 32 => "6000000000100000000001".to_string(), - 16 => "140000400001".to_string(), - _ => panic!(), - }, - ), - ( - 10, - match bits { - 64 => "1020847100762815390427017310442723737601".to_string(), - 32 => "55340232229718589441".to_string(), - 16 => "12885032961".to_string(), - _ => panic!(), - }, - ), - ( - 16, - format!( - "3{}2{}1", - repeat("0").take(bits / 4 - 1).collect::(), - repeat("0").take(bits / 4 - 1).collect::() - ), - ), - ], - ), - ] -} - -#[test] -fn test_to_str_radix() { - let r = to_str_pairs(); - for num_pair in r.iter() { - let &(ref n, ref rs) = num_pair; - for str_pair in rs.iter() { - let &(ref radix, ref str) = str_pair; - assert_eq!(n.to_str_radix(*radix), *str); - } - } -} - -#[test] -fn test_from_and_to_radix() { - const GROUND_TRUTH: &'static [(&'static [u8], u32, &'static [u8])] = &[ - (b"0", 42, &[0]), - ( - b"ffffeeffbb", - 2, - &[ - 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - ], - ), - ( - b"ffffeeffbb", - 3, - &[ - 2, 2, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 0, 2, 2, 0, 1, - ], - ), - ( - b"ffffeeffbb", - 4, - &[3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3], - ), - ( - b"ffffeeffbb", - 5, - &[0, 4, 3, 3, 1, 4, 2, 4, 1, 4, 4, 2, 3, 0, 0, 1, 2, 1], - ), - ( - b"ffffeeffbb", - 6, - &[5, 5, 4, 5, 5, 0, 0, 1, 2, 5, 3, 0, 1, 0, 2, 2], - ), - ( - b"ffffeeffbb", - 7, - &[4, 2, 3, 6, 0, 1, 6, 1, 6, 2, 0, 3, 2, 4, 1], - ), - ( - b"ffffeeffbb", - 8, - &[3, 7, 6, 7, 7, 5, 3, 7, 7, 7, 7, 7, 7, 1], - ), - (b"ffffeeffbb", 9, &[8, 4, 5, 7, 0, 0, 3, 2, 0, 3, 0, 8, 3]), - (b"ffffeeffbb", 10, &[5, 9, 5, 3, 1, 5, 0, 1, 5, 9, 9, 0, 1]), - (b"ffffeeffbb", 11, &[10, 7, 6, 5, 2, 0, 3, 3, 3, 4, 9, 3]), - (b"ffffeeffbb", 12, &[11, 8, 5, 10, 1, 10, 3, 1, 1, 9, 5, 1]), - (b"ffffeeffbb", 13, &[0, 5, 7, 4, 6, 5, 6, 11, 8, 12, 7]), - (b"ffffeeffbb", 14, &[11, 4, 4, 11, 8, 4, 6, 0, 3, 11, 3]), - (b"ffffeeffbb", 15, &[5, 11, 13, 2, 1, 10, 2, 0, 9, 13, 1]), - (b"ffffeeffbb", 16, &[11, 11, 15, 15, 14, 14, 15, 15, 15, 15]), - (b"ffffeeffbb", 17, &[0, 2, 14, 12, 2, 14, 8, 10, 4, 9]), - (b"ffffeeffbb", 18, &[17, 15, 5, 13, 10, 16, 16, 13, 9, 5]), - (b"ffffeeffbb", 19, &[14, 13, 2, 8, 9, 0, 1, 14, 7, 3]), - (b"ffffeeffbb", 20, &[15, 19, 3, 14, 0, 17, 19, 18, 2, 2]), - (b"ffffeeffbb", 21, &[11, 5, 4, 13, 5, 18, 9, 1, 8, 1]), - (b"ffffeeffbb", 22, &[21, 3, 7, 21, 15, 12, 17, 0, 20]), - (b"ffffeeffbb", 23, &[21, 21, 6, 9, 10, 7, 21, 0, 14]), - (b"ffffeeffbb", 24, &[11, 10, 19, 14, 22, 11, 17, 23, 9]), - (b"ffffeeffbb", 25, &[20, 18, 21, 22, 21, 14, 3, 5, 7]), - (b"ffffeeffbb", 26, &[13, 15, 24, 11, 17, 6, 23, 6, 5]), - (b"ffffeeffbb", 27, &[17, 16, 7, 0, 21, 0, 3, 24, 3]), - (b"ffffeeffbb", 28, &[11, 16, 11, 15, 14, 18, 13, 25, 2]), - (b"ffffeeffbb", 29, &[6, 8, 7, 19, 14, 13, 21, 5, 2]), - (b"ffffeeffbb", 30, &[5, 13, 18, 11, 10, 7, 8, 20, 1]), - (b"ffffeeffbb", 31, &[22, 26, 15, 19, 8, 27, 29, 8, 1]), - (b"ffffeeffbb", 32, &[27, 29, 31, 29, 30, 31, 31, 31]), - (b"ffffeeffbb", 33, &[32, 20, 27, 12, 1, 12, 26, 25]), - (b"ffffeeffbb", 34, &[17, 9, 16, 33, 13, 25, 31, 20]), - (b"ffffeeffbb", 35, &[25, 32, 2, 25, 11, 4, 3, 17]), - (b"ffffeeffbb", 36, &[35, 34, 5, 6, 32, 3, 1, 14]), - (b"ffffeeffbb", 37, &[16, 21, 18, 4, 33, 19, 21, 11]), - (b"ffffeeffbb", 38, &[33, 25, 19, 29, 20, 6, 23, 9]), - (b"ffffeeffbb", 39, &[26, 27, 29, 23, 16, 18, 0, 8]), - (b"ffffeeffbb", 40, &[35, 39, 30, 11, 16, 17, 28, 6]), - (b"ffffeeffbb", 41, &[36, 30, 9, 18, 12, 19, 26, 5]), - (b"ffffeeffbb", 42, &[11, 34, 37, 27, 1, 13, 32, 4]), - (b"ffffeeffbb", 43, &[3, 24, 11, 2, 10, 40, 1, 4]), - (b"ffffeeffbb", 44, &[43, 12, 40, 32, 3, 23, 19, 3]), - (b"ffffeeffbb", 45, &[35, 38, 44, 18, 22, 18, 42, 2]), - (b"ffffeeffbb", 46, &[21, 45, 18, 41, 17, 2, 24, 2]), - (b"ffffeeffbb", 47, &[37, 37, 11, 12, 6, 0, 8, 2]), - (b"ffffeeffbb", 48, &[11, 41, 40, 43, 5, 43, 41, 1]), - (b"ffffeeffbb", 49, &[18, 45, 7, 13, 20, 21, 30, 1]), - (b"ffffeeffbb", 50, &[45, 21, 5, 34, 21, 18, 20, 1]), - (b"ffffeeffbb", 51, &[17, 6, 26, 22, 38, 24, 11, 1]), - (b"ffffeeffbb", 52, &[39, 33, 38, 30, 46, 31, 3, 1]), - (b"ffffeeffbb", 53, &[31, 7, 44, 23, 9, 32, 49]), - (b"ffffeeffbb", 54, &[17, 35, 8, 37, 31, 18, 44]), - (b"ffffeeffbb", 55, &[10, 52, 9, 48, 36, 39, 39]), - (b"ffffeeffbb", 56, &[11, 50, 51, 22, 25, 36, 35]), - (b"ffffeeffbb", 57, &[14, 55, 12, 43, 20, 3, 32]), - (b"ffffeeffbb", 58, &[35, 18, 45, 56, 9, 51, 28]), - (b"ffffeeffbb", 59, &[51, 28, 20, 26, 55, 3, 26]), - (b"ffffeeffbb", 60, &[35, 6, 27, 46, 58, 33, 23]), - (b"ffffeeffbb", 61, &[58, 7, 6, 54, 49, 20, 21]), - (b"ffffeeffbb", 62, &[53, 59, 3, 14, 10, 22, 19]), - (b"ffffeeffbb", 63, &[53, 50, 23, 4, 56, 36, 17]), - (b"ffffeeffbb", 64, &[59, 62, 47, 59, 63, 63, 15]), - (b"ffffeeffbb", 65, &[0, 53, 39, 4, 40, 37, 14]), - (b"ffffeeffbb", 66, &[65, 59, 39, 1, 64, 19, 13]), - (b"ffffeeffbb", 67, &[35, 14, 19, 16, 25, 10, 12]), - (b"ffffeeffbb", 68, &[51, 38, 63, 50, 15, 8, 11]), - (b"ffffeeffbb", 69, &[44, 45, 18, 58, 68, 12, 10]), - (b"ffffeeffbb", 70, &[25, 51, 0, 60, 13, 24, 9]), - (b"ffffeeffbb", 71, &[54, 30, 9, 65, 28, 41, 8]), - (b"ffffeeffbb", 72, &[35, 35, 55, 54, 17, 64, 7]), - (b"ffffeeffbb", 73, &[34, 4, 48, 40, 27, 19, 7]), - (b"ffffeeffbb", 74, &[53, 47, 4, 56, 36, 51, 6]), - (b"ffffeeffbb", 75, &[20, 56, 10, 72, 24, 13, 6]), - (b"ffffeeffbb", 76, &[71, 31, 52, 60, 48, 53, 5]), - (b"ffffeeffbb", 77, &[32, 73, 14, 63, 15, 21, 5]), - (b"ffffeeffbb", 78, &[65, 13, 17, 32, 64, 68, 4]), - (b"ffffeeffbb", 79, &[37, 56, 2, 56, 25, 41, 4]), - (b"ffffeeffbb", 80, &[75, 59, 37, 41, 43, 15, 4]), - (b"ffffeeffbb", 81, &[44, 68, 0, 21, 27, 72, 3]), - (b"ffffeeffbb", 82, &[77, 35, 2, 74, 46, 50, 3]), - (b"ffffeeffbb", 83, &[52, 51, 19, 76, 10, 30, 3]), - (b"ffffeeffbb", 84, &[11, 80, 19, 19, 76, 10, 3]), - (b"ffffeeffbb", 85, &[0, 82, 20, 14, 68, 77, 2]), - (b"ffffeeffbb", 86, &[3, 12, 78, 37, 62, 61, 2]), - (b"ffffeeffbb", 87, &[35, 12, 20, 8, 52, 46, 2]), - (b"ffffeeffbb", 88, &[43, 6, 54, 42, 30, 32, 2]), - (b"ffffeeffbb", 89, &[49, 52, 85, 21, 80, 18, 2]), - (b"ffffeeffbb", 90, &[35, 64, 78, 24, 18, 6, 2]), - (b"ffffeeffbb", 91, &[39, 17, 83, 63, 17, 85, 1]), - (b"ffffeeffbb", 92, &[67, 22, 85, 79, 75, 74, 1]), - (b"ffffeeffbb", 93, &[53, 60, 39, 29, 4, 65, 1]), - (b"ffffeeffbb", 94, &[37, 89, 2, 72, 76, 55, 1]), - (b"ffffeeffbb", 95, &[90, 74, 89, 9, 9, 47, 1]), - (b"ffffeeffbb", 96, &[59, 20, 46, 35, 81, 38, 1]), - (b"ffffeeffbb", 97, &[94, 87, 60, 71, 3, 31, 1]), - (b"ffffeeffbb", 98, &[67, 22, 63, 50, 62, 23, 1]), - (b"ffffeeffbb", 99, &[98, 6, 69, 12, 61, 16, 1]), - (b"ffffeeffbb", 100, &[95, 35, 51, 10, 95, 9, 1]), - (b"ffffeeffbb", 101, &[87, 27, 7, 8, 62, 3, 1]), - (b"ffffeeffbb", 102, &[17, 3, 32, 79, 59, 99]), - (b"ffffeeffbb", 103, &[30, 22, 90, 0, 87, 94]), - (b"ffffeeffbb", 104, &[91, 68, 87, 68, 38, 90]), - (b"ffffeeffbb", 105, &[95, 80, 54, 73, 15, 86]), - (b"ffffeeffbb", 106, &[31, 30, 24, 16, 17, 82]), - (b"ffffeeffbb", 107, &[51, 50, 10, 12, 42, 78]), - (b"ffffeeffbb", 108, &[71, 71, 96, 78, 89, 74]), - (b"ffffeeffbb", 109, &[33, 18, 93, 22, 50, 71]), - (b"ffffeeffbb", 110, &[65, 53, 57, 88, 29, 68]), - (b"ffffeeffbb", 111, &[53, 93, 67, 90, 27, 65]), - (b"ffffeeffbb", 112, &[11, 109, 96, 65, 43, 62]), - (b"ffffeeffbb", 113, &[27, 23, 106, 56, 76, 59]), - (b"ffffeeffbb", 114, &[71, 84, 31, 112, 11, 57]), - (b"ffffeeffbb", 115, &[90, 22, 1, 56, 76, 54]), - (b"ffffeeffbb", 116, &[35, 38, 98, 57, 40, 52]), - (b"ffffeeffbb", 117, &[26, 113, 115, 62, 17, 50]), - (b"ffffeeffbb", 118, &[51, 14, 5, 18, 7, 48]), - (b"ffffeeffbb", 119, &[102, 31, 110, 108, 8, 46]), - (b"ffffeeffbb", 120, &[35, 93, 96, 50, 22, 44]), - (b"ffffeeffbb", 121, &[87, 61, 2, 36, 47, 42]), - (b"ffffeeffbb", 122, &[119, 64, 1, 22, 83, 40]), - (b"ffffeeffbb", 123, &[77, 119, 32, 90, 6, 39]), - (b"ffffeeffbb", 124, &[115, 122, 31, 79, 62, 37]), - (b"ffffeeffbb", 125, &[95, 108, 47, 74, 3, 36]), - (b"ffffeeffbb", 126, &[53, 25, 116, 39, 78, 34]), - (b"ffffeeffbb", 127, &[22, 23, 125, 67, 35, 33]), - (b"ffffeeffbb", 128, &[59, 127, 59, 127, 127, 31]), - (b"ffffeeffbb", 129, &[89, 36, 1, 59, 100, 30]), - (b"ffffeeffbb", 130, &[65, 91, 123, 89, 79, 29]), - (b"ffffeeffbb", 131, &[58, 72, 39, 63, 65, 28]), - (b"ffffeeffbb", 132, &[131, 62, 92, 82, 57, 27]), - (b"ffffeeffbb", 133, &[109, 31, 51, 123, 55, 26]), - (b"ffffeeffbb", 134, &[35, 74, 21, 27, 60, 25]), - (b"ffffeeffbb", 135, &[125, 132, 49, 37, 70, 24]), - (b"ffffeeffbb", 136, &[51, 121, 117, 133, 85, 23]), - (b"ffffeeffbb", 137, &[113, 60, 135, 22, 107, 22]), - (b"ffffeeffbb", 138, &[113, 91, 73, 93, 133, 21]), - (b"ffffeeffbb", 139, &[114, 75, 102, 51, 26, 21]), - (b"ffffeeffbb", 140, &[95, 25, 35, 16, 62, 20]), - (b"ffffeeffbb", 141, &[131, 137, 16, 110, 102, 19]), - (b"ffffeeffbb", 142, &[125, 121, 108, 34, 6, 19]), - (b"ffffeeffbb", 143, &[65, 78, 138, 55, 55, 18]), - (b"ffffeeffbb", 144, &[107, 125, 121, 15, 109, 17]), - (b"ffffeeffbb", 145, &[35, 13, 122, 42, 22, 17]), - (b"ffffeeffbb", 146, &[107, 38, 103, 123, 83, 16]), - (b"ffffeeffbb", 147, &[116, 96, 71, 98, 2, 16]), - (b"ffffeeffbb", 148, &[127, 23, 75, 99, 71, 15]), - (b"ffffeeffbb", 149, &[136, 110, 53, 114, 144, 14]), - (b"ffffeeffbb", 150, &[95, 140, 133, 130, 71, 14]), - (b"ffffeeffbb", 151, &[15, 50, 29, 137, 0, 14]), - (b"ffffeeffbb", 152, &[147, 15, 89, 121, 83, 13]), - (b"ffffeeffbb", 153, &[17, 87, 93, 72, 17, 13]), - (b"ffffeeffbb", 154, &[109, 113, 3, 133, 106, 12]), - (b"ffffeeffbb", 155, &[115, 141, 120, 139, 44, 12]), - (b"ffffeeffbb", 156, &[143, 45, 4, 82, 140, 11]), - (b"ffffeeffbb", 157, &[149, 92, 15, 106, 82, 11]), - (b"ffffeeffbb", 158, &[37, 107, 79, 46, 26, 11]), - (b"ffffeeffbb", 159, &[137, 37, 146, 51, 130, 10]), - (b"ffffeeffbb", 160, &[155, 69, 29, 115, 77, 10]), - (b"ffffeeffbb", 161, &[67, 98, 46, 68, 26, 10]), - (b"ffffeeffbb", 162, &[125, 155, 60, 63, 138, 9]), - (b"ffffeeffbb", 163, &[96, 43, 118, 93, 90, 9]), - (b"ffffeeffbb", 164, &[159, 99, 123, 152, 43, 9]), - (b"ffffeeffbb", 165, &[65, 17, 1, 69, 163, 8]), - (b"ffffeeffbb", 166, &[135, 108, 25, 165, 119, 8]), - (b"ffffeeffbb", 167, &[165, 116, 164, 103, 77, 8]), - (b"ffffeeffbb", 168, &[11, 166, 67, 44, 36, 8]), - (b"ffffeeffbb", 169, &[65, 59, 71, 149, 164, 7]), - (b"ffffeeffbb", 170, &[85, 83, 26, 76, 126, 7]), - (b"ffffeeffbb", 171, &[71, 132, 140, 157, 88, 7]), - (b"ffffeeffbb", 172, &[3, 6, 127, 47, 52, 7]), - (b"ffffeeffbb", 173, &[122, 66, 53, 83, 16, 7]), - (b"ffffeeffbb", 174, &[35, 6, 5, 88, 155, 6]), - (b"ffffeeffbb", 175, &[95, 20, 84, 56, 122, 6]), - (b"ffffeeffbb", 176, &[43, 91, 57, 159, 89, 6]), - (b"ffffeeffbb", 177, &[110, 127, 54, 40, 58, 6]), - (b"ffffeeffbb", 178, &[49, 115, 43, 47, 27, 6]), - (b"ffffeeffbb", 179, &[130, 91, 4, 178, 175, 5]), - (b"ffffeeffbb", 180, &[35, 122, 109, 70, 147, 5]), - (b"ffffeeffbb", 181, &[94, 94, 4, 79, 119, 5]), - (b"ffffeeffbb", 182, &[39, 54, 66, 19, 92, 5]), - (b"ffffeeffbb", 183, &[119, 2, 143, 69, 65, 5]), - (b"ffffeeffbb", 184, &[67, 57, 90, 44, 39, 5]), - (b"ffffeeffbb", 185, &[90, 63, 141, 123, 13, 5]), - (b"ffffeeffbb", 186, &[53, 123, 172, 119, 174, 4]), - (b"ffffeeffbb", 187, &[153, 21, 68, 28, 151, 4]), - (b"ffffeeffbb", 188, &[131, 138, 94, 32, 128, 4]), - (b"ffffeeffbb", 189, &[179, 121, 156, 130, 105, 4]), - (b"ffffeeffbb", 190, &[185, 179, 164, 131, 83, 4]), - (b"ffffeeffbb", 191, &[118, 123, 37, 31, 62, 4]), - (b"ffffeeffbb", 192, &[59, 106, 83, 16, 41, 4]), - (b"ffffeeffbb", 193, &[57, 37, 47, 86, 20, 4]), - (b"ffffeeffbb", 194, &[191, 140, 63, 45, 0, 4]), - (b"ffffeeffbb", 195, &[65, 169, 83, 84, 175, 3]), - (b"ffffeeffbb", 196, &[67, 158, 64, 6, 157, 3]), - (b"ffffeeffbb", 197, &[121, 26, 167, 3, 139, 3]), - (b"ffffeeffbb", 198, &[197, 151, 165, 75, 121, 3]), - (b"ffffeeffbb", 199, &[55, 175, 36, 22, 104, 3]), - (b"ffffeeffbb", 200, &[195, 167, 162, 38, 87, 3]), - (b"ffffeeffbb", 201, &[35, 27, 136, 124, 70, 3]), - (b"ffffeeffbb", 202, &[87, 64, 153, 76, 54, 3]), - (b"ffffeeffbb", 203, &[151, 191, 14, 94, 38, 3]), - (b"ffffeeffbb", 204, &[119, 103, 135, 175, 22, 3]), - (b"ffffeeffbb", 205, &[200, 79, 123, 115, 7, 3]), - (b"ffffeeffbb", 206, &[133, 165, 202, 115, 198, 2]), - (b"ffffeeffbb", 207, &[44, 153, 193, 175, 184, 2]), - (b"ffffeeffbb", 208, &[91, 190, 125, 86, 171, 2]), - (b"ffffeeffbb", 209, &[109, 151, 34, 53, 158, 2]), - (b"ffffeeffbb", 210, &[95, 40, 171, 74, 145, 2]), - (b"ffffeeffbb", 211, &[84, 195, 162, 150, 132, 2]), - (b"ffffeeffbb", 212, &[31, 15, 59, 68, 120, 2]), - (b"ffffeeffbb", 213, &[125, 57, 127, 36, 108, 2]), - (b"ffffeeffbb", 214, &[51, 132, 2, 55, 96, 2]), - (b"ffffeeffbb", 215, &[175, 133, 177, 122, 84, 2]), - (b"ffffeeffbb", 216, &[179, 35, 78, 23, 73, 2]), - (b"ffffeeffbb", 217, &[53, 101, 208, 186, 61, 2]), - (b"ffffeeffbb", 218, &[33, 9, 214, 179, 50, 2]), - (b"ffffeeffbb", 219, &[107, 147, 175, 217, 39, 2]), - (b"ffffeeffbb", 220, &[175, 81, 179, 79, 29, 2]), - (b"ffffeeffbb", 221, &[0, 76, 95, 204, 18, 2]), - (b"ffffeeffbb", 222, &[53, 213, 16, 150, 8, 2]), - (b"ffffeeffbb", 223, &[158, 161, 42, 136, 221, 1]), - (b"ffffeeffbb", 224, &[123, 54, 52, 162, 212, 1]), - (b"ffffeeffbb", 225, &[170, 43, 151, 2, 204, 1]), - (b"ffffeeffbb", 226, &[27, 68, 224, 105, 195, 1]), - (b"ffffeeffbb", 227, &[45, 69, 157, 20, 187, 1]), - (b"ffffeeffbb", 228, &[71, 213, 64, 199, 178, 1]), - (b"ffffeeffbb", 229, &[129, 203, 66, 186, 170, 1]), - (b"ffffeeffbb", 230, &[205, 183, 57, 208, 162, 1]), - (b"ffffeeffbb", 231, &[32, 50, 164, 33, 155, 1]), - (b"ffffeeffbb", 232, &[35, 135, 53, 123, 147, 1]), - (b"ffffeeffbb", 233, &[209, 47, 89, 13, 140, 1]), - (b"ffffeeffbb", 234, &[143, 56, 175, 168, 132, 1]), - (b"ffffeeffbb", 235, &[225, 157, 216, 121, 125, 1]), - (b"ffffeeffbb", 236, &[51, 66, 119, 105, 118, 1]), - (b"ffffeeffbb", 237, &[116, 150, 26, 119, 111, 1]), - (b"ffffeeffbb", 238, &[221, 15, 87, 162, 104, 1]), - (b"ffffeeffbb", 239, &[234, 155, 214, 234, 97, 1]), - (b"ffffeeffbb", 240, &[155, 46, 84, 96, 91, 1]), - (b"ffffeeffbb", 241, &[187, 48, 90, 225, 84, 1]), - (b"ffffeeffbb", 242, &[87, 212, 151, 140, 78, 1]), - (b"ffffeeffbb", 243, &[206, 22, 189, 81, 72, 1]), - (b"ffffeeffbb", 244, &[119, 93, 122, 48, 66, 1]), - (b"ffffeeffbb", 245, &[165, 224, 117, 40, 60, 1]), - (b"ffffeeffbb", 246, &[77, 121, 100, 57, 54, 1]), - (b"ffffeeffbb", 247, &[52, 128, 242, 98, 48, 1]), - (b"ffffeeffbb", 248, &[115, 247, 224, 164, 42, 1]), - (b"ffffeeffbb", 249, &[218, 127, 223, 5, 37, 1]), - (b"ffffeeffbb", 250, &[95, 54, 168, 118, 31, 1]), - (b"ffffeeffbb", 251, &[121, 204, 240, 3, 26, 1]), - (b"ffffeeffbb", 252, &[179, 138, 123, 162, 20, 1]), - (b"ffffeeffbb", 253, &[21, 50, 1, 91, 15, 1]), - (b"ffffeeffbb", 254, &[149, 11, 63, 40, 10, 1]), - (b"ffffeeffbb", 255, &[170, 225, 247, 9, 5, 1]), - (b"ffffeeffbb", 256, &[187, 255, 238, 255, 255]), - ]; - - for &(bigint, radix, inbaseradix_le) in GROUND_TRUTH.iter() { - let bigint = BigUint::parse_bytes(bigint, 16).unwrap(); - // to_radix_le - assert_eq!(bigint.to_radix_le(radix), inbaseradix_le); - // to_radix_be - let mut inbase_be = bigint.to_radix_be(radix); - inbase_be.reverse(); // now le - assert_eq!(inbase_be, inbaseradix_le); - // from_radix_le - assert_eq!( - BigUint::from_radix_le(inbaseradix_le, radix).unwrap(), - bigint - ); - // from_radix_be - let mut inbaseradix_be = Vec::from(inbaseradix_le); - inbaseradix_be.reverse(); - assert_eq!( - BigUint::from_radix_be(&inbaseradix_be, radix).unwrap(), - bigint - ); - } - - assert!(BigUint::from_radix_le(&[10, 100, 10], 50).is_none()); -} - -#[test] -fn test_from_str_radix() { - let r = to_str_pairs(); - for num_pair in r.iter() { - let &(ref n, ref rs) = num_pair; - for str_pair in rs.iter() { - let &(ref radix, ref str) = str_pair; - assert_eq!(n, &BigUint::from_str_radix(str, *radix).unwrap()); - } - } - - let zed = BigUint::from_str_radix("Z", 10).ok(); - assert_eq!(zed, None); - let blank = BigUint::from_str_radix("_", 2).ok(); - assert_eq!(blank, None); - let blank_one = BigUint::from_str_radix("_1", 2).ok(); - assert_eq!(blank_one, None); - let plus_one = BigUint::from_str_radix("+1", 10).ok(); - assert_eq!(plus_one, Some(BigUint::from_slice(&[1]))); - let plus_plus_one = BigUint::from_str_radix("++1", 10).ok(); - assert_eq!(plus_plus_one, None); - let minus_one = BigUint::from_str_radix("-1", 10).ok(); - assert_eq!(minus_one, None); - let zero_plus_two = BigUint::from_str_radix("0+2", 10).ok(); - assert_eq!(zero_plus_two, None); - let three = BigUint::from_str_radix("1_1", 2).ok(); - assert_eq!(three, Some(BigUint::from_slice(&[3]))); - let ff = BigUint::from_str_radix("1111_1111", 2).ok(); - assert_eq!(ff, Some(BigUint::from_slice(&[0xff]))); -} - -#[test] -fn test_all_str_radix() { - #[allow(deprecated, unused_imports)] - use std::ascii::AsciiExt; - - let n = BigUint::new((0..10).collect()); - for radix in 2..37 { - let s = n.to_str_radix(radix); - let x = BigUint::from_str_radix(&s, radix); - assert_eq!(x.unwrap(), n); - - let s = s.to_ascii_uppercase(); - let x = BigUint::from_str_radix(&s, radix); - assert_eq!(x.unwrap(), n); - } -} - -#[test] -fn test_lower_hex() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:x}", a), "a"); - assert_eq!(format!("{:x}", hello), "48656c6c6f20776f726c6421"); - assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); -} - -#[test] -fn test_upper_hex() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:X}", a), "A"); - assert_eq!(format!("{:X}", hello), "48656C6C6F20776F726C6421"); - assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); -} - -#[test] -fn test_binary() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("224055342307539".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:b}", a), "1010"); - assert_eq!( - format!("{:b}", hello), - "110010111100011011110011000101101001100011010011" - ); - assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); -} - -#[test] -fn test_octal() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:o}", a), "12"); - assert_eq!(format!("{:o}", hello), "22062554330674403566756233062041"); - assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); -} - -#[test] -fn test_display() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{}", a), "10"); - assert_eq!(format!("{}", hello), "22405534230753963835153736737"); - assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); -} - -#[test] -fn test_factor() { - fn factor(n: usize) -> BigUint { - let mut f: BigUint = One::one(); - for i in 2..n + 1 { - // FIXME(#5992): assignment operator overloads - // f *= FromPrimitive::from_usize(i); - let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); - f = f * bu; - } - return f; - } - - fn check(n: usize, s: &str) { - let n = factor(n); - let ans = match BigUint::from_str_radix(s, 10) { - Ok(x) => x, - Err(_) => panic!(), - }; - assert_eq!(n, ans); - } - - check(3, "6"); - check(10, "3628800"); - check(20, "2432902008176640000"); - check(30, "265252859812191058636308480000000"); -} - -#[test] -fn test_bits() { - assert_eq!(BigUint::new(vec![0, 0, 0, 0]).bits(), 0); - let n: BigUint = FromPrimitive::from_usize(0).unwrap(); - assert_eq!(n.bits(), 0); - let n: BigUint = FromPrimitive::from_usize(1).unwrap(); - assert_eq!(n.bits(), 1); - let n: BigUint = FromPrimitive::from_usize(3).unwrap(); - assert_eq!(n.bits(), 2); - let n: BigUint = BigUint::from_str_radix("4000000000", 16).unwrap(); - assert_eq!(n.bits(), 39); - let one: BigUint = One::one(); - assert_eq!((one << 426).bits(), 427); -} - -#[test] -fn test_iter_sum() { - let result: BigUint = FromPrimitive::from_isize(1234567).unwrap(); - let data: Vec = vec![ - FromPrimitive::from_u32(1000000).unwrap(), - FromPrimitive::from_u32(200000).unwrap(), - FromPrimitive::from_u32(30000).unwrap(), - FromPrimitive::from_u32(4000).unwrap(), - FromPrimitive::from_u32(500).unwrap(), - FromPrimitive::from_u32(60).unwrap(), - FromPrimitive::from_u32(7).unwrap(), - ]; - - assert_eq!(result, data.iter().sum()); - assert_eq!(result, data.into_iter().sum()); -} - -#[test] -fn test_iter_product() { - let data: Vec = vec![ - FromPrimitive::from_u32(1001).unwrap(), - FromPrimitive::from_u32(1002).unwrap(), - FromPrimitive::from_u32(1003).unwrap(), - FromPrimitive::from_u32(1004).unwrap(), - FromPrimitive::from_u32(1005).unwrap(), - ]; - let result = data.get(0).unwrap() - * data.get(1).unwrap() - * data.get(2).unwrap() - * data.get(3).unwrap() - * data.get(4).unwrap(); - - assert_eq!(result, data.iter().product()); - assert_eq!(result, data.into_iter().product()); -} - -#[test] -fn test_iter_sum_generic() { - let result: BigUint = FromPrimitive::from_isize(1234567).unwrap(); - let data = vec![1000000_u32, 200000, 30000, 4000, 500, 60, 7]; - - assert_eq!(result, data.iter().sum()); - assert_eq!(result, data.into_iter().sum()); -} - -#[test] -fn test_iter_product_generic() { - let data = vec![1001_u32, 1002, 1003, 1004, 1005]; - let result = data[0].to_biguint().unwrap() - * data[1].to_biguint().unwrap() - * data[2].to_biguint().unwrap() - * data[3].to_biguint().unwrap() - * data[4].to_biguint().unwrap(); - - assert_eq!(result, data.iter().product()); - assert_eq!(result, data.into_iter().product()); -} - -#[test] -fn test_pow() { - let one = BigUint::from(1u32); - let two = BigUint::from(2u32); - let four = BigUint::from(4u32); - let eight = BigUint::from(8u32); - let tentwentyfour = BigUint::from(1024u32); - let twentyfourtyeight = BigUint::from(2048u32); - macro_rules! check { - ($t:ty) => { - assert_eq!(two.pow(0 as $t), one); - assert_eq!(two.pow(1 as $t), two); - assert_eq!(two.pow(2 as $t), four); - assert_eq!(two.pow(3 as $t), eight); - assert_eq!(two.pow(10 as $t), tentwentyfour); - assert_eq!(two.pow(11 as $t), twentyfourtyeight); - assert_eq!(two.pow(&(11 as $t)), twentyfourtyeight); - }; - } - check!(u8); - check!(u16); - check!(u32); - check!(u64); - check!(usize); - #[cfg(has_i128)] - check!(u128); -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/biguint_scalar.rs b/third_party/rust/num-bigint-0.2.3/tests/biguint_scalar.rs deleted file mode 100644 index fb8fbf0357af..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/biguint_scalar.rs +++ /dev/null @@ -1,109 +0,0 @@ -extern crate num_bigint; -extern crate num_traits; - -use num_bigint::BigUint; -use num_traits::{ToPrimitive, Zero}; - -mod consts; -use consts::*; - -#[macro_use] -mod macros; - -#[test] -fn test_scalar_add() { - fn check(x: &BigUint, y: &BigUint, z: &BigUint) { - let (x, y, z) = (x.clone(), y.clone(), z.clone()); - assert_unsigned_scalar_op!(x + y == z); - } - - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - check(&a, &b, &c); - check(&b, &a, &c); - } -} - -#[test] -fn test_scalar_sub() { - fn check(x: &BigUint, y: &BigUint, z: &BigUint) { - let (x, y, z) = (x.clone(), y.clone(), z.clone()); - assert_unsigned_scalar_op!(x - y == z); - } - - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - check(&c, &a, &b); - check(&c, &b, &a); - } -} - -#[test] -fn test_scalar_mul() { - fn check(x: &BigUint, y: &BigUint, z: &BigUint) { - let (x, y, z) = (x.clone(), y.clone(), z.clone()); - assert_unsigned_scalar_op!(x * y == z); - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - check(&a, &b, &c); - check(&b, &a, &c); - } -} - -#[test] -fn test_scalar_rem_noncommutative() { - assert_eq!(5u8 % BigUint::from(7u8), 5u8.into()); - assert_eq!(BigUint::from(5u8) % 7u8, 5u8.into()); -} - -#[test] -fn test_scalar_div_rem() { - fn check(x: &BigUint, y: &BigUint, z: &BigUint, r: &BigUint) { - let (x, y, z, r) = (x.clone(), y.clone(), z.clone(), r.clone()); - assert_unsigned_scalar_op!(x / y == z); - assert_unsigned_scalar_op!(x % y == r); - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - check(&c, &a, &b, &Zero::zero()); - } - - if !b.is_zero() { - check(&c, &b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - if !b.is_zero() { - check(&a, &b, &c, &d); - assert_unsigned_scalar_op!(a / b == c); - assert_unsigned_scalar_op!(a % b == d); - } - } -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/consts/mod.rs b/third_party/rust/num-bigint-0.2.3/tests/consts/mod.rs deleted file mode 100644 index 87805d5e2427..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/consts/mod.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![allow(unused)] - -pub const N1: u32 = -1i32 as u32; -pub const N2: u32 = -2i32 as u32; - -pub const SUM_TRIPLES: &'static [(&'static [u32], &'static [u32], &'static [u32])] = &[ - (&[], &[], &[]), - (&[], &[1], &[1]), - (&[1], &[1], &[2]), - (&[1], &[1, 1], &[2, 1]), - (&[1], &[N1], &[0, 1]), - (&[1], &[N1, N1], &[0, 0, 1]), - (&[N1, N1], &[N1, N1], &[N2, N1, 1]), - (&[1, 1, 1], &[N1, N1], &[0, 1, 2]), - (&[2, 2, 1], &[N1, N2], &[1, 1, 2]), - (&[1, 2, 2, 1], &[N1, N2], &[0, 1, 3, 1]), -]; - -pub const M: u32 = ::std::u32::MAX; -pub const MUL_TRIPLES: &'static [(&'static [u32], &'static [u32], &'static [u32])] = &[ - (&[], &[], &[]), - (&[], &[1], &[]), - (&[2], &[], &[]), - (&[1], &[1], &[1]), - (&[2], &[3], &[6]), - (&[1], &[1, 1, 1], &[1, 1, 1]), - (&[1, 2, 3], &[3], &[3, 6, 9]), - (&[1, 1, 1], &[N1], &[N1, N1, N1]), - (&[1, 2, 3], &[N1], &[N1, N2, N2, 2]), - (&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]), - (&[N1], &[N1], &[1, N2]), - (&[N1, N1], &[N1], &[1, N1, N2]), - (&[N1, N1, N1], &[N1], &[1, N1, N1, N2]), - (&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]), - (&[M / 2 + 1], &[2], &[0, 1]), - (&[0, M / 2 + 1], &[2], &[0, 0, 1]), - (&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]), - (&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]), - (&[N1, N1, N1], &[N1, N1, N1, N1], &[1, 0, 0, N1, N2, N1, N1]), - (&[0, 0, 1], &[1, 2, 3], &[0, 0, 1, 2, 3]), - (&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]), -]; - -pub const DIV_REM_QUADRUPLES: &'static [( - &'static [u32], - &'static [u32], - &'static [u32], - &'static [u32], -)] = &[ - (&[1], &[2], &[], &[1]), - (&[3], &[2], &[1], &[1]), - (&[1, 1], &[2], &[M / 2 + 1], &[1]), - (&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]), - (&[0, 1], &[N1], &[1], &[1]), - (&[N1, N1], &[N2], &[2, 1], &[3]), -]; diff --git a/third_party/rust/num-bigint-0.2.3/tests/macros/mod.rs b/third_party/rust/num-bigint-0.2.3/tests/macros/mod.rs deleted file mode 100644 index d848b29b35ee..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/macros/mod.rs +++ /dev/null @@ -1,70 +0,0 @@ -#![allow(unused)] - -/// Assert that an op works for all val/ref combinations -macro_rules! assert_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_eq!((&$left) $op (&$right), $expected); - assert_eq!((&$left) $op $right.clone(), $expected); - assert_eq!($left.clone() $op (&$right), $expected); - assert_eq!($left.clone() $op $right.clone(), $expected); - }; -} - -/// Assert that an assign-op works for all val/ref combinations -macro_rules! assert_assign_op { - ($left:ident $op:tt $right:ident == $expected:expr) => {{ - let mut left = $left.clone(); - assert_eq!({ left $op &$right; left}, $expected); - - let mut left = $left.clone(); - assert_eq!({ left $op $right.clone(); left}, $expected); - }}; -} - -/// Assert that an op works for scalar left or right -macro_rules! assert_scalar_op { - (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { - $( - if let Some(left) = $left.$to() { - assert_op!(left $op $right == $expected); - } - if let Some(right) = $right.$to() { - assert_op!($left $op right == $expected); - } - )* - }; -} - -#[cfg(not(has_i128))] -macro_rules! assert_unsigned_scalar_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize) - $left $op $right == $expected); - }; -} - -#[cfg(has_i128)] -macro_rules! assert_unsigned_scalar_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128) - $left $op $right == $expected); - }; -} - -#[cfg(not(has_i128))] -macro_rules! assert_signed_scalar_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, - to_i8, to_i16, to_i32, to_i64, to_isize) - $left $op $right == $expected); - }; -} - -#[cfg(has_i128)] -macro_rules! assert_signed_scalar_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128, - to_i8, to_i16, to_i32, to_i64, to_isize, to_i128) - $left $op $right == $expected); - }; -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/modpow.rs b/third_party/rust/num-bigint-0.2.3/tests/modpow.rs deleted file mode 100644 index b7a992c863ad..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/modpow.rs +++ /dev/null @@ -1,150 +0,0 @@ -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; - -static BIG_B: &'static str = "\ - efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\ - ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\ - aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\ - 247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\ - 675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\ - 8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\ - 33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\ - 1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\ - 990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\ - b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\ - b4edf9cc_6ce540be_76229093_5c53893b"; - -static BIG_E: &'static str = "\ - be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\ - a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\ - 774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\ - eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\ - 449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\ - c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\ - 12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\ - f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\ - a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\ - e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\ - 17946850_2ddb1822_117b68a0_32f7db88"; - -// This modulus is the prime from the 2048-bit MODP DH group: -// https://tools.ietf.org/html/rfc3526#section-3 -static BIG_M: &'static str = "\ - FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ - 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ - EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ - E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ - EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ - C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ - 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ - 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ - E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ - DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ - 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; - -static BIG_R: &'static str = "\ - a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\ - eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\ - 9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\ - 055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\ - fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\ - 93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\ - 35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\ - d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\ - 5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\ - f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\ - 109c4735_6e7db425_7b5d74c7_0b709508"; - -mod biguint { - use num_bigint::BigUint; - use num_integer::Integer; - use num_traits::Num; - - fn check_modpow>(b: T, e: T, m: T, r: T) { - let b: BigUint = b.into(); - let e: BigUint = e.into(); - let m: BigUint = m.into(); - let r: BigUint = r.into(); - - assert_eq!(b.modpow(&e, &m), r); - - let even_m = &m << 1; - let even_modpow = b.modpow(&e, &even_m); - assert!(even_modpow < even_m); - assert_eq!(even_modpow.mod_floor(&m), r); - } - - #[test] - fn test_modpow() { - check_modpow::(1, 0, 11, 1); - check_modpow::(0, 15, 11, 0); - check_modpow::(3, 7, 11, 9); - check_modpow::(5, 117, 19, 1); - } - - #[test] - fn test_modpow_big() { - let b = BigUint::from_str_radix(super::BIG_B, 16).unwrap(); - let e = BigUint::from_str_radix(super::BIG_E, 16).unwrap(); - let m = BigUint::from_str_radix(super::BIG_M, 16).unwrap(); - let r = BigUint::from_str_radix(super::BIG_R, 16).unwrap(); - - assert_eq!(b.modpow(&e, &m), r); - - let even_m = &m << 1; - let even_modpow = b.modpow(&e, &even_m); - assert!(even_modpow < even_m); - assert_eq!(even_modpow % m, r); - } -} - -mod bigint { - use num_bigint::BigInt; - use num_integer::Integer; - use num_traits::{Num, One, Signed, Zero}; - - fn check_modpow>(b: T, e: T, m: T, r: T) { - fn check(b: &BigInt, e: &BigInt, m: &BigInt, r: &BigInt) { - assert_eq!(&b.modpow(e, m), r); - - let even_m = m << 1; - let even_modpow = b.modpow(e, m); - assert!(even_modpow.abs() < even_m.abs()); - assert_eq!(&even_modpow.mod_floor(&m), r); - - // the sign of the result follows the modulus like `mod_floor`, not `rem` - assert_eq!(b.modpow(&BigInt::one(), m), b.mod_floor(m)); - } - - let b: BigInt = b.into(); - let e: BigInt = e.into(); - let m: BigInt = m.into(); - let r: BigInt = r.into(); - - let neg_r = if r.is_zero() { BigInt::zero() } else { &m - &r }; - - check(&b, &e, &m, &r); - check(&-&b, &e, &m, &neg_r); - check(&b, &e, &-&m, &-neg_r); - check(&-b, &e, &-m, &-r); - } - - #[test] - fn test_modpow() { - check_modpow(1, 0, 11, 1); - check_modpow(0, 15, 11, 0); - check_modpow(3, 7, 11, 9); - check_modpow(5, 117, 19, 1); - } - - #[test] - fn test_modpow_big() { - let b = BigInt::from_str_radix(super::BIG_B, 16).unwrap(); - let e = BigInt::from_str_radix(super::BIG_E, 16).unwrap(); - let m = BigInt::from_str_radix(super::BIG_M, 16).unwrap(); - let r = BigInt::from_str_radix(super::BIG_R, 16).unwrap(); - - check_modpow(b, e, m, r); - } -} diff --git a/third_party/rust/num-bigint-0.2.3/tests/roots.rs b/third_party/rust/num-bigint-0.2.3/tests/roots.rs deleted file mode 100644 index 39201fa92851..000000000000 --- a/third_party/rust/num-bigint-0.2.3/tests/roots.rs +++ /dev/null @@ -1,186 +0,0 @@ -extern crate num_bigint; -extern crate num_integer; -extern crate num_traits; - -#[cfg(feature = "rand")] -extern crate rand; - -mod biguint { - use num_bigint::BigUint; - use num_traits::{One, Pow, Zero}; - use std::{i32, u32}; - - fn check>(x: T, n: u32) { - let x: BigUint = x.into(); - let root = x.nth_root(n); - println!("check {}.nth_root({}) = {}", x, n, root); - - if n == 2 { - assert_eq!(root, x.sqrt()) - } else if n == 3 { - assert_eq!(root, x.cbrt()) - } - - let lo = root.pow(n); - assert!(lo <= x); - assert_eq!(lo.nth_root(n), root); - if !lo.is_zero() { - assert_eq!((&lo - 1u32).nth_root(n), &root - 1u32); - } - - let hi = (&root + 1u32).pow(n); - assert!(hi > x); - assert_eq!(hi.nth_root(n), &root + 1u32); - assert_eq!((&hi - 1u32).nth_root(n), root); - } - - #[test] - fn test_sqrt() { - check(99u32, 2); - check(100u32, 2); - check(120u32, 2); - } - - #[test] - fn test_cbrt() { - check(8u32, 3); - check(26u32, 3); - } - - #[test] - fn test_nth_root() { - check(0u32, 1); - check(10u32, 1); - check(100u32, 4); - } - - #[test] - #[should_panic] - fn test_nth_root_n_is_zero() { - check(4u32, 0); - } - - #[test] - fn test_nth_root_big() { - let x = BigUint::from(123_456_789_u32); - let expected = BigUint::from(6u32); - - assert_eq!(x.nth_root(10), expected); - check(x, 10); - } - - #[test] - fn test_nth_root_googol() { - let googol = BigUint::from(10u32).pow(100u32); - - // perfect divisors of 100 - for &n in &[2, 4, 5, 10, 20, 25, 50, 100] { - let expected = BigUint::from(10u32).pow(100u32 / n); - assert_eq!(googol.nth_root(n), expected); - check(googol.clone(), n); - } - } - - #[test] - fn test_nth_root_twos() { - const EXP: u32 = 12; - const LOG2: usize = 1 << EXP; - let x = BigUint::one() << LOG2; - - // the perfect divisors are just powers of two - for exp in 1..EXP + 1 { - let n = 2u32.pow(exp); - let expected = BigUint::one() << (LOG2 / n as usize); - assert_eq!(x.nth_root(n), expected); - check(x.clone(), n); - } - - // degenerate cases should return quickly - assert!(x.nth_root(x.bits() as u32).is_one()); - assert!(x.nth_root(i32::MAX as u32).is_one()); - assert!(x.nth_root(u32::MAX).is_one()); - } - - #[cfg(feature = "rand")] - #[test] - fn test_roots_rand() { - use num_bigint::RandBigInt; - use rand::distributions::Uniform; - use rand::{thread_rng, Rng}; - - let mut rng = thread_rng(); - let bit_range = Uniform::new(0, 2048); - let sample_bits: Vec<_> = rng.sample_iter(&bit_range).take(100).collect(); - for bits in sample_bits { - let x = rng.gen_biguint(bits); - for n in 2..11 { - check(x.clone(), n); - } - check(x.clone(), 100); - } - } - - #[test] - fn test_roots_rand1() { - // A random input that found regressions - let s = "575981506858479247661989091587544744717244516135539456183849\ - 986593934723426343633698413178771587697273822147578889823552\ - 182702908597782734558103025298880194023243541613924361007059\ - 353344183590348785832467726433749431093350684849462759540710\ - 026019022227591412417064179299354183441181373862905039254106\ - 4781867"; - let x: BigUint = s.parse().unwrap(); - - check(x.clone(), 2); - check(x.clone(), 3); - check(x.clone(), 10); - check(x.clone(), 100); - } -} - -mod bigint { - use num_bigint::BigInt; - use num_traits::{Pow, Signed}; - - fn check(x: i64, n: u32) { - let big_x = BigInt::from(x); - let res = big_x.nth_root(n); - - if n == 2 { - assert_eq!(&res, &big_x.sqrt()) - } else if n == 3 { - assert_eq!(&res, &big_x.cbrt()) - } - - if big_x.is_negative() { - assert!(res.pow(n) >= big_x); - assert!((res - 1u32).pow(n) < big_x); - } else { - assert!(res.pow(n) <= big_x); - assert!((res + 1u32).pow(n) > big_x); - } - } - - #[test] - fn test_nth_root() { - check(-100, 3); - } - - #[test] - #[should_panic] - fn test_nth_root_x_neg_n_even() { - check(-100, 4); - } - - #[test] - #[should_panic] - fn test_sqrt_x_neg() { - check(-4, 2); - } - - #[test] - fn test_cbrt() { - check(8, 3); - check(-8, 3); - } -} diff --git a/third_party/rust/num-bigint/.cargo-checksum.json b/third_party/rust/num-bigint/.cargo-checksum.json index cbefa0f45fdf..288114fb2c67 100644 --- a/third_party/rust/num-bigint/.cargo-checksum.json +++ b/third_party/rust/num-bigint/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"7aa575d1baa6278a46c9702151962c48ba036e0858735cb785854bc5fe0c8d45","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"80ffdcb01563610a5c0eab802eeec39cbb21054f47a9df550f8495a7e861eb40","RELEASES.md":"566c43d664f1d6a242632febb661005fda9a479882673925093a5b688159393d","benches/bigint.rs":"e0388d1880c4ff508b2f871c5b70f058999dd8c6a703c16e8ea69f0a8e1ba50d","benches/factorial.rs":"ed1d276a780e7e5fe79121b941c22a00c2854dbf92fd8a5372619853ba0c13b7","benches/gcd.rs":"2b433e5699b45e5fb23e77ab025a07e16e3eb9a49c47207b477551542fc4ff1e","benches/roots.rs":"967161d58d1977452ec7fa988a41848d575008a3e148eb048bc049c884d98f5f","benches/shootout-pidigits.rs":"c2a48133f5b679928f7e3f4e764c78aaa8c5b811f58b86fe57fae8c63cb07136","build.rs":"93c67318349abcc216b64973dfb12055e9eb2e1fb6631b2a1b3728f298f8e07c","src/algorithms.rs":"df10d5784da66ad6984fac2845a4611fbb893d384994618561804263acce3a76","src/bigint.rs":"78f8bf8fbd6c06d0a628dd560cc143428200fba7aeedb3c939ea2ce9d70ec3e6","src/bigrand.rs":"f2d16738d6811d6cc0999e4ba3e9477074115e665ac68a550106d5e926176f84","src/biguint.rs":"5c54978e84bd1344c2e1558b44ab196d52d92fc727dae3684ab2981843b804f1","src/lib.rs":"e43f5cbfa4736e71e78bb6ce72aa3da4867ceac225cc945405b2cad51d0e577e","src/macros.rs":"800239723d637c3ea1d6beb6a62b38a2300bd4c69c20dc0d50855ad6a8b31e70","src/monty.rs":"91688835e0fd409df72c3df5e07e2a114982578f03dd62721c02f36d5fc64ac6","tests/bigint.rs":"deb1e882093a0fa67d3b9a360c6e282fa45b75fb2681e60ce549ef074008c086","tests/bigint_bitwise.rs":"e6a2f76fa1eb919e7c513d7e30a8a2a963841a295a71103462fb8ab9792419b5","tests/bigint_scalar.rs":"5d6131e021f96d476f7949fa2b302581bd9254e91efde1bf2926cdd5e8dffcdb","tests/biguint.rs":"6e390bcc037b04210edb7a81ff87df705edd0afa439c44ac8cf369ca4fef55bd","tests/biguint_scalar.rs":"f16450c0dfcaf23b6fb85669b3de7c2bb6f594a65e3cdf91014b2e49c941cc95","tests/consts/mod.rs":"e20bc49a7cc95077242cbe4016b37745ea986c779d2385cb367fbfe44f15ff94","tests/macros/mod.rs":"1a8f9f015e5caaac60ce9ccff01a75ae489801c3ede6e7b9b3c5079b6efefc9c","tests/modpow.rs":"f1e4ed4fe466b544d7c4e57d0a0dc7d1c97b430b4805cae12f0915b8c40ab66f","tests/roots.rs":"a3bc2de170a0f6297cc8d8830d608db537ca102ccf204fd4fb8e2d92675622d8"},"package":"b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0"} \ No newline at end of file +{"files":{"Cargo.toml":"ba1041ccca008388ab7d7432ae63b811d8e744c8fa9e50f371bfbeb78acd1995","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"25f684f15b0ed6ea216c3831e567a9b5dc02b78ff7e579e0d7323305db75218c","RELEASES.md":"5a3045437dc1850ae4e39acd14f2660ed7bace9b0c4d7dae3950f049dbfd4d65","benches/bigint.rs":"252c0dc1f220a6fbdc151e729069260c2f5909516467ceb873e412e5691d7042","benches/factorial.rs":"d536f5584987847f10321b94175a0d8fd2beb14b7c814ec28eef1f96ca081fbe","benches/gcd.rs":"7ec5ce7174e1d31bd08ccc5670f5a32a5c084f258d7980cd6d02e0a8bb5562c4","benches/roots.rs":"3f87db894c379122aee5cd8520c7c759c26d8a9649ac47f45d1bf4d560e1cb07","benches/shootout-pidigits.rs":"985b76d6dba05c396efe4da136c6a0bb2c02bcf5b05cbb346f0f802a891629bb","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"56d4fbb7a55750e61d2074df2735a31995c1decbd988c0e722926235e0fed487","ci/rustup.sh":"c976bb2756da3876363b01fdbf06c13de20df421e5add45e4017c4df42ed06a6","ci/test_full.sh":"a0ac26b85809eb43edd813c9dc88f34a1a8227b7618f4bede89c8f2ac9a4c05a","src/algorithms.rs":"8827c46df051214d1d0e7670680ca9f4834eae678ed340c86b5ea32fddbc7c3c","src/bigint.rs":"7f113fdc034c566bc8475ff0a7d136aa8250cae047b4356084e6797a15f968e1","src/bigrand.rs":"d2f72b8833f367dd8990b4b026f302d838144c5a4de942135d39a3a9932f137d","src/biguint.rs":"b95bfcf84e3f831fb07982aa4b058cd16a524eaa493946eed8e8c5fb8d65797a","src/lib.rs":"d5cc50306f73f07555e7d3413edd2ca5c7d54cbc80a2e83844d77fb8750ae314","src/macros.rs":"2e763517922d960c06e3ac4d319b1d81e66dffadfde8fdf300ff8b8bb95bd8cd","src/monty.rs":"6a867846b7f6af9115add2fd59fccd0651c71dd7f2316e8fb9c812ff3c27da12","tests/bigint.rs":"f7df454f085a862ad5a98e3a802303a3fdf06275a7a1b92074b40b76a715bed2","tests/bigint_bitwise.rs":"dc9436c8f200f2b0ac08cefb23bb8e39c4e688e9026a506a678416c3d573128b","tests/bigint_scalar.rs":"aa176ed102cafd425a215a93460806914d8f3ac288c98ec3e56772fa17379838","tests/biguint.rs":"9ae79f96d1a3beca5be95dffe9d79dc3436f886edc6cae51faf4203c3e0c4681","tests/biguint_scalar.rs":"9cc6f2bf2fe77f34b09eb2266c23aded3b27a60dc1859eb60d3013164292467e","tests/consts/mod.rs":"f9ea5f40733e2f5f432803d830be9db929d91e5e5efd8510b07c6ced2fe554be","tests/macros/mod.rs":"2789b680dd14a770d5ceef430018be0ada85098d69e218c61c17214084c4f763","tests/modpow.rs":"f14cdea11e355a371b314cc866dfa13281a3226706ab2cf01c1485273afde300","tests/quickcheck.rs":"6d6c1ec244b2384a8b34e989870aef8bcedccf6cc46e2626b29a032703bef03c","tests/rand.rs":"08370135bd78432660cfcd708a9ea852022d555bc92c1f3c482fabd17faa64a0","tests/roots.rs":"9ec1bdb0cd1c72402a41e5470325a5276af75979b7fc0f0b63e7bbbb9f3505b2","tests/serde.rs":"79d7a0347207b3a3666af67d2ed97fa34f2922732121a3cb8f5b9f990846acfa","tests/torture.rs":"9fe4897580c0ebe2b7062f5b0b890b4b03510daa45c9236f0edba7144f9eb6f8"},"package":"f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a"} \ No newline at end of file diff --git a/third_party/rust/num-bigint/Cargo.toml b/third_party/rust/num-bigint/Cargo.toml index 2a1175ae9609..d8403a5659fc 100644 --- a/third_party/rust/num-bigint/Cargo.toml +++ b/third_party/rust/num-bigint/Cargo.toml @@ -11,12 +11,10 @@ # will likely look very different (and much more reasonable) [package] -edition = "2018" name = "num-bigint" -version = "0.3.0" +version = "0.2.3" authors = ["The Rust Project Developers"] build = "build.rs" -exclude = ["/bors.toml", "/ci/*", "/.github/*"] description = "Big integer implementation for Rust" homepage = "https://github.com/rust-num/num-bigint" documentation = "https://docs.rs/num-bigint" @@ -44,32 +42,40 @@ name = "roots" name = "shootout-pidigits" harness = false [dependencies.num-integer] -version = "0.1.42" -features = ["i128"] +version = "0.1.39" default-features = false [dependencies.num-traits] -version = "0.2.11" -features = ["i128"] +version = "0.2.7" default-features = false [dependencies.quickcheck] -version = "0.9" +version = "0.8" +optional = true +default-features = false + +[dependencies.quickcheck_macros] +version = "0.8" optional = true default-features = false [dependencies.rand] -version = "0.7" +version = "0.5" +features = ["std"] optional = true default-features = false [dependencies.serde] version = "1.0" +features = ["std"] optional = true default-features = false +[dev-dependencies.serde_test] +version = "1.0" [build-dependencies.autocfg] -version = "1" +version = "0.1.2" [features] default = ["std"] +i128 = ["num-integer/i128", "num-traits/i128"] std = ["num-integer/std", "num-traits/std"] diff --git a/third_party/rust/num-bigint/README.md b/third_party/rust/num-bigint/README.md index 4f2f831f7af8..f7eefed87e69 100644 --- a/third_party/rust/num-bigint/README.md +++ b/third_party/rust/num-bigint/README.md @@ -2,8 +2,8 @@ [![crate](https://img.shields.io/crates/v/num-bigint.svg)](https://crates.io/crates/num-bigint) [![documentation](https://docs.rs/num-bigint/badge.svg)](https://docs.rs/num-bigint) -[![minimum rustc 1.31](https://img.shields.io/badge/rustc-1.31+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num-bigint/workflows/master/badge.svg)](https://github.com/rust-num/num-bigint/actions) +![minimum rustc 1.15](https://img.shields.io/badge/rustc-1.15+-red.svg) +[![Travis status](https://travis-ci.org/rust-num/num-bigint.svg?branch=master)](https://travis-ci.org/rust-num/num-bigint) Big integer types for Rust, `BigInt` and `BigUint`. @@ -13,28 +13,25 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -num-bigint = "0.3" +num-bigint = "0.2" +``` + +and this to your crate root: + +```rust +extern crate num_bigint; ``` ## Features -The `std` crate feature is enabled by default, and is mandatory before Rust -1.36 and the stabilized `alloc` crate. If you depend on `num-bigint` with -`default-features = false`, you must manually enable the `std` feature yourself -if your compiler is not new enough. +The `std` crate feature is mandatory and enabled by default. If you depend on +`num-bigint` with `default-features = false`, you must manually enable the +`std` feature yourself. In the future, we hope to support `#![no_std]` with +the `alloc` crate when `std` is not enabled. -### Random Generation - -`num-bigint` supports the generation of random big integers when the `rand` -feature is enabled. To enable it include rand as - -```toml -rand = "0.7" -num-bigint = { version = "0.3", features = ["rand"] } -``` - -Note that you must use the version of `rand` that `num-bigint` is compatible -with: `0.7`. +Implementations for `i128` and `u128` are only available with Rust 1.26 and +later. The build script automatically detects this, but you can make it +mandatory by enabling the `i128` crate feature. ## Releases @@ -42,7 +39,7 @@ Release notes are available in [RELEASES.md](RELEASES.md). ## Compatibility -The `num-bigint` crate is tested for rustc 1.31 and greater. +The `num-bigint` crate is tested for rustc 1.15 and greater. ## Alternatives @@ -52,9 +49,9 @@ table offers a brief comparison to a few alternatives. | Crate | License | Min rustc | Implementation | | :--------------- | :------------- | :-------- | :------------- | -| **`num-bigint`** | MIT/Apache-2.0 | 1.31 | pure rust | +| **`num-bigint`** | MIT/Apache-2.0 | 1.15 | pure rust | | [`ramp`] | Apache-2.0 | nightly | rust and inline assembly | -| [`rug`] | LGPL-3.0+ | 1.37 | bundles [GMP] via [`gmp-mpfr-sys`] | +| [`rug`] | LGPL-3.0+ | 1.31 | bundles [GMP] via [`gmp-mpfr-sys`] | | [`rust-gmp`] | MIT | stable? | links to [GMP] | | [`apint`] | MIT/Apache-2.0 | 1.26 | pure rust (unfinished) | diff --git a/third_party/rust/num-bigint/RELEASES.md b/third_party/rust/num-bigint/RELEASES.md index a20dc249b449..911dd7835f87 100644 --- a/third_party/rust/num-bigint/RELEASES.md +++ b/third_party/rust/num-bigint/RELEASES.md @@ -1,74 +1,3 @@ -# Release 0.3.0 (2020-06-12) - -### Enhancements - -- [The internal `BigDigit` may now be either `u32` or `u64`][62], although that - implementation detail is not exposed in the API. For now, this is chosen to - match the target pointer size, but may change in the future. -- [No-`std` is now supported with the `alloc` crate on Rust 1.36][101]. -- [`Pow` is now implemented for bigint values][137], not just references. -- [`TryFrom` is now implemented on Rust 1.34 and later][123], converting signed - integers to unsigned, and narrowing big integers to primitives. -- [`Shl` and `Shr` are now implemented for a variety of shift types][142]. -- A new `trailing_zeros()` returns the number of consecutive zeros from the - least significant bit. -- The new `BigInt::magnitude` and `into_parts` methods give access to its - `BigUint` part as the magnitude. - -### Breaking Changes - -- `num-bigint` now requires Rust 1.31 or greater. - - The "i128" opt-in feature was removed, now always available. -- [Updated public dependences][110]: - - `rand` support has been updated to 0.7, requiring Rust 1.32. - - `quickcheck` support has been updated to 0.9, requiring Rust 1.34. -- [Removed `impl Neg for BigUint`][145], which only ever panicked. -- [Bit counts are now `u64` instead of `usize`][143]. - -**Contributors**: @cuviper, @dignifiedquire, @hansihe, -@kpcyrd, @milesand, @tech6hutch - -[62]: https://github.com/rust-num/num-bigint/pull/62 -[101]: https://github.com/rust-num/num-bigint/pull/101 -[110]: https://github.com/rust-num/num-bigint/pull/110 -[123]: https://github.com/rust-num/num-bigint/pull/123 -[137]: https://github.com/rust-num/num-bigint/pull/137 -[142]: https://github.com/rust-num/num-bigint/pull/142 -[143]: https://github.com/rust-num/num-bigint/pull/143 -[145]: https://github.com/rust-num/num-bigint/pull/145 - -# Release 0.2.6 (2020-01-27) - -- [Fix the promotion of negative `isize` in `BigInt` assign-ops][133]. - -**Contributors**: @cuviper, @HactarCE - -[133]: https://github.com/rust-num/num-bigint/pull/133 - -# Release 0.2.5 (2020-01-09) - -- [Updated the `autocfg` build dependency to 1.0][126]. - -**Contributors**: @cuviper, @tspiteri - -[126]: https://github.com/rust-num/num-bigint/pull/126 - -# Release 0.2.4 (2020-01-01) - -- [The new `BigUint::to_u32_digits` method][104] returns the number as a - little-endian vector of base-232 digits. The same method on - `BigInt` also returns the sign. -- [`BigUint::modpow` now applies a modulus even for exponent 1][113], which - also affects `BigInt::modpow`. -- [`BigInt::modpow` now returns the correct sign for negative bases with even - exponents][114]. - -[104]: https://github.com/rust-num/num-bigint/pull/104 -[113]: https://github.com/rust-num/num-bigint/pull/113 -[114]: https://github.com/rust-num/num-bigint/pull/114 - -**Contributors**: @alex-ozdemir, @cuviper, @dingelish, @Speedy37, @youknowone - # Release 0.2.3 (2019-09-03) - [`Pow` is now implemented for `BigUint` exponents][77]. diff --git a/third_party/rust/num-bigint/benches/bigint.rs b/third_party/rust/num-bigint/benches/bigint.rs index 591e9a99290a..bc0875d8f6c2 100644 --- a/third_party/rust/num-bigint/benches/bigint.rs +++ b/third_party/rust/num-bigint/benches/bigint.rs @@ -1,12 +1,15 @@ #![feature(test)] #![cfg(feature = "rand")] +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; +extern crate rand; extern crate test; use num_bigint::{BigInt, BigUint, RandBigInt}; -use num_traits::{FromPrimitive, Num, One, Zero}; -use rand::rngs::StdRng; -use rand::SeedableRng; +use num_traits::{FromPrimitive, Num, One, Pow, Zero}; +use rand::{SeedableRng, StdRng}; use std::mem::replace; use test::Bencher; @@ -18,7 +21,7 @@ fn get_rng() -> StdRng { SeedableRng::from_seed(seed) } -fn multiply_bench(b: &mut Bencher, xbits: u64, ybits: u64) { +fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) { let mut rng = get_rng(); let x = rng.gen_bigint(xbits); let y = rng.gen_bigint(ybits); @@ -26,7 +29,7 @@ fn multiply_bench(b: &mut Bencher, xbits: u64, ybits: u64) { b.iter(|| &x * &y); } -fn divide_bench(b: &mut Bencher, xbits: u64, ybits: u64) { +fn divide_bench(b: &mut Bencher, xbits: usize, ybits: usize) { let mut rng = get_rng(); let x = rng.gen_bigint(xbits); let y = rng.gen_bigint(ybits); @@ -34,7 +37,7 @@ fn divide_bench(b: &mut Bencher, xbits: u64, ybits: u64) { b.iter(|| &x / &y); } -fn remainder_bench(b: &mut Bencher, xbits: u64, ybits: u64) { +fn remainder_bench(b: &mut Bencher, xbits: usize, ybits: usize) { let mut rng = get_rng(); let x = rng.gen_bigint(xbits); let y = rng.gen_bigint(ybits); @@ -44,9 +47,9 @@ fn remainder_bench(b: &mut Bencher, xbits: u64, ybits: u64) { fn factorial(n: usize) -> BigUint { let mut f: BigUint = One::one(); - for i in 1..=n { + for i in 1..(n + 1) { let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); - f += bu; + f = f * bu; } f } @@ -68,7 +71,7 @@ fn fib2(n: usize) -> BigUint { let mut f0: BigUint = Zero::zero(); let mut f1: BigUint = One::one(); for _ in 0..n { - f1 += &f0; + f1 = f1 + &f0; f0 = &f1 - f0; } f0 @@ -109,11 +112,6 @@ fn divide_2(b: &mut Bencher) { divide_bench(b, 1 << 16, 1 << 12); } -#[bench] -fn divide_big_little(b: &mut Bencher) { - divide_bench(b, 1 << 16, 1 << 4); -} - #[bench] fn remainder_0(b: &mut Bencher) { remainder_bench(b, 1 << 8, 1 << 6); @@ -129,11 +127,6 @@ fn remainder_2(b: &mut Bencher) { remainder_bench(b, 1 << 16, 1 << 12); } -#[bench] -fn remainder_big_little(b: &mut Bencher) { - remainder_bench(b, 1 << 16, 1 << 4); -} - #[bench] fn factorial_100(b: &mut Bencher) { b.iter(|| factorial(100)); @@ -245,7 +238,7 @@ fn from_str_radix_36(b: &mut Bencher) { from_str_radix_bench(b, 36); } -fn rand_bench(b: &mut Bencher, bits: u64) { +fn rand_bench(b: &mut Bencher, bits: usize) { let mut rng = get_rng(); b.iter(|| rng.gen_bigint(bits)); @@ -293,24 +286,22 @@ fn rand_131072(b: &mut Bencher) { #[bench] fn shl(b: &mut Bencher) { - let n = BigUint::one() << 1000u32; - let mut m = n.clone(); + let n = BigUint::one() << 1000; b.iter(|| { - m.clone_from(&n); + let mut m = n.clone(); for i in 0..50 { - m <<= i; + m = m << i; } }) } #[bench] fn shr(b: &mut Bencher) { - let n = BigUint::one() << 2000u32; - let mut m = n.clone(); + let n = BigUint::one() << 2000; b.iter(|| { - m.clone_from(&n); + let mut m = n.clone(); for i in 0..50 { - m >>= i; + m = m >> i; } }) } @@ -329,49 +320,31 @@ fn hash(b: &mut Bencher) { #[bench] fn pow_bench(b: &mut Bencher) { b.iter(|| { - let upper = 100_u32; - let mut i_big = BigUint::from(1u32); - for _i in 2..=upper { - i_big += 1u32; - for j in 2..=upper { + let upper = 100_usize; + for i in 2..upper + 1 { + for j in 2..upper + 1 { + let i_big = BigUint::from_usize(i).unwrap(); i_big.pow(j); } } }); } -#[bench] -fn pow_bench_bigexp(b: &mut Bencher) { - use num_traits::Pow; - - b.iter(|| { - let upper = 100_u32; - let mut i_big = BigUint::from(1u32); - for _i in 2..=upper { - i_big += 1u32; - let mut j_big = BigUint::from(1u32); - for _j in 2..=upper { - j_big += 1u32; - Pow::pow(&i_big, &j_big); - } - } - }); -} - /// This modulus is the prime from the 2048-bit MODP DH group: /// https://tools.ietf.org/html/rfc3526#section-3 -const RFC3526_2048BIT_MODP_GROUP: &str = "\ - FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ - 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ - EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ - E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ - EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ - C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ - 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ - 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ - E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ - DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ - 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; +const RFC3526_2048BIT_MODP_GROUP: &'static str = + "\ + FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ + 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ + EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ + E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ + EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ + C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ + 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ + 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ + E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ + DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ + 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; #[bench] fn modpow(b: &mut Bencher) { diff --git a/third_party/rust/num-bigint/benches/factorial.rs b/third_party/rust/num-bigint/benches/factorial.rs index a1e7b3cf1a78..4392df831915 100644 --- a/third_party/rust/num-bigint/benches/factorial.rs +++ b/third_party/rust/num-bigint/benches/factorial.rs @@ -1,5 +1,7 @@ #![feature(test)] +extern crate num_bigint; +extern crate num_traits; extern crate test; use num_bigint::BigUint; diff --git a/third_party/rust/num-bigint/benches/gcd.rs b/third_party/rust/num-bigint/benches/gcd.rs index 1a65654ca1fa..5fe5260ddfa0 100644 --- a/third_party/rust/num-bigint/benches/gcd.rs +++ b/third_party/rust/num-bigint/benches/gcd.rs @@ -1,13 +1,16 @@ #![feature(test)] #![cfg(feature = "rand")] +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; +extern crate rand; extern crate test; use num_bigint::{BigUint, RandBigInt}; use num_integer::Integer; use num_traits::Zero; -use rand::rngs::StdRng; -use rand::SeedableRng; +use rand::{SeedableRng, StdRng}; use test::Bencher; fn get_rng() -> StdRng { @@ -18,7 +21,7 @@ fn get_rng() -> StdRng { SeedableRng::from_seed(seed) } -fn bench(b: &mut Bencher, bits: u64, gcd: fn(&BigUint, &BigUint) -> BigUint) { +fn bench(b: &mut Bencher, bits: usize, gcd: fn(&BigUint, &BigUint) -> BigUint) { let mut rng = get_rng(); let x = rng.gen_biguint(bits); let y = rng.gen_biguint(bits); @@ -37,7 +40,7 @@ fn euclid(x: &BigUint, y: &BigUint) -> BigUint { m = n % &temp; n = temp; } - n + return n; } #[bench] diff --git a/third_party/rust/num-bigint/benches/roots.rs b/third_party/rust/num-bigint/benches/roots.rs index 2433cf0a4373..51e67d9f3d7e 100644 --- a/third_party/rust/num-bigint/benches/roots.rs +++ b/third_party/rust/num-bigint/benches/roots.rs @@ -1,11 +1,14 @@ #![feature(test)] #![cfg(feature = "rand")] +extern crate num_bigint; +extern crate num_traits; +extern crate rand; extern crate test; use num_bigint::{BigUint, RandBigInt}; -use rand::rngs::StdRng; -use rand::SeedableRng; +use num_traits::Pow; +use rand::{SeedableRng, StdRng}; use test::Bencher; // The `big64` cases demonstrate the speed of cases where the value @@ -43,7 +46,7 @@ fn check(x: &BigUint, n: u32) { assert_eq!((&hi - 1u32).nth_root(n), root); } -fn bench_sqrt(b: &mut Bencher, bits: u64) { +fn bench_sqrt(b: &mut Bencher, bits: usize) { let x = get_rng().gen_biguint(bits); eprintln!("bench_sqrt({})", x); @@ -71,7 +74,7 @@ fn big4k_sqrt(b: &mut Bencher) { bench_sqrt(b, 4096); } -fn bench_cbrt(b: &mut Bencher, bits: u64) { +fn bench_cbrt(b: &mut Bencher, bits: usize) { let x = get_rng().gen_biguint(bits); eprintln!("bench_cbrt({})", x); @@ -99,7 +102,7 @@ fn big4k_cbrt(b: &mut Bencher) { bench_cbrt(b, 4096); } -fn bench_nth_root(b: &mut Bencher, bits: u64, n: u32) { +fn bench_nth_root(b: &mut Bencher, bits: usize, n: u32) { let x = get_rng().gen_biguint(bits); eprintln!("bench_{}th_root({})", n, x); diff --git a/third_party/rust/num-bigint/benches/shootout-pidigits.rs b/third_party/rust/num-bigint/benches/shootout-pidigits.rs index b95d42cc40a5..f90a6973575b 100644 --- a/third_party/rust/num-bigint/benches/shootout-pidigits.rs +++ b/third_party/rust/num-bigint/benches/shootout-pidigits.rs @@ -38,6 +38,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; + use std::io; use std::str::FromStr; @@ -94,7 +98,7 @@ fn pidigits(n: isize, out: &mut dyn io::Write) -> io::Result<()> { let mut k = 0; let mut context = Context::new(); - for i in 1..=n { + for i in 1..(n + 1) { let mut d; loop { k += 1; @@ -107,7 +111,7 @@ fn pidigits(n: isize, out: &mut dyn io::Write) -> io::Result<()> { write!(out, "{}", d)?; if i % 10 == 0 { - writeln!(out, "\t:{}", i)?; + write!(out, "\t:{}\n", i)?; } context.eliminate_digit(d); @@ -118,7 +122,7 @@ fn pidigits(n: isize, out: &mut dyn io::Write) -> io::Result<()> { for _ in m..10 { write!(out, " ")?; } - writeln!(out, "\t:{}", n)?; + write!(out, "\t:{}\n", n)?; } Ok(()) } diff --git a/third_party/rust/num-bigint-0.2.3/bors.toml b/third_party/rust/num-bigint/bors.toml similarity index 100% rename from third_party/rust/num-bigint-0.2.3/bors.toml rename to third_party/rust/num-bigint/bors.toml diff --git a/third_party/rust/num-bigint/build.rs b/third_party/rust/num-bigint/build.rs index 93ee0998a817..15590bbc12bb 100644 --- a/third_party/rust/num-bigint/build.rs +++ b/third_party/rust/num-bigint/build.rs @@ -1,71 +1,14 @@ +extern crate autocfg; + use std::env; -use std::error::Error; -use std::fs::File; -use std::io::Write; -use std::path::Path; fn main() { - let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH"); - if pointer_width.as_ref().map(String::as_str) == Ok("64") { - autocfg::emit("u64_digit"); - } let ac = autocfg::new(); - if ac.probe_path("std::convert::TryFrom") || ac.probe_path("core::convert::TryFrom") { - autocfg::emit("has_try_from"); + if ac.probe_type("i128") { + println!("cargo:rustc-cfg=has_i128"); + } else if env::var_os("CARGO_FEATURE_I128").is_some() { + panic!("i128 support was not detected!"); } - autocfg::rerun_path("build.rs"); - - write_radix_bases().unwrap(); -} - -/// Write tables of the greatest power of each radix for the given bit size. These are returned -/// from `biguint::get_radix_base` to batch the multiplication/division of radix conversions on -/// full `BigUint` values, operating on primitive integers as much as possible. -/// -/// e.g. BASES_16[3] = (59049, 10) // 3¹⁰ fits in u16, but 3¹¹ is too big -/// BASES_32[3] = (3486784401, 20) -/// BASES_64[3] = (12157665459056928801, 40) -/// -/// Powers of two are not included, just zeroed, as they're implemented with shifts. -fn write_radix_bases() -> Result<(), Box> { - let out_dir = env::var("OUT_DIR")?; - let dest_path = Path::new(&out_dir).join("radix_bases.rs"); - let mut f = File::create(&dest_path)?; - - for &bits in &[16, 32, 64] { - let max = if bits < 64 { - (1 << bits) - 1 - } else { - std::u64::MAX - }; - - writeln!(f, "#[deny(overflowing_literals)]")?; - writeln!( - f, - "pub(crate) static BASES_{bits}: [(u{bits}, usize); 257] = [", - bits = bits - )?; - for radix in 0u64..257 { - let (base, power) = if radix == 0 || radix.is_power_of_two() { - (0, 0) - } else { - let mut power = 1; - let mut base = radix; - - while let Some(b) = base.checked_mul(radix) { - if b > max { - break; - } - base = b; - power += 1; - } - (base, power) - }; - writeln!(f, " ({}, {}), // {}", base, power, radix)?; - } - writeln!(f, "];")?; - } - - Ok(()) + autocfg::rerun_path(file!()); } diff --git a/third_party/rust/num-bigint-0.2.3/ci/rustup.sh b/third_party/rust/num-bigint/ci/rustup.sh similarity index 100% rename from third_party/rust/num-bigint-0.2.3/ci/rustup.sh rename to third_party/rust/num-bigint/ci/rustup.sh diff --git a/third_party/rust/num-bigint-0.2.3/ci/test_full.sh b/third_party/rust/num-bigint/ci/test_full.sh similarity index 100% rename from third_party/rust/num-bigint-0.2.3/ci/test_full.sh rename to third_party/rust/num-bigint/ci/test_full.sh diff --git a/third_party/rust/num-bigint/src/algorithms.rs b/third_party/rust/num-bigint/src/algorithms.rs index a9b52144a6e2..26f29b81546f 100644 --- a/third_party/rust/num-bigint/src/algorithms.rs +++ b/third_party/rust/num-bigint/src/algorithms.rs @@ -1,18 +1,18 @@ -use crate::std_alloc::{Cow, Vec}; -use core::cmp; -use core::cmp::Ordering::{self, Equal, Greater, Less}; -use core::iter::repeat; -use core::mem; -use num_traits::{One, PrimInt, Zero}; +use std::borrow::Cow; +use std::cmp; +use std::cmp::Ordering::{self, Equal, Greater, Less}; +use std::iter::repeat; +use std::mem; +use traits; +use traits::{One, Zero}; -use crate::biguint::biguint_from_vec; -use crate::biguint::BigUint; +use biguint::BigUint; -use crate::bigint::BigInt; -use crate::bigint::Sign; -use crate::bigint::Sign::{Minus, NoSign, Plus}; +use bigint::BigInt; +use bigint::Sign; +use bigint::Sign::{Minus, NoSign, Plus}; -use crate::big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; +use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; // Generic functions for add/subtract/multiply with carry/borrow: @@ -37,12 +37,7 @@ fn sbb(a: BigDigit, b: BigDigit, acc: &mut SignedDoubleBigDigit) -> BigDigit { } #[inline] -pub(crate) fn mac_with_carry( - a: BigDigit, - b: BigDigit, - c: BigDigit, - acc: &mut DoubleBigDigit, -) -> BigDigit { +pub fn mac_with_carry(a: BigDigit, b: BigDigit, c: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { *acc += DoubleBigDigit::from(a); *acc += DoubleBigDigit::from(b) * DoubleBigDigit::from(c); let lo = *acc as BigDigit; @@ -51,7 +46,7 @@ pub(crate) fn mac_with_carry( } #[inline] -pub(crate) fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { +pub fn mul_with_carry(a: BigDigit, b: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit { *acc += DoubleBigDigit::from(a) * DoubleBigDigit::from(b); let lo = *acc as BigDigit; *acc >>= big_digit::BITS; @@ -73,67 +68,31 @@ fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigi ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit) } -/// For small divisors, we can divide without promoting to `DoubleBigDigit` by -/// using half-size pieces of digit, like long-division. -#[inline] -fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) { - use crate::big_digit::{HALF, HALF_BITS}; - use num_integer::Integer; - - debug_assert!(rem < divisor && divisor <= HALF); - let (hi, rem) = ((rem << HALF_BITS) | (digit >> HALF_BITS)).div_rem(&divisor); - let (lo, rem) = ((rem << HALF_BITS) | (digit & HALF)).div_rem(&divisor); - ((hi << HALF_BITS) | lo, rem) -} - -#[inline] -pub(crate) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) { +pub fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) { let mut rem = 0; - if b <= big_digit::HALF { - for d in a.data.iter_mut().rev() { - let (q, r) = div_half(rem, *d, b); - *d = q; - rem = r; - } - } else { - for d in a.data.iter_mut().rev() { - let (q, r) = div_wide(rem, *d, b); - *d = q; - rem = r; - } + for d in a.data.iter_mut().rev() { + let (q, r) = div_wide(rem, *d, b); + *d = q; + rem = r; } (a.normalized(), rem) } -#[inline] -pub(crate) fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit { - let mut rem = 0; - - if b <= big_digit::HALF { - for &digit in a.data.iter().rev() { - let (_, r) = div_half(rem, digit, b); - rem = r; - } - } else { - for &digit in a.data.iter().rev() { - let (_, r) = div_wide(rem, digit, b); - rem = r; - } +pub fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit { + let mut rem: DoubleBigDigit = 0; + for &digit in a.data.iter().rev() { + rem = (rem << big_digit::BITS) + DoubleBigDigit::from(digit); + rem %= DoubleBigDigit::from(b); } - rem + rem as BigDigit } -/// Two argument addition of raw slices, `a += b`, returning the carry. -/// -/// This is used when the data `Vec` might need to resize to push a non-zero carry, so we perform -/// the addition first hoping that it will fit. -/// -/// The caller _must_ ensure that `a` is at least as long as `b`. +// Only for the Add impl: #[inline] -pub(crate) fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit { +pub fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit { debug_assert!(a.len() >= b.len()); let mut carry = 0; @@ -160,13 +119,13 @@ pub(crate) fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit { /// /// The caller _must_ ensure that a is big enough to store the result - typically this means /// resizing a to max(a.len(), b.len()) + 1, to fit a possible carry. -pub(crate) fn add2(a: &mut [BigDigit], b: &[BigDigit]) { +pub fn add2(a: &mut [BigDigit], b: &[BigDigit]) { let carry = __add2(a, b); debug_assert!(carry == 0); } -pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { +pub fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { let mut borrow = 0; let len = cmp::min(a.len(), b.len()); @@ -195,7 +154,7 @@ pub(crate) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { // Only for the Sub impl. `a` and `b` must have same length. #[inline] -pub(crate) fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit { +pub fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit { debug_assert!(b.len() == a.len()); let mut borrow = 0; @@ -207,7 +166,7 @@ pub(crate) fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> BigDigit { borrow as BigDigit } -pub(crate) fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { +pub fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { debug_assert!(b.len() >= a.len()); let len = cmp::min(a.len(), b.len()); @@ -225,7 +184,7 @@ pub(crate) fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { ); } -pub(crate) fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) { +pub fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) { // Normalize: let a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; let b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; @@ -234,12 +193,12 @@ pub(crate) fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) { Greater => { let mut a = a.to_vec(); sub2(&mut a, b); - (Plus, biguint_from_vec(a)) + (Plus, BigUint::new(a)) } Less => { let mut b = b.to_vec(); sub2(&mut b, a); - (Minus, biguint_from_vec(b)) + (Minus, BigUint::new(b)) } _ => (NoSign, Zero::zero()), } @@ -247,7 +206,7 @@ pub(crate) fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) { /// Three argument multiply accumulate: /// acc += b * c -pub(crate) fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { +pub fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { if c == 0 { return; } @@ -266,10 +225,6 @@ pub(crate) fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { } } -fn bigint_from_slice(slice: &[BigDigit]) -> BigInt { - BigInt::from(biguint_from_vec(slice.to_vec())) -} - /// Three argument multiply accumulate: /// acc += b * c fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) { @@ -432,14 +387,14 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) { // in place of multiplications. // // x(t) = x2*t^2 + x1*t + x0 - let x0 = bigint_from_slice(&x[..x0_len]); - let x1 = bigint_from_slice(&x[x0_len..x0_len + x1_len]); - let x2 = bigint_from_slice(&x[x0_len + x1_len..]); + let x0 = BigInt::from_slice(Plus, &x[..x0_len]); + let x1 = BigInt::from_slice(Plus, &x[x0_len..x0_len + x1_len]); + let x2 = BigInt::from_slice(Plus, &x[x0_len + x1_len..]); // y(t) = y2*t^2 + y1*t + y0 - let y0 = bigint_from_slice(&y[..y0_len]); - let y1 = bigint_from_slice(&y[y0_len..y0_len + y1_len]); - let y2 = bigint_from_slice(&y[y0_len + y1_len..]); + let y0 = BigInt::from_slice(Plus, &y[..y0_len]); + let y1 = BigInt::from_slice(Plus, &y[y0_len..y0_len + y1_len]); + let y2 = BigInt::from_slice(Plus, &y[y0_len + y1_len..]); // Let w(t) = x(t) * y(t) // @@ -515,24 +470,23 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) { let mut comp1: BigInt = (r1 - &r2) / 2; let mut comp2: BigInt = r2 - &r0; comp3 = (&comp2 - comp3) / 2 + &r4 * 2; - comp2 += &comp1 - &r4; - comp1 -= &comp3; + comp2 = comp2 + &comp1 - &r4; + comp1 = comp1 - &comp3; // Recomposition. The coefficients of the polynomial are now known. // // Evaluate at w(t) where t is our given base to get the result. - let bits = u64::from(big_digit::BITS) * i as u64; let result = r0 - + (comp1 << bits) - + (comp2 << (2 * bits)) - + (comp3 << (3 * bits)) - + (r4 << (4 * bits)); + + (comp1 << 32 * i) + + (comp2 << 2 * 32 * i) + + (comp3 << 3 * 32 * i) + + (r4 << 4 * 32 * i); let result_pos = result.to_biguint().unwrap(); add2(&mut acc[..], &result_pos.data); } } -pub(crate) fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { +pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { let len = x.len() + y.len() + 1; let mut prod = BigUint { data: vec![0; len] }; @@ -540,7 +494,7 @@ pub(crate) fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { prod.normalized() } -pub(crate) fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit { +pub fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit { let mut carry = 0; for a in a.iter_mut() { *a = mul_with_carry(*a, b, &mut carry); @@ -548,9 +502,9 @@ pub(crate) fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit { carry as BigDigit } -pub(crate) fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { +pub fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { if d.is_zero() { - panic!("attempt to divide by zero") + panic!() } if u.is_zero() { return (Zero::zero(), Zero::zero()); @@ -584,7 +538,6 @@ pub(crate) fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { // want it to be the largest number we can efficiently divide by. // let shift = d.data.last().unwrap().leading_zeros() as usize; - let (q, r) = if shift == 0 { // no need to clone d div_rem_core(u, &d) @@ -595,9 +548,9 @@ pub(crate) fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { (q, r >> shift) } -pub(crate) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { +pub fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { if d.is_zero() { - panic!("attempt to divide by zero") + panic!() } if u.is_zero() { return (Zero::zero(), Zero::zero()); @@ -702,8 +655,9 @@ fn div_rem_core(mut a: BigUint, b: &BigUint) -> (BigUint, BigUint) { let mut prod = b * &q0; while cmp_slice(&prod.data[..], &a.data[j..]) == Greater { - q0 -= 1u32; - prod -= b; + let one: BigUint = One::one(); + q0 = q0 - one; + prod = prod - b; } add2(&mut q.data[j..], &q0.data[..]); @@ -713,53 +667,41 @@ fn div_rem_core(mut a: BigUint, b: &BigUint) -> (BigUint, BigUint) { tmp = q0; } - debug_assert!(a < *b); + debug_assert!(&a < b); (q.normalized(), a) } /// Find last set bit /// fls(0) == 0, fls(u32::MAX) == 32 -pub(crate) fn fls(v: T) -> u8 { - mem::size_of::() as u8 * 8 - v.leading_zeros() as u8 +pub fn fls(v: T) -> usize { + mem::size_of::() * 8 - v.leading_zeros() as usize } -pub(crate) fn ilog2(v: T) -> u8 { +pub fn ilog2(v: T) -> usize { fls(v) - 1 } #[inline] -pub(crate) fn biguint_shl(n: Cow<'_, BigUint>, shift: T) -> BigUint { - if shift < T::zero() { - panic!("attempt to shift left with negative"); - } - if n.is_zero() { - return n.into_owned(); - } - let bits = T::from(big_digit::BITS).unwrap(); - let digits = (shift / bits).to_usize().expect("capacity overflow"); - let shift = (shift % bits).to_u8().unwrap(); - biguint_shl2(n, digits, shift) -} - -fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { - let mut data = match digits { +pub fn biguint_shl(n: Cow, bits: usize) -> BigUint { + let n_unit = bits / big_digit::BITS; + let mut data = match n_unit { 0 => n.into_owned().data, _ => { - let len = digits.saturating_add(n.data.len() + 1); + let len = n_unit + n.data.len() + 1; let mut data = Vec::with_capacity(len); - data.extend(repeat(0).take(digits)); - data.extend(n.data.iter()); + data.extend(repeat(0).take(n_unit)); + data.extend(n.data.iter().cloned()); data } }; - if shift > 0 { + let n_bits = bits % big_digit::BITS; + if n_bits > 0 { let mut carry = 0; - let carry_shift = big_digit::BITS as u8 - shift; - for elem in data[digits..].iter_mut() { - let new_carry = *elem >> carry_shift; - *elem = (*elem << shift) | carry; + for elem in data[n_unit..].iter_mut() { + let new_carry = *elem >> (big_digit::BITS - n_bits); + *elem = (*elem << n_bits) | carry; carry = new_carry; } if carry != 0 { @@ -767,65 +709,65 @@ fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { } } - biguint_from_vec(data) + BigUint::new(data) } #[inline] -pub(crate) fn biguint_shr(n: Cow<'_, BigUint>, shift: T) -> BigUint { - if shift < T::zero() { - panic!("attempt to shift right with negative"); - } - if n.is_zero() { - return n.into_owned(); - } - let bits = T::from(big_digit::BITS).unwrap(); - let digits = (shift / bits).to_usize().unwrap_or(core::usize::MAX); - let shift = (shift % bits).to_u8().unwrap(); - biguint_shr2(n, digits, shift) -} - -fn biguint_shr2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { - if digits >= n.data.len() { - let mut n = n.into_owned(); - n.set_zero(); - return n; +pub fn biguint_shr(n: Cow, bits: usize) -> BigUint { + let n_unit = bits / big_digit::BITS; + if n_unit >= n.data.len() { + return Zero::zero(); } let mut data = match n { - Cow::Borrowed(n) => n.data[digits..].to_vec(), + Cow::Borrowed(n) => n.data[n_unit..].to_vec(), Cow::Owned(mut n) => { - n.data.drain(..digits); + n.data.drain(..n_unit); n.data } }; - if shift > 0 { + let n_bits = bits % big_digit::BITS; + if n_bits > 0 { let mut borrow = 0; - let borrow_shift = big_digit::BITS as u8 - shift; for elem in data.iter_mut().rev() { - let new_borrow = *elem << borrow_shift; - *elem = (*elem >> shift) | borrow; + let new_borrow = *elem << (big_digit::BITS - n_bits); + *elem = (*elem >> n_bits) | borrow; borrow = new_borrow; } } - biguint_from_vec(data) + BigUint::new(data) } -pub(crate) fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { +pub fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { debug_assert!(a.last() != Some(&0)); debug_assert!(b.last() != Some(&0)); - match Ord::cmp(&a.len(), &b.len()) { - Equal => Iterator::cmp(a.iter().rev(), b.iter().rev()), - other => other, + let (a_len, b_len) = (a.len(), b.len()); + if a_len < b_len { + return Less; } + if a_len > b_len { + return Greater; + } + + for (&ai, &bi) in a.iter().rev().zip(b.iter().rev()) { + if ai < bi { + return Less; + } + if ai > bi { + return Greater; + } + } + return Equal; } #[cfg(test)] mod algorithm_tests { - use crate::big_digit::BigDigit; - use crate::{BigInt, BigUint}; - use num_traits::Num; + use big_digit::BigDigit; + use traits::Num; + use Sign::Plus; + use {BigInt, BigUint}; #[test] fn test_sub_sign() { @@ -838,8 +780,8 @@ mod algorithm_tests { let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap(); let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap(); - let a_i = BigInt::from(a.clone()); - let b_i = BigInt::from(b.clone()); + let a_i = BigInt::from_biguint(Plus, a.clone()); + let b_i = BigInt::from_biguint(Plus, b.clone()); assert_eq!(sub_sign_i(&a.data[..], &b.data[..]), &a_i - &b_i); assert_eq!(sub_sign_i(&b.data[..], &a.data[..]), &b_i - &a_i); diff --git a/third_party/rust/num-bigint/src/bigint.rs b/third_party/rust/num-bigint/src/bigint.rs index a78645e9e012..93c72be6af49 100644 --- a/third_party/rust/num-bigint/src/bigint.rs +++ b/third_party/rust/num-bigint/src/bigint.rs @@ -1,46 +1,38 @@ -// `Add`/`Sub` ops may flip from `BigInt` to its `BigUint` magnitude -#![allow(clippy::suspicious_arithmetic_impl)] - -#[cfg(feature = "quickcheck")] -use crate::std_alloc::Box; -use crate::std_alloc::{String, Vec}; -use core::cmp::Ordering::{self, Equal, Greater, Less}; -#[cfg(has_try_from)] -use core::convert::TryFrom; -use core::default::Default; -use core::fmt; -use core::hash; -use core::iter::{Product, Sum}; -use core::mem; -use core::ops::{ +#[allow(deprecated, unused_imports)] +use std::ascii::AsciiExt; +use std::cmp::Ordering::{self, Equal, Greater, Less}; +use std::default::Default; +use std::fmt; +use std::iter::{Product, Sum}; +use std::mem; +use std::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }; -use core::str::{self, FromStr}; -use core::{i128, u128}; -use core::{i64, u64}; +use std::str::{self, FromStr}; +#[cfg(has_i128)] +use std::{i128, u128}; +use std::{i64, u64}; #[cfg(feature = "serde")] use serde; -use num_integer::{Integer, Roots}; -use num_traits::{ - CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, PrimInt, Signed, +use integer::{Integer, Roots}; +use traits::{ + CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero, }; use self::Sign::{Minus, NoSign, Plus}; -use crate::big_digit::{self, BigDigit, DoubleBigDigit}; -use crate::biguint; -use crate::biguint::to_str_radix_reversed; -use crate::biguint::{BigUint, IntDigits}; -use crate::ParseBigIntError; -#[cfg(has_try_from)] -use crate::TryFromBigIntError; +use super::ParseBigIntError; +use big_digit::{self, BigDigit, DoubleBigDigit}; +use biguint; +use biguint::to_str_radix_reversed; +use biguint::{BigUint, IntDigits}; -use crate::IsizePromotion; -use crate::UsizePromotion; +use IsizePromotion; +use UsizePromotion; #[cfg(feature = "quickcheck")] use quickcheck::{Arbitrary, Gen}; @@ -119,30 +111,12 @@ impl<'de> serde::Deserialize<'de> for Sign { } /// A big signed integer type. -#[derive(Debug)] +#[derive(Clone, Debug, Hash)] pub struct BigInt { sign: Sign, data: BigUint, } -// Note: derived `Clone` doesn't specialize `clone_from`, -// but we want to keep the allocation in `data`. -impl Clone for BigInt { - #[inline] - fn clone(&self) -> Self { - BigInt { - sign: self.sign, - data: self.data.clone(), - } - } - - #[inline] - fn clone_from(&mut self, other: &Self) { - self.sign = other.sign; - self.data.clone_from(&other.data); - } -} - #[cfg(feature = "quickcheck")] impl Arbitrary for BigInt { fn arbitrary(g: &mut G) -> Self { @@ -151,7 +125,8 @@ impl Arbitrary for BigInt { Self::from_biguint(sign, BigUint::arbitrary(g)) } - fn shrink(&self) -> Box> { + #[allow(bare_trait_objects)] // `dyn` needs Rust 1.27 to parse, even when cfg-disabled + fn shrink(&self) -> Box> { let sign = self.sign(); let unsigned_shrink = self.data.shrink(); Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x))) @@ -159,34 +134,25 @@ impl Arbitrary for BigInt { } /// Return the magnitude of a `BigInt`. +/// +/// This is in a private module, pseudo pub(crate) #[cfg(feature = "rand")] -pub(crate) fn magnitude(i: &BigInt) -> &BigUint { +pub fn magnitude(i: &BigInt) -> &BigUint { &i.data } /// Return the owned magnitude of a `BigInt`. +/// +/// This is in a private module, pseudo pub(crate) #[cfg(feature = "rand")] -pub(crate) fn into_magnitude(i: BigInt) -> BigUint { +pub fn into_magnitude(i: BigInt) -> BigUint { i.data } -impl hash::Hash for BigInt { - #[inline] - fn hash(&self, state: &mut H) { - debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); - self.sign.hash(state); - if self.sign != NoSign { - self.data.hash(state); - } - } -} - impl PartialEq for BigInt { #[inline] fn eq(&self, other: &BigInt) -> bool { - debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); - debug_assert!((other.sign != NoSign) ^ other.data.is_zero()); - self.sign == other.sign && (self.sign == NoSign || self.data == other.data) + self.cmp(other) == Equal } } @@ -202,8 +168,6 @@ impl PartialOrd for BigInt { impl Ord for BigInt { #[inline] fn cmp(&self, other: &BigInt) -> Ordering { - debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); - debug_assert!((other.sign != NoSign) ^ other.data.is_zero()); let scmp = self.sign.cmp(&other.sign); if scmp != Equal { return scmp; @@ -225,31 +189,31 @@ impl Default for BigInt { } impl fmt::Display for BigInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "", &self.data.to_str_radix(10)) } } impl fmt::Binary for BigInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0b", &self.data.to_str_radix(2)) } } impl fmt::Octal for BigInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0o", &self.data.to_str_radix(8)) } } impl fmt::LowerHex for BigInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0x", &self.data.to_str_radix(16)) } } impl fmt::UpperHex for BigInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut s = self.data.to_str_radix(16); s.make_ascii_uppercase(); f.pad_integral(!self.is_negative(), "0x", &s) @@ -307,9 +271,8 @@ impl<'a> Not for &'a BigInt { fn not(self) -> BigInt { match self.sign { - NoSign => -BigInt::one(), - Plus => -BigInt::from(&self.data + 1u32), - Minus => BigInt::from(&self.data - 1u32), + NoSign | Plus => BigInt::from_biguint(Minus, &self.data + 1u32), + Minus => BigInt::from_biguint(Plus, &self.data - 1u32), } } } @@ -336,13 +299,11 @@ fn bitand_neg_pos(a: &mut Vec, b: &[BigDigit]) { *ai = twos_a & bi; } debug_assert!(a.len() > b.len() || carry_a == 0); - match Ord::cmp(&a.len(), &b.len()) { - Greater => a.truncate(b.len()), - Equal => {} - Less => { - let extra = &b[a.len()..]; - a.extend(extra.iter().cloned()); - } + if a.len() > b.len() { + a.truncate(b.len()); + } else if b.len() > a.len() { + let extra = &b[a.len()..]; + a.extend(extra.iter().cloned()); } } @@ -361,23 +322,19 @@ fn bitand_neg_neg(a: &mut Vec, b: &[BigDigit]) { } debug_assert!(a.len() > b.len() || carry_a == 0); debug_assert!(b.len() > a.len() || carry_b == 0); - match Ord::cmp(&a.len(), &b.len()) { - Greater => { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a, &mut carry_and); - } - debug_assert!(carry_a == 0); - } - Equal => {} - Less => { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_b = negate_carry(bi, &mut carry_b); - negate_carry(twos_b, &mut carry_and) - })); - debug_assert!(carry_b == 0); + if a.len() > b.len() { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a, &mut carry_and); } + debug_assert!(carry_a == 0); + } else if b.len() > a.len() { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_b = negate_carry(bi, &mut carry_b); + negate_carry(twos_b, &mut carry_and) + })); + debug_assert!(carry_b == 0); } if carry_and != 0 { a.push(1); @@ -395,8 +352,8 @@ impl<'a, 'b> BitAnd<&'b BigInt> for &'a BigInt { #[inline] fn bitand(self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { - (NoSign, _) | (_, NoSign) => BigInt::zero(), - (Plus, Plus) => BigInt::from(&self.data & &other.data), + (NoSign, _) | (_, NoSign) => BigInt::from_slice(NoSign, &[]), + (Plus, Plus) => BigInt::from_biguint(Plus, &self.data & &other.data), (Plus, Minus) => self.clone() & other, (Minus, Plus) => other.clone() & self, (Minus, Minus) => { @@ -427,7 +384,7 @@ impl<'a> BitAndAssign<&'a BigInt> for BigInt { fn bitand_assign(&mut self, other: &BigInt) { match (self.sign, other.sign) { (NoSign, _) => {} - (_, NoSign) => self.set_zero(), + (_, NoSign) => self.assign_from_slice(NoSign, &[]), (Plus, Plus) => { self.data &= &other.data; if self.data.is_zero() { @@ -462,19 +419,15 @@ fn bitor_pos_neg(a: &mut Vec, b: &[BigDigit]) { *ai = negate_carry(*ai | twos_b, &mut carry_or); } debug_assert!(b.len() > a.len() || carry_b == 0); - match Ord::cmp(&a.len(), &b.len()) { - Greater => { - a.truncate(b.len()); - } - Equal => {} - Less => { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_b = negate_carry(bi, &mut carry_b); - negate_carry(twos_b, &mut carry_or) - })); - debug_assert!(carry_b == 0); - } + if a.len() > b.len() { + a.truncate(b.len()); + } else if b.len() > a.len() { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_b = negate_carry(bi, &mut carry_b); + negate_carry(twos_b, &mut carry_or) + })); + debug_assert!(carry_b == 0); } // for carry_or to be non-zero, we would need twos_b == 0 debug_assert!(carry_or == 0); @@ -536,7 +489,7 @@ impl<'a, 'b> BitOr<&'b BigInt> for &'a BigInt { match (self.sign, other.sign) { (NoSign, _) => other.clone(), (_, NoSign) => self.clone(), - (Plus, Plus) => BigInt::from(&self.data | &other.data), + (Plus, Plus) => BigInt::from_biguint(Plus, &self.data | &other.data), (Plus, Minus) => other.clone() | self, (Minus, Plus) => self.clone() | other, (Minus, Minus) => { @@ -567,7 +520,7 @@ impl<'a> BitOrAssign<&'a BigInt> for BigInt { fn bitor_assign(&mut self, other: &BigInt) { match (self.sign, other.sign) { (_, NoSign) => {} - (NoSign, _) => self.clone_from(other), + (NoSign, _) => self.assign_from_slice(other.sign, other.digits()), (Plus, Plus) => self.data |= &other.data, (Plus, Minus) => { bitor_pos_neg(self.digits_mut(), other.digits()); @@ -597,22 +550,18 @@ fn bitxor_pos_neg(a: &mut Vec, b: &[BigDigit]) { *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); } debug_assert!(b.len() > a.len() || carry_b == 0); - match Ord::cmp(&a.len(), &b.len()) { - Greater => { - for ai in a[b.len()..].iter_mut() { - let twos_b = !0; - *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); - } - } - Equal => {} - Less => { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_b = negate_carry(bi, &mut carry_b); - negate_carry(twos_b, &mut carry_xor) - })); - debug_assert!(carry_b == 0); + if a.len() > b.len() { + for ai in a[b.len()..].iter_mut() { + let twos_b = !0; + *ai = negate_carry(*ai ^ twos_b, &mut carry_xor); } + } else if b.len() > a.len() { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_b = negate_carry(bi, &mut carry_b); + negate_carry(twos_b, &mut carry_xor) + })); + debug_assert!(carry_b == 0); } if carry_xor != 0 { a.push(1); @@ -630,22 +579,18 @@ fn bitxor_neg_pos(a: &mut Vec, b: &[BigDigit]) { *ai = negate_carry(twos_a ^ bi, &mut carry_xor); } debug_assert!(a.len() > b.len() || carry_a == 0); - match Ord::cmp(&a.len(), &b.len()) { - Greater => { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - *ai = negate_carry(twos_a, &mut carry_xor); - } - debug_assert!(carry_a == 0); - } - Equal => {} - Less => { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_a = !0; - negate_carry(twos_a ^ bi, &mut carry_xor) - })); + if a.len() > b.len() { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + *ai = negate_carry(twos_a, &mut carry_xor); } + debug_assert!(carry_a == 0); + } else if b.len() > a.len() { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_a = !0; + negate_carry(twos_a ^ bi, &mut carry_xor) + })); } if carry_xor != 0 { a.push(1); @@ -665,25 +610,21 @@ fn bitxor_neg_neg(a: &mut Vec, b: &[BigDigit]) { } debug_assert!(a.len() > b.len() || carry_a == 0); debug_assert!(b.len() > a.len() || carry_b == 0); - match Ord::cmp(&a.len(), &b.len()) { - Greater => { - for ai in a[b.len()..].iter_mut() { - let twos_a = negate_carry(*ai, &mut carry_a); - let twos_b = !0; - *ai = twos_a ^ twos_b; - } - debug_assert!(carry_a == 0); - } - Equal => {} - Less => { - let extra = &b[a.len()..]; - a.extend(extra.iter().map(|&bi| { - let twos_a = !0; - let twos_b = negate_carry(bi, &mut carry_b); - twos_a ^ twos_b - })); - debug_assert!(carry_b == 0); + if a.len() > b.len() { + for ai in a[b.len()..].iter_mut() { + let twos_a = negate_carry(*ai, &mut carry_a); + let twos_b = !0; + *ai = twos_a ^ twos_b; } + debug_assert!(carry_a == 0); + } else if b.len() > a.len() { + let extra = &b[a.len()..]; + a.extend(extra.iter().map(|&bi| { + let twos_a = !0; + let twos_b = negate_carry(bi, &mut carry_b); + twos_a ^ twos_b + })); + debug_assert!(carry_b == 0); } } @@ -705,7 +646,7 @@ impl<'a> BitXorAssign<&'a BigInt> for BigInt { fn bitxor_assign(&mut self, other: &BigInt) { match (self.sign, other.sign) { (_, NoSign) => {} - (NoSign, _) => self.clone_from(other), + (NoSign, _) => self.assign_from_slice(other.sign, other.digits()), (Plus, Plus) => { self.data ^= &other.data; if self.data.is_zero() { @@ -759,115 +700,79 @@ impl Num for BigInt { } } -macro_rules! impl_shift { - (@ref $Shx:ident :: $shx:ident, $ShxAssign:ident :: $shx_assign:ident, $rhs:ty) => { - impl<'b> $Shx<&'b $rhs> for BigInt { - type Output = BigInt; +impl Shl for BigInt { + type Output = BigInt; - #[inline] - fn $shx(self, rhs: &'b $rhs) -> BigInt { - $Shx::$shx(self, *rhs) - } - } - impl<'a, 'b> $Shx<&'b $rhs> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn $shx(self, rhs: &'b $rhs) -> BigInt { - $Shx::$shx(self, *rhs) - } - } - impl<'b> $ShxAssign<&'b $rhs> for BigInt { - #[inline] - fn $shx_assign(&mut self, rhs: &'b $rhs) { - $ShxAssign::$shx_assign(self, *rhs); - } - } - }; - ($($rhs:ty),+) => {$( - impl Shl<$rhs> for BigInt { - type Output = BigInt; - - #[inline] - fn shl(self, rhs: $rhs) -> BigInt { - BigInt::from_biguint(self.sign, self.data << rhs) - } - } - impl<'a> Shl<$rhs> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn shl(self, rhs: $rhs) -> BigInt { - BigInt::from_biguint(self.sign, &self.data << rhs) - } - } - impl ShlAssign<$rhs> for BigInt { - #[inline] - fn shl_assign(&mut self, rhs: $rhs) { - self.data <<= rhs - } - } - impl_shift! { @ref Shl::shl, ShlAssign::shl_assign, $rhs } - - impl Shr<$rhs> for BigInt { - type Output = BigInt; - - #[inline] - fn shr(self, rhs: $rhs) -> BigInt { - let round_down = shr_round_down(&self, rhs); - let data = self.data >> rhs; - let data = if round_down { data + 1u8 } else { data }; - BigInt::from_biguint(self.sign, data) - } - } - impl<'a> Shr<$rhs> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn shr(self, rhs: $rhs) -> BigInt { - let round_down = shr_round_down(self, rhs); - let data = &self.data >> rhs; - let data = if round_down { data + 1u8 } else { data }; - BigInt::from_biguint(self.sign, data) - } - } - impl ShrAssign<$rhs> for BigInt { - #[inline] - fn shr_assign(&mut self, rhs: $rhs) { - let round_down = shr_round_down(self, rhs); - self.data >>= rhs; - if round_down { - self.data += 1u8; - } else if self.data.is_zero() { - self.sign = NoSign; - } - } - } - impl_shift! { @ref Shr::shr, ShrAssign::shr_assign, $rhs } - )*}; + #[inline] + fn shl(mut self, rhs: usize) -> BigInt { + self <<= rhs; + self + } } -impl_shift! { u8, u16, u32, u64, u128, usize } -impl_shift! { i8, i16, i32, i64, i128, isize } +impl<'a> Shl for &'a BigInt { + type Output = BigInt; + + #[inline] + fn shl(self, rhs: usize) -> BigInt { + BigInt::from_biguint(self.sign, &self.data << rhs) + } +} + +impl ShlAssign for BigInt { + #[inline] + fn shl_assign(&mut self, rhs: usize) { + self.data <<= rhs; + } +} // Negative values need a rounding adjustment if there are any ones in the // bits that are getting shifted out. -fn shr_round_down(i: &BigInt, shift: T) -> bool { - if i.is_negative() { - let zeros = i.trailing_zeros().expect("negative values are non-zero"); - shift > T::zero() && shift.to_u64().map(|shift| zeros < shift).unwrap_or(true) - } else { - false +fn shr_round_down(i: &BigInt, rhs: usize) -> bool { + i.is_negative() + && biguint::trailing_zeros(&i.data) + .map(|n| n < rhs) + .unwrap_or(false) +} + +impl Shr for BigInt { + type Output = BigInt; + + #[inline] + fn shr(mut self, rhs: usize) -> BigInt { + self >>= rhs; + self + } +} + +impl<'a> Shr for &'a BigInt { + type Output = BigInt; + + #[inline] + fn shr(self, rhs: usize) -> BigInt { + let round_down = shr_round_down(self, rhs); + let data = &self.data >> rhs; + BigInt::from_biguint(self.sign, if round_down { data + 1u8 } else { data }) + } +} + +impl ShrAssign for BigInt { + #[inline] + fn shr_assign(&mut self, rhs: usize) { + let round_down = shr_round_down(self, rhs); + self.data >>= rhs; + if round_down { + self.data += 1u8; + } else if self.data.is_zero() { + self.sign = NoSign; + } } } impl Zero for BigInt { #[inline] fn zero() -> BigInt { - BigInt { - sign: NoSign, - data: BigUint::zero(), - } + BigInt::from_biguint(NoSign, Zero::zero()) } #[inline] @@ -885,10 +790,7 @@ impl Zero for BigInt { impl One for BigInt { #[inline] fn one() -> BigInt { - BigInt { - sign: Plus, - data: BigUint::one(), - } + BigInt::from_biguint(Plus, One::one()) } #[inline] @@ -908,7 +810,7 @@ impl Signed for BigInt { fn abs(&self) -> BigInt { match self.sign { Plus | NoSign => self.clone(), - Minus => BigInt::from(self.data.clone()), + Minus => BigInt::from_biguint(Plus, self.data.clone()), } } @@ -924,9 +826,9 @@ impl Signed for BigInt { #[inline] fn signum(&self) -> BigInt { match self.sign { - Plus => BigInt::one(), - Minus => -BigInt::one(), - NoSign => BigInt::zero(), + Plus => BigInt::from_biguint(Plus, One::one()), + Minus => BigInt::from_biguint(Minus, One::one()), + NoSign => Zero::zero(), } } @@ -948,7 +850,9 @@ impl Signed for BigInt { fn powsign(sign: Sign, other: &T) -> Sign { if other.is_zero() { Plus - } else if sign != Minus || other.is_odd() { + } else if sign != Minus { + sign + } else if other.is_odd() { sign } else { -sign @@ -957,30 +861,12 @@ fn powsign(sign: Sign, other: &T) -> Sign { macro_rules! pow_impl { ($T:ty) => { - impl Pow<$T> for BigInt { - type Output = BigInt; - - #[inline] - fn pow(self, rhs: $T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, &rhs), self.data.pow(rhs)) - } - } - - impl<'b> Pow<&'b $T> for BigInt { - type Output = BigInt; - - #[inline] - fn pow(self, rhs: &$T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, rhs), self.data.pow(rhs)) - } - } - impl<'a> Pow<$T> for &'a BigInt { type Output = BigInt; #[inline] fn pow(self, rhs: $T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, &rhs), Pow::pow(&self.data, rhs)) + BigInt::from_biguint(powsign(self.sign, &rhs), (&self.data).pow(rhs)) } } @@ -989,7 +875,7 @@ macro_rules! pow_impl { #[inline] fn pow(self, rhs: &$T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, rhs), Pow::pow(&self.data, rhs)) + BigInt::from_biguint(powsign(self.sign, rhs), (&self.data).pow(rhs)) } } }; @@ -1000,33 +886,40 @@ pow_impl!(u16); pow_impl!(u32); pow_impl!(u64); pow_impl!(usize); +#[cfg(has_i128)] pow_impl!(u128); pow_impl!(BigUint); -trait UnsignedAbs { - type Unsigned; - /// A convenience method for getting the absolute value of a signed primitive as unsigned - fn unsigned_abs(self) -> Self::Unsigned; +// A convenience method for getting the absolute value of an i32 in a u32. +#[inline] +fn i32_abs_as_u32(a: i32) -> u32 { + if a == i32::min_value() { + a as u32 + } else { + a.abs() as u32 + } } -macro_rules! impl_unsigned_abs { - ($Signed:ty, $Unsigned:ty) => { - impl UnsignedAbs for $Signed { - type Unsigned = $Unsigned; - - #[inline] - fn unsigned_abs(self) -> $Unsigned { - self.wrapping_abs() as $Unsigned - } - } - }; +// A convenience method for getting the absolute value of an i64 in a u64. +#[inline] +fn i64_abs_as_u64(a: i64) -> u64 { + if a == i64::min_value() { + a as u64 + } else { + a.abs() as u64 + } +} + +// A convenience method for getting the absolute value of an i128 in a u128. +#[cfg(has_i128)] +#[inline] +fn i128_abs_as_u128(a: i128) -> u128 { + if a == i128::min_value() { + a as u128 + } else { + a.abs() as u128 + } } -impl_unsigned_abs!(i8, u8); -impl_unsigned_abs!(i16, u16); -impl_unsigned_abs!(i32, u32); -impl_unsigned_abs!(i64, u64); -impl_unsigned_abs!(i128, u128); -impl_unsigned_abs!(isize, usize); // We want to forward to BigUint::add, but it's not clear how that will go until // we compare both sign and magnitude. So we duplicate this body for every @@ -1104,6 +997,7 @@ promote_all_scalars!(impl Add for BigInt, add); promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign); forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); impl Add for BigInt { @@ -1113,16 +1007,15 @@ impl Add for BigInt { fn add(self, other: u32) -> BigInt { match self.sign { NoSign => From::from(other), - Plus => BigInt::from(self.data + other), + Plus => BigInt::from_biguint(Plus, self.data + other), Minus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), - Less => BigInt::from(other - self.data), - Greater => -BigInt::from(self.data - other), + Less => BigInt::from_biguint(Plus, other - self.data), + Greater => BigInt::from_biguint(Minus, self.data - other), }, } } } - impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u32) { @@ -1138,16 +1031,15 @@ impl Add for BigInt { fn add(self, other: u64) -> BigInt { match self.sign { NoSign => From::from(other), - Plus => BigInt::from(self.data + other), + Plus => BigInt::from_biguint(Plus, self.data + other), Minus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), - Less => BigInt::from(other - self.data), - Greater => -BigInt::from(self.data - other), + Less => BigInt::from_biguint(Plus, other - self.data), + Greater => BigInt::from_biguint(Minus, self.data - other), }, } } } - impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u64) { @@ -1156,22 +1048,24 @@ impl AddAssign for BigInt { } } +#[cfg(has_i128)] impl Add for BigInt { type Output = BigInt; #[inline] fn add(self, other: u128) -> BigInt { match self.sign { - NoSign => BigInt::from(other), - Plus => BigInt::from(self.data + other), + NoSign => From::from(other), + Plus => BigInt::from_biguint(Plus, self.data + other), Minus => match self.data.cmp(&From::from(other)) { - Equal => BigInt::zero(), - Less => BigInt::from(other - self.data), - Greater => -BigInt::from(self.data - other), + Equal => Zero::zero(), + Less => BigInt::from_biguint(Plus, other - self.data), + Greater => BigInt::from_biguint(Minus, self.data - other), }, } } } +#[cfg(has_i128)] impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u128) { @@ -1182,6 +1076,7 @@ impl AddAssign for BigInt { forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); impl Add for BigInt { @@ -1192,7 +1087,7 @@ impl Add for BigInt { if other >= 0 { self + other as u32 } else { - self - other.unsigned_abs() + self - i32_abs_as_u32(other) } } } @@ -1202,7 +1097,7 @@ impl AddAssign for BigInt { if other >= 0 { *self += other as u32; } else { - *self -= other.unsigned_abs(); + *self -= i32_abs_as_u32(other); } } } @@ -1215,7 +1110,7 @@ impl Add for BigInt { if other >= 0 { self + other as u64 } else { - self - other.unsigned_abs() + self - i64_abs_as_u64(other) } } } @@ -1225,11 +1120,12 @@ impl AddAssign for BigInt { if other >= 0 { *self += other as u64; } else { - *self -= other.unsigned_abs(); + *self -= i64_abs_as_u64(other); } } } +#[cfg(has_i128)] impl Add for BigInt { type Output = BigInt; @@ -1238,17 +1134,18 @@ impl Add for BigInt { if other >= 0 { self + other as u128 } else { - self - other.unsigned_abs() + self - i128_abs_as_u128(other) } } } +#[cfg(has_i128)] impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: i128) { if other >= 0 { *self += other as u128; } else { - *self -= other.unsigned_abs(); + *self -= i128_abs_as_u128(other); } } } @@ -1329,6 +1226,7 @@ promote_all_scalars!(impl Sub for BigInt, sub); promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); impl Sub for BigInt { @@ -1337,12 +1235,12 @@ impl Sub for BigInt { #[inline] fn sub(self, other: u32) -> BigInt { match self.sign { - NoSign => -BigInt::from(other), - Minus => -BigInt::from(self.data + other), + NoSign => BigInt::from_biguint(Minus, From::from(other)), + Minus => BigInt::from_biguint(Minus, self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), - Greater => BigInt::from(self.data - other), - Less => -BigInt::from(other - self.data), + Greater => BigInt::from_biguint(Plus, self.data - other), + Less => BigInt::from_biguint(Minus, other - self.data), }, } } @@ -1372,7 +1270,7 @@ impl Sub for u64 { -(other - self) } } - +#[cfg(has_i128)] impl Sub for u128 { type Output = BigInt; @@ -1388,17 +1286,16 @@ impl Sub for BigInt { #[inline] fn sub(self, other: u64) -> BigInt { match self.sign { - NoSign => -BigInt::from(other), - Minus => -BigInt::from(self.data + other), + NoSign => BigInt::from_biguint(Minus, From::from(other)), + Minus => BigInt::from_biguint(Minus, self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), - Greater => BigInt::from(self.data - other), - Less => -BigInt::from(other - self.data), + Greater => BigInt::from_biguint(Plus, self.data - other), + Less => BigInt::from_biguint(Minus, other - self.data), }, } } } - impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u64) { @@ -1407,23 +1304,24 @@ impl SubAssign for BigInt { } } +#[cfg(has_i128)] impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: u128) -> BigInt { match self.sign { - NoSign => -BigInt::from(other), - Minus => -BigInt::from(self.data + other), + NoSign => BigInt::from_biguint(Minus, From::from(other)), + Minus => BigInt::from_biguint(Minus, self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), - Greater => BigInt::from(self.data - other), - Less => -BigInt::from(other - self.data), + Greater => BigInt::from_biguint(Plus, self.data - other), + Less => BigInt::from_biguint(Minus, other - self.data), }, } } } - +#[cfg(has_i128)] impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u128) { @@ -1434,6 +1332,7 @@ impl SubAssign for BigInt { forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); impl Sub for BigInt { @@ -1444,7 +1343,7 @@ impl Sub for BigInt { if other >= 0 { self - other as u32 } else { - self + other.unsigned_abs() + self + i32_abs_as_u32(other) } } } @@ -1454,7 +1353,7 @@ impl SubAssign for BigInt { if other >= 0 { *self -= other as u32; } else { - *self += other.unsigned_abs(); + *self += i32_abs_as_u32(other); } } } @@ -1467,7 +1366,7 @@ impl Sub for i32 { if self >= 0 { self as u32 - other } else { - -other - self.unsigned_abs() + -other - i32_abs_as_u32(self) } } } @@ -1480,7 +1379,7 @@ impl Sub for BigInt { if other >= 0 { self - other as u64 } else { - self + other.unsigned_abs() + self + i64_abs_as_u64(other) } } } @@ -1490,7 +1389,7 @@ impl SubAssign for BigInt { if other >= 0 { *self -= other as u64; } else { - *self += other.unsigned_abs(); + *self += i64_abs_as_u64(other); } } } @@ -1503,11 +1402,12 @@ impl Sub for i64 { if self >= 0 { self as u64 - other } else { - -other - self.unsigned_abs() + -other - i64_abs_as_u64(self) } } } +#[cfg(has_i128)] impl Sub for BigInt { type Output = BigInt; @@ -1516,22 +1416,22 @@ impl Sub for BigInt { if other >= 0 { self - other as u128 } else { - self + other.unsigned_abs() + self + i128_abs_as_u128(other) } } } - +#[cfg(has_i128)] impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i128) { if other >= 0 { *self -= other as u128; } else { - *self += other.unsigned_abs(); + *self += i128_abs_as_u128(other); } } } - +#[cfg(has_i128)] impl Sub for i128 { type Output = BigInt; @@ -1540,7 +1440,7 @@ impl Sub for i128 { if self >= 0 { self as u128 - other } else { - -other - self.unsigned_abs() + -other - i128_abs_as_u128(self) } } } @@ -1568,6 +1468,7 @@ promote_all_scalars!(impl Mul for BigInt, mul); promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); impl Mul for BigInt { @@ -1607,7 +1508,7 @@ impl MulAssign for BigInt { } } } - +#[cfg(has_i128)] impl Mul for BigInt { type Output = BigInt; @@ -1616,7 +1517,7 @@ impl Mul for BigInt { BigInt::from_biguint(self.sign, self.data * other) } } - +#[cfg(has_i128)] impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: u128) { @@ -1629,6 +1530,7 @@ impl MulAssign for BigInt { forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); impl Mul for BigInt { @@ -1639,7 +1541,7 @@ impl Mul for BigInt { if other >= 0 { self * other as u32 } else { - -(self * other.unsigned_abs()) + -(self * i32_abs_as_u32(other)) } } } @@ -1651,7 +1553,7 @@ impl MulAssign for BigInt { *self *= other as u32; } else { self.sign = -self.sign; - *self *= other.unsigned_abs(); + *self *= i32_abs_as_u32(other); } } } @@ -1664,7 +1566,7 @@ impl Mul for BigInt { if other >= 0 { self * other as u64 } else { - -(self * other.unsigned_abs()) + -(self * i64_abs_as_u64(other)) } } } @@ -1676,11 +1578,11 @@ impl MulAssign for BigInt { *self *= other as u64; } else { self.sign = -self.sign; - *self *= other.unsigned_abs(); + *self *= i64_abs_as_u64(other); } } } - +#[cfg(has_i128)] impl Mul for BigInt { type Output = BigInt; @@ -1689,11 +1591,11 @@ impl Mul for BigInt { if other >= 0 { self * other as u128 } else { - -(self * other.unsigned_abs()) + -(self * i128_abs_as_u128(other)) } } } - +#[cfg(has_i128)] impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: i128) { @@ -1701,7 +1603,7 @@ impl MulAssign for BigInt { *self *= other as u128; } else { self.sign = -self.sign; - *self *= other.unsigned_abs(); + *self *= i128_abs_as_u128(other); } } } @@ -1730,6 +1632,7 @@ promote_all_scalars!(impl Div for BigInt, div); promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); impl Div for BigInt { @@ -1788,6 +1691,7 @@ impl Div for u64 { } } +#[cfg(has_i128)] impl Div for BigInt { type Output = BigInt; @@ -1797,6 +1701,7 @@ impl Div for BigInt { } } +#[cfg(has_i128)] impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u128) { @@ -1807,6 +1712,7 @@ impl DivAssign for BigInt { } } +#[cfg(has_i128)] impl Div for u128 { type Output = BigInt; @@ -1818,6 +1724,7 @@ impl Div for u128 { forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); impl Div for BigInt { @@ -1828,7 +1735,7 @@ impl Div for BigInt { if other >= 0 { self / other as u32 } else { - -(self / other.unsigned_abs()) + -(self / i32_abs_as_u32(other)) } } } @@ -1840,7 +1747,7 @@ impl DivAssign for BigInt { *self /= other as u32; } else { self.sign = -self.sign; - *self /= other.unsigned_abs(); + *self /= i32_abs_as_u32(other); } } } @@ -1853,7 +1760,7 @@ impl Div for i32 { if self >= 0 { self as u32 / other } else { - -(self.unsigned_abs() / other) + -(i32_abs_as_u32(self) / other) } } } @@ -1866,7 +1773,7 @@ impl Div for BigInt { if other >= 0 { self / other as u64 } else { - -(self / other.unsigned_abs()) + -(self / i64_abs_as_u64(other)) } } } @@ -1878,7 +1785,7 @@ impl DivAssign for BigInt { *self /= other as u64; } else { self.sign = -self.sign; - *self /= other.unsigned_abs(); + *self /= i64_abs_as_u64(other); } } } @@ -1891,11 +1798,12 @@ impl Div for i64 { if self >= 0 { self as u64 / other } else { - -(self.unsigned_abs() / other) + -(i64_abs_as_u64(self) / other) } } } +#[cfg(has_i128)] impl Div for BigInt { type Output = BigInt; @@ -1904,11 +1812,12 @@ impl Div for BigInt { if other >= 0 { self / other as u128 } else { - -(self / other.unsigned_abs()) + -(self / i128_abs_as_u128(other)) } } } +#[cfg(has_i128)] impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i128) { @@ -1916,11 +1825,12 @@ impl DivAssign for BigInt { *self /= other as u128; } else { self.sign = -self.sign; - *self /= other.unsigned_abs(); + *self /= i128_abs_as_u128(other); } } } +#[cfg(has_i128)] impl Div for i128 { type Output = BigInt; @@ -1929,7 +1839,7 @@ impl Div for i128 { if self >= 0 { self as u128 / other } else { - -(self.unsigned_abs() / other) + -(i128_abs_as_u128(self) / other) } } } @@ -1941,14 +1851,8 @@ impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt { #[inline] fn rem(self, other: &BigInt) -> BigInt { - if let Some(other) = other.to_u32() { - self % other - } else if let Some(other) = other.to_i32() { - self % other - } else { - let (_, r) = self.div_rem(other); - r - } + let (_, r) = self.div_rem(other); + r } } @@ -1964,6 +1868,7 @@ promote_all_scalars!(impl Rem for BigInt, rem); promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); impl Rem for BigInt { @@ -1990,7 +1895,7 @@ impl Rem for u32 { #[inline] fn rem(self, other: BigInt) -> BigInt { - BigInt::from(self % other.data) + BigInt::from_biguint(Plus, self % other.data) } } @@ -2018,10 +1923,11 @@ impl Rem for u64 { #[inline] fn rem(self, other: BigInt) -> BigInt { - BigInt::from(self % other.data) + BigInt::from_biguint(Plus, self % other.data) } } +#[cfg(has_i128)] impl Rem for BigInt { type Output = BigInt; @@ -2031,6 +1937,7 @@ impl Rem for BigInt { } } +#[cfg(has_i128)] impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u128) { @@ -2041,17 +1948,19 @@ impl RemAssign for BigInt { } } +#[cfg(has_i128)] impl Rem for u128 { type Output = BigInt; #[inline] fn rem(self, other: BigInt) -> BigInt { - BigInt::from(self % other.data) + BigInt::from_biguint(Plus, self % other.data) } } forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); impl Rem for BigInt { @@ -2062,7 +1971,7 @@ impl Rem for BigInt { if other >= 0 { self % other as u32 } else { - self % other.unsigned_abs() + self % i32_abs_as_u32(other) } } } @@ -2073,7 +1982,7 @@ impl RemAssign for BigInt { if other >= 0 { *self %= other as u32; } else { - *self %= other.unsigned_abs(); + *self %= i32_abs_as_u32(other); } } } @@ -2086,7 +1995,7 @@ impl Rem for i32 { if self >= 0 { self as u32 % other } else { - -(self.unsigned_abs() % other) + -(i32_abs_as_u32(self) % other) } } } @@ -2099,7 +2008,7 @@ impl Rem for BigInt { if other >= 0 { self % other as u64 } else { - self % other.unsigned_abs() + self % i64_abs_as_u64(other) } } } @@ -2110,7 +2019,7 @@ impl RemAssign for BigInt { if other >= 0 { *self %= other as u64; } else { - *self %= other.unsigned_abs(); + *self %= i64_abs_as_u64(other); } } } @@ -2123,11 +2032,12 @@ impl Rem for i64 { if self >= 0 { self as u64 % other } else { - -(self.unsigned_abs() % other) + -(i64_abs_as_u64(self) % other) } } } +#[cfg(has_i128)] impl Rem for BigInt { type Output = BigInt; @@ -2136,22 +2046,22 @@ impl Rem for BigInt { if other >= 0 { self % other as u128 } else { - self % other.unsigned_abs() + self % i128_abs_as_u128(other) } } } - +#[cfg(has_i128)] impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i128) { if other >= 0 { *self %= other as u128; } else { - *self %= other.unsigned_abs(); + *self %= i128_abs_as_u128(other); } } } - +#[cfg(has_i128)] impl Rem for i128 { type Output = BigInt; @@ -2160,7 +2070,7 @@ impl Rem for i128 { if self >= 0 { self as u128 % other } else { - -(self.unsigned_abs() % other) + -(i128_abs_as_u128(self) % other) } } } @@ -2187,21 +2097,21 @@ impl<'a> Neg for &'a BigInt { impl CheckedAdd for BigInt { #[inline] fn checked_add(&self, v: &BigInt) -> Option { - Some(self.add(v)) + return Some(self.add(v)); } } impl CheckedSub for BigInt { #[inline] fn checked_sub(&self, v: &BigInt) -> Option { - Some(self.sub(v)) + return Some(self.sub(v)); } } impl CheckedMul for BigInt { #[inline] fn checked_mul(&self, v: &BigInt) -> Option { - Some(self.mul(v)) + return Some(self.mul(v)); } } @@ -2211,7 +2121,7 @@ impl CheckedDiv for BigInt { if v.is_zero() { return None; } - Some(self.div(v)) + return Some(self.div(v)); } } @@ -2219,7 +2129,7 @@ impl Integer for BigInt { #[inline] fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { // r.sign == self.sign - let (d_ui, r_ui) = self.data.div_rem(&other.data); + let (d_ui, r_ui) = self.data.div_mod_floor(&other.data); let d = BigInt::from_biguint(self.sign, d_ui); let r = BigInt::from_biguint(self.sign, r_ui); if other.is_negative() { @@ -2231,71 +2141,40 @@ impl Integer for BigInt { #[inline] fn div_floor(&self, other: &BigInt) -> BigInt { - let (d_ui, m) = self.data.div_mod_floor(&other.data); - let d = BigInt::from(d_ui); - match (self.sign, other.sign) { - (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => d, - (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => { - if m.is_zero() { - -d - } else { - -d - 1u32 - } - } - (_, NoSign) => unreachable!(), - } + let (d, _) = self.div_mod_floor(other); + d } #[inline] fn mod_floor(&self, other: &BigInt) -> BigInt { - // m.sign == other.sign - let m_ui = self.data.mod_floor(&other.data); - let m = BigInt::from_biguint(other.sign, m_ui); - match (self.sign, other.sign) { - (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => m, - (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => { - if m.is_zero() { - m - } else { - other - m - } - } - (_, NoSign) => unreachable!(), - } + let (_, m) = self.div_mod_floor(other); + m } fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign - let (d_ui, m_ui) = self.data.div_mod_floor(&other.data); - let d = BigInt::from(d_ui); - let m = BigInt::from_biguint(other.sign, m_ui); + let (d_ui, m_ui) = self.data.div_rem(&other.data); + let d = BigInt::from_biguint(Plus, d_ui); + let m = BigInt::from_biguint(Plus, m_ui); + let one: BigInt = One::one(); match (self.sign, other.sign) { - (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => (d, m), - (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => { + (_, NoSign) => panic!(), + (Plus, Plus) | (NoSign, Plus) => (d, m), + (Plus, Minus) | (NoSign, Minus) => { if m.is_zero() { - (-d, m) + (-d, Zero::zero()) } else { - (-d - 1u32, other - m) + (-d - one, m + other) } } - (_, NoSign) => unreachable!(), - } - } - - #[inline] - fn div_ceil(&self, other: &Self) -> Self { - let (d_ui, m) = self.data.div_mod_floor(&other.data); - let d = BigInt::from(d_ui); - match (self.sign, other.sign) { - (Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => -d, - (Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => { + (Minus, Plus) => { if m.is_zero() { - d + (-d, Zero::zero()) } else { - d + 1u32 + (-d - one, other - m) } } - (_, NoSign) => unreachable!(), + (Minus, Minus) => (d, -m), } } @@ -2304,39 +2183,19 @@ impl Integer for BigInt { /// The result is always positive. #[inline] fn gcd(&self, other: &BigInt) -> BigInt { - BigInt::from(self.data.gcd(&other.data)) + BigInt::from_biguint(Plus, self.data.gcd(&other.data)) } /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn lcm(&self, other: &BigInt) -> BigInt { - BigInt::from(self.data.lcm(&other.data)) - } - - /// Calculates the Greatest Common Divisor (GCD) and - /// Lowest Common Multiple (LCM) together. - #[inline] - fn gcd_lcm(&self, other: &BigInt) -> (BigInt, BigInt) { - let (gcd, lcm) = self.data.gcd_lcm(&other.data); - (BigInt::from(gcd), BigInt::from(lcm)) - } - - /// Greatest common divisor, least common multiple, and Bézout coefficients. - #[inline] - fn extended_gcd_lcm(&self, other: &BigInt) -> (num_integer::ExtendedGcd, BigInt) { - let egcd = self.extended_gcd(other); - let lcm = if egcd.gcd.is_zero() { - BigInt::zero() - } else { - BigInt::from(&self.data / &egcd.gcd.data * &other.data) - }; - (egcd, lcm) + BigInt::from_biguint(Plus, self.data.lcm(&other.data)) } /// Deprecated, use `is_multiple_of` instead. #[inline] fn divides(&self, other: &BigInt) -> bool { - self.is_multiple_of(other) + return self.is_multiple_of(other); } /// Returns `true` if the number is a multiple of `other`. @@ -2356,22 +2215,6 @@ impl Integer for BigInt { fn is_odd(&self) -> bool { self.data.is_odd() } - - /// Rounds up to nearest multiple of argument. - #[inline] - fn next_multiple_of(&self, other: &Self) -> Self { - let m = self.mod_floor(other); - if m.is_zero() { - self.clone() - } else { - self + (other - m) - } - } - /// Rounds down to nearest multiple of argument. - #[inline] - fn prev_multiple_of(&self, other: &Self) -> Self { - self - self.mod_floor(other) - } } impl Roots for BigInt { @@ -2402,32 +2245,35 @@ impl ToPrimitive for BigInt { match self.sign { Plus => self.data.to_i64(), NoSign => Some(0), - Minus => { - let n = self.data.to_u64()?; + Minus => self.data.to_u64().and_then(|n| { let m: u64 = 1 << 63; - match n.cmp(&m) { - Less => Some(-(n as i64)), - Equal => Some(i64::MIN), - Greater => None, + if n < m { + Some(-(n as i64)) + } else if n == m { + Some(i64::MIN) + } else { + None } - } + }), } } #[inline] + #[cfg(has_i128)] fn to_i128(&self) -> Option { match self.sign { Plus => self.data.to_i128(), NoSign => Some(0), - Minus => { - let n = self.data.to_u128()?; + Minus => self.data.to_u128().and_then(|n| { let m: u128 = 1 << 127; - match n.cmp(&m) { - Less => Some(-(n as i128)), - Equal => Some(i128::MIN), - Greater => None, + if n < m { + Some(-(n as i128)) + } else if n == m { + Some(i128::MIN) + } else { + None } - } + }), } } @@ -2441,6 +2287,7 @@ impl ToPrimitive for BigInt { } #[inline] + #[cfg(has_i128)] fn to_u128(&self) -> Option { match self.sign { Plus => self.data.to_u128(), @@ -2451,55 +2298,19 @@ impl ToPrimitive for BigInt { #[inline] fn to_f32(&self) -> Option { - let n = self.data.to_f32()?; - Some(if self.sign == Minus { -n } else { n }) + self.data + .to_f32() + .map(|n| if self.sign == Minus { -n } else { n }) } #[inline] fn to_f64(&self) -> Option { - let n = self.data.to_f64()?; - Some(if self.sign == Minus { -n } else { n }) + self.data + .to_f64() + .map(|n| if self.sign == Minus { -n } else { n }) } } -macro_rules! impl_try_from_bigint { - ($T:ty, $to_ty:path) => { - #[cfg(has_try_from)] - impl TryFrom<&BigInt> for $T { - type Error = TryFromBigIntError<()>; - - #[inline] - fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> { - $to_ty(value).ok_or(TryFromBigIntError::new(())) - } - } - - #[cfg(has_try_from)] - impl TryFrom for $T { - type Error = TryFromBigIntError; - - #[inline] - fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError> { - <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) - } - } - }; -} - -impl_try_from_bigint!(u8, ToPrimitive::to_u8); -impl_try_from_bigint!(u16, ToPrimitive::to_u16); -impl_try_from_bigint!(u32, ToPrimitive::to_u32); -impl_try_from_bigint!(u64, ToPrimitive::to_u64); -impl_try_from_bigint!(usize, ToPrimitive::to_usize); -impl_try_from_bigint!(u128, ToPrimitive::to_u128); - -impl_try_from_bigint!(i8, ToPrimitive::to_i8); -impl_try_from_bigint!(i16, ToPrimitive::to_i16); -impl_try_from_bigint!(i32, ToPrimitive::to_i32); -impl_try_from_bigint!(i64, ToPrimitive::to_i64); -impl_try_from_bigint!(isize, ToPrimitive::to_isize); -impl_try_from_bigint!(i128, ToPrimitive::to_i128); - impl FromPrimitive for BigInt { #[inline] fn from_i64(n: i64) -> Option { @@ -2507,6 +2318,7 @@ impl FromPrimitive for BigInt { } #[inline] + #[cfg(has_i128)] fn from_i128(n: i128) -> Option { Some(BigInt::from(n)) } @@ -2517,6 +2329,7 @@ impl FromPrimitive for BigInt { } #[inline] + #[cfg(has_i128)] fn from_u128(n: u128) -> Option { Some(BigInt::from(n)) } @@ -2524,10 +2337,9 @@ impl FromPrimitive for BigInt { #[inline] fn from_f64(n: f64) -> Option { if n >= 0.0 { - BigUint::from_f64(n).map(BigInt::from) + BigUint::from_f64(n).map(|x| BigInt::from_biguint(Plus, x)) } else { - let x = BigUint::from_f64(-n)?; - Some(-BigInt::from(x)) + BigUint::from_f64(-n).map(|x| BigInt::from_biguint(Minus, x)) } } } @@ -2547,6 +2359,7 @@ impl From for BigInt { } } +#[cfg(has_i128)] impl From for BigInt { #[inline] fn from(n: i128) -> Self { @@ -2592,6 +2405,7 @@ impl From for BigInt { } } +#[cfg(has_i128)] impl From for BigInt { #[inline] fn from(n: u128) -> Self { @@ -2725,30 +2539,6 @@ impl biguint::ToBigUint for BigInt { } } -#[cfg(has_try_from)] -impl TryFrom<&BigInt> for BigUint { - type Error = TryFromBigIntError<()>; - - #[inline] - fn try_from(value: &BigInt) -> Result> { - value.to_biguint().ok_or(TryFromBigIntError::new(())) - } -} - -#[cfg(has_try_from)] -impl TryFrom for BigUint { - type Error = TryFromBigIntError; - - #[inline] - fn try_from(value: BigInt) -> Result> { - if value.sign() == Sign::Minus { - Err(TryFromBigIntError::new(value)) - } else { - Ok(value.data) - } - } -} - macro_rules! impl_to_bigint { ($T:ty, $from_ty:path) => { impl ToBigInt for $T { @@ -2765,6 +2555,7 @@ impl_to_bigint!(i8, FromPrimitive::from_i8); impl_to_bigint!(i16, FromPrimitive::from_i16); impl_to_bigint!(i32, FromPrimitive::from_i32); impl_to_bigint!(i64, FromPrimitive::from_i64); +#[cfg(has_i128)] impl_to_bigint!(i128, FromPrimitive::from_i128); impl_to_bigint!(usize, FromPrimitive::from_usize); @@ -2772,6 +2563,7 @@ impl_to_bigint!(u8, FromPrimitive::from_u8); impl_to_bigint!(u16, FromPrimitive::from_u16); impl_to_bigint!(u32, FromPrimitive::from_u32); impl_to_bigint!(u64, FromPrimitive::from_u64); +#[cfg(has_i128)] impl_to_bigint!(u128, FromPrimitive::from_u128); impl_to_bigint!(f32, FromPrimitive::from_f32); @@ -2780,7 +2572,7 @@ impl_to_bigint!(f64, FromPrimitive::from_f64); impl BigInt { /// Creates and initializes a BigInt. /// - /// The base 232 digits are ordered least significant digit first. + /// The digits are in little-endian base 232. #[inline] pub fn new(sign: Sign, digits: Vec) -> BigInt { BigInt::from_biguint(sign, BigUint::new(digits)) @@ -2788,7 +2580,7 @@ impl BigInt { /// Creates and initializes a `BigInt`. /// - /// The base 232 digits are ordered least significant digit first. + /// The digits are in little-endian base 232. #[inline] pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { if sign == NoSign { @@ -2797,27 +2589,30 @@ impl BigInt { sign = NoSign; } - BigInt { sign, data } + BigInt { + sign: sign, + data: data, + } } /// Creates and initializes a `BigInt`. - /// - /// The base 232 digits are ordered least significant digit first. #[inline] pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_slice(slice)) } /// Reinitializes a `BigInt`. - /// - /// The base 232 digits are ordered least significant digit first. #[inline] pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) { if sign == NoSign { - self.set_zero(); + self.data.assign_from_slice(&[]); + self.sign = NoSign; } else { self.data.assign_from_slice(slice); - self.sign = if self.data.is_zero() { NoSign } else { sign }; + self.sign = match self.data.is_zero() { + true => NoSign, + false => sign, + } } } @@ -2908,8 +2703,9 @@ impl BigInt { /// ``` #[inline] pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - let s = str::from_utf8(buf).ok()?; - BigInt::from_str_radix(s, radix).ok() + str::from_utf8(buf) + .ok() + .and_then(|s| BigInt::from_str_radix(s, radix).ok()) } /// Creates and initializes a `BigInt`. Each u8 of the input slice is @@ -2929,8 +2725,7 @@ impl BigInt { /// assert_eq!(a.to_radix_be(190), (Sign:: Minus, inbase190)); /// ``` pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option { - let u = BigUint::from_radix_be(buf, radix)?; - Some(BigInt::from_biguint(sign, u)) + BigUint::from_radix_be(buf, radix).map(|u| BigInt::from_biguint(sign, u)) } /// Creates and initializes a `BigInt`. Each u8 of the input slice is @@ -2950,8 +2745,7 @@ impl BigInt { /// assert_eq!(a.to_radix_be(190), (Sign::Minus, inbase190)); /// ``` pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option { - let u = BigUint::from_radix_le(buf, radix)?; - Some(BigInt::from_biguint(sign, u)) + BigUint::from_radix_le(buf, radix).map(|u| BigInt::from_biguint(sign, u)) } /// Returns the sign and the byte representation of the `BigInt` in big-endian byte order. @@ -2984,26 +2778,7 @@ impl BigInt { (self.sign, self.data.to_bytes_le()) } - /// Returns the sign and the `u32` digits representation of the `BigInt` ordered least - /// significant digit first. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from(-1125).to_u32_digits(), (Sign::Minus, vec![1125])); - /// assert_eq!(BigInt::from(4294967295u32).to_u32_digits(), (Sign::Plus, vec![4294967295])); - /// assert_eq!(BigInt::from(4294967296u64).to_u32_digits(), (Sign::Plus, vec![0, 1])); - /// assert_eq!(BigInt::from(-112500000000i64).to_u32_digits(), (Sign::Minus, vec![830850304, 26])); - /// assert_eq!(BigInt::from(112500000000i64).to_u32_digits(), (Sign::Plus, vec![830850304, 26])); - /// ``` - #[inline] - pub fn to_u32_digits(&self) -> (Sign, Vec) { - (self.sign, self.data.to_u32_digits()) - } - - /// Returns the two's-complement byte representation of the `BigInt` in big-endian byte order. + /// Returns the two's complement byte representation of the `BigInt` in big-endian byte order. /// /// # Examples /// @@ -3016,7 +2791,7 @@ impl BigInt { #[inline] pub fn to_signed_bytes_be(&self) -> Vec { let mut bytes = self.data.to_bytes_be(); - let first_byte = bytes.first().cloned().unwrap_or(0); + let first_byte = bytes.first().map(|v| *v).unwrap_or(0); if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) @@ -3031,7 +2806,7 @@ impl BigInt { bytes } - /// Returns the two's-complement byte representation of the `BigInt` in little-endian byte order. + /// Returns the two's complement byte representation of the `BigInt` in little-endian byte order. /// /// # Examples /// @@ -3044,7 +2819,7 @@ impl BigInt { #[inline] pub fn to_signed_bytes_le(&self) -> Vec { let mut bytes = self.data.to_bytes_le(); - let last_byte = bytes.last().cloned().unwrap_or(0); + let last_byte = bytes.last().map(|v| *v).unwrap_or(0); if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) @@ -3125,57 +2900,21 @@ impl BigInt { /// # Examples /// /// ``` - /// use num_bigint::{BigInt, Sign}; - /// use num_traits::Zero; + /// use num_bigint::{ToBigInt, Sign}; /// - /// assert_eq!(BigInt::from(1234).sign(), Sign::Plus); - /// assert_eq!(BigInt::from(-4321).sign(), Sign::Minus); - /// assert_eq!(BigInt::zero().sign(), Sign::NoSign); + /// assert_eq!(ToBigInt::to_bigint(&1234).unwrap().sign(), Sign::Plus); + /// assert_eq!(ToBigInt::to_bigint(&-4321).unwrap().sign(), Sign::Minus); + /// assert_eq!(ToBigInt::to_bigint(&0).unwrap().sign(), Sign::NoSign); /// ``` #[inline] pub fn sign(&self) -> Sign { self.sign } - /// Returns the magnitude of the `BigInt` as a `BigUint`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, BigUint}; - /// use num_traits::Zero; - /// - /// assert_eq!(BigInt::from(1234).magnitude(), &BigUint::from(1234u32)); - /// assert_eq!(BigInt::from(-4321).magnitude(), &BigUint::from(4321u32)); - /// assert!(BigInt::zero().magnitude().is_zero()); - /// ``` - #[inline] - pub fn magnitude(&self) -> &BigUint { - &self.data - } - - /// Convert this `BigInt` into its `Sign` and `BigUint` magnitude, - /// the reverse of `BigInt::from_biguint`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, BigUint, Sign}; - /// use num_traits::Zero; - /// - /// assert_eq!(BigInt::from(1234).into_parts(), (Sign::Plus, BigUint::from(1234u32))); - /// assert_eq!(BigInt::from(-4321).into_parts(), (Sign::Minus, BigUint::from(4321u32))); - /// assert_eq!(BigInt::zero().into_parts(), (Sign::NoSign, BigUint::zero())); - /// ``` - #[inline] - pub fn into_parts(self) -> (Sign, BigUint) { - (self.sign, self.data) - } - /// Determines the fewest bits necessary to express the `BigInt`, /// not including the sign. #[inline] - pub fn bits(&self) -> u64 { + pub fn bits(&self) -> usize { self.data.bits() } @@ -3191,17 +2930,17 @@ impl BigInt { #[inline] pub fn checked_add(&self, v: &BigInt) -> Option { - Some(self.add(v)) + return Some(self.add(v)); } #[inline] pub fn checked_sub(&self, v: &BigInt) -> Option { - Some(self.sub(v)) + return Some(self.sub(v)); } #[inline] pub fn checked_mul(&self, v: &BigInt) -> Option { - Some(self.mul(v)) + return Some(self.mul(v)); } #[inline] @@ -3209,12 +2948,7 @@ impl BigInt { if v.is_zero() { return None; } - Some(self.div(v)) - } - - /// Returns `self ^ exponent`. - pub fn pow(&self, exponent: u32) -> Self { - Pow::pow(self, exponent) + return Some(self.div(v)); } /// Returns `(self ^ exponent) mod modulus` @@ -3230,10 +2964,7 @@ impl BigInt { !exponent.is_negative(), "negative exponentiation is not supported!" ); - assert!( - !modulus.is_zero(), - "attempt to calculate with zero modulus!" - ); + assert!(!modulus.is_zero(), "divide by zero!"); let result = self.data.modpow(&exponent.data, &modulus.data); if result.is_zero() { @@ -3241,10 +2972,7 @@ impl BigInt { } // The sign of the result follows the modulus, like `mod_floor`. - let (sign, mag) = match ( - self.is_negative() && exponent.is_odd(), - modulus.is_negative(), - ) { + let (sign, mag) = match (self.is_negative(), modulus.is_negative()) { (false, false) => (Plus, result), (true, false) => (Plus, &modulus.data - result), (false, true) => (Minus, &modulus.data - result), @@ -3270,12 +2998,6 @@ impl BigInt { pub fn nth_root(&self, n: u32) -> Self { Roots::nth_root(self, n) } - - /// Returns the number of least-significant bits that are zero, - /// or `None` if the entire number is zero. - pub fn trailing_zeros(&self) -> Option { - self.data.trailing_zeros() - } } impl_sum_iter_type!(BigInt); diff --git a/third_party/rust/num-bigint/src/bigrand.rs b/third_party/rust/num-bigint/src/bigrand.rs index ae00b7e437c2..4a13b29df48b 100644 --- a/third_party/rust/num-bigint/src/bigrand.rs +++ b/third_party/rust/num-bigint/src/bigrand.rs @@ -1,27 +1,25 @@ //! Randomization of big integers -use rand::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler}; +use rand::distributions::uniform::{SampleUniform, UniformSampler}; use rand::prelude::*; +use rand::AsByteSliceMut; -use crate::BigInt; -use crate::BigUint; -use crate::Sign::*; +use BigInt; +use BigUint; +use Sign::*; -use crate::bigint::{into_magnitude, magnitude}; -use crate::biguint::biguint_from_vec; +use big_digit::BigDigit; +use bigint::{into_magnitude, magnitude}; -use num_integer::Integer; -use num_traits::{ToPrimitive, Zero}; +use integer::Integer; +use traits::Zero; -/// A trait for sampling random big integers. -/// -/// The `rand` feature must be enabled to use this. See crate-level documentation for details. pub trait RandBigInt { /// Generate a random `BigUint` of the given bit size. - fn gen_biguint(&mut self, bit_size: u64) -> BigUint; + fn gen_biguint(&mut self, bit_size: usize) -> BigUint; /// Generate a random BigInt of the given bit size. - fn gen_bigint(&mut self, bit_size: u64) -> BigInt; + fn gen_bigint(&mut self, bit_size: usize) -> BigInt; /// Generate a random `BigUint` less than the given bound. Fails /// when the bound is zero. @@ -38,54 +36,24 @@ pub trait RandBigInt { fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt; } -fn gen_bits(rng: &mut R, data: &mut [u32], rem: u64) { - // `fill` is faster than many `gen::` calls - rng.fill(data); - if rem > 0 { - let last = data.len() - 1; - data[last] >>= 32 - rem; - } -} - impl RandBigInt for R { - #[cfg(not(u64_digit))] - fn gen_biguint(&mut self, bit_size: u64) -> BigUint { - let (digits, rem) = bit_size.div_rem(&32); - let len = (digits + (rem > 0) as u64) - .to_usize() - .expect("capacity overflow"); - let mut data = vec![0u32; len]; - gen_bits(self, &mut data, rem); - biguint_from_vec(data) + fn gen_biguint(&mut self, bit_size: usize) -> BigUint { + use super::big_digit::BITS; + let (digits, rem) = bit_size.div_rem(&BITS); + let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize]; + // `fill_bytes` is faster than many `gen::` calls + self.fill_bytes(data[..].as_byte_slice_mut()); + // Swap bytes per the `Rng::fill` source. This might be + // unnecessary if reproducibility across architectures is not + // desired. + data.to_le(); + if rem > 0 { + data[digits] >>= BITS - rem; + } + BigUint::new(data) } - #[cfg(u64_digit)] - fn gen_biguint(&mut self, bit_size: u64) -> BigUint { - use core::slice; - - let (digits, rem) = bit_size.div_rem(&32); - let len = (digits + (rem > 0) as u64) - .to_usize() - .expect("capacity overflow"); - let native_digits = bit_size.div_ceil(&64); - let native_len = native_digits.to_usize().expect("capacity overflow"); - let mut data = vec![0u64; native_len]; - unsafe { - // Generate bits in a `&mut [u32]` slice for value stability - let ptr = data.as_mut_ptr() as *mut u32; - debug_assert!(native_len * 2 >= len); - let data = slice::from_raw_parts_mut(ptr, len); - gen_bits(self, data, rem); - } - #[cfg(target_endian = "big")] - for digit in &mut data { - // swap u32 digits into u64 endianness - *digit = (*digit << 32) | (*digit >> 32); - } - biguint_from_vec(data) - } - - fn gen_bigint(&mut self, bit_size: u64) -> BigInt { + fn gen_bigint(&mut self, bit_size: usize) -> BigInt { loop { // Generate a random BigUint... let biguint = self.gen_biguint(bit_size); @@ -153,28 +121,16 @@ impl UniformSampler for UniformBigUint { type X = BigUint; #[inline] - fn new(low_b: B1, high_b: B2) -> Self - where - B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized, - { - let low = low_b.borrow(); - let high = high_b.borrow(); + fn new(low: Self::X, high: Self::X) -> Self { assert!(low < high); UniformBigUint { - len: high - low, - base: low.clone(), + len: high - &low, + base: low, } } #[inline] - fn new_inclusive(low_b: B1, high_b: B2) -> Self - where - B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized, - { - let low = low_b.borrow(); - let high = high_b.borrow(); + fn new_inclusive(low: Self::X, high: Self::X) -> Self { assert!(low <= high); Self::new(low, high + 1u32) } @@ -185,12 +141,8 @@ impl UniformSampler for UniformBigUint { } #[inline] - fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X - where - B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized, - { - rng.gen_biguint_range(low.borrow(), high.borrow()) + fn sample_single(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { + rng.gen_biguint_range(&low, &high) } } @@ -209,28 +161,16 @@ impl UniformSampler for UniformBigInt { type X = BigInt; #[inline] - fn new(low_b: B1, high_b: B2) -> Self - where - B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized, - { - let low = low_b.borrow(); - let high = high_b.borrow(); + fn new(low: Self::X, high: Self::X) -> Self { assert!(low < high); UniformBigInt { - len: into_magnitude(high - low), - base: low.clone(), + len: into_magnitude(high - &low), + base: low, } } #[inline] - fn new_inclusive(low_b: B1, high_b: B2) -> Self - where - B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized, - { - let low = low_b.borrow(); - let high = high_b.borrow(); + fn new_inclusive(low: Self::X, high: Self::X) -> Self { assert!(low <= high); Self::new(low, high + 1u32) } @@ -241,12 +181,8 @@ impl UniformSampler for UniformBigInt { } #[inline] - fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X - where - B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized, - { - rng.gen_bigint_range(low.borrow(), high.borrow()) + fn sample_single(low: Self::X, high: Self::X, rng: &mut R) -> Self::X { + rng.gen_bigint_range(&low, &high) } } @@ -255,16 +191,14 @@ impl SampleUniform for BigInt { } /// A random distribution for `BigUint` and `BigInt` values of a particular bit size. -/// -/// The `rand` feature must be enabled to use this. See crate-level documentation for details. #[derive(Clone, Copy, Debug)] pub struct RandomBits { - bits: u64, + bits: usize, } impl RandomBits { #[inline] - pub fn new(bits: u64) -> RandomBits { + pub fn new(bits: usize) -> RandomBits { RandomBits { bits } } } diff --git a/third_party/rust/num-bigint/src/biguint.rs b/third_party/rust/num-bigint/src/biguint.rs index bf3487355422..e6e9fbcce5ab 100644 --- a/third_party/rust/num-bigint/src/biguint.rs +++ b/third_party/rust/num-bigint/src/biguint.rs @@ -1,34 +1,30 @@ -#[cfg(feature = "quickcheck")] -use crate::std_alloc::Box; -use crate::std_alloc::{Cow, String, Vec}; -use core::cmp; -use core::cmp::Ordering::{self, Equal, Greater, Less}; -#[cfg(has_try_from)] -use core::convert::TryFrom; -use core::default::Default; -use core::fmt; -use core::hash; -use core::iter::{Product, Sum}; -use core::mem; -use core::ops::{ +#[allow(deprecated, unused_imports)] +use std::ascii::AsciiExt; +use std::borrow::Cow; +use std::cmp; +use std::cmp::Ordering::{self, Equal, Greater, Less}; +use std::default::Default; +use std::fmt; +use std::iter::{Product, Sum}; +use std::mem; +use std::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, - Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, + Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }; -use core::str::{self, FromStr}; -use core::{f32, f64}; -use core::{u32, u64, u8}; +use std::str::{self, FromStr}; +use std::{f32, f64}; +use std::{u64, u8}; #[cfg(feature = "serde")] use serde; -use num_integer::{Integer, Roots}; -use num_traits::float::FloatCore; -use num_traits::{ - CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, ToPrimitive, - Unsigned, Zero, +use integer::{Integer, Roots}; +use traits::{ + CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Float, FromPrimitive, Num, One, Pow, + ToPrimitive, Unsigned, Zero, }; -use crate::big_digit::{self, BigDigit}; +use big_digit::{self, BigDigit}; #[path = "algorithms.rs"] mod algorithms; @@ -42,64 +38,40 @@ use self::algorithms::{div_rem, div_rem_digit, div_rem_ref, rem_digit}; use self::algorithms::{mac_with_carry, mul3, scalar_mul}; use self::monty::monty_modpow; -use crate::UsizePromotion; +use UsizePromotion; -use crate::ParseBigIntError; -#[cfg(has_try_from)] -use crate::TryFromBigIntError; +use ParseBigIntError; #[cfg(feature = "quickcheck")] use quickcheck::{Arbitrary, Gen}; /// A big unsigned integer type. -#[derive(Debug)] +#[derive(Clone, Debug, Hash)] pub struct BigUint { data: Vec, } -// Note: derived `Clone` doesn't specialize `clone_from`, -// but we want to keep the allocation in `data`. -impl Clone for BigUint { - #[inline] - fn clone(&self) -> Self { - BigUint { - data: self.data.clone(), - } - } - - #[inline] - fn clone_from(&mut self, other: &Self) { - self.data.clone_from(&other.data); - } -} - #[cfg(feature = "quickcheck")] impl Arbitrary for BigUint { fn arbitrary(g: &mut G) -> Self { // Use arbitrary from Vec - biguint_from_vec(Vec::::arbitrary(g)) + Self::new(Vec::::arbitrary(g)) } - fn shrink(&self) -> Box> { + #[allow(bare_trait_objects)] // `dyn` needs Rust 1.27 to parse, even when cfg-disabled + fn shrink(&self) -> Box> { // Use shrinker from Vec - Box::new(self.data.shrink().map(biguint_from_vec)) - } -} - -impl hash::Hash for BigUint { - #[inline] - fn hash(&self, state: &mut H) { - debug_assert!(self.data.last() != Some(&0)); - self.data.hash(state); + Box::new(self.data.shrink().map(|x| BigUint::new(x))) } } impl PartialEq for BigUint { #[inline] fn eq(&self, other: &BigUint) -> bool { - debug_assert!(self.data.last() != Some(&0)); - debug_assert!(other.data.last() != Some(&0)); - self.data == other.data + match self.cmp(other) { + Equal => true, + _ => false, + } } } impl Eq for BigUint {} @@ -126,19 +98,19 @@ impl Default for BigUint { } impl fmt::Display for BigUint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "", &self.to_str_radix(10)) } } impl fmt::LowerHex for BigUint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0x", &self.to_str_radix(16)) } } impl fmt::UpperHex for BigUint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut s = self.to_str_radix(16); s.make_ascii_uppercase(); f.pad_integral(true, "0x", &s) @@ -146,13 +118,13 @@ impl fmt::UpperHex for BigUint { } impl fmt::Binary for BigUint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0b", &self.to_str_radix(2)) } } impl fmt::Octal for BigUint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0o", &self.to_str_radix(8)) } } @@ -168,14 +140,14 @@ impl FromStr for BigUint { // Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides // BigDigit::BITS -fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { +fn from_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); let digits_per_big_digit = big_digit::BITS / bits; let data = v - .chunks(digits_per_big_digit.into()) + .chunks(digits_per_big_digit) .map(|chunk| { chunk .iter() @@ -184,20 +156,16 @@ fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { }) .collect(); - biguint_from_vec(data) + BigUint::new(data) } // Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide // BigDigit::BITS -fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { +fn from_inexact_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); - let big_digits = (v.len() as u64) - .saturating_mul(bits.into()) - .div_ceil(&big_digit::BITS.into()) - .to_usize() - .unwrap_or(core::usize::MAX); + let big_digits = (v.len() * bits + big_digit::BITS - 1) / big_digit::BITS; let mut data = Vec::with_capacity(big_digits); let mut d = 0; @@ -223,7 +191,7 @@ fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { data.push(d as BigDigit); } - biguint_from_vec(data) + BigUint::new(data) } // Read little-endian radix digits @@ -231,17 +199,12 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { debug_assert!(!v.is_empty() && !radix.is_power_of_two()); debug_assert!(v.iter().all(|&c| u32::from(c) < radix)); - #[cfg(feature = "std")] - let radix_log2 = f64::from(radix).log2(); - #[cfg(not(feature = "std"))] - let radix_log2 = ilog2(radix.next_power_of_two()) as f64; - // Estimate how big the result will be, so we can pre-allocate it. - let bits = radix_log2 * v.len() as f64; + let bits = f64::from(radix).log2() * v.len() as f64; let big_digits = (bits / big_digit::BITS as f64).ceil(); - let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0)); + let mut data = Vec::with_capacity(big_digits as usize); - let (base, power) = get_radix_base(radix, big_digit::BITS); + let (base, power) = get_radix_base(radix); let radix = radix as BigDigit; let r = v.len() % power; @@ -271,7 +234,7 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { add2(&mut data, &[n]); } - biguint_from_vec(data) + BigUint::new(data) } impl Num for BigUint { @@ -300,10 +263,11 @@ impl Num for BigUint { // First normalize all characters to plain digit values let mut v = Vec::with_capacity(s.len()); for b in s.bytes() { + #[allow(unknown_lints, ellipsis_inclusive_range_patterns)] let d = match b { - b'0'..=b'9' => b - b'0', - b'a'..=b'z' => b - b'a' + 10, - b'A'..=b'Z' => b - b'A' + 10, + b'0'...b'9' => b - b'0', + b'a'...b'z' => b - b'a' + 10, + b'A'...b'Z' => b - b'A' + 10, b'_' => continue, _ => u8::MAX, }; @@ -420,91 +384,60 @@ impl<'a> BitXorAssign<&'a BigUint> for BigUint { } } -macro_rules! impl_shift { - (@ref $Shx:ident :: $shx:ident, $ShxAssign:ident :: $shx_assign:ident, $rhs:ty) => { - impl<'b> $Shx<&'b $rhs> for BigUint { - type Output = BigUint; +impl Shl for BigUint { + type Output = BigUint; - #[inline] - fn $shx(self, rhs: &'b $rhs) -> BigUint { - $Shx::$shx(self, *rhs) - } - } - impl<'a, 'b> $Shx<&'b $rhs> for &'a BigUint { - type Output = BigUint; + #[inline] + fn shl(self, rhs: usize) -> BigUint { + biguint_shl(Cow::Owned(self), rhs) + } +} +impl<'a> Shl for &'a BigUint { + type Output = BigUint; - #[inline] - fn $shx(self, rhs: &'b $rhs) -> BigUint { - $Shx::$shx(self, *rhs) - } - } - impl<'b> $ShxAssign<&'b $rhs> for BigUint { - #[inline] - fn $shx_assign(&mut self, rhs: &'b $rhs) { - $ShxAssign::$shx_assign(self, *rhs); - } - } - }; - ($($rhs:ty),+) => {$( - impl Shl<$rhs> for BigUint { - type Output = BigUint; - - #[inline] - fn shl(self, rhs: $rhs) -> BigUint { - biguint_shl(Cow::Owned(self), rhs) - } - } - impl<'a> Shl<$rhs> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn shl(self, rhs: $rhs) -> BigUint { - biguint_shl(Cow::Borrowed(self), rhs) - } - } - impl ShlAssign<$rhs> for BigUint { - #[inline] - fn shl_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, BigUint::zero()); - *self = n << rhs; - } - } - impl_shift! { @ref Shl::shl, ShlAssign::shl_assign, $rhs } - - impl Shr<$rhs> for BigUint { - type Output = BigUint; - - #[inline] - fn shr(self, rhs: $rhs) -> BigUint { - biguint_shr(Cow::Owned(self), rhs) - } - } - impl<'a> Shr<$rhs> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn shr(self, rhs: $rhs) -> BigUint { - biguint_shr(Cow::Borrowed(self), rhs) - } - } - impl ShrAssign<$rhs> for BigUint { - #[inline] - fn shr_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, BigUint::zero()); - *self = n >> rhs; - } - } - impl_shift! { @ref Shr::shr, ShrAssign::shr_assign, $rhs } - )*}; + #[inline] + fn shl(self, rhs: usize) -> BigUint { + biguint_shl(Cow::Borrowed(self), rhs) + } } -impl_shift! { u8, u16, u32, u64, u128, usize } -impl_shift! { i8, i16, i32, i64, i128, isize } +impl ShlAssign for BigUint { + #[inline] + fn shl_assign(&mut self, rhs: usize) { + let n = mem::replace(self, BigUint::zero()); + *self = n << rhs; + } +} + +impl Shr for BigUint { + type Output = BigUint; + + #[inline] + fn shr(self, rhs: usize) -> BigUint { + biguint_shr(Cow::Owned(self), rhs) + } +} +impl<'a> Shr for &'a BigUint { + type Output = BigUint; + + #[inline] + fn shr(self, rhs: usize) -> BigUint { + biguint_shr(Cow::Borrowed(self), rhs) + } +} + +impl ShrAssign for BigUint { + #[inline] + fn shr_assign(&mut self, rhs: usize) { + let n = mem::replace(self, BigUint::zero()); + *self = n >> rhs; + } +} impl Zero for BigUint { #[inline] fn zero() -> BigUint { - BigUint { data: Vec::new() } + BigUint::new(Vec::new()) } #[inline] @@ -521,7 +454,7 @@ impl Zero for BigUint { impl One for BigUint { #[inline] fn one() -> BigUint { - BigUint { data: vec![1] } + BigUint::new(vec![1]) } #[inline] @@ -538,33 +471,12 @@ impl One for BigUint { impl Unsigned for BigUint {} -impl<'b> Pow<&'b BigUint> for BigUint { +impl<'a> Pow for &'a BigUint { type Output = BigUint; #[inline] - fn pow(self, exp: &BigUint) -> BigUint { - if self.is_one() || exp.is_zero() { - BigUint::one() - } else if self.is_zero() { - BigUint::zero() - } else if let Some(exp) = exp.to_u64() { - self.pow(exp) - } else if let Some(exp) = exp.to_u128() { - self.pow(exp) - } else { - // At this point, `self >= 2` and `exp >= 2¹²⁸`. The smallest possible result given - // `2.pow(2¹²⁸)` would require far more memory than 64-bit targets can address! - panic!("memory overflow") - } - } -} - -impl Pow for BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: BigUint) -> BigUint { - Pow::pow(self, &exp) + fn pow(self, exp: BigUint) -> Self::Output { + self.pow(&exp) } } @@ -572,36 +484,32 @@ impl<'a, 'b> Pow<&'b BigUint> for &'a BigUint { type Output = BigUint; #[inline] - fn pow(self, exp: &BigUint) -> BigUint { + fn pow(self, exp: &BigUint) -> Self::Output { if self.is_one() || exp.is_zero() { BigUint::one() } else if self.is_zero() { BigUint::zero() + } else if let Some(exp) = exp.to_u64() { + self.pow(exp) } else { - self.clone().pow(exp) + // At this point, `self >= 2` and `exp >= 2⁶⁴`. The smallest possible result + // given `2.pow(2⁶⁴)` would take 2.3 exabytes of memory! + panic!("memory overflow") } } } -impl<'a> Pow for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: BigUint) -> BigUint { - Pow::pow(self, &exp) - } -} - macro_rules! pow_impl { ($T:ty) => { - impl Pow<$T> for BigUint { + impl<'a> Pow<$T> for &'a BigUint { type Output = BigUint; - fn pow(self, mut exp: $T) -> BigUint { + #[inline] + fn pow(self, mut exp: $T) -> Self::Output { if exp == 0 { return BigUint::one(); } - let mut base = self; + let mut base = self.clone(); while exp & 1 == 0 { base = &base * &base; @@ -624,33 +532,12 @@ macro_rules! pow_impl { } } - impl<'b> Pow<&'b $T> for BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: &$T) -> BigUint { - Pow::pow(self, *exp) - } - } - - impl<'a> Pow<$T> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn pow(self, exp: $T) -> BigUint { - if exp == 0 { - return BigUint::one(); - } - Pow::pow(self.clone(), exp) - } - } - impl<'a, 'b> Pow<&'b $T> for &'a BigUint { type Output = BigUint; #[inline] - fn pow(self, exp: &$T) -> BigUint { - Pow::pow(self, *exp) + fn pow(self, exp: &$T) -> Self::Output { + self.pow(*exp) } } }; @@ -661,6 +548,7 @@ pow_impl!(u16); pow_impl!(u32); pow_impl!(u64); pow_impl!(usize); +#[cfg(has_i128)] pow_impl!(u128); forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); @@ -695,6 +583,7 @@ promote_unsigned_scalars!(impl Add for BigUint, add); promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign); forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); impl Add for BigUint { @@ -711,7 +600,7 @@ impl AddAssign for BigUint { #[inline] fn add_assign(&mut self, other: u32) { if other != 0 { - if self.data.is_empty() { + if self.data.len() == 0 { self.data.push(0); } @@ -734,7 +623,6 @@ impl Add for BigUint { } impl AddAssign for BigUint { - #[cfg(not(u64_digit))] #[inline] fn add_assign(&mut self, other: u64) { let (hi, lo) = big_digit::from_doublebigdigit(other); @@ -751,23 +639,9 @@ impl AddAssign for BigUint { } } } - - #[cfg(u64_digit)] - #[inline] - fn add_assign(&mut self, other: u64) { - if other != 0 { - if self.data.is_empty() { - self.data.push(0); - } - - let carry = __add2(&mut self.data, &[other as BigDigit]); - if carry != 0 { - self.data.push(carry); - } - } - } } +#[cfg(has_i128)] impl Add for BigUint { type Output = BigUint; @@ -778,8 +652,8 @@ impl Add for BigUint { } } +#[cfg(has_i128)] impl AddAssign for BigUint { - #[cfg(not(u64_digit))] #[inline] fn add_assign(&mut self, other: u128) { if other <= u128::from(u64::max_value()) { @@ -804,24 +678,6 @@ impl AddAssign for BigUint { } } } - - #[cfg(u64_digit)] - #[inline] - fn add_assign(&mut self, other: u128) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - if hi == 0 { - *self += lo; - } else { - while self.data.len() < 2 { - self.data.push(0); - } - - let carry = __add2(&mut self.data, &[lo, hi]); - if carry != 0 { - self.data.push(carry); - } - } - } } forward_val_val_binop!(impl Sub for BigUint, sub); @@ -865,6 +721,7 @@ promote_unsigned_scalars!(impl Sub for BigUint, sub); promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign); forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); impl Sub for BigUint { @@ -876,7 +733,6 @@ impl Sub for BigUint { self } } - impl SubAssign for BigUint { fn sub_assign(&mut self, other: u32) { sub2(&mut self.data[..], &[other as BigDigit]); @@ -887,21 +743,9 @@ impl SubAssign for BigUint { impl Sub for u32 { type Output = BigUint; - #[cfg(not(u64_digit))] #[inline] fn sub(self, mut other: BigUint) -> BigUint { if other.data.len() == 0 { - other.data.push(self); - } else { - sub2rev(&[self], &mut other.data[..]); - } - other.normalized() - } - - #[cfg(u64_digit)] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.is_empty() { other.data.push(self as BigDigit); } else { sub2rev(&[self as BigDigit], &mut other.data[..]); @@ -921,26 +765,17 @@ impl Sub for BigUint { } impl SubAssign for BigUint { - #[cfg(not(u64_digit))] #[inline] fn sub_assign(&mut self, other: u64) { let (hi, lo) = big_digit::from_doublebigdigit(other); sub2(&mut self.data[..], &[lo, hi]); self.normalize(); } - - #[cfg(u64_digit)] - #[inline] - fn sub_assign(&mut self, other: u64) { - sub2(&mut self.data[..], &[other as BigDigit]); - self.normalize(); - } } impl Sub for u64 { type Output = BigUint; - #[cfg(not(u64_digit))] #[inline] fn sub(self, mut other: BigUint) -> BigUint { while other.data.len() < 2 { @@ -951,19 +786,9 @@ impl Sub for u64 { sub2rev(&[lo, hi], &mut other.data[..]); other.normalized() } - - #[cfg(u64_digit)] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.is_empty() { - other.data.push(self); - } else { - sub2rev(&[self], &mut other.data[..]); - } - other.normalized() - } } +#[cfg(has_i128)] impl Sub for BigUint { type Output = BigUint; @@ -973,29 +798,19 @@ impl Sub for BigUint { self } } - +#[cfg(has_i128)] impl SubAssign for BigUint { - #[cfg(not(u64_digit))] - #[inline] fn sub_assign(&mut self, other: u128) { let (a, b, c, d) = u32_from_u128(other); sub2(&mut self.data[..], &[d, c, b, a]); self.normalize(); } - - #[cfg(u64_digit)] - #[inline] - fn sub_assign(&mut self, other: u128) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - sub2(&mut self.data[..], &[lo, hi]); - self.normalize(); - } } +#[cfg(has_i128)] impl Sub for u128 { type Output = BigUint; - #[cfg(not(u64_digit))] #[inline] fn sub(self, mut other: BigUint) -> BigUint { while other.data.len() < 4 { @@ -1006,18 +821,6 @@ impl Sub for u128 { sub2rev(&[d, c, b, a], &mut other.data[..]); other.normalized() } - - #[cfg(u64_digit)] - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 2 { - other.data.push(0); - } - - let (hi, lo) = big_digit::from_doublebigdigit(self); - sub2rev(&[lo, hi], &mut other.data[..]); - other.normalized() - } } forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul); @@ -1042,6 +845,7 @@ promote_unsigned_scalars!(impl Mul for BigUint, mul); promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); impl Mul for BigUint { @@ -1077,7 +881,6 @@ impl Mul for BigUint { } } impl MulAssign for BigUint { - #[cfg(not(u64_digit))] #[inline] fn mul_assign(&mut self, other: u64) { if other == 0 { @@ -1089,21 +892,9 @@ impl MulAssign for BigUint { *self = mul3(&self.data[..], &[lo, hi]) } } - - #[cfg(u64_digit)] - #[inline] - fn mul_assign(&mut self, other: u64) { - if other == 0 { - self.data.clear(); - } else { - let carry = scalar_mul(&mut self.data[..], other as BigDigit); - if carry != 0 { - self.data.push(carry); - } - } - } } +#[cfg(has_i128)] impl Mul for BigUint { type Output = BigUint; @@ -1113,9 +904,8 @@ impl Mul for BigUint { self } } - +#[cfg(has_i128)] impl MulAssign for BigUint { - #[cfg(not(u64_digit))] #[inline] fn mul_assign(&mut self, other: u128) { if other == 0 { @@ -1127,19 +917,6 @@ impl MulAssign for BigUint { *self = mul3(&self.data[..], &[d, c, b, a]) } } - - #[cfg(u64_digit)] - #[inline] - fn mul_assign(&mut self, other: u128) { - if other == 0 { - self.data.clear(); - } else if other <= BigDigit::max_value() as u128 { - *self *= other as BigDigit - } else { - let (hi, lo) = big_digit::from_doublebigdigit(other); - *self = mul3(&self.data[..], &[lo, hi]) - } - } } forward_val_ref_binop!(impl Div for BigUint, div); @@ -1176,6 +953,7 @@ promote_unsigned_scalars!(impl Div for BigUint, div); promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign); forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); impl Div for BigUint { @@ -1200,7 +978,7 @@ impl Div for u32 { #[inline] fn div(self, other: BigUint) -> BigUint { match other.data.len() { - 0 => panic!("attempt to divide by zero"), + 0 => panic!(), 1 => From::from(self as BigDigit / other.data[0]), _ => Zero::zero(), } @@ -1228,28 +1006,18 @@ impl DivAssign for BigUint { impl Div for u64 { type Output = BigUint; - #[cfg(not(u64_digit))] #[inline] fn div(self, other: BigUint) -> BigUint { match other.data.len() { - 0 => panic!("attempt to divide by zero"), + 0 => panic!(), 1 => From::from(self / u64::from(other.data[0])), 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), _ => Zero::zero(), } } - - #[cfg(u64_digit)] - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!("attempt to divide by zero"), - 1 => From::from(self / other.data[0]), - _ => Zero::zero(), - } - } } +#[cfg(has_i128)] impl Div for BigUint { type Output = BigUint; @@ -1259,7 +1027,7 @@ impl Div for BigUint { q } } - +#[cfg(has_i128)] impl DivAssign for BigUint { #[inline] fn div_assign(&mut self, other: u128) { @@ -1267,14 +1035,14 @@ impl DivAssign for BigUint { } } +#[cfg(has_i128)] impl Div for u128 { type Output = BigUint; - #[cfg(not(u64_digit))] #[inline] fn div(self, other: BigUint) -> BigUint { match other.data.len() { - 0 => panic!("attempt to divide by zero"), + 0 => panic!(), 1 => From::from(self / u128::from(other.data[0])), 2 => From::from( self / u128::from(big_digit::to_doublebigdigit(other.data[1], other.data[0])), @@ -1286,17 +1054,6 @@ impl Div for u128 { _ => Zero::zero(), } } - - #[cfg(u64_digit)] - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!("attempt to divide by zero"), - 1 => From::from(self / other.data[0] as u128), - 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => Zero::zero(), - } - } } forward_val_ref_binop!(impl Rem for BigUint, rem); @@ -1308,12 +1065,8 @@ impl Rem for BigUint { #[inline] fn rem(self, other: BigUint) -> BigUint { - if let Some(other) = other.to_u32() { - &self % other - } else { - let (_, r) = div_rem(self, other); - r - } + let (_, r) = div_rem(self, other); + r } } @@ -1322,12 +1075,8 @@ impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint { #[inline] fn rem(self, other: &BigUint) -> BigUint { - if let Some(other) = other.to_u32() { - self % other - } else { - let (_, r) = self.div_rem(other); - r - } + let (_, r) = self.div_rem(other); + r } } impl<'a> RemAssign<&'a BigUint> for BigUint { @@ -1341,6 +1090,7 @@ promote_unsigned_scalars!(impl Rem for BigUint, rem); promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign); forward_all_scalar_binop_to_ref_val!(impl Rem for BigUint, rem); forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); +#[cfg(has_i128)] forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); impl<'a> Rem for &'a BigUint { @@ -1348,7 +1098,7 @@ impl<'a> Rem for &'a BigUint { #[inline] fn rem(self, other: u32) -> BigUint { - rem_digit(self, other as BigDigit).into() + From::from(rem_digit(self, other as BigDigit)) } } impl RemAssign for BigUint { @@ -1376,21 +1126,22 @@ macro_rules! impl_rem_assign_scalar { fn rem_assign(&mut self, other: &BigUint) { *self = match other.$to_scalar() { None => *self, - Some(0) => panic!("attempt to divide by zero"), + Some(0) => panic!(), Some(v) => *self % v }; } } } } - // we can scalar %= BigUint for any scalar, including signed types +#[cfg(has_i128)] impl_rem_assign_scalar!(u128, to_u128); impl_rem_assign_scalar!(usize, to_usize); impl_rem_assign_scalar!(u64, to_u64); impl_rem_assign_scalar!(u32, to_u32); impl_rem_assign_scalar!(u16, to_u16); impl_rem_assign_scalar!(u8, to_u8); +#[cfg(has_i128)] impl_rem_assign_scalar!(i128, to_i128); impl_rem_assign_scalar!(isize, to_isize); impl_rem_assign_scalar!(i64, to_i64); @@ -1424,6 +1175,7 @@ impl Rem for u64 { } } +#[cfg(has_i128)] impl Rem for BigUint { type Output = BigUint; @@ -1433,7 +1185,7 @@ impl Rem for BigUint { r } } - +#[cfg(has_i128)] impl RemAssign for BigUint { #[inline] fn rem_assign(&mut self, other: u128) { @@ -1441,6 +1193,7 @@ impl RemAssign for BigUint { } } +#[cfg(has_i128)] impl Rem for u128 { type Output = BigUint; @@ -1451,10 +1204,28 @@ impl Rem for u128 { } } +impl Neg for BigUint { + type Output = BigUint; + + #[inline] + fn neg(self) -> BigUint { + panic!() + } +} + +impl<'a> Neg for &'a BigUint { + type Output = BigUint; + + #[inline] + fn neg(self) -> BigUint { + panic!() + } +} + impl CheckedAdd for BigUint { #[inline] fn checked_add(&self, v: &BigUint) -> Option { - Some(self.add(v)) + return Some(self.add(v)); } } @@ -1472,7 +1243,7 @@ impl CheckedSub for BigUint { impl CheckedMul for BigUint { #[inline] fn checked_mul(&self, v: &BigUint) -> Option { - Some(self.mul(v)) + return Some(self.mul(v)); } } @@ -1482,7 +1253,7 @@ impl CheckedDiv for BigUint { if v.is_zero() { return None; } - Some(self.div(v)) + return Some(self.div(v)); } } @@ -1509,24 +1280,14 @@ impl Integer for BigUint { div_rem_ref(self, other) } - #[inline] - fn div_ceil(&self, other: &BigUint) -> BigUint { - let (d, m) = div_rem_ref(self, other); - if m.is_zero() { - d - } else { - d + 1u32 - } - } - /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. /// /// The result is always positive. #[inline] fn gcd(&self, other: &Self) -> Self { #[inline] - fn twos(x: &BigUint) -> u64 { - x.trailing_zeros().unwrap_or(0) + fn twos(x: &BigUint) -> usize { + trailing_zeros(x).unwrap_or(0) } // Stein's algorithm @@ -1567,19 +1328,6 @@ impl Integer for BigUint { } } - /// Calculates the Greatest Common Divisor (GCD) and - /// Lowest Common Multiple (LCM) together. - #[inline] - fn gcd_lcm(&self, other: &Self) -> (Self, Self) { - let gcd = self.gcd(other); - let lcm = if gcd.is_zero() { - Self::zero() - } else { - self / &gcd * other - }; - (gcd, lcm) - } - /// Deprecated, use `is_multiple_of` instead. #[inline] fn divides(&self, other: &BigUint) -> bool { @@ -1607,26 +1355,10 @@ impl Integer for BigUint { fn is_odd(&self) -> bool { !self.is_even() } - - /// Rounds up to nearest multiple of argument. - #[inline] - fn next_multiple_of(&self, other: &Self) -> Self { - let m = self.mod_floor(other); - if m.is_zero() { - self.clone() - } else { - self + (other - m) - } - } - /// Rounds down to nearest multiple of argument. - #[inline] - fn prev_multiple_of(&self, other: &Self) -> Self { - self - self.mod_floor(other) - } } #[inline] -fn fixpoint(mut x: BigUint, max_bits: u64, f: F) -> BigUint +fn fixpoint(mut x: BigUint, max_bits: usize, f: F) -> BigUint where F: Fn(&BigUint) -> BigUint, { @@ -1677,8 +1409,7 @@ impl Roots for BigUint { // The root of non-zero values less than 2ⁿ can only be 1. let bits = self.bits(); - let n64 = u64::from(n); - if bits <= n64 { + if bits <= n as usize { return BigUint::one(); } @@ -1687,28 +1418,25 @@ impl Roots for BigUint { return x.nth_root(n).into(); } - let max_bits = bits / n64 + 1; + let max_bits = bits / n as usize + 1; - #[cfg(feature = "std")] let guess = if let Some(f) = self.to_f64() { // We fit in `f64` (lossy), so get a better initial guess from that. BigUint::from_f64((f.ln() / f64::from(n)).exp()).unwrap() } else { // Try to guess by scaling down such that it does fit in `f64`. // With some (x * 2ⁿᵏ), its nth root ≈ (ⁿ√x * 2ᵏ) - let extra_bits = bits - (f64::MAX_EXP as u64 - 1); - let root_scale = extra_bits.div_ceil(&n64); - let scale = root_scale * n64; - if scale < bits && bits - scale > n64 { + let nsz = n as usize; + let extra_bits = bits - (f64::MAX_EXP as usize - 1); + let root_scale = (extra_bits + (nsz - 1)) / nsz; + let scale = root_scale * nsz; + if scale < bits && bits - scale > nsz { (self >> scale).nth_root(n) << root_scale } else { BigUint::one() << max_bits } }; - #[cfg(not(feature = "std"))] - let guess = BigUint::one() << max_bits; - let n_min_1 = n - 1; fixpoint(guess, max_bits, move |s| { let q = self / s.pow(n_min_1); @@ -1730,24 +1458,20 @@ impl Roots for BigUint { } let bits = self.bits(); - let max_bits = bits / 2 + 1; + let max_bits = bits / 2 as usize + 1; - #[cfg(feature = "std")] let guess = if let Some(f) = self.to_f64() { // We fit in `f64` (lossy), so get a better initial guess from that. BigUint::from_f64(f.sqrt()).unwrap() } else { // Try to guess by scaling down such that it does fit in `f64`. // With some (x * 2²ᵏ), its sqrt ≈ (√x * 2ᵏ) - let extra_bits = bits - (f64::MAX_EXP as u64 - 1); + let extra_bits = bits - (f64::MAX_EXP as usize - 1); let root_scale = (extra_bits + 1) / 2; let scale = root_scale * 2; (self >> scale).sqrt() << root_scale }; - #[cfg(not(feature = "std"))] - let guess = BigUint::one() << max_bits; - fixpoint(guess, max_bits, move |s| { let q = self / s; let t = s + q; @@ -1766,24 +1490,20 @@ impl Roots for BigUint { } let bits = self.bits(); - let max_bits = bits / 3 + 1; + let max_bits = bits / 3 as usize + 1; - #[cfg(feature = "std")] let guess = if let Some(f) = self.to_f64() { // We fit in `f64` (lossy), so get a better initial guess from that. BigUint::from_f64(f.cbrt()).unwrap() } else { // Try to guess by scaling down such that it does fit in `f64`. // With some (x * 2³ᵏ), its cbrt ≈ (∛x * 2ᵏ) - let extra_bits = bits - (f64::MAX_EXP as u64 - 1); + let extra_bits = bits - (f64::MAX_EXP as usize - 1); let root_scale = (extra_bits + 2) / 3; let scale = root_scale * 3; (self >> scale).cbrt() << root_scale }; - #[cfg(not(feature = "std"))] - let guess = BigUint::one() << max_bits; - fixpoint(guess, max_bits, move |s| { let q = self / (s * s); let t = (s << 1) + q; @@ -1802,7 +1522,7 @@ fn high_bits_to_u64(v: &BigUint) -> u64 { let mut ret_bits = 0; for d in v.data.iter().rev() { - let digit_bits = (bits - 1) % u64::from(big_digit::BITS) + 1; + let digit_bits = (bits - 1) % big_digit::BITS + 1; let bits_want = cmp::min(64 - ret_bits, digit_bits); if bits_want != 64 { @@ -1829,6 +1549,7 @@ impl ToPrimitive for BigUint { } #[inline] + #[cfg(has_i128)] fn to_i128(&self) -> Option { self.to_u128().as_ref().and_then(u128::to_i128) } @@ -1851,6 +1572,7 @@ impl ToPrimitive for BigUint { } #[inline] + #[cfg(has_i128)] fn to_u128(&self) -> Option { let mut ret: u128 = 0; let mut bits = 0; @@ -1870,9 +1592,9 @@ impl ToPrimitive for BigUint { #[inline] fn to_f32(&self) -> Option { let mantissa = high_bits_to_u64(self); - let exponent = self.bits() - u64::from(fls(mantissa)); + let exponent = self.bits() - fls(mantissa); - if exponent > f32::MAX_EXP as u64 { + if exponent > f32::MAX_EXP as usize { None } else { let ret = (mantissa as f32) * 2.0f32.powi(exponent as i32); @@ -1887,9 +1609,9 @@ impl ToPrimitive for BigUint { #[inline] fn to_f64(&self) -> Option { let mantissa = high_bits_to_u64(self); - let exponent = self.bits() - u64::from(fls(mantissa)); + let exponent = self.bits() - fls(mantissa); - if exponent > f64::MAX_EXP as u64 { + if exponent > f64::MAX_EXP as usize { None } else { let ret = (mantissa as f64) * 2.0f64.powi(exponent as i32); @@ -1902,44 +1624,6 @@ impl ToPrimitive for BigUint { } } -macro_rules! impl_try_from_biguint { - ($T:ty, $to_ty:path) => { - #[cfg(has_try_from)] - impl TryFrom<&BigUint> for $T { - type Error = TryFromBigIntError<()>; - - #[inline] - fn try_from(value: &BigUint) -> Result<$T, TryFromBigIntError<()>> { - $to_ty(value).ok_or(TryFromBigIntError::new(())) - } - } - - #[cfg(has_try_from)] - impl TryFrom for $T { - type Error = TryFromBigIntError; - - #[inline] - fn try_from(value: BigUint) -> Result<$T, TryFromBigIntError> { - <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) - } - } - }; -} - -impl_try_from_biguint!(u8, ToPrimitive::to_u8); -impl_try_from_biguint!(u16, ToPrimitive::to_u16); -impl_try_from_biguint!(u32, ToPrimitive::to_u32); -impl_try_from_biguint!(u64, ToPrimitive::to_u64); -impl_try_from_biguint!(usize, ToPrimitive::to_usize); -impl_try_from_biguint!(u128, ToPrimitive::to_u128); - -impl_try_from_biguint!(i8, ToPrimitive::to_i8); -impl_try_from_biguint!(i16, ToPrimitive::to_i16); -impl_try_from_biguint!(i32, ToPrimitive::to_i32); -impl_try_from_biguint!(i64, ToPrimitive::to_i64); -impl_try_from_biguint!(isize, ToPrimitive::to_isize); -impl_try_from_biguint!(i128, ToPrimitive::to_i128); - impl FromPrimitive for BigUint { #[inline] fn from_i64(n: i64) -> Option { @@ -1951,6 +1635,7 @@ impl FromPrimitive for BigUint { } #[inline] + #[cfg(has_i128)] fn from_i128(n: i128) -> Option { if n >= 0 { Some(BigUint::from(n as u128)) @@ -1965,6 +1650,7 @@ impl FromPrimitive for BigUint { } #[inline] + #[cfg(has_i128)] fn from_u128(n: u128) -> Option { Some(BigUint::from(n)) } @@ -1984,17 +1670,17 @@ impl FromPrimitive for BigUint { return Some(BigUint::zero()); } - let (mantissa, exponent, sign) = FloatCore::integer_decode(n); + let (mantissa, exponent, sign) = Float::integer_decode(n); if sign == -1 { return None; } let mut ret = BigUint::from(mantissa); - match exponent.cmp(&0) { - Greater => ret <<= exponent as usize, - Equal => {} - Less => ret >>= (-exponent) as usize, + if exponent > 0 { + ret = ret << exponent as usize; + } else if exponent < 0 { + ret = ret >> (-exponent) as usize; } Some(ret) } @@ -2015,6 +1701,7 @@ impl From for BigUint { } } +#[cfg(has_i128)] impl From for BigUint { #[inline] fn from(mut n: u128) -> Self { @@ -2045,27 +1732,6 @@ impl_biguint_from_uint!(u16); impl_biguint_from_uint!(u32); impl_biguint_from_uint!(usize); -macro_rules! impl_biguint_try_from_int { - ($T:ty, $from_ty:path) => { - #[cfg(has_try_from)] - impl TryFrom<$T> for BigUint { - type Error = TryFromBigIntError<()>; - - #[inline] - fn try_from(value: $T) -> Result> { - $from_ty(value).ok_or(TryFromBigIntError::new(())) - } - } - }; -} - -impl_biguint_try_from_int!(i8, FromPrimitive::from_i8); -impl_biguint_try_from_int!(i16, FromPrimitive::from_i16); -impl_biguint_try_from_int!(i32, FromPrimitive::from_i32); -impl_biguint_try_from_int!(i64, FromPrimitive::from_i64); -impl_biguint_try_from_int!(isize, FromPrimitive::from_isize); -impl_biguint_try_from_int!(i128, FromPrimitive::from_i128); - /// A generic trait for converting a value to a `BigUint`. pub trait ToBigUint { /// Converts the value of `self` to a `BigUint`. @@ -2095,6 +1761,7 @@ impl_to_biguint!(i8, FromPrimitive::from_i8); impl_to_biguint!(i16, FromPrimitive::from_i16); impl_to_biguint!(i32, FromPrimitive::from_i32); impl_to_biguint!(i64, FromPrimitive::from_i64); +#[cfg(has_i128)] impl_to_biguint!(i128, FromPrimitive::from_i128); impl_to_biguint!(usize, FromPrimitive::from_usize); @@ -2102,23 +1769,20 @@ impl_to_biguint!(u8, FromPrimitive::from_u8); impl_to_biguint!(u16, FromPrimitive::from_u16); impl_to_biguint!(u32, FromPrimitive::from_u32); impl_to_biguint!(u64, FromPrimitive::from_u64); +#[cfg(has_i128)] impl_to_biguint!(u128, FromPrimitive::from_u128); impl_to_biguint!(f32, FromPrimitive::from_f32); impl_to_biguint!(f64, FromPrimitive::from_f64); // Extract bitwise digits that evenly divide BigDigit -fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { +fn to_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); let last_i = u.data.len() - 1; let mask: BigDigit = (1 << bits) - 1; let digits_per_big_digit = big_digit::BITS / bits; - let digits = u - .bits() - .div_ceil(&u64::from(bits)) - .to_usize() - .unwrap_or(core::usize::MAX); + let digits = (u.bits() + bits - 1) / bits; let mut res = Vec::with_capacity(digits); for mut r in u.data[..last_i].iter().cloned() { @@ -2138,15 +1802,11 @@ fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { } // Extract bitwise digits that don't evenly divide BigDigit -fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { +fn to_inexact_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); let mask: BigDigit = (1 << bits) - 1; - let digits = u - .bits() - .div_ceil(&u64::from(bits)) - .to_usize() - .unwrap_or(core::usize::MAX); + let digits = (u.bits() + bits - 1) / bits; let mut res = Vec::with_capacity(digits); let mut r = 0; @@ -2185,18 +1845,12 @@ fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { debug_assert!(!u.is_zero() && !radix.is_power_of_two()); - #[cfg(feature = "std")] - let radix_log2 = f64::from(radix).log2(); - #[cfg(not(feature = "std"))] - let radix_log2 = ilog2(radix) as f64; - // Estimate how big the result will be, so we can pre-allocate it. - let radix_digits = ((u.bits() as f64) / radix_log2).ceil(); - let mut res = Vec::with_capacity(radix_digits.to_usize().unwrap_or(0)); - + let radix_digits = ((u.bits() as f64) / f64::from(radix).log2()).ceil(); + let mut res = Vec::with_capacity(radix_digits as usize); let mut digits = u.clone(); - let (base, power) = get_radix_base(radix, big_digit::HALF_BITS); + let (base, power) = get_radix_base(radix); let radix = radix as BigDigit; while digits.data.len() > 1 { @@ -2217,7 +1871,7 @@ fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { res } -pub(crate) fn to_radix_le(u: &BigUint, radix: u32) -> Vec { +pub fn to_radix_le(u: &BigUint, radix: u32) -> Vec { if u.is_zero() { vec![0] } else if radix.is_power_of_two() { @@ -2237,7 +1891,7 @@ pub(crate) fn to_radix_le(u: &BigUint, radix: u32) -> Vec { } } -pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { +pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); if u.is_zero() { @@ -2258,64 +1912,30 @@ pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { res } -/// Creates and initializes a `BigUint`. -/// -/// The digits are in little-endian base matching `BigDigit`. -#[inline] -pub(crate) fn biguint_from_vec(digits: Vec) -> BigUint { - BigUint { data: digits }.normalized() -} - impl BigUint { /// Creates and initializes a `BigUint`. /// - /// The base 232 digits are ordered least significant digit first. + /// The digits are in little-endian base 232. #[inline] pub fn new(digits: Vec) -> BigUint { - let mut big = BigUint::zero(); - - #[cfg(not(u64_digit))] - { - big.data = digits; - big.normalize(); - } - - #[cfg(u64_digit)] - big.assign_from_slice(&digits); - - big + BigUint { data: digits }.normalized() } /// Creates and initializes a `BigUint`. /// - /// The base 232 digits are ordered least significant digit first. + /// The digits are in little-endian base 232. #[inline] pub fn from_slice(slice: &[u32]) -> BigUint { - let mut big = BigUint::zero(); - big.assign_from_slice(slice); - big + BigUint::new(slice.to_vec()) } /// Assign a value to a `BigUint`. /// - /// The base 232 digits are ordered least significant digit first. + /// The digits are in little-endian base 232. #[inline] pub fn assign_from_slice(&mut self, slice: &[u32]) { - self.data.clear(); - - #[cfg(not(u64_digit))] - self.data.extend_from_slice(slice); - - #[cfg(u64_digit)] - self.data.extend(slice.chunks(2).map(|chunk| { - // raw could have odd length - let mut digit = BigDigit::from(chunk[0]); - if let Some(&hi) = chunk.get(1) { - digit |= BigDigit::from(hi) << 32; - } - digit - })); - + self.data.resize(slice.len(), 0); + self.data.clone_from_slice(slice); self.normalize(); } @@ -2378,8 +1998,9 @@ impl BigUint { /// ``` #[inline] pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - let s = str::from_utf8(buf).ok()?; - BigUint::from_str_radix(s, radix).ok() + str::from_utf8(buf) + .ok() + .and_then(|s| BigUint::from_str_radix(s, radix).ok()) } /// Creates and initializes a `BigUint`. Each u8 of the input slice is @@ -2504,47 +2125,6 @@ impl BigUint { } } - /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit - /// first. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from(1125u32).to_u32_digits(), vec![1125]); - /// assert_eq!(BigUint::from(4294967295u32).to_u32_digits(), vec![4294967295]); - /// assert_eq!(BigUint::from(4294967296u64).to_u32_digits(), vec![0, 1]); - /// assert_eq!(BigUint::from(112500000000u64).to_u32_digits(), vec![830850304, 26]); - /// ``` - #[inline] - pub fn to_u32_digits(&self) -> Vec { - let mut digits = Vec::new(); - - #[cfg(not(u64_digit))] - digits.clone_from(&self.data); - - #[cfg(u64_digit)] - { - if let Some((&last, data)) = self.data.split_last() { - let last_lo = last as u32; - let last_hi = (last >> 32) as u32; - let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize; - digits.reserve_exact(u32_len); - for &x in data { - digits.push(x as u32); - digits.push((x >> 32) as u32); - } - digits.push(last_lo); - if last_hi != 0 { - digits.push(last_hi); - } - } - } - - digits - } - /// Returns the integer formatted as a string in the given radix. /// `radix` must be in the range `2...36`. /// @@ -2605,12 +2185,12 @@ impl BigUint { /// Determines the fewest bits necessary to express the `BigUint`. #[inline] - pub fn bits(&self) -> u64 { + pub fn bits(&self) -> usize { if self.is_zero() { return 0; } - let zeros: u64 = self.data.last().unwrap().leading_zeros().into(); - self.data.len() as u64 * u64::from(big_digit::BITS) - zeros + let zeros = self.data.last().unwrap().leading_zeros(); + return self.data.len() * big_digit::BITS - zeros as usize; } /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to @@ -2629,19 +2209,11 @@ impl BigUint { self } - /// Returns `self ^ exponent`. - pub fn pow(&self, exponent: u32) -> Self { - Pow::pow(self, exponent) - } - /// Returns `(self ^ exponent) % modulus`. /// /// Panics if the modulus is zero. pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { - assert!( - !modulus.is_zero(), - "attempt to calculate with zero modulus!" - ); + assert!(!modulus.is_zero(), "divide by zero!"); if modulus.is_odd() { // For an odd modulus, we can use Montgomery multiplication in base 2^32. @@ -2669,28 +2241,17 @@ impl BigUint { pub fn nth_root(&self, n: u32) -> Self { Roots::nth_root(self, n) } - - /// Returns the number of least-significant bits that are zero, - /// or `None` if the entire number is zero. - pub fn trailing_zeros(&self) -> Option { - let i = self.data.iter().position(|&digit| digit != 0)?; - let zeros: u64 = self.data[i].trailing_zeros().into(); - Some(i as u64 * u64::from(big_digit::BITS) + zeros) - } } fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> BigUint { - assert!( - !modulus.is_zero(), - "attempt to calculate with zero modulus!" - ); + assert!(!modulus.is_zero(), "divide by zero!"); let i = match exp_data.iter().position(|&r| r != 0) { None => return BigUint::one(), Some(i) => i, }; - let mut base = base % modulus; + let mut base = base.clone(); for _ in 0..i { for _ in 0..big_digit::BITS { base = &base * &base % modulus; @@ -2698,7 +2259,7 @@ fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> Big } let mut r = exp_data[i]; - let mut b = 0u8; + let mut b = 0usize; while r.is_even() { base = &base * &base % modulus; r >>= 1; @@ -2751,7 +2312,7 @@ fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> Big #[test] fn test_plain_modpow() { - let two = &BigUint::from(2u32); + let two = BigUint::from(2u32); let modulus = BigUint::from(0x1100u32); let exp = vec![0, 0b1]; @@ -2781,10 +2342,20 @@ fn test_plain_modpow() { ); } +/// Returns the number of least-significant bits that are zero, +/// or `None` if the entire number is zero. +pub fn trailing_zeros(u: &BigUint) -> Option { + u.data + .iter() + .enumerate() + .find(|&(_, &digit)| digit != 0) + .map(|(i, digit)| i * big_digit::BITS + digit.trailing_zeros() as usize) +} + impl_sum_iter_type!(BigUint); impl_product_iter_type!(BigUint); -pub(crate) trait IntDigits { +pub trait IntDigits { fn digits(&self) -> &[BigDigit]; fn digits_mut(&mut self) -> &mut Vec; fn normalize(&mut self); @@ -2816,14 +2387,14 @@ impl IntDigits for BigUint { } /// Combine four `u32`s into a single `u128`. -#[cfg(any(test, not(u64_digit)))] +#[cfg(has_i128)] #[inline] fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 { u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96) } /// Split a single `u128` into four `u32`. -#[cfg(any(test, not(u64_digit)))] +#[cfg(has_i128)] #[inline] fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { ( @@ -2836,7 +2407,6 @@ fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { #[cfg(feature = "serde")] impl serde::Serialize for BigUint { - #[cfg(not(u64_digit))] fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -2844,35 +2414,9 @@ impl serde::Serialize for BigUint { // Note: do not change the serialization format, or it may break forward // and backward compatibility of serialized data! If we ever change the // internal representation, we should still serialize in base-`u32`. - let data: &[u32] = &self.data; + let data: &Vec = &self.data; data.serialize(serializer) } - - #[cfg(u64_digit)] - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - use serde::ser::SerializeSeq; - if let Some((&last, data)) = self.data.split_last() { - let last_lo = last as u32; - let last_hi = (last >> 32) as u32; - let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize; - let mut seq = serializer.serialize_seq(Some(u32_len))?; - for &x in data { - seq.serialize_element(&(x as u32))?; - seq.serialize_element(&((x >> 32) as u32))?; - } - seq.serialize_element(&last_lo)?; - if last_hi != 0 { - seq.serialize_element(&last_hi)?; - } - seq.end() - } else { - let data: &[u32] = &[]; - data.serialize(serializer) - } - } } #[cfg(feature = "serde")] @@ -2881,126 +2425,609 @@ impl<'de> serde::Deserialize<'de> for BigUint { where D: serde::Deserializer<'de>, { - use serde::de::{SeqAccess, Visitor}; - - struct U32Visitor; - - impl<'de> Visitor<'de> for U32Visitor { - type Value = BigUint; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence of unsigned 32-bit numbers") - } - - #[cfg(not(u64_digit))] - fn visit_seq(self, mut seq: S) -> Result - where - S: SeqAccess<'de>, - { - let len = seq.size_hint().unwrap_or(0); - let mut data = Vec::with_capacity(len); - - while let Some(value) = seq.next_element::()? { - data.push(value); - } - - Ok(biguint_from_vec(data)) - } - - #[cfg(u64_digit)] - fn visit_seq(self, mut seq: S) -> Result - where - S: SeqAccess<'de>, - { - let u32_len = seq.size_hint().unwrap_or(0); - let len = u32_len.div_ceil(&2); - let mut data = Vec::with_capacity(len); - - while let Some(lo) = seq.next_element::()? { - let mut value = BigDigit::from(lo); - if let Some(hi) = seq.next_element::()? { - value |= BigDigit::from(hi) << 32; - data.push(value); - } else { - data.push(value); - break; - } - } - - Ok(biguint_from_vec(data)) - } - } - - deserializer.deserialize_seq(U32Visitor) + let data: Vec = Vec::deserialize(deserializer)?; + Ok(BigUint::new(data)) } } -/// Returns the greatest power of the radix for the given bit size +/// Returns the greatest power of the radix <= big_digit::BASE #[inline] -fn get_radix_base(radix: u32, bits: u8) -> (BigDigit, usize) { - mod gen { - include! { concat!(env!("OUT_DIR"), "/radix_bases.rs") } - } - +fn get_radix_base(radix: u32) -> (BigDigit, usize) { debug_assert!( 2 <= radix && radix <= 256, "The radix must be within 2...256" ); debug_assert!(!radix.is_power_of_two()); - debug_assert!(bits <= big_digit::BITS); - match bits { - 16 => { - let (base, power) = gen::BASES_16[radix as usize]; - (base as BigDigit, power) - } + // To generate this table: + // for radix in 2u64..257 { + // let mut power = big_digit::BITS / fls(radix as u64); + // let mut base = radix.pow(power as u32); + // + // while let Some(b) = base.checked_mul(radix) { + // if b > big_digit::MAX { + // break; + // } + // base = b; + // power += 1; + // } + // + // println!("({:10}, {:2}), // {:2}", base, power, radix); + // } + // and + // for radix in 2u64..257 { + // let mut power = 64 / fls(radix as u64); + // let mut base = radix.pow(power as u32); + // + // while let Some(b) = base.checked_mul(radix) { + // base = b; + // power += 1; + // } + // + // println!("({:20}, {:2}), // {:2}", base, power, radix); + // } + match big_digit::BITS { 32 => { - let (base, power) = gen::BASES_32[radix as usize]; + const BASES: [(u32, usize); 257] = [ + (0, 0), + (0, 0), + (0, 0), // 2 + (3486784401, 20), // 3 + (0, 0), // 4 + (1220703125, 13), // 5 + (2176782336, 12), // 6 + (1977326743, 11), // 7 + (0, 0), // 8 + (3486784401, 10), // 9 + (1000000000, 9), // 10 + (2357947691, 9), // 11 + (429981696, 8), // 12 + (815730721, 8), // 13 + (1475789056, 8), // 14 + (2562890625, 8), // 15 + (0, 0), // 16 + (410338673, 7), // 17 + (612220032, 7), // 18 + (893871739, 7), // 19 + (1280000000, 7), // 20 + (1801088541, 7), // 21 + (2494357888, 7), // 22 + (3404825447, 7), // 23 + (191102976, 6), // 24 + (244140625, 6), // 25 + (308915776, 6), // 26 + (387420489, 6), // 27 + (481890304, 6), // 28 + (594823321, 6), // 29 + (729000000, 6), // 30 + (887503681, 6), // 31 + (0, 0), // 32 + (1291467969, 6), // 33 + (1544804416, 6), // 34 + (1838265625, 6), // 35 + (2176782336, 6), // 36 + (2565726409, 6), // 37 + (3010936384, 6), // 38 + (3518743761, 6), // 39 + (4096000000, 6), // 40 + (115856201, 5), // 41 + (130691232, 5), // 42 + (147008443, 5), // 43 + (164916224, 5), // 44 + (184528125, 5), // 45 + (205962976, 5), // 46 + (229345007, 5), // 47 + (254803968, 5), // 48 + (282475249, 5), // 49 + (312500000, 5), // 50 + (345025251, 5), // 51 + (380204032, 5), // 52 + (418195493, 5), // 53 + (459165024, 5), // 54 + (503284375, 5), // 55 + (550731776, 5), // 56 + (601692057, 5), // 57 + (656356768, 5), // 58 + (714924299, 5), // 59 + (777600000, 5), // 60 + (844596301, 5), // 61 + (916132832, 5), // 62 + (992436543, 5), // 63 + (0, 0), // 64 + (1160290625, 5), // 65 + (1252332576, 5), // 66 + (1350125107, 5), // 67 + (1453933568, 5), // 68 + (1564031349, 5), // 69 + (1680700000, 5), // 70 + (1804229351, 5), // 71 + (1934917632, 5), // 72 + (2073071593, 5), // 73 + (2219006624, 5), // 74 + (2373046875, 5), // 75 + (2535525376, 5), // 76 + (2706784157, 5), // 77 + (2887174368, 5), // 78 + (3077056399, 5), // 79 + (3276800000, 5), // 80 + (3486784401, 5), // 81 + (3707398432, 5), // 82 + (3939040643, 5), // 83 + (4182119424, 5), // 84 + (52200625, 4), // 85 + (54700816, 4), // 86 + (57289761, 4), // 87 + (59969536, 4), // 88 + (62742241, 4), // 89 + (65610000, 4), // 90 + (68574961, 4), // 91 + (71639296, 4), // 92 + (74805201, 4), // 93 + (78074896, 4), // 94 + (81450625, 4), // 95 + (84934656, 4), // 96 + (88529281, 4), // 97 + (92236816, 4), // 98 + (96059601, 4), // 99 + (100000000, 4), // 100 + (104060401, 4), // 101 + (108243216, 4), // 102 + (112550881, 4), // 103 + (116985856, 4), // 104 + (121550625, 4), // 105 + (126247696, 4), // 106 + (131079601, 4), // 107 + (136048896, 4), // 108 + (141158161, 4), // 109 + (146410000, 4), // 110 + (151807041, 4), // 111 + (157351936, 4), // 112 + (163047361, 4), // 113 + (168896016, 4), // 114 + (174900625, 4), // 115 + (181063936, 4), // 116 + (187388721, 4), // 117 + (193877776, 4), // 118 + (200533921, 4), // 119 + (207360000, 4), // 120 + (214358881, 4), // 121 + (221533456, 4), // 122 + (228886641, 4), // 123 + (236421376, 4), // 124 + (244140625, 4), // 125 + (252047376, 4), // 126 + (260144641, 4), // 127 + (0, 0), // 128 + (276922881, 4), // 129 + (285610000, 4), // 130 + (294499921, 4), // 131 + (303595776, 4), // 132 + (312900721, 4), // 133 + (322417936, 4), // 134 + (332150625, 4), // 135 + (342102016, 4), // 136 + (352275361, 4), // 137 + (362673936, 4), // 138 + (373301041, 4), // 139 + (384160000, 4), // 140 + (395254161, 4), // 141 + (406586896, 4), // 142 + (418161601, 4), // 143 + (429981696, 4), // 144 + (442050625, 4), // 145 + (454371856, 4), // 146 + (466948881, 4), // 147 + (479785216, 4), // 148 + (492884401, 4), // 149 + (506250000, 4), // 150 + (519885601, 4), // 151 + (533794816, 4), // 152 + (547981281, 4), // 153 + (562448656, 4), // 154 + (577200625, 4), // 155 + (592240896, 4), // 156 + (607573201, 4), // 157 + (623201296, 4), // 158 + (639128961, 4), // 159 + (655360000, 4), // 160 + (671898241, 4), // 161 + (688747536, 4), // 162 + (705911761, 4), // 163 + (723394816, 4), // 164 + (741200625, 4), // 165 + (759333136, 4), // 166 + (777796321, 4), // 167 + (796594176, 4), // 168 + (815730721, 4), // 169 + (835210000, 4), // 170 + (855036081, 4), // 171 + (875213056, 4), // 172 + (895745041, 4), // 173 + (916636176, 4), // 174 + (937890625, 4), // 175 + (959512576, 4), // 176 + (981506241, 4), // 177 + (1003875856, 4), // 178 + (1026625681, 4), // 179 + (1049760000, 4), // 180 + (1073283121, 4), // 181 + (1097199376, 4), // 182 + (1121513121, 4), // 183 + (1146228736, 4), // 184 + (1171350625, 4), // 185 + (1196883216, 4), // 186 + (1222830961, 4), // 187 + (1249198336, 4), // 188 + (1275989841, 4), // 189 + (1303210000, 4), // 190 + (1330863361, 4), // 191 + (1358954496, 4), // 192 + (1387488001, 4), // 193 + (1416468496, 4), // 194 + (1445900625, 4), // 195 + (1475789056, 4), // 196 + (1506138481, 4), // 197 + (1536953616, 4), // 198 + (1568239201, 4), // 199 + (1600000000, 4), // 200 + (1632240801, 4), // 201 + (1664966416, 4), // 202 + (1698181681, 4), // 203 + (1731891456, 4), // 204 + (1766100625, 4), // 205 + (1800814096, 4), // 206 + (1836036801, 4), // 207 + (1871773696, 4), // 208 + (1908029761, 4), // 209 + (1944810000, 4), // 210 + (1982119441, 4), // 211 + (2019963136, 4), // 212 + (2058346161, 4), // 213 + (2097273616, 4), // 214 + (2136750625, 4), // 215 + (2176782336, 4), // 216 + (2217373921, 4), // 217 + (2258530576, 4), // 218 + (2300257521, 4), // 219 + (2342560000, 4), // 220 + (2385443281, 4), // 221 + (2428912656, 4), // 222 + (2472973441, 4), // 223 + (2517630976, 4), // 224 + (2562890625, 4), // 225 + (2608757776, 4), // 226 + (2655237841, 4), // 227 + (2702336256, 4), // 228 + (2750058481, 4), // 229 + (2798410000, 4), // 230 + (2847396321, 4), // 231 + (2897022976, 4), // 232 + (2947295521, 4), // 233 + (2998219536, 4), // 234 + (3049800625, 4), // 235 + (3102044416, 4), // 236 + (3154956561, 4), // 237 + (3208542736, 4), // 238 + (3262808641, 4), // 239 + (3317760000, 4), // 240 + (3373402561, 4), // 241 + (3429742096, 4), // 242 + (3486784401, 4), // 243 + (3544535296, 4), // 244 + (3603000625, 4), // 245 + (3662186256, 4), // 246 + (3722098081, 4), // 247 + (3782742016, 4), // 248 + (3844124001, 4), // 249 + (3906250000, 4), // 250 + (3969126001, 4), // 251 + (4032758016, 4), // 252 + (4097152081, 4), // 253 + (4162314256, 4), // 254 + (4228250625, 4), // 255 + (0, 0), // 256 + ]; + + let (base, power) = BASES[radix as usize]; (base as BigDigit, power) } 64 => { - let (base, power) = gen::BASES_64[radix as usize]; + const BASES: [(u64, usize); 257] = [ + (0, 0), + (0, 0), + (9223372036854775808, 63), // 2 + (12157665459056928801, 40), // 3 + (4611686018427387904, 31), // 4 + (7450580596923828125, 27), // 5 + (4738381338321616896, 24), // 6 + (3909821048582988049, 22), // 7 + (9223372036854775808, 21), // 8 + (12157665459056928801, 20), // 9 + (10000000000000000000, 19), // 10 + (5559917313492231481, 18), // 11 + (2218611106740436992, 17), // 12 + (8650415919381337933, 17), // 13 + (2177953337809371136, 16), // 14 + (6568408355712890625, 16), // 15 + (1152921504606846976, 15), // 16 + (2862423051509815793, 15), // 17 + (6746640616477458432, 15), // 18 + (15181127029874798299, 15), // 19 + (1638400000000000000, 14), // 20 + (3243919932521508681, 14), // 21 + (6221821273427820544, 14), // 22 + (11592836324538749809, 14), // 23 + (876488338465357824, 13), // 24 + (1490116119384765625, 13), // 25 + (2481152873203736576, 13), // 26 + (4052555153018976267, 13), // 27 + (6502111422497947648, 13), // 28 + (10260628712958602189, 13), // 29 + (15943230000000000000, 13), // 30 + (787662783788549761, 12), // 31 + (1152921504606846976, 12), // 32 + (1667889514952984961, 12), // 33 + (2386420683693101056, 12), // 34 + (3379220508056640625, 12), // 35 + (4738381338321616896, 12), // 36 + (6582952005840035281, 12), // 37 + (9065737908494995456, 12), // 38 + (12381557655576425121, 12), // 39 + (16777216000000000000, 12), // 40 + (550329031716248441, 11), // 41 + (717368321110468608, 11), // 42 + (929293739471222707, 11), // 43 + (1196683881290399744, 11), // 44 + (1532278301220703125, 11), // 45 + (1951354384207722496, 11), // 46 + (2472159215084012303, 11), // 47 + (3116402981210161152, 11), // 48 + (3909821048582988049, 11), // 49 + (4882812500000000000, 11), // 50 + (6071163615208263051, 11), // 51 + (7516865509350965248, 11), // 52 + (9269035929372191597, 11), // 53 + (11384956040305711104, 11), // 54 + (13931233916552734375, 11), // 55 + (16985107389382393856, 11), // 56 + (362033331456891249, 10), // 57 + (430804206899405824, 10), // 58 + (511116753300641401, 10), // 59 + (604661760000000000, 10), // 60 + (713342911662882601, 10), // 61 + (839299365868340224, 10), // 62 + (984930291881790849, 10), // 63 + (1152921504606846976, 10), // 64 + (1346274334462890625, 10), // 65 + (1568336880910795776, 10), // 66 + (1822837804551761449, 10), // 67 + (2113922820157210624, 10), // 68 + (2446194060654759801, 10), // 69 + (2824752490000000000, 10), // 70 + (3255243551009881201, 10), // 71 + (3743906242624487424, 10), // 72 + (4297625829703557649, 10), // 73 + (4923990397355877376, 10), // 74 + (5631351470947265625, 10), // 75 + (6428888932339941376, 10), // 76 + (7326680472586200649, 10), // 77 + (8335775831236199424, 10), // 78 + (9468276082626847201, 10), // 79 + (10737418240000000000, 10), // 80 + (12157665459056928801, 10), // 81 + (13744803133596058624, 10), // 82 + (15516041187205853449, 10), // 83 + (17490122876598091776, 10), // 84 + (231616946283203125, 9), // 85 + (257327417311663616, 9), // 86 + (285544154243029527, 9), // 87 + (316478381828866048, 9), // 88 + (350356403707485209, 9), // 89 + (387420489000000000, 9), // 90 + (427929800129788411, 9), // 91 + (472161363286556672, 9), // 92 + (520411082988487293, 9), // 93 + (572994802228616704, 9), // 94 + (630249409724609375, 9), // 95 + (692533995824480256, 9), // 96 + (760231058654565217, 9), // 97 + (833747762130149888, 9), // 98 + (913517247483640899, 9), // 99 + (1000000000000000000, 9), // 100 + (1093685272684360901, 9), // 101 + (1195092568622310912, 9), // 102 + (1304773183829244583, 9), // 103 + (1423311812421484544, 9), // 104 + (1551328215978515625, 9), // 105 + (1689478959002692096, 9), // 106 + (1838459212420154507, 9), // 107 + (1999004627104432128, 9), // 108 + (2171893279442309389, 9), // 109 + (2357947691000000000, 9), // 110 + (2558036924386500591, 9), // 111 + (2773078757450186752, 9), // 112 + (3004041937984268273, 9), // 113 + (3251948521156637184, 9), // 114 + (3517876291919921875, 9), // 115 + (3802961274698203136, 9), // 116 + (4108400332687853397, 9), // 117 + (4435453859151328768, 9), // 118 + (4785448563124474679, 9), // 119 + (5159780352000000000, 9), // 120 + (5559917313492231481, 9), // 121 + (5987402799531080192, 9), // 122 + (6443858614676334363, 9), // 123 + (6930988311686938624, 9), // 124 + (7450580596923828125, 9), // 125 + (8004512848309157376, 9), // 126 + (8594754748609397887, 9), // 127 + (9223372036854775808, 9), // 128 + (9892530380752880769, 9), // 129 + (10604499373000000000, 9), // 130 + (11361656654439817571, 9), // 131 + (12166492167065567232, 9), // 132 + (13021612539908538853, 9), // 133 + (13929745610903012864, 9), // 134 + (14893745087865234375, 9), // 135 + (15916595351771938816, 9), // 136 + (17001416405572203977, 9), // 137 + (18151468971815029248, 9), // 138 + (139353667211683681, 8), // 139 + (147578905600000000, 8), // 140 + (156225851787813921, 8), // 141 + (165312903998914816, 8), // 142 + (174859124550883201, 8), // 143 + (184884258895036416, 8), // 144 + (195408755062890625, 8), // 145 + (206453783524884736, 8), // 146 + (218041257467152161, 8), // 147 + (230193853492166656, 8), // 148 + (242935032749128801, 8), // 149 + (256289062500000000, 8), // 150 + (270281038127131201, 8), // 151 + (284936905588473856, 8), // 152 + (300283484326400961, 8), // 153 + (316348490636206336, 8), // 154 + (333160561500390625, 8), // 155 + (350749278894882816, 8), // 156 + (369145194573386401, 8), // 157 + (388379855336079616, 8), // 158 + (408485828788939521, 8), // 159 + (429496729600000000, 8), // 160 + (451447246258894081, 8), // 161 + (474373168346071296, 8), // 162 + (498311414318121121, 8), // 163 + (523300059815673856, 8), // 164 + (549378366500390625, 8), // 165 + (576586811427594496, 8), // 166 + (604967116961135041, 8), // 167 + (634562281237118976, 8), // 168 + (665416609183179841, 8), // 169 + (697575744100000000, 8), // 170 + (731086699811838561, 8), // 171 + (765997893392859136, 8), // 172 + (802359178476091681, 8), // 173 + (840221879151902976, 8), // 174 + (879638824462890625, 8), // 175 + (920664383502155776, 8), // 176 + (963354501121950081, 8), // 177 + (1007766734259732736, 8), // 178 + (1053960288888713761, 8), // 179 + (1101996057600000000, 8), // 180 + (1151936657823500641, 8), // 181 + (1203846470694789376, 8), // 182 + (1257791680575160641, 8), // 183 + (1313840315232157696, 8), // 184 + (1372062286687890625, 8), // 185 + (1432529432742502656, 8), // 186 + (1495315559180183521, 8), // 187 + (1560496482665168896, 8), // 188 + (1628150074335205281, 8), // 189 + (1698356304100000000, 8), // 190 + (1771197285652216321, 8), // 191 + (1846757322198614016, 8), // 192 + (1925122952918976001, 8), // 193 + (2006383000160502016, 8), // 194 + (2090628617375390625, 8), // 195 + (2177953337809371136, 8), // 196 + (2268453123948987361, 8), // 197 + (2362226417735475456, 8), // 198 + (2459374191553118401, 8), // 199 + (2560000000000000000, 8), // 200 + (2664210032449121601, 8), // 201 + (2772113166407885056, 8), // 202 + (2883821021683985761, 8), // 203 + (2999448015365799936, 8), // 204 + (3119111417625390625, 8), // 205 + (3242931408352297216, 8), // 206 + (3371031134626313601, 8), // 207 + (3503536769037500416, 8), // 208 + (3640577568861717121, 8), // 209 + (3782285936100000000, 8), // 210 + (3928797478390152481, 8), // 211 + (4080251070798954496, 8), // 212 + (4236788918503437921, 8), // 213 + (4398556620369715456, 8), // 214 + (4565703233437890625, 8), // 215 + (4738381338321616896, 8), // 216 + (4916747105530914241, 8), // 217 + (5100960362726891776, 8), // 218 + (5291184662917065441, 8), // 219 + (5487587353600000000, 8), // 220 + (5690339646868044961, 8), // 221 + (5899616690476974336, 8), // 222 + (6115597639891380481, 8), // 223 + (6338465731314712576, 8), // 224 + (6568408355712890625, 8), // 225 + (6805617133840466176, 8), // 226 + (7050287992278341281, 8), // 227 + (7302621240492097536, 8), // 228 + (7562821648920027361, 8), // 229 + (7831098528100000000, 8), // 230 + (8107665808844335041, 8), // 231 + (8392742123471896576, 8), // 232 + (8686550888106661441, 8), // 233 + (8989320386052055296, 8), // 234 + (9301283852250390625, 8), // 235 + (9622679558836781056, 8), // 236 + (9953750901796946721, 8), // 237 + (10294746488738365696, 8), // 238 + (10645920227784266881, 8), // 239 + (11007531417600000000, 8), // 240 + (11379844838561358721, 8), // 241 + (11763130845074473216, 8), // 242 + (12157665459056928801, 8), // 243 + (12563730464589807616, 8), // 244 + (12981613503750390625, 8), // 245 + (13411608173635297536, 8), // 246 + (13854014124583882561, 8), // 247 + (14309137159611744256, 8), // 248 + (14777289335064248001, 8), // 249 + (15258789062500000000, 8), // 250 + (15753961211814252001, 8), // 251 + (16263137215612256256, 8), // 252 + (16786655174842630561, 8), // 253 + (17324859965700833536, 8), // 254 + (17878103347812890625, 8), // 255 + (72057594037927936, 7), // 256 + ]; + + let (base, power) = BASES[radix as usize]; (base as BigDigit, power) } _ => panic!("Invalid bigdigit size"), } } -#[cfg(not(u64_digit))] #[test] fn test_from_slice() { - fn check(slice: &[u32], data: &[BigDigit]) { - assert_eq!(BigUint::from_slice(slice).data, data); + fn check(slice: &[BigDigit], data: &[BigDigit]) { + assert!(BigUint::from_slice(slice).data == data); } check(&[1], &[1]); check(&[0, 0, 0], &[]); check(&[1, 2, 0, 0], &[1, 2]); check(&[0, 0, 1, 2], &[0, 0, 1, 2]); check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); - check(&[-1i32 as u32], &[-1i32 as BigDigit]); + check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); } -#[cfg(u64_digit)] #[test] -fn test_from_slice() { - fn check(slice: &[u32], data: &[BigDigit]) { - assert_eq!( - BigUint::from_slice(slice).data, - data, - "from {:?}, to {:?}", - slice, - data - ); +fn test_assign_from_slice() { + fn check(slice: &[BigDigit], data: &[BigDigit]) { + let mut p = BigUint::from_slice(&[2627_u32, 0_u32, 9182_u32, 42_u32]); + p.assign_from_slice(slice); + assert!(p.data == data); } check(&[1], &[1]); check(&[0, 0, 0], &[]); - check(&[1, 2], &[8_589_934_593]); - check(&[1, 2, 0, 0], &[8_589_934_593]); - check(&[0, 0, 1, 2], &[0, 8_589_934_593]); - check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]); - check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]); + check(&[1, 2, 0, 0], &[1, 2]); + check(&[0, 0, 1, 2], &[0, 0, 1, 2]); + check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]); + check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); } +#[cfg(has_i128)] #[test] fn test_u32_u128() { assert_eq!(u32_from_u128(0u128), (0, 0, 0, 0)); @@ -3032,6 +3059,7 @@ fn test_u32_u128() { assert_eq!(u32_from_u128(36_893_488_151_714_070_528), (0, 2, 1, 0)); } +#[cfg(has_i128)] #[test] fn test_u128_u32_roundtrip() { // roundtrips diff --git a/third_party/rust/num-bigint/src/lib.rs b/third_party/rust/num-bigint/src/lib.rs index 30c5abecf0b5..dece7bab0070 100644 --- a/third_party/rust/num-bigint/src/lib.rs +++ b/third_party/rust/num-bigint/src/lib.rs @@ -19,6 +19,9 @@ //! ## Example //! //! ```rust +//! extern crate num_bigint; +//! extern crate num_traits; +//! //! # fn main() { //! use num_bigint::BigUint; //! use num_traits::{Zero, One}; @@ -43,8 +46,14 @@ //! //! It's easy to generate large random numbers: //! -//! ```rust,ignore -//! use num_bigint::{ToBigInt, RandBigInt}; +//! ```rust +//! # #[cfg(feature = "rand")] +//! extern crate rand; +//! extern crate num_bigint as bigint; +//! +//! # #[cfg(feature = "rand")] +//! # fn main() { +//! use bigint::{ToBigInt, RandBigInt}; //! //! let mut rng = rand::thread_rng(); //! let a = rng.gen_bigint(1000); @@ -55,67 +64,34 @@ //! //! // Probably an even larger number. //! println!("{}", a * b); +//! # } +//! +//! # #[cfg(not(feature = "rand"))] +//! # fn main() { +//! # } //! ``` //! -//! See the "Features" section for instructions for enabling random number generation. -//! -//! ## Features -//! -//! The `std` crate feature is enabled by default, and is mandatory before Rust -//! 1.36 and the stabilized `alloc` crate. If you depend on `num-bigint` with -//! `default-features = false`, you must manually enable the `std` feature yourself -//! if your compiler is not new enough. -//! -//! ### Random Generation -//! -//! `num-bigint` supports the generation of random big integers when the `rand` -//! feature is enabled. To enable it include rand as -//! -//! ```toml -//! rand = "0.7" -//! num-bigint = { version = "0.3", features = ["rand"] } -//! ``` -//! -//! Note that you must use the version of `rand` that `num-bigint` is compatible -//! with: `0.7`. -//! -//! //! ## Compatibility //! -//! The `num-bigint` crate is tested for rustc 1.31 and greater. +//! The `num-bigint` crate is tested for rustc 1.15 and greater. -#![doc(html_root_url = "https://docs.rs/num-bigint/0.3")] -#![no_std] +#![doc(html_root_url = "https://docs.rs/num-bigint/0.2")] +// We don't actually support `no_std` yet, and probably won't until `alloc` is stable. We're just +// reserving this ability with the "std" feature now, and compilation will fail without. +#![cfg_attr(not(feature = "std"), no_std)] -#[cfg(feature = "std")] -#[macro_use] -extern crate std; +#[cfg(feature = "rand")] +extern crate rand; +#[cfg(feature = "serde")] +extern crate serde; -#[cfg(feature = "std")] -mod std_alloc { - pub(crate) use std::borrow::Cow; - #[cfg(feature = "quickcheck")] - pub(crate) use std::boxed::Box; - pub(crate) use std::string::String; - pub(crate) use std::vec::Vec; -} +extern crate num_integer as integer; +extern crate num_traits as traits; +#[cfg(feature = "quickcheck")] +extern crate quickcheck; -#[cfg(not(feature = "std"))] -#[macro_use] -extern crate alloc; - -#[cfg(not(feature = "std"))] -mod std_alloc { - pub(crate) use alloc::borrow::Cow; - #[cfg(feature = "quickcheck")] - pub(crate) use alloc::boxed::Box; - pub(crate) use alloc::string::String; - pub(crate) use alloc::vec::Vec; -} - -use core::fmt; -#[cfg(feature = "std")] use std::error::Error; +use std::fmt; #[macro_use] mod macros; @@ -149,7 +125,7 @@ enum BigIntErrorKind { impl ParseBigIntError { fn __description(&self) -> &str { - use crate::BigIntErrorKind::*; + use BigIntErrorKind::*; match self.kind { Empty => "cannot parse integer from empty string", InvalidDigit => "invalid digit found in string", @@ -170,102 +146,42 @@ impl ParseBigIntError { } impl fmt::Display for ParseBigIntError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.__description().fmt(f) } } -#[cfg(feature = "std")] impl Error for ParseBigIntError { fn description(&self) -> &str { self.__description() } } -/// The error type returned when a checked conversion regarding big integer fails. -#[cfg(has_try_from)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct TryFromBigIntError { - original: T, -} +pub use biguint::BigUint; +pub use biguint::ToBigUint; -#[cfg(has_try_from)] -impl TryFromBigIntError { - fn new(original: T) -> Self { - TryFromBigIntError { original } - } - - fn __description(&self) -> &str { - "out of range conversion regarding big integer attempted" - } - - /// Extract the original value, if available. The value will be available - /// if the type before conversion was either [`BigInt`] or [`BigUint`]. - /// - /// [`BigInt`]: struct.BigInt.html - /// [`BigUint`]: struct.BigUint.html - pub fn into_original(self) -> T { - self.original - } -} - -#[cfg(all(feature = "std", has_try_from))] -impl std::error::Error for TryFromBigIntError -where - T: fmt::Debug, -{ - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(has_try_from)] -impl fmt::Display for TryFromBigIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.__description().fmt(f) - } -} - -pub use crate::biguint::BigUint; -pub use crate::biguint::ToBigUint; - -pub use crate::bigint::BigInt; -pub use crate::bigint::Sign; -pub use crate::bigint::ToBigInt; +pub use bigint::BigInt; +pub use bigint::Sign; +pub use bigint::ToBigInt; #[cfg(feature = "rand")] -pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint}; +pub use bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint}; mod big_digit { /// A `BigDigit` is a `BigUint`'s composing element. - #[cfg(not(u64_digit))] - pub(crate) type BigDigit = u32; - #[cfg(u64_digit)] - pub(crate) type BigDigit = u64; + pub type BigDigit = u32; /// A `DoubleBigDigit` is the internal type used to do the computations. Its /// size is the double of the size of `BigDigit`. - #[cfg(not(u64_digit))] - pub(crate) type DoubleBigDigit = u64; - #[cfg(u64_digit)] - pub(crate) type DoubleBigDigit = u128; + pub type DoubleBigDigit = u64; /// A `SignedDoubleBigDigit` is the signed version of `DoubleBigDigit`. - #[cfg(not(u64_digit))] - pub(crate) type SignedDoubleBigDigit = i64; - #[cfg(u64_digit)] - pub(crate) type SignedDoubleBigDigit = i128; + pub type SignedDoubleBigDigit = i64; // `DoubleBigDigit` size dependent - #[cfg(not(u64_digit))] - pub(crate) const BITS: u8 = 32; - #[cfg(u64_digit)] - pub(crate) const BITS: u8 = 64; + pub const BITS: usize = 32; - pub(crate) const HALF_BITS: u8 = BITS / 2; - pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1; - - const LO_MASK: DoubleBigDigit = (1 << BITS) - 1; + const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS; #[inline] fn get_hi(n: DoubleBigDigit) -> BigDigit { @@ -278,13 +194,13 @@ mod big_digit { /// Split one `DoubleBigDigit` into two `BigDigit`s. #[inline] - pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { + pub fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { (get_hi(n), get_lo(n)) } /// Join two `BigDigit`s into one `DoubleBigDigit` #[inline] - pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { + pub fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS) } } diff --git a/third_party/rust/num-bigint/src/macros.rs b/third_party/rust/num-bigint/src/macros.rs index a03cb6769c63..0ba6e48c72fe 100644 --- a/third_party/rust/num-bigint/src/macros.rs +++ b/third_party/rust/num-bigint/src/macros.rs @@ -1,3 +1,4 @@ +#![allow(unknown_lints)] // older rustc doesn't know `unused_macros` #![allow(unused_macros)] macro_rules! forward_val_val_binop { @@ -283,7 +284,8 @@ macro_rules! promote_scalars { impl $imp<$scalar> for $res { type Output = $res; - #[allow(clippy::cast_lossless)] + #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] + #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] #[inline] fn $method(self, other: $scalar) -> $res { $imp::$method(self, other as $promo) @@ -293,7 +295,8 @@ macro_rules! promote_scalars { impl $imp<$res> for $scalar { type Output = $res; - #[allow(clippy::cast_lossless)] + #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] + #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] #[inline] fn $method(self, other: $res) -> $res { $imp::$method(self as $promo, other) @@ -306,7 +309,8 @@ macro_rules! promote_scalars_assign { (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { $( impl $imp<$scalar> for $res { - #[allow(clippy::cast_lossless)] + #[cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] + #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] #[inline] fn $method(&mut self, other: $scalar) { self.$method(other as $promo); @@ -340,7 +344,7 @@ macro_rules! promote_signed_scalars { macro_rules! promote_signed_scalars_assign { (impl $imp:ident for $res:ty, $method:ident) => { promote_scalars_assign!(impl $imp for $res, $method, i8, i16); - promote_scalars_assign!(impl $imp for $res, $method, isize); + promote_scalars_assign!(impl $imp for $res, $method, isize); } } diff --git a/third_party/rust/num-bigint/src/monty.rs b/third_party/rust/num-bigint/src/monty.rs index b9a0bd06ca04..72a4ab53eb68 100644 --- a/third_party/rust/num-bigint/src/monty.rs +++ b/third_party/rust/num-bigint/src/monty.rs @@ -1,223 +1,129 @@ -use crate::std_alloc::Vec; -use core::mem; -use core::ops::Shl; -use num_traits::{One, Zero}; +use integer::Integer; +use traits::Zero; -use crate::big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; -use crate::biguint::BigUint; +use biguint::BigUint; -struct MontyReducer { - n0inv: BigDigit, +struct MontyReducer<'a> { + n: &'a BigUint, + n0inv: u32, } -// k0 = -m**-1 mod 2**BITS. Algorithm from: Dumas, J.G. "On Newton–Raphson -// Iteration for Multiplicative Inverses Modulo Prime Powers". -fn inv_mod_alt(b: BigDigit) -> BigDigit { - assert_ne!(b & 1, 0); +// Calculate the modular inverse of `num`, using Extended GCD. +// +// Reference: +// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20 +fn inv_mod_u32(num: u32) -> u32 { + // num needs to be relatively prime to 2**32 -- i.e. it must be odd. + assert!(num % 2 != 0); - let mut k0 = 2 - b as SignedDoubleBigDigit; - let mut t = (b - 1) as SignedDoubleBigDigit; - let mut i = 1; - while i < big_digit::BITS { - t = t.wrapping_mul(t); - k0 = k0.wrapping_mul(t + 1); + let mut a: i64 = i64::from(num); + let mut b: i64 = i64::from(u32::max_value()) + 1; - i <<= 1; + // ExtendedGcd + // Input: positive integers a and b + // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb + // As we don't need v for modular inverse, we don't calculate it. + + // 1: (u, w) <- (1, 0) + let mut u = 1; + let mut w = 0; + // 3: while b != 0 + while b != 0 { + // 4: (q, r) <- DivRem(a, b) + let q = a / b; + let r = a % b; + // 5: (a, b) <- (b, r) + a = b; + b = r; + // 6: (u, w) <- (w, u - qw) + let m = u - w * q; + u = w; + w = m; } - -k0 as BigDigit + + assert!(a == 1); + // Downcasting acts like a mod 2^32 too. + u as u32 } -impl MontyReducer { - fn new(n: &BigUint) -> Self { - let n0inv = inv_mod_alt(n.data[0]); - MontyReducer { n0inv } +impl<'a> MontyReducer<'a> { + fn new(n: &'a BigUint) -> Self { + let n0inv = inv_mod_u32(n.data[0]); + MontyReducer { n: n, n0inv: n0inv } } } -/// Computes z mod m = x * y * 2 ** (-n*_W) mod m -/// assuming k = -1/m mod 2**_W -/// See Gueron, "Efficient Software Implementations of Modular Exponentiation". -/// https://eprint.iacr.org/2011/239.pdf -/// In the terminology of that paper, this is an "Almost Montgomery Multiplication": -/// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result -/// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m. -fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> BigUint { - // This code assumes x, y, m are all the same length, n. - // (required by addMulVVW and the for loop). - // It also assumes that x, y are already reduced mod m, - // or else the result will not be properly reduced. - assert!( - x.data.len() == n && y.data.len() == n && m.data.len() == n, - "{:?} {:?} {:?} {}", - x, - y, - m, - n - ); +// Montgomery Reduction +// +// Reference: +// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6 +fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint { + let mut c = a.data; + let n = &mr.n.data; + let n_size = n.len(); - let mut z = BigUint::zero(); - z.data.resize(n * 2, 0); + // Allocate sufficient work space + c.resize(2 * n_size + 2, 0); - let mut c: BigDigit = 0; - for i in 0..n { - let c2 = add_mul_vvw(&mut z.data[i..n + i], &x.data, y.data[i]); - let t = z.data[i].wrapping_mul(k); - let c3 = add_mul_vvw(&mut z.data[i..n + i], &m.data, t); - let cx = c.wrapping_add(c2); - let cy = cx.wrapping_add(c3); - z.data[n + i] = cy; - if cx < c2 || cy < c3 { - c = 1; - } else { - c = 0; - } + // β is the size of a word, in this case 32 bits. So "a mod β" is + // equivalent to masking a to 32 bits. + // mu <- -N^(-1) mod β + let mu = 0u32.wrapping_sub(mr.n0inv); + + // 1: for i = 0 to (n-1) + for i in 0..n_size { + // 2: q_i <- mu*c_i mod β + let q_i = c[i].wrapping_mul(mu); + + // 3: C <- C + q_i * N * β^i + super::algorithms::mac_digit(&mut c[i..], n, q_i); } - if c == 0 { - z.data = z.data[n..].to_vec(); + // 4: R <- C * β^(-n) + // This is an n-word bitshift, equivalent to skipping n words. + let ret = BigUint::new(c[n_size..].to_vec()); + + // 5: if R >= β^n then return R-N else return R. + if &ret < mr.n { + ret } else { - { - let (mut first, second) = z.data.split_at_mut(n); - sub_vv(&mut first, &second, &m.data); + ret - mr.n + } +} + +// Montgomery Multiplication +fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint { + monty_redc(a * b, mr) +} + +// Montgomery Squaring +fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint { + // TODO: Replace with an optimised squaring function + monty_redc(&a * &a, mr) +} + +pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { + let mr = MontyReducer::new(modulus); + + // Calculate the Montgomery parameter + let mut v = vec![0; modulus.data.len()]; + v.push(1); + let r = BigUint::new(v); + + // Map the base to the Montgomery domain + let mut apri = a * &r % modulus; + + // Binary exponentiation + let mut ans = &r % modulus; + let mut e = exp.clone(); + while !e.is_zero() { + if e.is_odd() { + ans = monty_mult(ans, &apri, &mr); } - z.data = z.data[..n].to_vec(); + apri = monty_sqr(apri, &mr); + e = e >> 1; } - z -} - -#[inline(always)] -fn add_mul_vvw(z: &mut [BigDigit], x: &[BigDigit], y: BigDigit) -> BigDigit { - let mut c = 0; - for (zi, xi) in z.iter_mut().zip(x.iter()) { - let (z1, z0) = mul_add_www(*xi, y, *zi); - let (c_, zi_) = add_ww(z0, c, 0); - *zi = zi_; - c = c_ + z1; - } - - c -} - -/// The resulting carry c is either 0 or 1. -#[inline(always)] -fn sub_vv(z: &mut [BigDigit], x: &[BigDigit], y: &[BigDigit]) -> BigDigit { - let mut c = 0; - for (i, (xi, yi)) in x.iter().zip(y.iter()).enumerate().take(z.len()) { - let zi = xi.wrapping_sub(*yi).wrapping_sub(c); - z[i] = zi; - // see "Hacker's Delight", section 2-12 (overflow detection) - c = ((yi & !xi) | ((yi | !xi) & zi)) >> (big_digit::BITS - 1) - } - - c -} - -/// z1<<_W + z0 = x+y+c, with c == 0 or 1 -#[inline(always)] -fn add_ww(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) { - let yc = y.wrapping_add(c); - let z0 = x.wrapping_add(yc); - let z1 = if z0 < x || yc < y { 1 } else { 0 }; - - (z1, z0) -} - -/// z1 << _W + z0 = x * y + c -#[inline(always)] -fn mul_add_www(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) { - let z = x as DoubleBigDigit * y as DoubleBigDigit + c as DoubleBigDigit; - ((z >> big_digit::BITS) as BigDigit, z as BigDigit) -} - -/// Calculates x ** y mod m using a fixed, 4-bit window. -pub(crate) fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint { - assert!(m.data[0] & 1 == 1); - let mr = MontyReducer::new(m); - let num_words = m.data.len(); - - let mut x = x.clone(); - - // We want the lengths of x and m to be equal. - // It is OK if x >= m as long as len(x) == len(m). - if x.data.len() > num_words { - x %= m; - // Note: now len(x) <= numWords, not guaranteed ==. - } - if x.data.len() < num_words { - x.data.resize(num_words, 0); - } - - // rr = 2**(2*_W*len(m)) mod m - let mut rr = BigUint::one(); - rr = (rr.shl(2 * num_words as u64 * u64::from(big_digit::BITS))) % m; - if rr.data.len() < num_words { - rr.data.resize(num_words, 0); - } - // one = 1, with equal length to that of m - let mut one = BigUint::one(); - one.data.resize(num_words, 0); - - let n = 4; - // powers[i] contains x^i - let mut powers = Vec::with_capacity(1 << n); - powers.push(montgomery(&one, &rr, m, mr.n0inv, num_words)); - powers.push(montgomery(&x, &rr, m, mr.n0inv, num_words)); - for i in 2..1 << n { - let r = montgomery(&powers[i - 1], &powers[1], m, mr.n0inv, num_words); - powers.push(r); - } - - // initialize z = 1 (Montgomery 1) - let mut z = powers[0].clone(); - z.data.resize(num_words, 0); - let mut zz = BigUint::zero(); - zz.data.resize(num_words, 0); - - // same windowed exponent, but with Montgomery multiplications - for i in (0..y.data.len()).rev() { - let mut yi = y.data[i]; - let mut j = 0; - while j < big_digit::BITS { - if i != y.data.len() - 1 || j != 0 { - zz = montgomery(&z, &z, m, mr.n0inv, num_words); - z = montgomery(&zz, &zz, m, mr.n0inv, num_words); - zz = montgomery(&z, &z, m, mr.n0inv, num_words); - z = montgomery(&zz, &zz, m, mr.n0inv, num_words); - } - zz = montgomery( - &z, - &powers[(yi >> (big_digit::BITS - n)) as usize], - m, - mr.n0inv, - num_words, - ); - mem::swap(&mut z, &mut zz); - yi <<= n; - j += n; - } - } - - // convert to regular number - zz = montgomery(&z, &one, m, mr.n0inv, num_words); - - zz.normalize(); - // One last reduction, just in case. - // See golang.org/issue/13907. - if zz >= *m { - // Common case is m has high bit set; in that case, - // since zz is the same length as m, there can be just - // one multiple of m to remove. Just subtract. - // We think that the subtract should be sufficient in general, - // so do that unconditionally, but double-check, - // in case our beliefs are wrong. - // The div is not expected to be reached. - zz -= m; - if zz >= *m { - zz %= m; - } - } - - zz.normalize(); - zz + // Map the result back to the residues domain + monty_redc(ans, &mr) } diff --git a/third_party/rust/num-bigint/tests/bigint.rs b/third_party/rust/num-bigint/tests/bigint.rs index 72a43088e123..911bff0020a9 100644 --- a/third_party/rust/num-bigint/tests/bigint.rs +++ b/third_party/rust/num-bigint/tests/bigint.rs @@ -1,3 +1,9 @@ +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; +#[cfg(feature = "rand")] +extern crate rand; + use num_bigint::BigUint; use num_bigint::Sign::{Minus, NoSign, Plus}; use num_bigint::{BigInt, ToBigInt}; @@ -8,15 +14,16 @@ use std::hash::{BuildHasher, Hash, Hasher}; use std::iter::repeat; use std::ops::Neg; use std::{f32, f64}; +#[cfg(has_i128)] use std::{i128, u128}; use std::{i16, i32, i64, i8, isize}; use std::{u16, u32, u64, u8, usize}; use num_integer::Integer; -use num_traits::{pow, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero}; +use num_traits::{Float, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero}; mod consts; -use crate::consts::*; +use consts::*; #[macro_use] mod macros; @@ -33,8 +40,8 @@ fn test_from_bytes_be() { check("AA", "16705"); check("AB", "16706"); check("Hello world!", "22405534230753963835153736737"); - assert_eq!(BigInt::from_bytes_be(Plus, &[]), BigInt::zero()); - assert_eq!(BigInt::from_bytes_be(Minus, &[]), BigInt::zero()); + assert_eq!(BigInt::from_bytes_be(Plus, &[]), Zero::zero()); + assert_eq!(BigInt::from_bytes_be(Minus, &[]), Zero::zero()); } #[test] @@ -68,8 +75,8 @@ fn test_from_bytes_le() { check("AA", "16705"); check("BA", "16706"); check("!dlrow olleH", "22405534230753963835153736737"); - assert_eq!(BigInt::from_bytes_le(Plus, &[]), BigInt::zero()); - assert_eq!(BigInt::from_bytes_le(Minus, &[]), BigInt::zero()); + assert_eq!(BigInt::from_bytes_le(Plus, &[]), Zero::zero()); + assert_eq!(BigInt::from_bytes_le(Minus, &[]), Zero::zero()); } #[test] @@ -287,6 +294,7 @@ fn test_convert_i64() { } #[test] +#[cfg(has_i128)] fn test_convert_i128() { fn check(b1: BigInt, i: i128) { let b2: BigInt = FromPrimitive::from_i128(i).unwrap(); @@ -344,6 +352,7 @@ fn test_convert_u64() { } #[test] +#[cfg(has_i128)] fn test_convert_u128() { fn check(b1: BigInt, u: u128) { let b2: BigInt = FromPrimitive::from_u128(u).unwrap(); @@ -370,7 +379,6 @@ fn test_convert_u128() { } #[test] -#[allow(clippy::float_cmp)] fn test_convert_f32() { fn check(b1: &BigInt, f: f32) { let b2 = BigInt::from_f32(f).unwrap(); @@ -384,14 +392,14 @@ fn test_convert_f32() { check(&BigInt::zero(), 0.0); check(&BigInt::one(), 1.0); - check(&BigInt::from(u16::MAX), pow(2.0_f32, 16) - 1.0); - check(&BigInt::from(1u64 << 32), pow(2.0_f32, 32)); - check(&BigInt::from_slice(Plus, &[0, 0, 1]), pow(2.0_f32, 64)); + check(&BigInt::from(u16::MAX), 2.0.powi(16) - 1.0); + check(&BigInt::from(1u64 << 32), 2.0.powi(32)); + check(&BigInt::from_slice(Plus, &[0, 0, 1]), 2.0.powi(64)); check( &((BigInt::one() << 100) + (BigInt::one() << 123)), - pow(2.0_f32, 100) + pow(2.0_f32, 123), + 2.0.powi(100) + 2.0.powi(123), ); - check(&(BigInt::one() << 127), pow(2.0_f32, 127)); + check(&(BigInt::one() << 127), 2.0.powi(127)); check(&(BigInt::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); // keeping all 24 digits with the bits at different offsets to the BigDigits @@ -401,7 +409,7 @@ fn test_convert_f32() { for _ in 0..64 { check(&b, f); f *= 2.0; - b <<= 1; + b = b << 1; } // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 @@ -418,7 +426,7 @@ fn test_convert_f32() { for _ in 0..64 { assert_eq!(b.to_f32(), Some(f)); f *= 2.0; - b <<= 1; + b = b << 1; } // rounding @@ -446,20 +454,19 @@ fn test_convert_f32() { assert_eq!(BigInt::from_f32(f32::NEG_INFINITY), None); // largest BigInt that will round to a finite f32 value - let big_num = (BigInt::one() << 128u8) - 1u8 - (BigInt::one() << (128u8 - 25)); + let big_num = (BigInt::one() << 128) - BigInt::one() - (BigInt::one() << (128 - 25)); assert_eq!(big_num.to_f32(), Some(f32::MAX)); - assert_eq!((&big_num + 1u8).to_f32(), None); + assert_eq!((&big_num + BigInt::one()).to_f32(), None); assert_eq!((-&big_num).to_f32(), Some(f32::MIN)); - assert_eq!(((-&big_num) - 1u8).to_f32(), None); + assert_eq!(((-&big_num) - BigInt::one()).to_f32(), None); - assert_eq!(((BigInt::one() << 128u8) - 1u8).to_f32(), None); - assert_eq!((BigInt::one() << 128u8).to_f32(), None); - assert_eq!((-((BigInt::one() << 128u8) - 1u8)).to_f32(), None); - assert_eq!((-(BigInt::one() << 128u8)).to_f32(), None); + assert_eq!(((BigInt::one() << 128) - BigInt::one()).to_f32(), None); + assert_eq!((BigInt::one() << 128).to_f32(), None); + assert_eq!((-((BigInt::one() << 128) - BigInt::one())).to_f32(), None); + assert_eq!((-(BigInt::one() << 128)).to_f32(), None); } #[test] -#[allow(clippy::float_cmp)] fn test_convert_f64() { fn check(b1: &BigInt, f: f64) { let b2 = BigInt::from_f64(f).unwrap(); @@ -473,14 +480,14 @@ fn test_convert_f64() { check(&BigInt::zero(), 0.0); check(&BigInt::one(), 1.0); - check(&BigInt::from(u32::MAX), pow(2.0_f64, 32) - 1.0); - check(&BigInt::from(1u64 << 32), pow(2.0_f64, 32)); - check(&BigInt::from_slice(Plus, &[0, 0, 1]), pow(2.0_f64, 64)); + check(&BigInt::from(u32::MAX), 2.0.powi(32) - 1.0); + check(&BigInt::from(1u64 << 32), 2.0.powi(32)); + check(&BigInt::from_slice(Plus, &[0, 0, 1]), 2.0.powi(64)); check( &((BigInt::one() << 100) + (BigInt::one() << 152)), - pow(2.0_f64, 100) + pow(2.0_f64, 152), + 2.0.powi(100) + 2.0.powi(152), ); - check(&(BigInt::one() << 1023), pow(2.0_f64, 1023)); + check(&(BigInt::one() << 1023), 2.0.powi(1023)); check(&(BigInt::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); // keeping all 53 digits with the bits at different offsets to the BigDigits @@ -490,7 +497,7 @@ fn test_convert_f64() { for _ in 0..128 { check(&b, f); f *= 2.0; - b <<= 1; + b = b << 1; } // test rounding up with the bits at different offsets to the BigDigits @@ -499,7 +506,7 @@ fn test_convert_f64() { for _ in 0..128 { assert_eq!(b.to_f64(), Some(f)); f *= 2.0; - b <<= 1; + b = b << 1; } // rounding @@ -527,16 +534,16 @@ fn test_convert_f64() { assert_eq!(BigInt::from_f64(f64::NEG_INFINITY), None); // largest BigInt that will round to a finite f64 value - let big_num = (BigInt::one() << 1024u16) - 1u8 - (BigInt::one() << (1024u16 - 54)); + let big_num = (BigInt::one() << 1024) - BigInt::one() - (BigInt::one() << (1024 - 54)); assert_eq!(big_num.to_f64(), Some(f64::MAX)); - assert_eq!((&big_num + 1u8).to_f64(), None); + assert_eq!((&big_num + BigInt::one()).to_f64(), None); assert_eq!((-&big_num).to_f64(), Some(f64::MIN)); - assert_eq!(((-&big_num) - 1u8).to_f64(), None); + assert_eq!(((-&big_num) - BigInt::one()).to_f64(), None); - assert_eq!(((BigInt::one() << 1024u16) - 1u8).to_f64(), None); - assert_eq!((BigInt::one() << 1024u16).to_f64(), None); - assert_eq!((-((BigInt::one() << 1024u16) - 1u8)).to_f64(), None); - assert_eq!((-(BigInt::one() << 1024u16)).to_f64(), None); + assert_eq!(((BigInt::one() << 1024) - BigInt::one()).to_f64(), None); + assert_eq!((BigInt::one() << 1024).to_f64(), None); + assert_eq!((-((BigInt::one() << 1024) - BigInt::one())).to_f64(), None); + assert_eq!((-(BigInt::one() << 1024)).to_f64(), None); } #[test] @@ -571,6 +578,7 @@ fn test_convert_from_uint() { check!(u16, BigInt::from_slice(Plus, &[u16::MAX as u32])); check!(u32, BigInt::from_slice(Plus, &[u32::MAX])); check!(u64, BigInt::from_slice(Plus, &[u32::MAX, u32::MAX])); + #[cfg(has_i128)] check!( u128, BigInt::from_slice(Plus, &[u32::MAX, u32::MAX, u32::MAX, u32::MAX]) @@ -612,6 +620,7 @@ fn test_convert_from_int() { BigInt::from_slice(Minus, &[0, 1 << 31]), BigInt::from_slice(Plus, &[u32::MAX, i32::MAX as u32]) ); + #[cfg(has_i128)] check!( i128, BigInt::from_slice(Minus, &[0, 0, 0, 1 << 31]), @@ -650,7 +659,7 @@ fn test_add() { assert_op!(a + nc == nb); assert_op!(b + nc == na); assert_op!(na + nb == nc); - assert_op!(a + na == BigInt::zero()); + assert_op!(a + na == Zero::zero()); assert_assign_op!(a += b == c); assert_assign_op!(b += a == c); @@ -659,7 +668,7 @@ fn test_add() { assert_assign_op!(a += nc == nb); assert_assign_op!(b += nc == na); assert_assign_op!(na += nb == nc); - assert_assign_op!(a += na == BigInt::zero()); + assert_assign_op!(a += na == Zero::zero()); } } @@ -679,7 +688,7 @@ fn test_sub() { assert_op!(b - na == c); assert_op!(a - nb == c); assert_op!(nc - na == nb); - assert_op!(a - a == BigInt::zero()); + assert_op!(a - a == Zero::zero()); assert_assign_op!(c -= a == b); assert_assign_op!(c -= b == a); @@ -688,7 +697,7 @@ fn test_sub() { assert_assign_op!(b -= na == c); assert_assign_op!(a -= nb == c); assert_assign_op!(nc -= na == nb); - assert_assign_op!(a -= a == BigInt::zero()); + assert_assign_op!(a -= a == Zero::zero()); } } @@ -732,8 +741,6 @@ fn test_mul() { fn test_div_mod_floor() { fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { let (d, m) = a.div_mod_floor(b); - assert_eq!(d, a.div_floor(b)); - assert_eq!(m, a.mod_floor(b)); if !m.is_zero() { assert_eq!(m.sign(), b.sign()); } @@ -837,53 +844,6 @@ fn test_div_rem() { } } -#[test] -fn test_div_ceil() { - fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt) { - assert_eq!(a.div_ceil(b), *ans_d); - } - - fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) { - if m.is_zero() { - check_sub(a, b, d); - check_sub(a, &b.neg(), &d.neg()); - check_sub(&a.neg(), b, &d.neg()); - check_sub(&a.neg(), &b.neg(), d); - } else { - check_sub(a, b, &(d + 1)); - check_sub(a, &b.neg(), &d.neg()); - check_sub(&a.neg(), b, &d.neg()); - check_sub(&a.neg(), &b.neg(), &(d + 1)); - } - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if !a.is_zero() { - check(&c, &a, &b, &Zero::zero()); - } - if !b.is_zero() { - check(&c, &b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - if !b.is_zero() { - check(&a, &b, &c, &d); - } - } -} - #[test] fn test_checked_add() { for elm in SUM_TRIPLES.iter() { @@ -899,7 +859,7 @@ fn test_checked_add() { assert!(a.checked_add(&(-&c)).unwrap() == (-&b)); assert!(b.checked_add(&(-&c)).unwrap() == (-&a)); assert!((-&a).checked_add(&(-&b)).unwrap() == (-&c)); - assert!(a.checked_add(&(-&a)).unwrap() == BigInt::zero()); + assert!(a.checked_add(&(-&a)).unwrap() == Zero::zero()); } } @@ -918,7 +878,7 @@ fn test_checked_sub() { assert!(b.checked_sub(&(-&a)).unwrap() == c); assert!(a.checked_sub(&(-&b)).unwrap() == c); assert!((-&c).checked_sub(&(-&a)).unwrap() == (-&b)); - assert!(a.checked_sub(&a).unwrap() == BigInt::zero()); + assert!(a.checked_sub(&a).unwrap() == Zero::zero()); } } @@ -980,9 +940,6 @@ fn test_gcd() { let big_c: BigInt = FromPrimitive::from_isize(c).unwrap(); assert_eq!(big_a.gcd(&big_b), big_c); - assert_eq!(big_a.extended_gcd(&big_b).gcd, big_c); - assert_eq!(big_a.gcd_lcm(&big_b).0, big_c); - assert_eq!(big_a.extended_gcd_lcm(&big_b).0.gcd, big_c); } check(10, 2, 2); @@ -1003,8 +960,6 @@ fn test_lcm() { let big_c: BigInt = FromPrimitive::from_isize(c).unwrap(); assert_eq!(big_a.lcm(&big_b), big_c); - assert_eq!(big_a.gcd_lcm(&big_b).1, big_c); - assert_eq!(big_a.extended_gcd_lcm(&big_b).1, big_c); } check(0, 0, 0); @@ -1018,78 +973,6 @@ fn test_lcm() { check(11, 5, 55); } -#[test] -fn test_next_multiple_of() { - assert_eq!( - BigInt::from(16).next_multiple_of(&BigInt::from(8)), - BigInt::from(16) - ); - assert_eq!( - BigInt::from(23).next_multiple_of(&BigInt::from(8)), - BigInt::from(24) - ); - assert_eq!( - BigInt::from(16).next_multiple_of(&BigInt::from(-8)), - BigInt::from(16) - ); - assert_eq!( - BigInt::from(23).next_multiple_of(&BigInt::from(-8)), - BigInt::from(16) - ); - assert_eq!( - BigInt::from(-16).next_multiple_of(&BigInt::from(8)), - BigInt::from(-16) - ); - assert_eq!( - BigInt::from(-23).next_multiple_of(&BigInt::from(8)), - BigInt::from(-16) - ); - assert_eq!( - BigInt::from(-16).next_multiple_of(&BigInt::from(-8)), - BigInt::from(-16) - ); - assert_eq!( - BigInt::from(-23).next_multiple_of(&BigInt::from(-8)), - BigInt::from(-24) - ); -} - -#[test] -fn test_prev_multiple_of() { - assert_eq!( - BigInt::from(16).prev_multiple_of(&BigInt::from(8)), - BigInt::from(16) - ); - assert_eq!( - BigInt::from(23).prev_multiple_of(&BigInt::from(8)), - BigInt::from(16) - ); - assert_eq!( - BigInt::from(16).prev_multiple_of(&BigInt::from(-8)), - BigInt::from(16) - ); - assert_eq!( - BigInt::from(23).prev_multiple_of(&BigInt::from(-8)), - BigInt::from(24) - ); - assert_eq!( - BigInt::from(-16).prev_multiple_of(&BigInt::from(8)), - BigInt::from(-16) - ); - assert_eq!( - BigInt::from(-23).prev_multiple_of(&BigInt::from(8)), - BigInt::from(-24) - ); - assert_eq!( - BigInt::from(-16).prev_multiple_of(&BigInt::from(-8)), - BigInt::from(-16) - ); - assert_eq!( - BigInt::from(-23).prev_multiple_of(&BigInt::from(-8)), - BigInt::from(-16) - ); -} - #[test] fn test_abs_sub() { let zero: BigInt = Zero::zero(); @@ -1139,7 +1022,7 @@ fn test_from_str_radix() { #[test] fn test_lower_hex() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{:x}", a), "a"); assert_eq!(format!("{:x}", hello), "-48656c6c6f20776f726c6421"); @@ -1149,7 +1032,7 @@ fn test_lower_hex() { #[test] fn test_upper_hex() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{:X}", a), "A"); assert_eq!(format!("{:X}", hello), "-48656C6C6F20776F726C6421"); @@ -1159,7 +1042,7 @@ fn test_upper_hex() { #[test] fn test_binary() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes(b"-224055342307539", 10).unwrap(); + let hello = BigInt::parse_bytes("-224055342307539".as_bytes(), 10).unwrap(); assert_eq!(format!("{:b}", a), "1010"); assert_eq!( @@ -1172,7 +1055,7 @@ fn test_binary() { #[test] fn test_octal() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{:o}", a), "12"); assert_eq!(format!("{:o}", hello), "-22062554330674403566756233062041"); @@ -1182,7 +1065,7 @@ fn test_octal() { #[test] fn test_display() { let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes(b"-22405534230753963835153736737", 10).unwrap(); + let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{}", a), "10"); assert_eq!(format!("{}", hello), "-22405534230753963835153736737"); @@ -1205,6 +1088,25 @@ fn test_negative_shr() { assert_eq!(BigInt::from(-3) >> 2, BigInt::from(-1)); } +#[test] +#[cfg(feature = "rand")] +fn test_random_shr() { + use rand::distributions::Standard; + use rand::Rng; + let mut rng = rand::thread_rng(); + + for p in rng.sample_iter::(&Standard).take(1000) { + let big = BigInt::from(p); + let bigger = &big << 1000; + assert_eq!(&bigger >> 1000, big); + for i in 0..64 { + let answer = BigInt::from(p >> i); + assert_eq!(&big >> i, answer); + assert_eq!(&bigger >> (1000 + i), answer); + } + } +} + #[test] fn test_iter_sum() { let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); @@ -1218,8 +1120,8 @@ fn test_iter_sum() { FromPrimitive::from_i32(-7).unwrap(), ]; - assert_eq!(result, data.iter().sum::()); - assert_eq!(result, data.into_iter().sum::()); + assert_eq!(result, data.iter().sum()); + assert_eq!(result, data.into_iter().sum()); } #[test] @@ -1237,8 +1139,8 @@ fn test_iter_product() { * data.get(3).unwrap() * data.get(4).unwrap(); - assert_eq!(result, data.iter().product::()); - assert_eq!(result, data.into_iter().product::()); + assert_eq!(result, data.iter().product()); + assert_eq!(result, data.into_iter().product()); } #[test] @@ -1246,8 +1148,8 @@ fn test_iter_sum_generic() { let result: BigInt = FromPrimitive::from_isize(-1234567).unwrap(); let data = vec![-1000000, -200000, -30000, -4000, -500, -60, -7]; - assert_eq!(result, data.iter().sum::()); - assert_eq!(result, data.into_iter().sum::()); + assert_eq!(result, data.iter().sum()); + assert_eq!(result, data.into_iter().sum()); } #[test] @@ -1259,8 +1161,8 @@ fn test_iter_product_generic() { * data[3].to_bigint().unwrap() * data[4].to_bigint().unwrap(); - assert_eq!(result, data.iter().product::()); - assert_eq!(result, data.into_iter().product::()); + assert_eq!(result, data.iter().product()); + assert_eq!(result, data.into_iter().product()); } #[test] @@ -1272,15 +1174,15 @@ fn test_pow() { let minus_two = BigInt::from(-2i32); macro_rules! check { ($t:ty) => { - assert_eq!(Pow::pow(&two, 0 as $t), one); - assert_eq!(Pow::pow(&two, 1 as $t), two); - assert_eq!(Pow::pow(&two, 2 as $t), four); - assert_eq!(Pow::pow(&two, 3 as $t), eight); - assert_eq!(Pow::pow(&two, &(3 as $t)), eight); - assert_eq!(Pow::pow(&minus_two, 0 as $t), one, "-2^0"); - assert_eq!(Pow::pow(&minus_two, 1 as $t), minus_two, "-2^1"); - assert_eq!(Pow::pow(&minus_two, 2 as $t), four, "-2^2"); - assert_eq!(Pow::pow(&minus_two, 3 as $t), -&eight, "-2^3"); + assert_eq!(two.pow(0 as $t), one); + assert_eq!(two.pow(1 as $t), two); + assert_eq!(two.pow(2 as $t), four); + assert_eq!(two.pow(3 as $t), eight); + assert_eq!(two.pow(&(3 as $t)), eight); + assert_eq!(minus_two.pow(0 as $t), one, "-2^0"); + assert_eq!(minus_two.pow(1 as $t), minus_two, "-2^1"); + assert_eq!(minus_two.pow(2 as $t), four, "-2^2"); + assert_eq!(minus_two.pow(3 as $t), -&eight, "-2^3"); }; } check!(u8); diff --git a/third_party/rust/num-bigint/tests/bigint_bitwise.rs b/third_party/rust/num-bigint/tests/bigint_bitwise.rs index 6c1e82fee383..cc0c493cb5e0 100644 --- a/third_party/rust/num-bigint/tests/bigint_bitwise.rs +++ b/third_party/rust/num-bigint/tests/bigint_bitwise.rs @@ -1,3 +1,6 @@ +extern crate num_bigint; +extern crate num_traits; + use num_bigint::{BigInt, Sign, ToBigInt}; use num_traits::ToPrimitive; use std::{i32, i64, u32}; @@ -8,7 +11,7 @@ enum ValueVec { M(&'static [u32]), } -use crate::ValueVec::*; +use ValueVec::*; impl ToBigInt for ValueVec { fn to_bigint(&self) -> Option { @@ -21,7 +24,7 @@ impl ToBigInt for ValueVec { } // a, !a -const NOT_VALUES: &[(ValueVec, ValueVec)] = &[ +const NOT_VALUES: &'static [(ValueVec, ValueVec)] = &[ (N, M(&[1])), (P(&[1]), M(&[2])), (P(&[2]), M(&[3])), @@ -33,7 +36,7 @@ const NOT_VALUES: &[(ValueVec, ValueVec)] = &[ ]; // a, b, a & b, a | b, a ^ b -const BITWISE_VALUES: &[(ValueVec, ValueVec, ValueVec, ValueVec, ValueVec)] = &[ +const BITWISE_VALUES: &'static [(ValueVec, ValueVec, ValueVec, ValueVec, ValueVec)] = &[ (N, N, N, N, N), (N, P(&[1]), N, P(&[1]), P(&[1])), (N, P(&[!0]), N, P(&[!0]), P(&[!0])), @@ -59,7 +62,7 @@ const I32_MAX: i64 = i32::MAX as i64; const U32_MAX: i64 = u32::MAX as i64; // some corner cases -const I64_VALUES: &[i64] = &[ +const I64_VALUES: &'static [i64] = &[ i64::MIN, i64::MIN + 1, i64::MIN + 2, diff --git a/third_party/rust/num-bigint/tests/bigint_scalar.rs b/third_party/rust/num-bigint/tests/bigint_scalar.rs index 485f2c5b1b74..ae9a6d7aa22f 100644 --- a/third_party/rust/num-bigint/tests/bigint_scalar.rs +++ b/third_party/rust/num-bigint/tests/bigint_scalar.rs @@ -1,3 +1,6 @@ +extern crate num_bigint; +extern crate num_traits; + use num_bigint::BigInt; use num_bigint::Sign::Plus; use num_traits::{Signed, ToPrimitive, Zero}; @@ -5,7 +8,7 @@ use num_traits::{Signed, ToPrimitive, Zero}; use std::ops::Neg; mod consts; -use crate::consts::*; +use consts::*; #[macro_use] mod macros; @@ -15,7 +18,6 @@ fn test_scalar_add() { fn check(x: &BigInt, y: &BigInt, z: &BigInt) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_signed_scalar_op!(x + y == z); - assert_signed_scalar_assign_op!(x += y == z); } for elm in SUM_TRIPLES.iter() { @@ -41,7 +43,6 @@ fn test_scalar_sub() { fn check(x: &BigInt, y: &BigInt, z: &BigInt) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_signed_scalar_op!(x - y == z); - assert_signed_scalar_assign_op!(x -= y == z); } for elm in SUM_TRIPLES.iter() { @@ -67,7 +68,6 @@ fn test_scalar_mul() { fn check(x: &BigInt, y: &BigInt, z: &BigInt) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_signed_scalar_op!(x * y == z); - assert_signed_scalar_assign_op!(x *= y == z); } for elm in MUL_TRIPLES.iter() { @@ -93,23 +93,20 @@ fn test_scalar_div_rem() { if !r.is_zero() { assert_eq!(r.sign(), a.sign()); } - assert!(r.abs() <= BigInt::from(b)); + assert!(r.abs() <= From::from(b)); assert!(*a == b * &q + &r); assert!(q == *ans_q); assert!(r == *ans_r); - let b = BigInt::from(b); - let (a, ans_q, ans_r) = (a.clone(), ans_q.clone(), ans_r.clone()); - assert_signed_scalar_op!(a / b == ans_q); - assert_signed_scalar_op!(a % b == ans_r); - assert_signed_scalar_assign_op!(a /= b == ans_q); - assert_signed_scalar_assign_op!(a %= b == ans_r); + let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone()); + assert_op!(a / b == ans_q); + assert_op!(a % b == ans_r); - let nb = -b; - assert_signed_scalar_op!(a / nb == -ans_q.clone()); - assert_signed_scalar_op!(a % nb == ans_r); - assert_signed_scalar_assign_op!(a /= nb == -ans_q.clone()); - assert_signed_scalar_assign_op!(a %= nb == ans_r); + if b <= i32::max_value() as u32 { + let nb = -(b as i32); + assert_op!(a / nb == -ans_q.clone()); + assert_op!(a % nb == ans_r); + } } fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) { diff --git a/third_party/rust/num-bigint/tests/biguint.rs b/third_party/rust/num-bigint/tests/biguint.rs index 3f1a47d356bf..1e23aa17f9e4 100644 --- a/third_party/rust/num-bigint/tests/biguint.rs +++ b/third_party/rust/num-bigint/tests/biguint.rs @@ -1,3 +1,7 @@ +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; + use num_bigint::Sign::Plus; use num_bigint::{BigInt, ToBigInt}; use num_bigint::{BigUint, ToBigUint}; @@ -10,16 +14,17 @@ use std::i64; use std::iter::repeat; use std::str::FromStr; use std::{f32, f64}; +#[cfg(has_i128)] use std::{i128, u128}; use std::{u16, u32, u64, u8, usize}; use num_traits::{ - pow, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, ToPrimitive, - Zero, + CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Float, FromPrimitive, Num, One, Pow, + ToPrimitive, Zero, }; mod consts; -use crate::consts::*; +use consts::*; #[macro_use] mod macros; @@ -36,7 +41,7 @@ fn test_from_bytes_be() { check("AA", "16705"); check("AB", "16706"); check("Hello world!", "22405534230753963835153736737"); - assert_eq!(BigUint::from_bytes_be(&[]), BigUint::zero()); + assert_eq!(BigUint::from_bytes_be(&[]), Zero::zero()); } #[test] @@ -69,7 +74,7 @@ fn test_from_bytes_le() { check("AA", "16705"); check("BA", "16706"); check("!dlrow olleH", "22405534230753963835153736737"); - assert_eq!(BigUint::from_bytes_le(&[]), BigUint::zero()); + assert_eq!(BigUint::from_bytes_le(&[]), Zero::zero()); } #[test] @@ -135,7 +140,7 @@ fn hash(x: &T) -> u64 { #[test] fn test_hash() { - use crate::hash; + use hash; let a = BigUint::new(vec![]); let b = BigUint::new(vec![0]); @@ -149,7 +154,13 @@ fn test_hash() { } // LEFT, RIGHT, AND, OR, XOR -const BIT_TESTS: &[(&[u32], &[u32], &[u32], &[u32], &[u32])] = &[ +const BIT_TESTS: &'static [( + &'static [u32], + &'static [u32], + &'static [u32], + &'static [u32], + &'static [u32], +)] = &[ (&[], &[], &[], &[], &[]), (&[1, 0, 1], &[1, 1], &[1], &[1, 1, 1], &[0, 1, 1]), (&[1, 0, 1], &[0, 1, 1], &[0, 0, 1], &[1, 1, 1], &[1, 1]), @@ -531,6 +542,7 @@ fn test_convert_i64() { } #[test] +#[cfg(has_i128)] fn test_convert_i128() { fn check(b1: BigUint, i: i128) { let b2: BigUint = FromPrimitive::from_i128(i).unwrap(); @@ -579,6 +591,7 @@ fn test_convert_u64() { } #[test] +#[cfg(has_i128)] fn test_convert_u128() { fn check(b1: BigUint, u: u128) { let b2: BigUint = FromPrimitive::from_u128(u).unwrap(); @@ -602,7 +615,6 @@ fn test_convert_u128() { } #[test] -#[allow(clippy::float_cmp)] fn test_convert_f32() { fn check(b1: &BigUint, f: f32) { let b2 = BigUint::from_f32(f).unwrap(); @@ -612,14 +624,14 @@ fn test_convert_f32() { check(&BigUint::zero(), 0.0); check(&BigUint::one(), 1.0); - check(&BigUint::from(u16::MAX), pow(2.0_f32, 16) - 1.0); - check(&BigUint::from(1u64 << 32), pow(2.0_f32, 32)); - check(&BigUint::from_slice(&[0, 0, 1]), pow(2.0_f32, 64)); + check(&BigUint::from(u16::MAX), 2.0.powi(16) - 1.0); + check(&BigUint::from(1u64 << 32), 2.0.powi(32)); + check(&BigUint::from_slice(&[0, 0, 1]), 2.0.powi(64)); check( &((BigUint::one() << 100) + (BigUint::one() << 123)), - pow(2.0_f32, 100) + pow(2.0_f32, 123), + 2.0.powi(100) + 2.0.powi(123), ); - check(&(BigUint::one() << 127), pow(2.0_f32, 127)); + check(&(BigUint::one() << 127), 2.0.powi(127)); check(&(BigUint::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); // keeping all 24 digits with the bits at different offsets to the BigDigits @@ -629,7 +641,7 @@ fn test_convert_f32() { for _ in 0..64 { check(&b, f); f *= 2.0; - b <<= 1; + b = b << 1; } // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 @@ -643,7 +655,7 @@ fn test_convert_f32() { for _ in 0..64 { assert_eq!(b.to_f32(), Some(f)); f *= 2.0; - b <<= 1; + b = b << 1; } // rounding @@ -671,16 +683,15 @@ fn test_convert_f32() { assert_eq!(BigUint::from_f32(f32::MIN), None); // largest BigUint that will round to a finite f32 value - let big_num = (BigUint::one() << 128u8) - 1u8 - (BigUint::one() << (128u8 - 25)); + let big_num = (BigUint::one() << 128) - BigUint::one() - (BigUint::one() << (128 - 25)); assert_eq!(big_num.to_f32(), Some(f32::MAX)); - assert_eq!((big_num + 1u8).to_f32(), None); + assert_eq!((big_num + BigUint::one()).to_f32(), None); - assert_eq!(((BigUint::one() << 128u8) - 1u8).to_f32(), None); - assert_eq!((BigUint::one() << 128u8).to_f32(), None); + assert_eq!(((BigUint::one() << 128) - BigUint::one()).to_f32(), None); + assert_eq!((BigUint::one() << 128).to_f32(), None); } #[test] -#[allow(clippy::float_cmp)] fn test_convert_f64() { fn check(b1: &BigUint, f: f64) { let b2 = BigUint::from_f64(f).unwrap(); @@ -690,14 +701,14 @@ fn test_convert_f64() { check(&BigUint::zero(), 0.0); check(&BigUint::one(), 1.0); - check(&BigUint::from(u32::MAX), pow(2.0_f64, 32) - 1.0); - check(&BigUint::from(1u64 << 32), pow(2.0_f64, 32)); - check(&BigUint::from_slice(&[0, 0, 1]), pow(2.0_f64, 64)); + check(&BigUint::from(u32::MAX), 2.0.powi(32) - 1.0); + check(&BigUint::from(1u64 << 32), 2.0.powi(32)); + check(&BigUint::from_slice(&[0, 0, 1]), 2.0.powi(64)); check( &((BigUint::one() << 100) + (BigUint::one() << 152)), - pow(2.0_f64, 100) + pow(2.0_f64, 152), + 2.0.powi(100) + 2.0.powi(152), ); - check(&(BigUint::one() << 1023), pow(2.0_f64, 1023)); + check(&(BigUint::one() << 1023), 2.0.powi(1023)); check(&(BigUint::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); // keeping all 53 digits with the bits at different offsets to the BigDigits @@ -707,7 +718,7 @@ fn test_convert_f64() { for _ in 0..128 { check(&b, f); f *= 2.0; - b <<= 1; + b = b << 1; } // test rounding up with the bits at different offsets to the BigDigits @@ -716,7 +727,7 @@ fn test_convert_f64() { for _ in 0..128 { assert_eq!(b.to_f64(), Some(f)); f *= 2.0; - b <<= 1; + b = b << 1; } // rounding @@ -744,12 +755,12 @@ fn test_convert_f64() { assert_eq!(BigUint::from_f64(f64::MIN), None); // largest BigUint that will round to a finite f64 value - let big_num = (BigUint::one() << 1024u16) - 1u8 - (BigUint::one() << (1024u16 - 54)); + let big_num = (BigUint::one() << 1024) - BigUint::one() - (BigUint::one() << (1024 - 54)); assert_eq!(big_num.to_f64(), Some(f64::MAX)); - assert_eq!((big_num + 1u8).to_f64(), None); + assert_eq!((big_num + BigUint::one()).to_f64(), None); - assert_eq!(((BigUint::one() << 1024u16) - 1u8).to_f64(), None); - assert_eq!((BigUint::one() << 1024u16).to_f64(), None); + assert_eq!(((BigInt::one() << 1024) - BigInt::one()).to_f64(), None); + assert_eq!((BigUint::one() << 1024).to_f64(), None); } #[test] @@ -780,6 +791,7 @@ fn test_convert_from_uint() { check!(u16, BigUint::from_slice(&[u16::MAX as u32])); check!(u32, BigUint::from_slice(&[u32::MAX])); check!(u64, BigUint::from_slice(&[u32::MAX, u32::MAX])); + #[cfg(has_i128)] check!( u128, BigUint::from_slice(&[u32::MAX, u32::MAX, u32::MAX, u32::MAX]) @@ -860,17 +872,17 @@ fn test_div_rem() { if !a.is_zero() { assert_op!(c / a == b); - assert_op!(c % a == BigUint::zero()); + assert_op!(c % a == Zero::zero()); assert_assign_op!(c /= a == b); - assert_assign_op!(c %= a == BigUint::zero()); - assert_eq!(c.div_rem(&a), (b.clone(), BigUint::zero())); + assert_assign_op!(c %= a == Zero::zero()); + assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero())); } if !b.is_zero() { assert_op!(c / b == a); - assert_op!(c % b == BigUint::zero()); + assert_op!(c % b == Zero::zero()); assert_assign_op!(c /= b == a); - assert_assign_op!(c %= b == BigUint::zero()); - assert_eq!(c.div_rem(&b), (a.clone(), BigUint::zero())); + assert_assign_op!(c %= b == Zero::zero()); + assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero())); } } @@ -891,43 +903,6 @@ fn test_div_rem() { } } -#[test] -fn test_div_ceil() { - fn check(a: &BigUint, b: &BigUint, d: &BigUint, m: &BigUint) { - if m.is_zero() { - assert_eq!(a.div_ceil(b), *d); - } else { - assert_eq!(a.div_ceil(b), d + 1u32); - } - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - check(&c, &a, &b, &Zero::zero()); - } - if !b.is_zero() { - check(&c, &b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - if !b.is_zero() { - check(&a, &b, &c, &d); - } - } -} - #[test] fn test_checked_add() { for elm in SUM_TRIPLES.iter() { @@ -1021,7 +996,6 @@ fn test_gcd() { let big_c: BigUint = FromPrimitive::from_usize(c).unwrap(); assert_eq!(big_a.gcd(&big_b), big_c); - assert_eq!(big_a.gcd_lcm(&big_b).0, big_c); } check(10, 2, 2); @@ -1039,7 +1013,6 @@ fn test_lcm() { let big_c: BigUint = FromPrimitive::from_usize(c).unwrap(); assert_eq!(big_a.lcm(&big_b), big_c); - assert_eq!(big_a.gcd_lcm(&big_b).1, big_c); } check(0, 0, 0); @@ -1051,30 +1024,6 @@ fn test_lcm() { check(99, 17, 1683); } -#[test] -fn test_next_multiple_of() { - assert_eq!( - BigUint::from(16u32).next_multiple_of(&BigUint::from(8u32)), - BigUint::from(16u32) - ); - assert_eq!( - BigUint::from(23u32).next_multiple_of(&BigUint::from(8u32)), - BigUint::from(24u32) - ); -} - -#[test] -fn test_prev_multiple_of() { - assert_eq!( - BigUint::from(16u32).prev_multiple_of(&BigUint::from(8u32)), - BigUint::from(16u32) - ); - assert_eq!( - BigUint::from(23u32).prev_multiple_of(&BigUint::from(8u32)), - BigUint::from(16u32) - ); -} - #[test] fn test_is_even() { let one: BigUint = FromStr::from_str("1").unwrap(); @@ -1087,8 +1036,8 @@ fn test_is_even() { assert!(thousand.is_even()); assert!(big.is_even()); assert!(bigger.is_odd()); - assert!((&one << 64u8).is_even()); - assert!(((&one << 64u8) + one).is_odd()); + assert!((&one << 64).is_even()); + assert!(((&one << 64) + one).is_odd()); } fn to_str_pairs() -> Vec<(BigUint, Vec<(u32, String)>)> { @@ -1216,7 +1165,7 @@ fn test_to_str_radix() { #[test] fn test_from_and_to_radix() { - const GROUND_TRUTH: &[(&[u8], u32, &[u8])] = &[ + const GROUND_TRUTH: &'static [(&'static [u8], u32, &'static [u8])] = &[ (b"0", 42, &[0]), ( b"ffffeeffbb", @@ -1566,6 +1515,9 @@ fn test_from_str_radix() { #[test] fn test_all_str_radix() { + #[allow(deprecated, unused_imports)] + use std::ascii::AsciiExt; + let n = BigUint::new((0..10).collect()); for radix in 2..37 { let s = n.to_str_radix(radix); @@ -1581,7 +1533,7 @@ fn test_all_str_radix() { #[test] fn test_lower_hex() { let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{:x}", a), "a"); assert_eq!(format!("{:x}", hello), "48656c6c6f20776f726c6421"); @@ -1591,7 +1543,7 @@ fn test_lower_hex() { #[test] fn test_upper_hex() { let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{:X}", a), "A"); assert_eq!(format!("{:X}", hello), "48656C6C6F20776F726C6421"); @@ -1601,7 +1553,7 @@ fn test_upper_hex() { #[test] fn test_binary() { let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes(b"224055342307539", 10).unwrap(); + let hello = BigUint::parse_bytes("224055342307539".as_bytes(), 10).unwrap(); assert_eq!(format!("{:b}", a), "1010"); assert_eq!( @@ -1614,7 +1566,7 @@ fn test_binary() { #[test] fn test_octal() { let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{:o}", a), "12"); assert_eq!(format!("{:o}", hello), "22062554330674403566756233062041"); @@ -1624,7 +1576,7 @@ fn test_octal() { #[test] fn test_display() { let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap(); + let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); assert_eq!(format!("{}", a), "10"); assert_eq!(format!("{}", hello), "22405534230753963835153736737"); @@ -1635,18 +1587,21 @@ fn test_display() { fn test_factor() { fn factor(n: usize) -> BigUint { let mut f: BigUint = One::one(); - for i in 2..=n { + for i in 2..n + 1 { // FIXME(#5992): assignment operator overloads // f *= FromPrimitive::from_usize(i); let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); - f *= bu; + f = f * bu; } - f + return f; } fn check(n: usize, s: &str) { let n = factor(n); - let ans = BigUint::from_str_radix(s, 10).unwrap(); + let ans = match BigUint::from_str_radix(s, 10) { + Ok(x) => x, + Err(_) => panic!(), + }; assert_eq!(n, ans); } @@ -1668,7 +1623,7 @@ fn test_bits() { let n: BigUint = BigUint::from_str_radix("4000000000", 16).unwrap(); assert_eq!(n.bits(), 39); let one: BigUint = One::one(); - assert_eq!((one << 426u16).bits(), 427); + assert_eq!((one << 426).bits(), 427); } #[test] @@ -1684,8 +1639,8 @@ fn test_iter_sum() { FromPrimitive::from_u32(7).unwrap(), ]; - assert_eq!(result, data.iter().sum::()); - assert_eq!(result, data.into_iter().sum::()); + assert_eq!(result, data.iter().sum()); + assert_eq!(result, data.into_iter().sum()); } #[test] @@ -1703,8 +1658,8 @@ fn test_iter_product() { * data.get(3).unwrap() * data.get(4).unwrap(); - assert_eq!(result, data.iter().product::()); - assert_eq!(result, data.into_iter().product::()); + assert_eq!(result, data.iter().product()); + assert_eq!(result, data.into_iter().product()); } #[test] @@ -1712,8 +1667,8 @@ fn test_iter_sum_generic() { let result: BigUint = FromPrimitive::from_isize(1234567).unwrap(); let data = vec![1000000_u32, 200000, 30000, 4000, 500, 60, 7]; - assert_eq!(result, data.iter().sum::()); - assert_eq!(result, data.into_iter().sum::()); + assert_eq!(result, data.iter().sum()); + assert_eq!(result, data.into_iter().sum()); } #[test] @@ -1725,8 +1680,8 @@ fn test_iter_product_generic() { * data[3].to_biguint().unwrap() * data[4].to_biguint().unwrap(); - assert_eq!(result, data.iter().product::()); - assert_eq!(result, data.into_iter().product::()); + assert_eq!(result, data.iter().product()); + assert_eq!(result, data.into_iter().product()); } #[test] @@ -1739,19 +1694,20 @@ fn test_pow() { let twentyfourtyeight = BigUint::from(2048u32); macro_rules! check { ($t:ty) => { - assert_eq!(Pow::pow(&two, 0 as $t), one); - assert_eq!(Pow::pow(&two, 1 as $t), two); - assert_eq!(Pow::pow(&two, 2 as $t), four); - assert_eq!(Pow::pow(&two, 3 as $t), eight); - assert_eq!(Pow::pow(&two, 10 as $t), tentwentyfour); - assert_eq!(Pow::pow(&two, 11 as $t), twentyfourtyeight); - assert_eq!(Pow::pow(&two, &(11 as $t)), twentyfourtyeight); + assert_eq!(two.pow(0 as $t), one); + assert_eq!(two.pow(1 as $t), two); + assert_eq!(two.pow(2 as $t), four); + assert_eq!(two.pow(3 as $t), eight); + assert_eq!(two.pow(10 as $t), tentwentyfour); + assert_eq!(two.pow(11 as $t), twentyfourtyeight); + assert_eq!(two.pow(&(11 as $t)), twentyfourtyeight); }; } check!(u8); check!(u16); check!(u32); check!(u64); - check!(u128); check!(usize); + #[cfg(has_i128)] + check!(u128); } diff --git a/third_party/rust/num-bigint/tests/biguint_scalar.rs b/third_party/rust/num-bigint/tests/biguint_scalar.rs index b6eadd9e197a..fb8fbf0357af 100644 --- a/third_party/rust/num-bigint/tests/biguint_scalar.rs +++ b/third_party/rust/num-bigint/tests/biguint_scalar.rs @@ -1,8 +1,11 @@ +extern crate num_bigint; +extern crate num_traits; + use num_bigint::BigUint; use num_traits::{ToPrimitive, Zero}; mod consts; -use crate::consts::*; +use consts::*; #[macro_use] mod macros; @@ -12,7 +15,6 @@ fn test_scalar_add() { fn check(x: &BigUint, y: &BigUint, z: &BigUint) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_unsigned_scalar_op!(x + y == z); - assert_unsigned_scalar_assign_op!(x += y == z); } for elm in SUM_TRIPLES.iter() { @@ -31,7 +33,6 @@ fn test_scalar_sub() { fn check(x: &BigUint, y: &BigUint, z: &BigUint) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_unsigned_scalar_op!(x - y == z); - assert_unsigned_scalar_assign_op!(x -= y == z); } for elm in SUM_TRIPLES.iter() { @@ -50,7 +51,6 @@ fn test_scalar_mul() { fn check(x: &BigUint, y: &BigUint, z: &BigUint) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_unsigned_scalar_op!(x * y == z); - assert_unsigned_scalar_assign_op!(x *= y == z); } for elm in MUL_TRIPLES.iter() { @@ -66,8 +66,8 @@ fn test_scalar_mul() { #[test] fn test_scalar_rem_noncommutative() { - assert_eq!(5u8 % BigUint::from(7u8), BigUint::from(5u8)); - assert_eq!(BigUint::from(5u8) % 7u8, BigUint::from(5u8)); + assert_eq!(5u8 % BigUint::from(7u8), 5u8.into()); + assert_eq!(BigUint::from(5u8) % 7u8, 5u8.into()); } #[test] @@ -76,8 +76,6 @@ fn test_scalar_div_rem() { let (x, y, z, r) = (x.clone(), y.clone(), z.clone(), r.clone()); assert_unsigned_scalar_op!(x / y == z); assert_unsigned_scalar_op!(x % y == r); - assert_unsigned_scalar_assign_op!(x /= y == z); - assert_unsigned_scalar_assign_op!(x %= y == r); } for elm in MUL_TRIPLES.iter() { @@ -106,8 +104,6 @@ fn test_scalar_div_rem() { check(&a, &b, &c, &d); assert_unsigned_scalar_op!(a / b == c); assert_unsigned_scalar_op!(a % b == d); - assert_unsigned_scalar_assign_op!(a /= b == c); - assert_unsigned_scalar_assign_op!(a %= b == d); } } } diff --git a/third_party/rust/num-bigint/tests/consts/mod.rs b/third_party/rust/num-bigint/tests/consts/mod.rs index 5d0555d0188b..87805d5e2427 100644 --- a/third_party/rust/num-bigint/tests/consts/mod.rs +++ b/third_party/rust/num-bigint/tests/consts/mod.rs @@ -3,7 +3,7 @@ pub const N1: u32 = -1i32 as u32; pub const N2: u32 = -2i32 as u32; -pub const SUM_TRIPLES: &[(&[u32], &[u32], &[u32])] = &[ +pub const SUM_TRIPLES: &'static [(&'static [u32], &'static [u32], &'static [u32])] = &[ (&[], &[], &[]), (&[], &[1], &[1]), (&[1], &[1], &[2]), @@ -17,7 +17,7 @@ pub const SUM_TRIPLES: &[(&[u32], &[u32], &[u32])] = &[ ]; pub const M: u32 = ::std::u32::MAX; -pub const MUL_TRIPLES: &[(&[u32], &[u32], &[u32])] = &[ +pub const MUL_TRIPLES: &'static [(&'static [u32], &'static [u32], &'static [u32])] = &[ (&[], &[], &[]), (&[], &[1], &[]), (&[2], &[], &[]), @@ -41,7 +41,12 @@ pub const MUL_TRIPLES: &[(&[u32], &[u32], &[u32])] = &[ (&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]), ]; -pub const DIV_REM_QUADRUPLES: &[(&[u32], &[u32], &[u32], &[u32])] = &[ +pub const DIV_REM_QUADRUPLES: &'static [( + &'static [u32], + &'static [u32], + &'static [u32], + &'static [u32], +)] = &[ (&[1], &[2], &[], &[1]), (&[3], &[2], &[1], &[1]), (&[1, 1], &[2], &[M / 2 + 1], &[1]), diff --git a/third_party/rust/num-bigint/tests/macros/mod.rs b/third_party/rust/num-bigint/tests/macros/mod.rs index b14cd577de00..d848b29b35ee 100644 --- a/third_party/rust/num-bigint/tests/macros/mod.rs +++ b/third_party/rust/num-bigint/tests/macros/mod.rs @@ -35,6 +35,15 @@ macro_rules! assert_scalar_op { }; } +#[cfg(not(has_i128))] +macro_rules! assert_unsigned_scalar_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize) + $left $op $right == $expected); + }; +} + +#[cfg(has_i128)] macro_rules! assert_unsigned_scalar_op { ($left:ident $op:tt $right:ident == $expected:expr) => { assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128) @@ -42,6 +51,16 @@ macro_rules! assert_unsigned_scalar_op { }; } +#[cfg(not(has_i128))] +macro_rules! assert_signed_scalar_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, + to_i8, to_i16, to_i32, to_i64, to_isize) + $left $op $right == $expected); + }; +} + +#[cfg(has_i128)] macro_rules! assert_signed_scalar_op { ($left:ident $op:tt $right:ident == $expected:expr) => { assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128, @@ -49,30 +68,3 @@ macro_rules! assert_signed_scalar_op { $left $op $right == $expected); }; } - -/// Assert that an op works for scalar right -macro_rules! assert_scalar_assign_op { - (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { - $( - if let Some(right) = $right.$to() { - let mut left = $left.clone(); - assert_eq!({ left $op right; left}, $expected); - } - )* - }; -} - -macro_rules! assert_unsigned_scalar_assign_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128) - $left $op $right == $expected); - }; -} - -macro_rules! assert_signed_scalar_assign_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128, - to_i8, to_i16, to_i32, to_i64, to_isize, to_i128) - $left $op $right == $expected); - }; -} diff --git a/third_party/rust/num-bigint/tests/modpow.rs b/third_party/rust/num-bigint/tests/modpow.rs index 276f066eb2e3..b7a992c863ad 100644 --- a/third_party/rust/num-bigint/tests/modpow.rs +++ b/third_party/rust/num-bigint/tests/modpow.rs @@ -1,56 +1,60 @@ -static BIG_B: &str = "\ - efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\ - ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\ - aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\ - 247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\ - 675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\ - 8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\ - 33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\ - 1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\ - 990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\ - b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\ - b4edf9cc_6ce540be_76229093_5c53893b"; +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; -static BIG_E: &str = "\ - be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\ - a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\ - 774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\ - eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\ - 449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\ - c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\ - 12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\ - f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\ - a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\ - e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\ - 17946850_2ddb1822_117b68a0_32f7db88"; +static BIG_B: &'static str = "\ + efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\ + ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\ + aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\ + 247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\ + 675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\ + 8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\ + 33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\ + 1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\ + 990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\ + b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\ + b4edf9cc_6ce540be_76229093_5c53893b"; + +static BIG_E: &'static str = "\ + be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\ + a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\ + 774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\ + eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\ + 449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\ + c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\ + 12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\ + f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\ + a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\ + e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\ + 17946850_2ddb1822_117b68a0_32f7db88"; // This modulus is the prime from the 2048-bit MODP DH group: // https://tools.ietf.org/html/rfc3526#section-3 -static BIG_M: &str = "\ - FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ - 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ - EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ - E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ - EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ - C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ - 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ - 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ - E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ - DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ - 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; +static BIG_M: &'static str = "\ + FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ + 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ + EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ + E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ + EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ + C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ + 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ + 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ + E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ + DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ + 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; -static BIG_R: &str = "\ - a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\ - eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\ - 9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\ - 055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\ - fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\ - 93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\ - 35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\ - d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\ - 5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\ - f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\ - 109c4735_6e7db425_7b5d74c7_0b709508"; +static BIG_R: &'static str = "\ + a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\ + eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\ + 9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\ + 055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\ + fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\ + 93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\ + 35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\ + d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\ + 5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\ + f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\ + 109c4735_6e7db425_7b5d74c7_0b709508"; mod biguint { use num_bigint::BigUint; @@ -72,24 +76,11 @@ mod biguint { } #[test] - fn test_modpow_single() { + fn test_modpow() { check_modpow::(1, 0, 11, 1); check_modpow::(0, 15, 11, 0); check_modpow::(3, 7, 11, 9); check_modpow::(5, 117, 19, 1); - check_modpow::(20, 1, 2, 0); - check_modpow::(20, 1, 3, 2); - } - - #[test] - fn test_modpow_small() { - for b in 0u64..11 { - for e in 0u64..11 { - for m in 1..11 { - check_modpow::(b, e, m, b.pow(e as u32) % m); - } - } - } } #[test] @@ -111,13 +102,13 @@ mod biguint { mod bigint { use num_bigint::BigInt; use num_integer::Integer; - use num_traits::{Num, One, Signed}; + use num_traits::{Num, One, Signed, Zero}; fn check_modpow>(b: T, e: T, m: T, r: T) { fn check(b: &BigInt, e: &BigInt, m: &BigInt, r: &BigInt) { - assert_eq!(&b.modpow(e, m), r, "{} ** {} (mod {}) != {}", b, e, m, r); + assert_eq!(&b.modpow(e, m), r); - let even_m = m << 1u8; + let even_m = m << 1; let even_modpow = b.modpow(e, m); assert!(even_modpow.abs() < even_m.abs()); assert_eq!(&even_modpow.mod_floor(&m), r); @@ -131,18 +122,12 @@ mod bigint { let m: BigInt = m.into(); let r: BigInt = r.into(); - let neg_b_r = if e.is_odd() { - (-&r).mod_floor(&m) - } else { - r.clone() - }; - let neg_m_r = r.mod_floor(&-&m); - let neg_bm_r = neg_b_r.mod_floor(&-&m); + let neg_r = if r.is_zero() { BigInt::zero() } else { &m - &r }; check(&b, &e, &m, &r); - check(&-&b, &e, &m, &neg_b_r); - check(&b, &e, &-&m, &neg_m_r); - check(&-b, &e, &-&m, &neg_bm_r); + check(&-&b, &e, &m, &neg_r); + check(&b, &e, &-&m, &-neg_r); + check(&-b, &e, &-m, &-r); } #[test] @@ -151,22 +136,6 @@ mod bigint { check_modpow(0, 15, 11, 0); check_modpow(3, 7, 11, 9); check_modpow(5, 117, 19, 1); - check_modpow(-20, 1, 2, 0); - check_modpow(-20, 1, 3, 1); - } - - #[test] - fn test_modpow_small() { - for b in -10i64..11 { - for e in 0i64..11 { - for m in -10..11 { - if m == 0 { - continue; - } - check_modpow(b, e, m, b.pow(e as u32).mod_floor(&m)); - } - } - } } #[test] diff --git a/third_party/rust/num-bigint-0.2.3/tests/quickcheck.rs b/third_party/rust/num-bigint/tests/quickcheck.rs similarity index 100% rename from third_party/rust/num-bigint-0.2.3/tests/quickcheck.rs rename to third_party/rust/num-bigint/tests/quickcheck.rs diff --git a/third_party/rust/num-bigint-0.2.3/tests/rand.rs b/third_party/rust/num-bigint/tests/rand.rs similarity index 100% rename from third_party/rust/num-bigint-0.2.3/tests/rand.rs rename to third_party/rust/num-bigint/tests/rand.rs diff --git a/third_party/rust/num-bigint/tests/roots.rs b/third_party/rust/num-bigint/tests/roots.rs index cfef80c47ba9..39201fa92851 100644 --- a/third_party/rust/num-bigint/tests/roots.rs +++ b/third_party/rust/num-bigint/tests/roots.rs @@ -1,6 +1,13 @@ +extern crate num_bigint; +extern crate num_integer; +extern crate num_traits; + +#[cfg(feature = "rand")] +extern crate rand; + mod biguint { use num_bigint::BigUint; - use num_traits::{One, Zero}; + use num_traits::{One, Pow, Zero}; use std::{i32, u32}; fn check>(x: T, n: u32) { @@ -81,7 +88,7 @@ mod biguint { let x = BigUint::one() << LOG2; // the perfect divisors are just powers of two - for exp in 1..=EXP { + for exp in 1..EXP + 1 { let n = 2u32.pow(exp); let expected = BigUint::one() << (LOG2 / n as usize); assert_eq!(x.nth_root(n), expected); @@ -94,6 +101,25 @@ mod biguint { assert!(x.nth_root(u32::MAX).is_one()); } + #[cfg(feature = "rand")] + #[test] + fn test_roots_rand() { + use num_bigint::RandBigInt; + use rand::distributions::Uniform; + use rand::{thread_rng, Rng}; + + let mut rng = thread_rng(); + let bit_range = Uniform::new(0, 2048); + let sample_bits: Vec<_> = rng.sample_iter(&bit_range).take(100).collect(); + for bits in sample_bits { + let x = rng.gen_biguint(bits); + for n in 2..11 { + check(x.clone(), n); + } + check(x.clone(), 100); + } + } + #[test] fn test_roots_rand1() { // A random input that found regressions @@ -108,13 +134,13 @@ mod biguint { check(x.clone(), 2); check(x.clone(), 3); check(x.clone(), 10); - check(x, 100); + check(x.clone(), 100); } } mod bigint { use num_bigint::BigInt; - use num_traits::Signed; + use num_traits::{Pow, Signed}; fn check(x: i64, n: u32) { let big_x = BigInt::from(x); diff --git a/third_party/rust/num-bigint-0.2.3/tests/serde.rs b/third_party/rust/num-bigint/tests/serde.rs similarity index 100% rename from third_party/rust/num-bigint-0.2.3/tests/serde.rs rename to third_party/rust/num-bigint/tests/serde.rs diff --git a/third_party/rust/num-bigint-0.2.3/tests/torture.rs b/third_party/rust/num-bigint/tests/torture.rs similarity index 100% rename from third_party/rust/num-bigint-0.2.3/tests/torture.rs rename to third_party/rust/num-bigint/tests/torture.rs diff --git a/third_party/rust/num-complex/.cargo-checksum.json b/third_party/rust/num-complex/.cargo-checksum.json deleted file mode 100644 index 81b66b44b012..000000000000 --- a/third_party/rust/num-complex/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"ae77ec097a983a6d365193723032ccc161f15ef5a37ffc14c1b3fd26caacbf1d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"60255cfba4fe9fc25ca1e1f51702ce8e52e7a8b2d747e3e2055eacb04e2bae70","RELEASES.md":"834ab68be8ce6e4a46fb2f591bc93ff01e6481955e6b027adfb60f393c24a6b6","src/cast.rs":"8206bcfb99b712340383332fb760dba9cee4be8c994bd9a38d0b8c6e6bc5f7b1","src/crand.rs":"81dd604ea3bc74d7ed5e132cddecb3d6a1aaa5f6cdadac7311b62beac5e7ef89","src/lib.rs":"ef7fff45cc8ef75df68836f0b5d8dd3bd9f3a686c20e7b8761295c3b6e39699a","src/pow.rs":"974fd585da8c2b7ac3f68e93a3881c56a3f0f3e506009fb3d862c6000064abb7"},"package":"b05ad05bd8977050b171b3f6b48175fea6e0565b7981059b486075e1026a9fb5"} \ No newline at end of file diff --git a/third_party/rust/num-complex/Cargo.toml b/third_party/rust/num-complex/Cargo.toml deleted file mode 100644 index 3a211f9d23ee..000000000000 --- a/third_party/rust/num-complex/Cargo.toml +++ /dev/null @@ -1,47 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -edition = "2018" -name = "num-complex" -version = "0.3.0" -authors = ["The Rust Project Developers"] -exclude = ["/bors.toml", "/ci/*", "/.github/*"] -description = "Complex numbers implementation for Rust" -homepage = "https://github.com/rust-num/num-complex" -documentation = "https://docs.rs/num-complex" -readme = "README.md" -keywords = ["mathematics", "numerics"] -categories = ["algorithms", "data-structures", "science", "no-std"] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num-complex" -[package.metadata.docs.rs] -features = ["std", "serde", "rand"] -[dependencies.num-traits] -version = "0.2.11" -features = ["i128"] -default-features = false - -[dependencies.rand] -version = "0.7" -optional = true -default-features = false - -[dependencies.serde] -version = "1.0" -optional = true -default-features = false - -[features] -default = ["std"] -libm = ["num-traits/libm"] -std = ["num-traits/std"] diff --git a/third_party/rust/num-complex/LICENSE-APACHE b/third_party/rust/num-complex/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/third_party/rust/num-complex/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/third_party/rust/num-complex/LICENSE-MIT b/third_party/rust/num-complex/LICENSE-MIT deleted file mode 100644 index 39d4bdb5acd3..000000000000 --- a/third_party/rust/num-complex/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/num-complex/README.md b/third_party/rust/num-complex/README.md deleted file mode 100644 index 73bcb48dd745..000000000000 --- a/third_party/rust/num-complex/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# num-complex - -[![crate](https://img.shields.io/crates/v/num-complex.svg)](https://crates.io/crates/num-complex) -[![documentation](https://docs.rs/num-complex/badge.svg)](https://docs.rs/num-complex) -[![minimum rustc 1.31](https://img.shields.io/badge/rustc-1.31+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num-complex/workflows/master/badge.svg)](https://github.com/rust-num/num-complex/actions) - -`Complex` numbers for Rust. - -## Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] -num-complex = "0.3" -``` - -## Features - -This crate can be used without the standard library (`#![no_std]`) by disabling -the default `std` feature. Use this in `Cargo.toml`: - -```toml -[dependencies.num-complex] -version = "0.3" -default-features = false -``` - -Features based on `Float` types are only available when `std` or `libm` is -enabled. Where possible, `FloatCore` is used instead. Formatting complex -numbers only supports format width when `std` is enabled. - -## Releases - -Release notes are available in [RELEASES.md](RELEASES.md). - -## Compatibility - -The `num-complex` crate is tested for rustc 1.31 and greater. diff --git a/third_party/rust/num-complex/RELEASES.md b/third_party/rust/num-complex/RELEASES.md deleted file mode 100644 index 3986d61b3abd..000000000000 --- a/third_party/rust/num-complex/RELEASES.md +++ /dev/null @@ -1,125 +0,0 @@ -# Release 0.3.0 (2020-06-13) - -### Enhancements - -- [The new "libm" feature passes through to `num-traits`][73], enabling `Float` - features on no-`std` builds. - -### Breaking Changes - -- `num-complex` now requires Rust 1.31 or greater. - - The "i128" opt-in feature was removed, now always available. -- [Updated public dependences][65]: - - `rand` support has been updated to 0.7, requiring Rust 1.32. -- [Methods for `T: Float` now take values instead of references][82], most - notably affecting the constructor `from_polar`. - -**Contributors**: @cuviper, @SOF3, @vks - -[65]: https://github.com/rust-num/num-complex/pull/65 -[73]: https://github.com/rust-num/num-complex/pull/73 -[82]: https://github.com/rust-num/num-complex/pull/82 - -# Release 0.2.4 (2020-01-09) - -- [`Complex::new` is now a `const fn` for Rust 1.31 and later][63]. -- [Updated the `autocfg` build dependency to 1.0][68]. - -**Contributors**: @burrbull, @cuviper, @dingelish - -[63]: https://github.com/rust-num/num-complex/pull/63 -[68]: https://github.com/rust-num/num-complex/pull/68 - -# Release 0.2.3 (2019-06-11) - -- [`Complex::sqrt()` is now more accurate for negative reals][60]. -- [`Complex::cbrt()` computes the principal cube root][61]. - -**Contributors**: @cuviper - -[60]: https://github.com/rust-num/num-complex/pull/60 -[61]: https://github.com/rust-num/num-complex/pull/61 - -# Release 0.2.2 (2019-06-10) - -- [`Complex::l1_norm()` computes the Manhattan distance from the origin][43]. -- [`Complex::fdiv()` and `finv()` use floating-point for inversion][41], which - may avoid overflows for some inputs, at the cost of trigonometric rounding. -- [`Complex` now implements `num_traits::MulAdd` and `MulAddAssign`][44]. -- [`Complex` now implements `Zero::set_zero` and `One::set_one`][57]. -- [`Complex` now implements `num_traits::Pow` and adds `powi` and `powu`][56]. - -**Contributors**: @adamnemecek, @cuviper, @ignatenkobrain, @Schultzer - -[41]: https://github.com/rust-num/num-complex/pull/41 -[43]: https://github.com/rust-num/num-complex/pull/43 -[44]: https://github.com/rust-num/num-complex/pull/44 -[56]: https://github.com/rust-num/num-complex/pull/56 -[57]: https://github.com/rust-num/num-complex/pull/57 - -# Release 0.2.1 (2018-10-08) - -- [`Complex` now implements `ToPrimitive`, `FromPrimitive`, `AsPrimitive`, and `NumCast`][33]. - -**Contributors**: @cuviper, @termoshtt - -[33]: https://github.com/rust-num/num-complex/pull/33 - -# Release 0.2.0 (2018-05-24) - -### Enhancements - -- [`Complex` now implements `num_traits::Inv` and `One::is_one`][17]. -- [`Complex` now implements `Sum` and `Product`][11]. -- [`Complex` now supports `i128` and `u128` components][27] with Rust 1.26+. -- [`Complex` now optionally supports `rand` 0.5][28], implementing the - `Standard` distribution and [a generic `ComplexDistribution`][30]. -- [`Rem` with a scalar divisor now avoids `norm_sqr` overflow][25]. - -### Breaking Changes - -- [`num-complex` now requires rustc 1.15 or greater][16]. -- [There is now a `std` feature][22], enabled by default, along with the - implication that building *without* this feature makes this a `#![no_std]` - crate. A few methods now require `FloatCore`, and the remaining methods - based on `Float` are only supported with `std`. -- [The `serde` dependency has been updated to 1.0][7], and `rustc-serialize` - is no longer supported by `num-complex`. - -**Contributors**: @clarcharr, @cuviper, @shingtaklam1324, @termoshtt - -[7]: https://github.com/rust-num/num-complex/pull/7 -[11]: https://github.com/rust-num/num-complex/pull/11 -[16]: https://github.com/rust-num/num-complex/pull/16 -[17]: https://github.com/rust-num/num-complex/pull/17 -[22]: https://github.com/rust-num/num-complex/pull/22 -[25]: https://github.com/rust-num/num-complex/pull/25 -[27]: https://github.com/rust-num/num-complex/pull/27 -[28]: https://github.com/rust-num/num-complex/pull/28 -[30]: https://github.com/rust-num/num-complex/pull/30 - - -# Release 0.1.43 (2018-03-08) - -- [Fix a usage typo in README.md][20]. - -**Contributors**: @shingtaklam1324 - -[20]: https://github.com/rust-num/num-complex/pull/20 - - -# Release 0.1.42 (2018-02-07) - -- [num-complex now has its own source repository][num-356] at [rust-num/num-complex][home]. - -**Contributors**: @cuviper - -[home]: https://github.com/rust-num/num-complex -[num-356]: https://github.com/rust-num/num/pull/356 - - -# Prior releases - -No prior release notes were kept. Thanks all the same to the many -contributors that have made this crate what it is! - diff --git a/third_party/rust/num-complex/src/cast.rs b/third_party/rust/num-complex/src/cast.rs deleted file mode 100644 index e12f5cd37ce7..000000000000 --- a/third_party/rust/num-complex/src/cast.rs +++ /dev/null @@ -1,119 +0,0 @@ -use super::Complex; -use num_traits::{AsPrimitive, FromPrimitive, Num, NumCast, ToPrimitive}; - -macro_rules! impl_to_primitive { - ($ty:ty, $to:ident) => { - #[inline] - fn $to(&self) -> Option<$ty> { - if self.im.is_zero() { - self.re.$to() - } else { - None - } - } - }; -} // impl_to_primitive - -// Returns None if Complex part is non-zero -impl ToPrimitive for Complex { - impl_to_primitive!(usize, to_usize); - impl_to_primitive!(isize, to_isize); - impl_to_primitive!(u8, to_u8); - impl_to_primitive!(u16, to_u16); - impl_to_primitive!(u32, to_u32); - impl_to_primitive!(u64, to_u64); - impl_to_primitive!(i8, to_i8); - impl_to_primitive!(i16, to_i16); - impl_to_primitive!(i32, to_i32); - impl_to_primitive!(i64, to_i64); - impl_to_primitive!(u128, to_u128); - impl_to_primitive!(i128, to_i128); - impl_to_primitive!(f32, to_f32); - impl_to_primitive!(f64, to_f64); -} - -macro_rules! impl_from_primitive { - ($ty:ty, $from_xx:ident) => { - #[inline] - fn $from_xx(n: $ty) -> Option { - Some(Complex { - re: T::$from_xx(n)?, - im: T::zero(), - }) - } - }; -} // impl_from_primitive - -impl FromPrimitive for Complex { - impl_from_primitive!(usize, from_usize); - impl_from_primitive!(isize, from_isize); - impl_from_primitive!(u8, from_u8); - impl_from_primitive!(u16, from_u16); - impl_from_primitive!(u32, from_u32); - impl_from_primitive!(u64, from_u64); - impl_from_primitive!(i8, from_i8); - impl_from_primitive!(i16, from_i16); - impl_from_primitive!(i32, from_i32); - impl_from_primitive!(i64, from_i64); - impl_from_primitive!(u128, from_u128); - impl_from_primitive!(i128, from_i128); - impl_from_primitive!(f32, from_f32); - impl_from_primitive!(f64, from_f64); -} - -impl NumCast for Complex { - fn from(n: U) -> Option { - Some(Complex { - re: T::from(n)?, - im: T::zero(), - }) - } -} - -impl AsPrimitive for Complex -where - T: AsPrimitive, - U: 'static + Copy, -{ - fn as_(self) -> U { - self.re.as_() - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_to_primitive() { - let a: Complex = Complex { re: 3, im: 0 }; - assert_eq!(a.to_i32(), Some(3_i32)); - let b: Complex = Complex { re: 3, im: 1 }; - assert_eq!(b.to_i32(), None); - let x: Complex = Complex { re: 1.0, im: 0.1 }; - assert_eq!(x.to_f32(), None); - let y: Complex = Complex { re: 1.0, im: 0.0 }; - assert_eq!(y.to_f32(), Some(1.0)); - let z: Complex = Complex { re: 1.0, im: 0.0 }; - assert_eq!(z.to_i32(), Some(1)); - } - - #[test] - fn test_from_primitive() { - let a: Complex = FromPrimitive::from_i32(2).unwrap(); - assert_eq!(a, Complex { re: 2.0, im: 0.0 }); - } - - #[test] - fn test_num_cast() { - let a: Complex = NumCast::from(2_i32).unwrap(); - assert_eq!(a, Complex { re: 2.0, im: 0.0 }); - } - - #[test] - fn test_as_primitive() { - let a: Complex = Complex { re: 2.0, im: 0.2 }; - let a_: i32 = a.as_(); - assert_eq!(a_, 2_i32); - } -} diff --git a/third_party/rust/num-complex/src/crand.rs b/third_party/rust/num-complex/src/crand.rs deleted file mode 100644 index 6df2ff4ddea2..000000000000 --- a/third_party/rust/num-complex/src/crand.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Rand implementations for complex numbers - -use crate::Complex; -use num_traits::Num; -use rand::distributions::Standard; -use rand::prelude::*; - -impl Distribution> for Standard -where - T: Num + Clone, - Standard: Distribution, -{ - fn sample(&self, rng: &mut R) -> Complex { - Complex::new(self.sample(rng), self.sample(rng)) - } -} - -/// A generic random value distribution for complex numbers. -#[derive(Clone, Copy, Debug)] -pub struct ComplexDistribution { - re: Re, - im: Im, -} - -impl ComplexDistribution { - /// Creates a complex distribution from independent - /// distributions of the real and imaginary parts. - pub fn new(re: Re, im: Im) -> Self { - ComplexDistribution { re, im } - } -} - -impl Distribution> for ComplexDistribution -where - T: Num + Clone, - Re: Distribution, - Im: Distribution, -{ - fn sample(&self, rng: &mut R) -> Complex { - Complex::new(self.re.sample(rng), self.im.sample(rng)) - } -} - -#[cfg(test)] -fn test_rng() -> StdRng { - StdRng::from_seed([42; 32]) -} - -#[test] -fn standard_f64() { - let mut rng = test_rng(); - for _ in 0..100 { - let c: Complex = rng.gen(); - assert!(c.re >= 0.0 && c.re < 1.0); - assert!(c.im >= 0.0 && c.im < 1.0); - } -} - -#[test] -fn generic_standard_f64() { - let mut rng = test_rng(); - let dist = ComplexDistribution::new(Standard, Standard); - for _ in 0..100 { - let c: Complex = rng.sample(&dist); - assert!(c.re >= 0.0 && c.re < 1.0); - assert!(c.im >= 0.0 && c.im < 1.0); - } -} - -#[test] -fn generic_uniform_f64() { - use rand::distributions::Uniform; - - let mut rng = test_rng(); - let re = Uniform::new(-100.0, 0.0); - let im = Uniform::new(0.0, 100.0); - let dist = ComplexDistribution::new(re, im); - for _ in 0..100 { - // no type annotation required, since `Uniform` only produces one type. - let c = rng.sample(&dist); - assert!(c.re >= -100.0 && c.re < 0.0); - assert!(c.im >= 0.0 && c.im < 100.0); - } -} - -#[test] -fn generic_mixed_f64() { - use rand::distributions::Uniform; - - let mut rng = test_rng(); - let re = Uniform::new(-100.0, 0.0); - let dist = ComplexDistribution::new(re, Standard); - for _ in 0..100 { - // no type annotation required, since `Uniform` only produces one type. - let c = rng.sample(&dist); - assert!(c.re >= -100.0 && c.re < 0.0); - assert!(c.im >= 0.0 && c.im < 1.0); - } -} - -#[test] -fn generic_uniform_i32() { - use rand::distributions::Uniform; - - let mut rng = test_rng(); - let re = Uniform::new(-100, 0); - let im = Uniform::new(0, 100); - let dist = ComplexDistribution::new(re, im); - for _ in 0..100 { - // no type annotation required, since `Uniform` only produces one type. - let c = rng.sample(&dist); - assert!(c.re >= -100 && c.re < 0); - assert!(c.im >= 0 && c.im < 100); - } -} diff --git a/third_party/rust/num-complex/src/lib.rs b/third_party/rust/num-complex/src/lib.rs deleted file mode 100644 index 491937d737fd..000000000000 --- a/third_party/rust/num-complex/src/lib.rs +++ /dev/null @@ -1,2636 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Complex numbers. -//! -//! ## Compatibility -//! -//! The `num-complex` crate is tested for rustc 1.31 and greater. - -#![doc(html_root_url = "https://docs.rs/num-complex/0.3")] -#![no_std] - -#[cfg(any(test, feature = "std"))] -#[cfg_attr(test, macro_use)] -extern crate std; - -use core::fmt; -#[cfg(test)] -use core::hash; -use core::iter::{Product, Sum}; -use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; -use core::str::FromStr; -#[cfg(feature = "std")] -use std::error::Error; - -use num_traits::{Inv, MulAdd, Num, One, Pow, Signed, Zero}; - -#[cfg(any(feature = "std", feature = "libm"))] -use num_traits::float::Float; -use num_traits::float::FloatCore; - -mod cast; -mod pow; - -#[cfg(feature = "rand")] -mod crand; -#[cfg(feature = "rand")] -pub use crate::crand::ComplexDistribution; - -// FIXME #1284: handle complex NaN & infinity etc. This -// probably doesn't map to C's _Complex correctly. - -/// A complex number in Cartesian form. -/// -/// ## Representation and Foreign Function Interface Compatibility -/// -/// `Complex` is memory layout compatible with an array `[T; 2]`. -/// -/// Note that `Complex` where F is a floating point type is **only** memory -/// layout compatible with C's complex types, **not** necessarily calling -/// convention compatible. This means that for FFI you can only pass -/// `Complex` behind a pointer, not as a value. -/// -/// ## Examples -/// -/// Example of extern function declaration. -/// -/// ``` -/// use num_complex::Complex; -/// use std::os::raw::c_int; -/// -/// extern "C" { -/// fn zaxpy_(n: *const c_int, alpha: *const Complex, -/// x: *const Complex, incx: *const c_int, -/// y: *mut Complex, incy: *const c_int); -/// } -/// ``` -#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct Complex { - /// Real portion of the complex number - pub re: T, - /// Imaginary portion of the complex number - pub im: T, -} - -pub type Complex32 = Complex; -pub type Complex64 = Complex; - -impl Complex { - /// Create a new Complex - #[inline] - pub const fn new(re: T, im: T) -> Self { - Complex { re, im } - } -} - -impl Complex { - /// Returns imaginary unit - #[inline] - pub fn i() -> Self { - Self::new(T::zero(), T::one()) - } - - /// Returns the square of the norm (since `T` doesn't necessarily - /// have a sqrt function), i.e. `re^2 + im^2`. - #[inline] - pub fn norm_sqr(&self) -> T { - self.re.clone() * self.re.clone() + self.im.clone() * self.im.clone() - } - - /// Multiplies `self` by the scalar `t`. - #[inline] - pub fn scale(&self, t: T) -> Self { - Self::new(self.re.clone() * t.clone(), self.im.clone() * t) - } - - /// Divides `self` by the scalar `t`. - #[inline] - pub fn unscale(&self, t: T) -> Self { - Self::new(self.re.clone() / t.clone(), self.im.clone() / t) - } - - /// Raises `self` to an unsigned integer power. - #[inline] - pub fn powu(&self, exp: u32) -> Self { - Pow::pow(self, exp) - } -} - -impl> Complex { - /// Returns the complex conjugate. i.e. `re - i im` - #[inline] - pub fn conj(&self) -> Self { - Self::new(self.re.clone(), -self.im.clone()) - } - - /// Returns `1/self` - #[inline] - pub fn inv(&self) -> Self { - let norm_sqr = self.norm_sqr(); - Self::new( - self.re.clone() / norm_sqr.clone(), - -self.im.clone() / norm_sqr, - ) - } - - /// Raises `self` to a signed integer power. - #[inline] - pub fn powi(&self, exp: i32) -> Self { - Pow::pow(self, exp) - } -} - -impl Complex { - /// Returns the L1 norm `|re| + |im|` -- the [Manhattan distance] from the origin. - /// - /// [Manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry - #[inline] - pub fn l1_norm(&self) -> T { - self.re.abs() + self.im.abs() - } -} - -#[cfg(any(feature = "std", feature = "libm"))] -impl Complex { - /// Calculate |self| - #[inline] - pub fn norm(self) -> T { - self.re.hypot(self.im) - } - /// Calculate the principal Arg of self. - #[inline] - pub fn arg(self) -> T { - self.im.atan2(self.re) - } - /// Convert to polar form (r, theta), such that - /// `self = r * exp(i * theta)` - #[inline] - pub fn to_polar(self) -> (T, T) { - (self.norm(), self.arg()) - } - /// Convert a polar representation into a complex number. - #[inline] - pub fn from_polar(r: T, theta: T) -> Self { - Self::new(r * theta.cos(), r * theta.sin()) - } - - /// Computes `e^(self)`, where `e` is the base of the natural logarithm. - #[inline] - pub fn exp(self) -> Self { - // formula: e^(a + bi) = e^a (cos(b) + i*sin(b)) - // = from_polar(e^a, b) - Self::from_polar(self.re.exp(), self.im) - } - - /// Computes the principal value of natural logarithm of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 0]`, continuous from above. - /// - /// The branch satisfies `-π ≤ arg(ln(z)) ≤ π`. - #[inline] - pub fn ln(self) -> Self { - // formula: ln(z) = ln|z| + i*arg(z) - let (r, theta) = self.to_polar(); - Self::new(r.ln(), theta) - } - - /// Computes the principal value of the square root of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 0)`, continuous from above. - /// - /// The branch satisfies `-π/2 ≤ arg(sqrt(z)) ≤ π/2`. - #[inline] - pub fn sqrt(self) -> Self { - if self.im.is_zero() { - if self.re.is_sign_positive() { - // simple positive real √r, and copy `im` for its sign - Self::new(self.re.sqrt(), self.im) - } else { - // √(r e^(iπ)) = √r e^(iπ/2) = i√r - // √(r e^(-iπ)) = √r e^(-iπ/2) = -i√r - let re = T::zero(); - let im = (-self.re).sqrt(); - if self.im.is_sign_positive() { - Self::new(re, im) - } else { - Self::new(re, -im) - } - } - } else if self.re.is_zero() { - // √(r e^(iπ/2)) = √r e^(iπ/4) = √(r/2) + i√(r/2) - // √(r e^(-iπ/2)) = √r e^(-iπ/4) = √(r/2) - i√(r/2) - let one = T::one(); - let two = one + one; - let x = (self.im.abs() / two).sqrt(); - if self.im.is_sign_positive() { - Self::new(x, x) - } else { - Self::new(x, -x) - } - } else { - // formula: sqrt(r e^(it)) = sqrt(r) e^(it/2) - let one = T::one(); - let two = one + one; - let (r, theta) = self.to_polar(); - Self::from_polar(r.sqrt(), theta / two) - } - } - - /// Computes the principal value of the cube root of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 0)`, continuous from above. - /// - /// The branch satisfies `-π/3 ≤ arg(cbrt(z)) ≤ π/3`. - /// - /// Note that this does not match the usual result for the cube root of - /// negative real numbers. For example, the real cube root of `-8` is `-2`, - /// but the principal complex cube root of `-8` is `1 + i√3`. - #[inline] - pub fn cbrt(self) -> Self { - if self.im.is_zero() { - if self.re.is_sign_positive() { - // simple positive real ∛r, and copy `im` for its sign - Self::new(self.re.cbrt(), self.im) - } else { - // ∛(r e^(iπ)) = ∛r e^(iπ/3) = ∛r/2 + i∛r√3/2 - // ∛(r e^(-iπ)) = ∛r e^(-iπ/3) = ∛r/2 - i∛r√3/2 - let one = T::one(); - let two = one + one; - let three = two + one; - let re = (-self.re).cbrt() / two; - let im = three.sqrt() * re; - if self.im.is_sign_positive() { - Self::new(re, im) - } else { - Self::new(re, -im) - } - } - } else if self.re.is_zero() { - // ∛(r e^(iπ/2)) = ∛r e^(iπ/6) = ∛r√3/2 + i∛r/2 - // ∛(r e^(-iπ/2)) = ∛r e^(-iπ/6) = ∛r√3/2 - i∛r/2 - let one = T::one(); - let two = one + one; - let three = two + one; - let im = self.im.abs().cbrt() / two; - let re = three.sqrt() * im; - if self.im.is_sign_positive() { - Self::new(re, im) - } else { - Self::new(re, -im) - } - } else { - // formula: cbrt(r e^(it)) = cbrt(r) e^(it/3) - let one = T::one(); - let three = one + one + one; - let (r, theta) = self.to_polar(); - Self::from_polar(r.cbrt(), theta / three) - } - } - - /// Raises `self` to a floating point power. - #[inline] - pub fn powf(self, exp: T) -> Self { - // formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y) - // = from_polar(ρ^y, θ y) - let (r, theta) = self.to_polar(); - Self::from_polar(r.powf(exp), theta * exp) - } - - /// Returns the logarithm of `self` with respect to an arbitrary base. - #[inline] - pub fn log(self, base: T) -> Self { - // formula: log_y(x) = log_y(ρ e^(i θ)) - // = log_y(ρ) + log_y(e^(i θ)) = log_y(ρ) + ln(e^(i θ)) / ln(y) - // = log_y(ρ) + i θ / ln(y) - let (r, theta) = self.to_polar(); - Self::new(r.log(base), theta / base.ln()) - } - - /// Raises `self` to a complex power. - #[inline] - pub fn powc(self, exp: Self) -> Self { - // formula: x^y = (a + i b)^(c + i d) - // = (ρ e^(i θ))^c (ρ e^(i θ))^(i d) - // where ρ=|x| and θ=arg(x) - // = ρ^c e^(−d θ) e^(i c θ) ρ^(i d) - // = p^c e^(−d θ) (cos(c θ) - // + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ))) - // = p^c e^(−d θ) ( - // cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ)) - // + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ)))) - // = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ))) - // = from_polar(p^c e^(−d θ), c θ + d ln(ρ)) - let (r, theta) = self.to_polar(); - Self::from_polar( - r.powf(exp.re) * (-exp.im * theta).exp(), - exp.re * theta + exp.im * r.ln(), - ) - } - - /// Raises a floating point number to the complex power `self`. - #[inline] - pub fn expf(self, base: T) -> Self { - // formula: x^(a+bi) = x^a x^bi = x^a e^(b ln(x) i) - // = from_polar(x^a, b ln(x)) - Self::from_polar(base.powf(self.re), self.im * base.ln()) - } - - /// Computes the sine of `self`. - #[inline] - pub fn sin(self) -> Self { - // formula: sin(a + bi) = sin(a)cosh(b) + i*cos(a)sinh(b) - Self::new( - self.re.sin() * self.im.cosh(), - self.re.cos() * self.im.sinh(), - ) - } - - /// Computes the cosine of `self`. - #[inline] - pub fn cos(self) -> Self { - // formula: cos(a + bi) = cos(a)cosh(b) - i*sin(a)sinh(b) - Self::new( - self.re.cos() * self.im.cosh(), - -self.re.sin() * self.im.sinh(), - ) - } - - /// Computes the tangent of `self`. - #[inline] - pub fn tan(self) -> Self { - // formula: tan(a + bi) = (sin(2a) + i*sinh(2b))/(cos(2a) + cosh(2b)) - let (two_re, two_im) = (self.re + self.re, self.im + self.im); - Self::new(two_re.sin(), two_im.sinh()).unscale(two_re.cos() + two_im.cosh()) - } - - /// Computes the principal value of the inverse sine of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞, -1)`, continuous from above. - /// * `(1, ∞)`, continuous from below. - /// - /// The branch satisfies `-π/2 ≤ Re(asin(z)) ≤ π/2`. - #[inline] - pub fn asin(self) -> Self { - // formula: arcsin(z) = -i ln(sqrt(1-z^2) + iz) - let i = Self::i(); - -i * ((Self::one() - self * self).sqrt() + i * self).ln() - } - - /// Computes the principal value of the inverse cosine of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞, -1)`, continuous from above. - /// * `(1, ∞)`, continuous from below. - /// - /// The branch satisfies `0 ≤ Re(acos(z)) ≤ π`. - #[inline] - pub fn acos(self) -> Self { - // formula: arccos(z) = -i ln(i sqrt(1-z^2) + z) - let i = Self::i(); - -i * (i * (Self::one() - self * self).sqrt() + self).ln() - } - - /// Computes the principal value of the inverse tangent of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞i, -i]`, continuous from the left. - /// * `[i, ∞i)`, continuous from the right. - /// - /// The branch satisfies `-π/2 ≤ Re(atan(z)) ≤ π/2`. - #[inline] - pub fn atan(self) -> Self { - // formula: arctan(z) = (ln(1+iz) - ln(1-iz))/(2i) - let i = Self::i(); - let one = Self::one(); - let two = one + one; - if self == i { - return Self::new(T::zero(), T::infinity()); - } else if self == -i { - return Self::new(T::zero(), -T::infinity()); - } - ((one + i * self).ln() - (one - i * self).ln()) / (two * i) - } - - /// Computes the hyperbolic sine of `self`. - #[inline] - pub fn sinh(self) -> Self { - // formula: sinh(a + bi) = sinh(a)cos(b) + i*cosh(a)sin(b) - Self::new( - self.re.sinh() * self.im.cos(), - self.re.cosh() * self.im.sin(), - ) - } - - /// Computes the hyperbolic cosine of `self`. - #[inline] - pub fn cosh(self) -> Self { - // formula: cosh(a + bi) = cosh(a)cos(b) + i*sinh(a)sin(b) - Self::new( - self.re.cosh() * self.im.cos(), - self.re.sinh() * self.im.sin(), - ) - } - - /// Computes the hyperbolic tangent of `self`. - #[inline] - pub fn tanh(self) -> Self { - // formula: tanh(a + bi) = (sinh(2a) + i*sin(2b))/(cosh(2a) + cos(2b)) - let (two_re, two_im) = (self.re + self.re, self.im + self.im); - Self::new(two_re.sinh(), two_im.sin()).unscale(two_re.cosh() + two_im.cos()) - } - - /// Computes the principal value of inverse hyperbolic sine of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞i, -i)`, continuous from the left. - /// * `(i, ∞i)`, continuous from the right. - /// - /// The branch satisfies `-π/2 ≤ Im(asinh(z)) ≤ π/2`. - #[inline] - pub fn asinh(self) -> Self { - // formula: arcsinh(z) = ln(z + sqrt(1+z^2)) - let one = Self::one(); - (self + (one + self * self).sqrt()).ln() - } - - /// Computes the principal value of inverse hyperbolic cosine of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 1)`, continuous from above. - /// - /// The branch satisfies `-π ≤ Im(acosh(z)) ≤ π` and `0 ≤ Re(acosh(z)) < ∞`. - #[inline] - pub fn acosh(self) -> Self { - // formula: arccosh(z) = 2 ln(sqrt((z+1)/2) + sqrt((z-1)/2)) - let one = Self::one(); - let two = one + one; - two * (((self + one) / two).sqrt() + ((self - one) / two).sqrt()).ln() - } - - /// Computes the principal value of inverse hyperbolic tangent of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞, -1]`, continuous from above. - /// * `[1, ∞)`, continuous from below. - /// - /// The branch satisfies `-π/2 ≤ Im(atanh(z)) ≤ π/2`. - #[inline] - pub fn atanh(self) -> Self { - // formula: arctanh(z) = (ln(1+z) - ln(1-z))/2 - let one = Self::one(); - let two = one + one; - if self == one { - return Self::new(T::infinity(), T::zero()); - } else if self == -one { - return Self::new(-T::infinity(), T::zero()); - } - ((one + self).ln() - (one - self).ln()) / two - } - - /// Returns `1/self` using floating-point operations. - /// - /// This may be more accurate than the generic `self.inv()` in cases - /// where `self.norm_sqr()` would overflow to ∞ or underflow to 0. - /// - /// # Examples - /// - /// ``` - /// use num_complex::Complex64; - /// let c = Complex64::new(1e300, 1e300); - /// - /// // The generic `inv()` will overflow. - /// assert!(!c.inv().is_normal()); - /// - /// // But we can do better for `Float` types. - /// let inv = c.finv(); - /// assert!(inv.is_normal()); - /// println!("{:e}", inv); - /// - /// let expected = Complex64::new(5e-301, -5e-301); - /// assert!((inv - expected).norm() < 1e-315); - /// ``` - #[inline] - pub fn finv(self) -> Complex { - let norm = self.norm(); - self.conj() / norm / norm - } - - /// Returns `self/other` using floating-point operations. - /// - /// This may be more accurate than the generic `Div` implementation in cases - /// where `other.norm_sqr()` would overflow to ∞ or underflow to 0. - /// - /// # Examples - /// - /// ``` - /// use num_complex::Complex64; - /// let a = Complex64::new(2.0, 3.0); - /// let b = Complex64::new(1e300, 1e300); - /// - /// // Generic division will overflow. - /// assert!(!(a / b).is_normal()); - /// - /// // But we can do better for `Float` types. - /// let quotient = a.fdiv(b); - /// assert!(quotient.is_normal()); - /// println!("{:e}", quotient); - /// - /// let expected = Complex64::new(2.5e-300, 5e-301); - /// assert!((quotient - expected).norm() < 1e-315); - /// ``` - #[inline] - pub fn fdiv(self, other: Complex) -> Complex { - self * other.finv() - } -} - -impl Complex { - /// Checks if the given complex number is NaN - #[inline] - pub fn is_nan(self) -> bool { - self.re.is_nan() || self.im.is_nan() - } - - /// Checks if the given complex number is infinite - #[inline] - pub fn is_infinite(self) -> bool { - !self.is_nan() && (self.re.is_infinite() || self.im.is_infinite()) - } - - /// Checks if the given complex number is finite - #[inline] - pub fn is_finite(self) -> bool { - self.re.is_finite() && self.im.is_finite() - } - - /// Checks if the given complex number is normal - #[inline] - pub fn is_normal(self) -> bool { - self.re.is_normal() && self.im.is_normal() - } -} - -impl From for Complex { - #[inline] - fn from(re: T) -> Self { - Self::new(re, T::zero()) - } -} - -impl<'a, T: Clone + Num> From<&'a T> for Complex { - #[inline] - fn from(re: &T) -> Self { - From::from(re.clone()) - } -} - -macro_rules! forward_ref_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, 'b, T: Clone + Num> $imp<&'b Complex> for &'a Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &Complex) -> Self::Output { - self.clone().$method(other.clone()) - } - } - }; -} - -macro_rules! forward_ref_val_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + Num> $imp> for &'a Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: Complex) -> Self::Output { - self.clone().$method(other) - } - } - }; -} - -macro_rules! forward_val_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + Num> $imp<&'a Complex> for Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &Complex) -> Self::Output { - self.$method(other.clone()) - } - } - }; -} - -macro_rules! forward_all_binop { - (impl $imp:ident, $method:ident) => { - forward_ref_ref_binop!(impl $imp, $method); - forward_ref_val_binop!(impl $imp, $method); - forward_val_ref_binop!(impl $imp, $method); - }; -} - -/* arithmetic */ -forward_all_binop!(impl Add, add); - -// (a + i b) + (c + i d) == (a + c) + i (b + d) -impl Add> for Complex { - type Output = Self; - - #[inline] - fn add(self, other: Self) -> Self::Output { - Self::Output::new(self.re + other.re, self.im + other.im) - } -} - -forward_all_binop!(impl Sub, sub); - -// (a + i b) - (c + i d) == (a - c) + i (b - d) -impl Sub> for Complex { - type Output = Self; - - #[inline] - fn sub(self, other: Self) -> Self::Output { - Self::Output::new(self.re - other.re, self.im - other.im) - } -} - -forward_all_binop!(impl Mul, mul); - -// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) -impl Mul> for Complex { - type Output = Self; - - #[inline] - fn mul(self, other: Self) -> Self::Output { - let re = self.re.clone() * other.re.clone() - self.im.clone() * other.im.clone(); - let im = self.re * other.im + self.im * other.re; - Self::Output::new(re, im) - } -} - -// (a + i b) * (c + i d) + (e + i f) == ((a*c + e) - b*d) + i (a*d + (b*c + f)) -impl> MulAdd> for Complex { - type Output = Complex; - - #[inline] - fn mul_add(self, other: Complex, add: Complex) -> Complex { - let re = self.re.clone().mul_add(other.re.clone(), add.re) - - (self.im.clone() * other.im.clone()); // FIXME: use mulsub when available in rust - let im = self.re.mul_add(other.im, self.im.mul_add(other.re, add.im)); - Complex::new(re, im) - } -} -impl<'a, 'b, T: Clone + Num + MulAdd> MulAdd<&'b Complex> for &'a Complex { - type Output = Complex; - - #[inline] - fn mul_add(self, other: &Complex, add: &Complex) -> Complex { - self.clone().mul_add(other.clone(), add.clone()) - } -} - -forward_all_binop!(impl Div, div); - -// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d) -// == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)] -impl Div> for Complex { - type Output = Self; - - #[inline] - fn div(self, other: Self) -> Self::Output { - let norm_sqr = other.norm_sqr(); - let re = self.re.clone() * other.re.clone() + self.im.clone() * other.im.clone(); - let im = self.im * other.re - self.re * other.im; - Self::Output::new(re / norm_sqr.clone(), im / norm_sqr) - } -} - -forward_all_binop!(impl Rem, rem); - -impl Complex { - /// Find the gaussian integer corresponding to the true ratio rounded towards zero. - fn div_trunc(&self, divisor: &Self) -> Self { - let Complex { re, im } = self / divisor; - Complex::new(re.clone() - re % T::one(), im.clone() - im % T::one()) - } -} - -impl Rem> for Complex { - type Output = Self; - - #[inline] - fn rem(self, modulus: Self) -> Self::Output { - let gaussian = self.div_trunc(&modulus); - self - modulus * gaussian - } -} - -// Op Assign - -mod opassign { - use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; - - use num_traits::{MulAddAssign, NumAssign}; - - use crate::Complex; - - impl AddAssign for Complex { - fn add_assign(&mut self, other: Self) { - self.re += other.re; - self.im += other.im; - } - } - - impl SubAssign for Complex { - fn sub_assign(&mut self, other: Self) { - self.re -= other.re; - self.im -= other.im; - } - } - - // (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) - impl MulAssign for Complex { - fn mul_assign(&mut self, other: Self) { - let a = self.re.clone(); - - self.re *= other.re.clone(); - self.re -= self.im.clone() * other.im.clone(); - - self.im *= other.re; - self.im += a * other.im; - } - } - - // (a + i b) * (c + i d) + (e + i f) == ((a*c + e) - b*d) + i (b*c + (a*d + f)) - impl MulAddAssign for Complex { - fn mul_add_assign(&mut self, other: Complex, add: Complex) { - let a = self.re.clone(); - - self.re.mul_add_assign(other.re.clone(), add.re); // (a*c + e) - self.re -= self.im.clone() * other.im.clone(); // ((a*c + e) - b*d) - - let mut adf = a; - adf.mul_add_assign(other.im, add.im); // (a*d + f) - self.im.mul_add_assign(other.re, adf); // (b*c + (a*d + f)) - } - } - - impl<'a, 'b, T: Clone + NumAssign + MulAddAssign> MulAddAssign<&'a Complex, &'b Complex> - for Complex - { - fn mul_add_assign(&mut self, other: &Complex, add: &Complex) { - self.mul_add_assign(other.clone(), add.clone()); - } - } - - // (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d) - // == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)] - impl DivAssign for Complex { - fn div_assign(&mut self, other: Self) { - let a = self.re.clone(); - let norm_sqr = other.norm_sqr(); - - self.re *= other.re.clone(); - self.re += self.im.clone() * other.im.clone(); - self.re /= norm_sqr.clone(); - - self.im *= other.re; - self.im -= a * other.im; - self.im /= norm_sqr; - } - } - - impl RemAssign for Complex { - fn rem_assign(&mut self, modulus: Self) { - let gaussian = self.div_trunc(&modulus); - *self -= modulus * gaussian; - } - } - - impl AddAssign for Complex { - fn add_assign(&mut self, other: T) { - self.re += other; - } - } - - impl SubAssign for Complex { - fn sub_assign(&mut self, other: T) { - self.re -= other; - } - } - - impl MulAssign for Complex { - fn mul_assign(&mut self, other: T) { - self.re *= other.clone(); - self.im *= other; - } - } - - impl DivAssign for Complex { - fn div_assign(&mut self, other: T) { - self.re /= other.clone(); - self.im /= other; - } - } - - impl RemAssign for Complex { - fn rem_assign(&mut self, other: T) { - self.re %= other.clone(); - self.im %= other; - } - } - - macro_rules! forward_op_assign { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + NumAssign> $imp<&'a Complex> for Complex { - #[inline] - fn $method(&mut self, other: &Self) { - self.$method(other.clone()) - } - } - impl<'a, T: Clone + NumAssign> $imp<&'a T> for Complex { - #[inline] - fn $method(&mut self, other: &T) { - self.$method(other.clone()) - } - } - }; - } - - forward_op_assign!(impl AddAssign, add_assign); - forward_op_assign!(impl SubAssign, sub_assign); - forward_op_assign!(impl MulAssign, mul_assign); - forward_op_assign!(impl DivAssign, div_assign); - forward_op_assign!(impl RemAssign, rem_assign); -} - -impl> Neg for Complex { - type Output = Self; - - #[inline] - fn neg(self) -> Self::Output { - Self::Output::new(-self.re, -self.im) - } -} - -impl<'a, T: Clone + Num + Neg> Neg for &'a Complex { - type Output = Complex; - - #[inline] - fn neg(self) -> Self::Output { - -self.clone() - } -} - -impl> Inv for Complex { - type Output = Self; - - #[inline] - fn inv(self) -> Self::Output { - (&self).inv() - } -} - -impl<'a, T: Clone + Num + Neg> Inv for &'a Complex { - type Output = Complex; - - #[inline] - fn inv(self) -> Self::Output { - self.inv() - } -} - -macro_rules! real_arithmetic { - (@forward $imp:ident::$method:ident for $($real:ident),*) => ( - impl<'a, T: Clone + Num> $imp<&'a T> for Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &T) -> Self::Output { - self.$method(other.clone()) - } - } - impl<'a, T: Clone + Num> $imp for &'a Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: T) -> Self::Output { - self.clone().$method(other) - } - } - impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &T) -> Self::Output { - self.clone().$method(other.clone()) - } - } - $( - impl<'a> $imp<&'a Complex<$real>> for $real { - type Output = Complex<$real>; - - #[inline] - fn $method(self, other: &Complex<$real>) -> Complex<$real> { - self.$method(other.clone()) - } - } - impl<'a> $imp> for &'a $real { - type Output = Complex<$real>; - - #[inline] - fn $method(self, other: Complex<$real>) -> Complex<$real> { - self.clone().$method(other) - } - } - impl<'a, 'b> $imp<&'a Complex<$real>> for &'b $real { - type Output = Complex<$real>; - - #[inline] - fn $method(self, other: &Complex<$real>) -> Complex<$real> { - self.clone().$method(other.clone()) - } - } - )* - ); - ($($real:ident),*) => ( - real_arithmetic!(@forward Add::add for $($real),*); - real_arithmetic!(@forward Sub::sub for $($real),*); - real_arithmetic!(@forward Mul::mul for $($real),*); - real_arithmetic!(@forward Div::div for $($real),*); - real_arithmetic!(@forward Rem::rem for $($real),*); - - $( - impl Add> for $real { - type Output = Complex<$real>; - - #[inline] - fn add(self, other: Complex<$real>) -> Self::Output { - Self::Output::new(self + other.re, other.im) - } - } - - impl Sub> for $real { - type Output = Complex<$real>; - - #[inline] - fn sub(self, other: Complex<$real>) -> Self::Output { - Self::Output::new(self - other.re, $real::zero() - other.im) - } - } - - impl Mul> for $real { - type Output = Complex<$real>; - - #[inline] - fn mul(self, other: Complex<$real>) -> Self::Output { - Self::Output::new(self * other.re, self * other.im) - } - } - - impl Div> for $real { - type Output = Complex<$real>; - - #[inline] - fn div(self, other: Complex<$real>) -> Self::Output { - // a / (c + i d) == [a * (c - i d)] / (c*c + d*d) - let norm_sqr = other.norm_sqr(); - Self::Output::new(self * other.re / norm_sqr.clone(), - $real::zero() - self * other.im / norm_sqr) - } - } - - impl Rem> for $real { - type Output = Complex<$real>; - - #[inline] - fn rem(self, other: Complex<$real>) -> Self::Output { - Self::Output::new(self, Self::zero()) % other - } - } - )* - ); -} - -impl Add for Complex { - type Output = Complex; - - #[inline] - fn add(self, other: T) -> Self::Output { - Self::Output::new(self.re + other, self.im) - } -} - -impl Sub for Complex { - type Output = Complex; - - #[inline] - fn sub(self, other: T) -> Self::Output { - Self::Output::new(self.re - other, self.im) - } -} - -impl Mul for Complex { - type Output = Complex; - - #[inline] - fn mul(self, other: T) -> Self::Output { - Self::Output::new(self.re * other.clone(), self.im * other) - } -} - -impl Div for Complex { - type Output = Self; - - #[inline] - fn div(self, other: T) -> Self::Output { - Self::Output::new(self.re / other.clone(), self.im / other) - } -} - -impl Rem for Complex { - type Output = Complex; - - #[inline] - fn rem(self, other: T) -> Self::Output { - Self::Output::new(self.re % other.clone(), self.im % other) - } -} - -real_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64); - -/* constants */ -impl Zero for Complex { - #[inline] - fn zero() -> Self { - Self::new(Zero::zero(), Zero::zero()) - } - - #[inline] - fn is_zero(&self) -> bool { - self.re.is_zero() && self.im.is_zero() - } - - #[inline] - fn set_zero(&mut self) { - self.re.set_zero(); - self.im.set_zero(); - } -} - -impl One for Complex { - #[inline] - fn one() -> Self { - Self::new(One::one(), Zero::zero()) - } - - #[inline] - fn is_one(&self) -> bool { - self.re.is_one() && self.im.is_zero() - } - - #[inline] - fn set_one(&mut self) { - self.re.set_one(); - self.im.set_zero(); - } -} - -macro_rules! write_complex { - ($f:ident, $t:expr, $prefix:expr, $re:expr, $im:expr, $T:ident) => {{ - let abs_re = if $re < Zero::zero() { - $T::zero() - $re.clone() - } else { - $re.clone() - }; - let abs_im = if $im < Zero::zero() { - $T::zero() - $im.clone() - } else { - $im.clone() - }; - - return if let Some(prec) = $f.precision() { - fmt_re_im( - $f, - $re < $T::zero(), - $im < $T::zero(), - format_args!(concat!("{:.1$", $t, "}"), abs_re, prec), - format_args!(concat!("{:.1$", $t, "}"), abs_im, prec), - ) - } else { - fmt_re_im( - $f, - $re < $T::zero(), - $im < $T::zero(), - format_args!(concat!("{:", $t, "}"), abs_re), - format_args!(concat!("{:", $t, "}"), abs_im), - ) - }; - - fn fmt_re_im( - f: &mut fmt::Formatter<'_>, - re_neg: bool, - im_neg: bool, - real: fmt::Arguments<'_>, - imag: fmt::Arguments<'_>, - ) -> fmt::Result { - let prefix = if f.alternate() { $prefix } else { "" }; - let sign = if re_neg { - "-" - } else if f.sign_plus() { - "+" - } else { - "" - }; - - if im_neg { - fmt_complex( - f, - format_args!( - "{}{pre}{re}-{pre}{im}i", - sign, - re = real, - im = imag, - pre = prefix - ), - ) - } else { - fmt_complex( - f, - format_args!( - "{}{pre}{re}+{pre}{im}i", - sign, - re = real, - im = imag, - pre = prefix - ), - ) - } - } - - #[cfg(feature = "std")] - // Currently, we can only apply width using an intermediate `String` (and thus `std`) - fn fmt_complex(f: &mut fmt::Formatter<'_>, complex: fmt::Arguments<'_>) -> fmt::Result { - use std::string::ToString; - if let Some(width) = f.width() { - write!(f, "{0: >1$}", complex.to_string(), width) - } else { - write!(f, "{}", complex) - } - } - - #[cfg(not(feature = "std"))] - fn fmt_complex(f: &mut fmt::Formatter<'_>, complex: fmt::Arguments<'_>) -> fmt::Result { - write!(f, "{}", complex) - } - }}; -} - -/* string conversions */ -impl fmt::Display for Complex -where - T: fmt::Display + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "", "", self.re, self.im, T) - } -} - -impl fmt::LowerExp for Complex -where - T: fmt::LowerExp + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "e", "", self.re, self.im, T) - } -} - -impl fmt::UpperExp for Complex -where - T: fmt::UpperExp + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "E", "", self.re, self.im, T) - } -} - -impl fmt::LowerHex for Complex -where - T: fmt::LowerHex + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "x", "0x", self.re, self.im, T) - } -} - -impl fmt::UpperHex for Complex -where - T: fmt::UpperHex + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "X", "0x", self.re, self.im, T) - } -} - -impl fmt::Octal for Complex -where - T: fmt::Octal + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "o", "0o", self.re, self.im, T) - } -} - -impl fmt::Binary for Complex -where - T: fmt::Binary + Num + PartialOrd + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write_complex!(f, "b", "0b", self.re, self.im, T) - } -} - -#[allow(deprecated)] // `trim_left_matches` and `trim_right_matches` since 1.33 -fn from_str_generic(s: &str, from: F) -> Result, ParseComplexError> -where - F: Fn(&str) -> Result, - T: Clone + Num, -{ - let imag = match s.rfind('j') { - None => 'i', - _ => 'j', - }; - - let mut neg_b = false; - let mut a = s; - let mut b = ""; - - for (i, w) in s.as_bytes().windows(2).enumerate() { - let p = w[0]; - let c = w[1]; - - // ignore '+'/'-' if part of an exponent - if (c == b'+' || c == b'-') && !(p == b'e' || p == b'E') { - // trim whitespace around the separator - a = &s[..=i].trim_right_matches(char::is_whitespace); - b = &s[i + 2..].trim_left_matches(char::is_whitespace); - neg_b = c == b'-'; - - if b.is_empty() || (neg_b && b.starts_with('-')) { - return Err(ParseComplexError::new()); - } - break; - } - } - - // split off real and imaginary parts - if b.is_empty() { - // input was either pure real or pure imaginary - b = if a.ends_with(imag) { "0" } else { "0i" }; - } - - let re; - let neg_re; - let im; - let neg_im; - if a.ends_with(imag) { - im = a; - neg_im = false; - re = b; - neg_re = neg_b; - } else if b.ends_with(imag) { - re = a; - neg_re = false; - im = b; - neg_im = neg_b; - } else { - return Err(ParseComplexError::new()); - } - - // parse re - let re = from(re).map_err(ParseComplexError::from_error)?; - let re = if neg_re { T::zero() - re } else { re }; - - // pop imaginary unit off - let mut im = &im[..im.len() - 1]; - // handle im == "i" or im == "-i" - if im.is_empty() || im == "+" { - im = "1"; - } else if im == "-" { - im = "-1"; - } - - // parse im - let im = from(im).map_err(ParseComplexError::from_error)?; - let im = if neg_im { T::zero() - im } else { im }; - - Ok(Complex::new(re, im)) -} - -impl FromStr for Complex -where - T: FromStr + Num + Clone, -{ - type Err = ParseComplexError; - - /// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T` - fn from_str(s: &str) -> Result { - from_str_generic(s, T::from_str) - } -} - -impl Num for Complex { - type FromStrRadixErr = ParseComplexError; - - /// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T` - fn from_str_radix(s: &str, radix: u32) -> Result { - from_str_generic(s, |x| -> Result { - T::from_str_radix(x, radix) - }) - } -} - -impl Sum for Complex { - fn sum(iter: I) -> Self - where - I: Iterator, - { - iter.fold(Self::zero(), |acc, c| acc + c) - } -} - -impl<'a, T: 'a + Num + Clone> Sum<&'a Complex> for Complex { - fn sum(iter: I) -> Self - where - I: Iterator>, - { - iter.fold(Self::zero(), |acc, c| acc + c) - } -} - -impl Product for Complex { - fn product(iter: I) -> Self - where - I: Iterator, - { - iter.fold(Self::one(), |acc, c| acc * c) - } -} - -impl<'a, T: 'a + Num + Clone> Product<&'a Complex> for Complex { - fn product(iter: I) -> Self - where - I: Iterator>, - { - iter.fold(Self::one(), |acc, c| acc * c) - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Complex -where - T: serde::Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - (&self.re, &self.im).serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de, T> serde::Deserialize<'de> for Complex -where - T: serde::Deserialize<'de> + Num + Clone, -{ - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let (re, im) = serde::Deserialize::deserialize(deserializer)?; - Ok(Self::new(re, im)) - } -} - -#[derive(Debug, PartialEq)] -pub struct ParseComplexError { - kind: ComplexErrorKind, -} - -#[derive(Debug, PartialEq)] -enum ComplexErrorKind { - ParseError(E), - ExprError, -} - -impl ParseComplexError { - fn new() -> Self { - ParseComplexError { - kind: ComplexErrorKind::ExprError, - } - } - - fn from_error(error: E) -> Self { - ParseComplexError { - kind: ComplexErrorKind::ParseError(error), - } - } -} - -#[cfg(feature = "std")] -impl Error for ParseComplexError { - #[allow(deprecated)] - fn description(&self) -> &str { - match self.kind { - ComplexErrorKind::ParseError(ref e) => e.description(), - ComplexErrorKind::ExprError => "invalid or unsupported complex expression", - } - } -} - -impl fmt::Display for ParseComplexError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ComplexErrorKind::ParseError(ref e) => e.fmt(f), - ComplexErrorKind::ExprError => "invalid or unsupported complex expression".fmt(f), - } - } -} - -#[cfg(test)] -fn hash(x: &T) -> u64 { - use std::collections::hash_map::RandomState; - use std::hash::{BuildHasher, Hasher}; - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[cfg(test)] -mod test { - #![allow(non_upper_case_globals)] - - use super::{Complex, Complex64}; - use core::f64; - use core::str::FromStr; - - use std::string::{String, ToString}; - - use num_traits::{Num, One, Zero}; - - pub const _0_0i: Complex64 = Complex { re: 0.0, im: 0.0 }; - pub const _1_0i: Complex64 = Complex { re: 1.0, im: 0.0 }; - pub const _1_1i: Complex64 = Complex { re: 1.0, im: 1.0 }; - pub const _0_1i: Complex64 = Complex { re: 0.0, im: 1.0 }; - pub const _neg1_1i: Complex64 = Complex { re: -1.0, im: 1.0 }; - pub const _05_05i: Complex64 = Complex { re: 0.5, im: 0.5 }; - pub const all_consts: [Complex64; 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i]; - pub const _4_2i: Complex64 = Complex { re: 4.0, im: 2.0 }; - - #[test] - fn test_consts() { - // check our constants are what Complex::new creates - fn test(c: Complex64, r: f64, i: f64) { - assert_eq!(c, Complex::new(r, i)); - } - test(_0_0i, 0.0, 0.0); - test(_1_0i, 1.0, 0.0); - test(_1_1i, 1.0, 1.0); - test(_neg1_1i, -1.0, 1.0); - test(_05_05i, 0.5, 0.5); - - assert_eq!(_0_0i, Zero::zero()); - assert_eq!(_1_0i, One::one()); - } - - #[test] - fn test_scale_unscale() { - assert_eq!(_05_05i.scale(2.0), _1_1i); - assert_eq!(_1_1i.unscale(2.0), _05_05i); - for &c in all_consts.iter() { - assert_eq!(c.scale(2.0).unscale(2.0), c); - } - } - - #[test] - fn test_conj() { - for &c in all_consts.iter() { - assert_eq!(c.conj(), Complex::new(c.re, -c.im)); - assert_eq!(c.conj().conj(), c); - } - } - - #[test] - fn test_inv() { - assert_eq!(_1_1i.inv(), _05_05i.conj()); - assert_eq!(_1_0i.inv(), _1_0i.inv()); - } - - #[test] - #[should_panic] - fn test_divide_by_zero_natural() { - let n = Complex::new(2, 3); - let d = Complex::new(0, 0); - let _x = n / d; - } - - #[test] - fn test_inv_zero() { - // FIXME #20: should this really fail, or just NaN? - assert!(_0_0i.inv().is_nan()); - } - - #[test] - #[allow(clippy::float_cmp)] - fn test_l1_norm() { - assert_eq!(_0_0i.l1_norm(), 0.0); - assert_eq!(_1_0i.l1_norm(), 1.0); - assert_eq!(_1_1i.l1_norm(), 2.0); - assert_eq!(_0_1i.l1_norm(), 1.0); - assert_eq!(_neg1_1i.l1_norm(), 2.0); - assert_eq!(_05_05i.l1_norm(), 1.0); - assert_eq!(_4_2i.l1_norm(), 6.0); - } - - #[test] - fn test_pow() { - for c in all_consts.iter() { - assert_eq!(c.powi(0), _1_0i); - let mut pos = _1_0i; - let mut neg = _1_0i; - for i in 1i32..20 { - pos *= c; - assert_eq!(pos, c.powi(i)); - if c.is_zero() { - assert!(c.powi(-i).is_nan()); - } else { - neg /= c; - assert_eq!(neg, c.powi(-i)); - } - } - } - } - - #[cfg(any(feature = "std", feature = "libm"))] - mod float { - use super::*; - use num_traits::{Float, Pow}; - - #[test] - #[cfg_attr(target_arch = "x86", ignore)] - // FIXME #7158: (maybe?) currently failing on x86. - #[allow(clippy::float_cmp)] - fn test_norm() { - fn test(c: Complex64, ns: f64) { - assert_eq!(c.norm_sqr(), ns); - assert_eq!(c.norm(), ns.sqrt()) - } - test(_0_0i, 0.0); - test(_1_0i, 1.0); - test(_1_1i, 2.0); - test(_neg1_1i, 2.0); - test(_05_05i, 0.5); - } - - #[test] - fn test_arg() { - fn test(c: Complex64, arg: f64) { - assert!((c.arg() - arg).abs() < 1.0e-6) - } - test(_1_0i, 0.0); - test(_1_1i, 0.25 * f64::consts::PI); - test(_neg1_1i, 0.75 * f64::consts::PI); - test(_05_05i, 0.25 * f64::consts::PI); - } - - #[test] - fn test_polar_conv() { - fn test(c: Complex64) { - let (r, theta) = c.to_polar(); - assert!((c - Complex::from_polar(r, theta)).norm() < 1e-6); - } - for &c in all_consts.iter() { - test(c); - } - } - - fn close(a: Complex64, b: Complex64) -> bool { - close_to_tol(a, b, 1e-10) - } - - fn close_to_tol(a: Complex64, b: Complex64, tol: f64) -> bool { - // returns true if a and b are reasonably close - let close = (a == b) || (a - b).norm() < tol; - if !close { - println!("{:?} != {:?}", a, b); - } - close - } - - #[test] - fn test_exp() { - assert!(close(_1_0i.exp(), _1_0i.scale(f64::consts::E))); - assert!(close(_0_0i.exp(), _1_0i)); - assert!(close(_0_1i.exp(), Complex::new(1.0.cos(), 1.0.sin()))); - assert!(close(_05_05i.exp() * _05_05i.exp(), _1_1i.exp())); - assert!(close( - _0_1i.scale(-f64::consts::PI).exp(), - _1_0i.scale(-1.0) - )); - for &c in all_consts.iter() { - // e^conj(z) = conj(e^z) - assert!(close(c.conj().exp(), c.exp().conj())); - // e^(z + 2 pi i) = e^z - assert!(close( - c.exp(), - (c + _0_1i.scale(f64::consts::PI * 2.0)).exp() - )); - } - } - - #[test] - fn test_ln() { - assert!(close(_1_0i.ln(), _0_0i)); - assert!(close(_0_1i.ln(), _0_1i.scale(f64::consts::PI / 2.0))); - assert!(close(_0_0i.ln(), Complex::new(f64::neg_infinity(), 0.0))); - assert!(close( - (_neg1_1i * _05_05i).ln(), - _neg1_1i.ln() + _05_05i.ln() - )); - for &c in all_consts.iter() { - // ln(conj(z() = conj(ln(z)) - assert!(close(c.conj().ln(), c.ln().conj())); - // for this branch, -pi <= arg(ln(z)) <= pi - assert!(-f64::consts::PI <= c.ln().arg() && c.ln().arg() <= f64::consts::PI); - } - } - - #[test] - fn test_powc() { - let a = Complex::new(2.0, -3.0); - let b = Complex::new(3.0, 0.0); - assert!(close(a.powc(b), a.powf(b.re))); - assert!(close(b.powc(a), a.expf(b.re))); - let c = Complex::new(1.0 / 3.0, 0.1); - assert!(close_to_tol( - a.powc(c), - Complex::new(1.65826, -0.33502), - 1e-5 - )); - } - - #[test] - fn test_powf() { - let c = Complex64::new(2.0, -1.0); - let expected = Complex64::new(-0.8684746, -16.695934); - assert!(close_to_tol(c.powf(3.5), expected, 1e-5)); - assert!(close_to_tol(Pow::pow(c, 3.5_f64), expected, 1e-5)); - assert!(close_to_tol(Pow::pow(c, 3.5_f32), expected, 1e-5)); - } - - #[test] - fn test_log() { - let c = Complex::new(2.0, -1.0); - let r = c.log(10.0); - assert!(close_to_tol(r, Complex::new(0.349485, -0.20135958), 1e-5)); - } - - #[test] - fn test_some_expf_cases() { - let c = Complex::new(2.0, -1.0); - let r = c.expf(10.0); - assert!(close_to_tol(r, Complex::new(-66.82015, -74.39803), 1e-5)); - - let c = Complex::new(5.0, -2.0); - let r = c.expf(3.4); - assert!(close_to_tol(r, Complex::new(-349.25, -290.63), 1e-2)); - - let c = Complex::new(-1.5, 2.0 / 3.0); - let r = c.expf(1.0 / 3.0); - assert!(close_to_tol(r, Complex::new(3.8637, -3.4745), 1e-2)); - } - - #[test] - fn test_sqrt() { - assert!(close(_0_0i.sqrt(), _0_0i)); - assert!(close(_1_0i.sqrt(), _1_0i)); - assert!(close(Complex::new(-1.0, 0.0).sqrt(), _0_1i)); - assert!(close(Complex::new(-1.0, -0.0).sqrt(), _0_1i.scale(-1.0))); - assert!(close(_0_1i.sqrt(), _05_05i.scale(2.0.sqrt()))); - for &c in all_consts.iter() { - // sqrt(conj(z() = conj(sqrt(z)) - assert!(close(c.conj().sqrt(), c.sqrt().conj())); - // for this branch, -pi/2 <= arg(sqrt(z)) <= pi/2 - assert!( - -f64::consts::FRAC_PI_2 <= c.sqrt().arg() - && c.sqrt().arg() <= f64::consts::FRAC_PI_2 - ); - // sqrt(z) * sqrt(z) = z - assert!(close(c.sqrt() * c.sqrt(), c)); - } - } - - #[test] - fn test_sqrt_real() { - for n in (0..100).map(f64::from) { - // √(n² + 0i) = n + 0i - let n2 = n * n; - assert_eq!(Complex64::new(n2, 0.0).sqrt(), Complex64::new(n, 0.0)); - // √(-n² + 0i) = 0 + ni - assert_eq!(Complex64::new(-n2, 0.0).sqrt(), Complex64::new(0.0, n)); - // √(-n² - 0i) = 0 - ni - assert_eq!(Complex64::new(-n2, -0.0).sqrt(), Complex64::new(0.0, -n)); - } - } - - #[test] - fn test_sqrt_imag() { - for n in (0..100).map(f64::from) { - // √(0 + n²i) = n e^(iπ/4) - let n2 = n * n; - assert!(close( - Complex64::new(0.0, n2).sqrt(), - Complex64::from_polar(n, f64::consts::FRAC_PI_4) - )); - // √(0 - n²i) = n e^(-iπ/4) - assert!(close( - Complex64::new(0.0, -n2).sqrt(), - Complex64::from_polar(n, -f64::consts::FRAC_PI_4) - )); - } - } - - #[test] - fn test_cbrt() { - assert!(close(_0_0i.cbrt(), _0_0i)); - assert!(close(_1_0i.cbrt(), _1_0i)); - assert!(close( - Complex::new(-1.0, 0.0).cbrt(), - Complex::new(0.5, 0.75.sqrt()) - )); - assert!(close( - Complex::new(-1.0, -0.0).cbrt(), - Complex::new(0.5, -(0.75.sqrt())) - )); - assert!(close(_0_1i.cbrt(), Complex::new(0.75.sqrt(), 0.5))); - assert!(close(_0_1i.conj().cbrt(), Complex::new(0.75.sqrt(), -0.5))); - for &c in all_consts.iter() { - // cbrt(conj(z() = conj(cbrt(z)) - assert!(close(c.conj().cbrt(), c.cbrt().conj())); - // for this branch, -pi/3 <= arg(cbrt(z)) <= pi/3 - assert!( - -f64::consts::FRAC_PI_3 <= c.cbrt().arg() - && c.cbrt().arg() <= f64::consts::FRAC_PI_3 - ); - // cbrt(z) * cbrt(z) cbrt(z) = z - assert!(close(c.cbrt() * c.cbrt() * c.cbrt(), c)); - } - } - - #[test] - fn test_cbrt_real() { - for n in (0..100).map(f64::from) { - // ∛(n³ + 0i) = n + 0i - let n3 = n * n * n; - assert!(close( - Complex64::new(n3, 0.0).cbrt(), - Complex64::new(n, 0.0) - )); - // ∛(-n³ + 0i) = n e^(iπ/3) - assert!(close( - Complex64::new(-n3, 0.0).cbrt(), - Complex64::from_polar(n, f64::consts::FRAC_PI_3) - )); - // ∛(-n³ - 0i) = n e^(-iπ/3) - assert!(close( - Complex64::new(-n3, -0.0).cbrt(), - Complex64::from_polar(n, -f64::consts::FRAC_PI_3) - )); - } - } - - #[test] - fn test_cbrt_imag() { - for n in (0..100).map(f64::from) { - // ∛(0 + n³i) = n e^(iπ/6) - let n3 = n * n * n; - assert!(close( - Complex64::new(0.0, n3).cbrt(), - Complex64::from_polar(n, f64::consts::FRAC_PI_6) - )); - // ∛(0 - n³i) = n e^(-iπ/6) - assert!(close( - Complex64::new(0.0, -n3).cbrt(), - Complex64::from_polar(n, -f64::consts::FRAC_PI_6) - )); - } - } - - #[test] - fn test_sin() { - assert!(close(_0_0i.sin(), _0_0i)); - assert!(close(_1_0i.scale(f64::consts::PI * 2.0).sin(), _0_0i)); - assert!(close(_0_1i.sin(), _0_1i.scale(1.0.sinh()))); - for &c in all_consts.iter() { - // sin(conj(z)) = conj(sin(z)) - assert!(close(c.conj().sin(), c.sin().conj())); - // sin(-z) = -sin(z) - assert!(close(c.scale(-1.0).sin(), c.sin().scale(-1.0))); - } - } - - #[test] - fn test_cos() { - assert!(close(_0_0i.cos(), _1_0i)); - assert!(close(_1_0i.scale(f64::consts::PI * 2.0).cos(), _1_0i)); - assert!(close(_0_1i.cos(), _1_0i.scale(1.0.cosh()))); - for &c in all_consts.iter() { - // cos(conj(z)) = conj(cos(z)) - assert!(close(c.conj().cos(), c.cos().conj())); - // cos(-z) = cos(z) - assert!(close(c.scale(-1.0).cos(), c.cos())); - } - } - - #[test] - fn test_tan() { - assert!(close(_0_0i.tan(), _0_0i)); - assert!(close(_1_0i.scale(f64::consts::PI / 4.0).tan(), _1_0i)); - assert!(close(_1_0i.scale(f64::consts::PI).tan(), _0_0i)); - for &c in all_consts.iter() { - // tan(conj(z)) = conj(tan(z)) - assert!(close(c.conj().tan(), c.tan().conj())); - // tan(-z) = -tan(z) - assert!(close(c.scale(-1.0).tan(), c.tan().scale(-1.0))); - } - } - - #[test] - fn test_asin() { - assert!(close(_0_0i.asin(), _0_0i)); - assert!(close(_1_0i.asin(), _1_0i.scale(f64::consts::PI / 2.0))); - assert!(close( - _1_0i.scale(-1.0).asin(), - _1_0i.scale(-f64::consts::PI / 2.0) - )); - assert!(close(_0_1i.asin(), _0_1i.scale((1.0 + 2.0.sqrt()).ln()))); - for &c in all_consts.iter() { - // asin(conj(z)) = conj(asin(z)) - assert!(close(c.conj().asin(), c.asin().conj())); - // asin(-z) = -asin(z) - assert!(close(c.scale(-1.0).asin(), c.asin().scale(-1.0))); - // for this branch, -pi/2 <= asin(z).re <= pi/2 - assert!( - -f64::consts::PI / 2.0 <= c.asin().re && c.asin().re <= f64::consts::PI / 2.0 - ); - } - } - - #[test] - fn test_acos() { - assert!(close(_0_0i.acos(), _1_0i.scale(f64::consts::PI / 2.0))); - assert!(close(_1_0i.acos(), _0_0i)); - assert!(close( - _1_0i.scale(-1.0).acos(), - _1_0i.scale(f64::consts::PI) - )); - assert!(close( - _0_1i.acos(), - Complex::new(f64::consts::PI / 2.0, (2.0.sqrt() - 1.0).ln()) - )); - for &c in all_consts.iter() { - // acos(conj(z)) = conj(acos(z)) - assert!(close(c.conj().acos(), c.acos().conj())); - // for this branch, 0 <= acos(z).re <= pi - assert!(0.0 <= c.acos().re && c.acos().re <= f64::consts::PI); - } - } - - #[test] - fn test_atan() { - assert!(close(_0_0i.atan(), _0_0i)); - assert!(close(_1_0i.atan(), _1_0i.scale(f64::consts::PI / 4.0))); - assert!(close( - _1_0i.scale(-1.0).atan(), - _1_0i.scale(-f64::consts::PI / 4.0) - )); - assert!(close(_0_1i.atan(), Complex::new(0.0, f64::infinity()))); - for &c in all_consts.iter() { - // atan(conj(z)) = conj(atan(z)) - assert!(close(c.conj().atan(), c.atan().conj())); - // atan(-z) = -atan(z) - assert!(close(c.scale(-1.0).atan(), c.atan().scale(-1.0))); - // for this branch, -pi/2 <= atan(z).re <= pi/2 - assert!( - -f64::consts::PI / 2.0 <= c.atan().re && c.atan().re <= f64::consts::PI / 2.0 - ); - } - } - - #[test] - fn test_sinh() { - assert!(close(_0_0i.sinh(), _0_0i)); - assert!(close( - _1_0i.sinh(), - _1_0i.scale((f64::consts::E - 1.0 / f64::consts::E) / 2.0) - )); - assert!(close(_0_1i.sinh(), _0_1i.scale(1.0.sin()))); - for &c in all_consts.iter() { - // sinh(conj(z)) = conj(sinh(z)) - assert!(close(c.conj().sinh(), c.sinh().conj())); - // sinh(-z) = -sinh(z) - assert!(close(c.scale(-1.0).sinh(), c.sinh().scale(-1.0))); - } - } - - #[test] - fn test_cosh() { - assert!(close(_0_0i.cosh(), _1_0i)); - assert!(close( - _1_0i.cosh(), - _1_0i.scale((f64::consts::E + 1.0 / f64::consts::E) / 2.0) - )); - assert!(close(_0_1i.cosh(), _1_0i.scale(1.0.cos()))); - for &c in all_consts.iter() { - // cosh(conj(z)) = conj(cosh(z)) - assert!(close(c.conj().cosh(), c.cosh().conj())); - // cosh(-z) = cosh(z) - assert!(close(c.scale(-1.0).cosh(), c.cosh())); - } - } - - #[test] - fn test_tanh() { - assert!(close(_0_0i.tanh(), _0_0i)); - assert!(close( - _1_0i.tanh(), - _1_0i.scale((f64::consts::E.powi(2) - 1.0) / (f64::consts::E.powi(2) + 1.0)) - )); - assert!(close(_0_1i.tanh(), _0_1i.scale(1.0.tan()))); - for &c in all_consts.iter() { - // tanh(conj(z)) = conj(tanh(z)) - assert!(close(c.conj().tanh(), c.conj().tanh())); - // tanh(-z) = -tanh(z) - assert!(close(c.scale(-1.0).tanh(), c.tanh().scale(-1.0))); - } - } - - #[test] - fn test_asinh() { - assert!(close(_0_0i.asinh(), _0_0i)); - assert!(close(_1_0i.asinh(), _1_0i.scale(1.0 + 2.0.sqrt()).ln())); - assert!(close(_0_1i.asinh(), _0_1i.scale(f64::consts::PI / 2.0))); - assert!(close( - _0_1i.asinh().scale(-1.0), - _0_1i.scale(-f64::consts::PI / 2.0) - )); - for &c in all_consts.iter() { - // asinh(conj(z)) = conj(asinh(z)) - assert!(close(c.conj().asinh(), c.conj().asinh())); - // asinh(-z) = -asinh(z) - assert!(close(c.scale(-1.0).asinh(), c.asinh().scale(-1.0))); - // for this branch, -pi/2 <= asinh(z).im <= pi/2 - assert!( - -f64::consts::PI / 2.0 <= c.asinh().im && c.asinh().im <= f64::consts::PI / 2.0 - ); - } - } - - #[test] - fn test_acosh() { - assert!(close(_0_0i.acosh(), _0_1i.scale(f64::consts::PI / 2.0))); - assert!(close(_1_0i.acosh(), _0_0i)); - assert!(close( - _1_0i.scale(-1.0).acosh(), - _0_1i.scale(f64::consts::PI) - )); - for &c in all_consts.iter() { - // acosh(conj(z)) = conj(acosh(z)) - assert!(close(c.conj().acosh(), c.conj().acosh())); - // for this branch, -pi <= acosh(z).im <= pi and 0 <= acosh(z).re - assert!( - -f64::consts::PI <= c.acosh().im - && c.acosh().im <= f64::consts::PI - && 0.0 <= c.cosh().re - ); - } - } - - #[test] - fn test_atanh() { - assert!(close(_0_0i.atanh(), _0_0i)); - assert!(close(_0_1i.atanh(), _0_1i.scale(f64::consts::PI / 4.0))); - assert!(close(_1_0i.atanh(), Complex::new(f64::infinity(), 0.0))); - for &c in all_consts.iter() { - // atanh(conj(z)) = conj(atanh(z)) - assert!(close(c.conj().atanh(), c.conj().atanh())); - // atanh(-z) = -atanh(z) - assert!(close(c.scale(-1.0).atanh(), c.atanh().scale(-1.0))); - // for this branch, -pi/2 <= atanh(z).im <= pi/2 - assert!( - -f64::consts::PI / 2.0 <= c.atanh().im && c.atanh().im <= f64::consts::PI / 2.0 - ); - } - } - - #[test] - fn test_exp_ln() { - for &c in all_consts.iter() { - // e^ln(z) = z - assert!(close(c.ln().exp(), c)); - } - } - - #[test] - fn test_trig_to_hyperbolic() { - for &c in all_consts.iter() { - // sin(iz) = i sinh(z) - assert!(close((_0_1i * c).sin(), _0_1i * c.sinh())); - // cos(iz) = cosh(z) - assert!(close((_0_1i * c).cos(), c.cosh())); - // tan(iz) = i tanh(z) - assert!(close((_0_1i * c).tan(), _0_1i * c.tanh())); - } - } - - #[test] - fn test_trig_identities() { - for &c in all_consts.iter() { - // tan(z) = sin(z)/cos(z) - assert!(close(c.tan(), c.sin() / c.cos())); - // sin(z)^2 + cos(z)^2 = 1 - assert!(close(c.sin() * c.sin() + c.cos() * c.cos(), _1_0i)); - - // sin(asin(z)) = z - assert!(close(c.asin().sin(), c)); - // cos(acos(z)) = z - assert!(close(c.acos().cos(), c)); - // tan(atan(z)) = z - // i and -i are branch points - if c != _0_1i && c != _0_1i.scale(-1.0) { - assert!(close(c.atan().tan(), c)); - } - - // sin(z) = (e^(iz) - e^(-iz))/(2i) - assert!(close( - ((_0_1i * c).exp() - (_0_1i * c).exp().inv()) / _0_1i.scale(2.0), - c.sin() - )); - // cos(z) = (e^(iz) + e^(-iz))/2 - assert!(close( - ((_0_1i * c).exp() + (_0_1i * c).exp().inv()).unscale(2.0), - c.cos() - )); - // tan(z) = i (1 - e^(2iz))/(1 + e^(2iz)) - assert!(close( - _0_1i * (_1_0i - (_0_1i * c).scale(2.0).exp()) - / (_1_0i + (_0_1i * c).scale(2.0).exp()), - c.tan() - )); - } - } - - #[test] - fn test_hyperbolic_identites() { - for &c in all_consts.iter() { - // tanh(z) = sinh(z)/cosh(z) - assert!(close(c.tanh(), c.sinh() / c.cosh())); - // cosh(z)^2 - sinh(z)^2 = 1 - assert!(close(c.cosh() * c.cosh() - c.sinh() * c.sinh(), _1_0i)); - - // sinh(asinh(z)) = z - assert!(close(c.asinh().sinh(), c)); - // cosh(acosh(z)) = z - assert!(close(c.acosh().cosh(), c)); - // tanh(atanh(z)) = z - // 1 and -1 are branch points - if c != _1_0i && c != _1_0i.scale(-1.0) { - assert!(close(c.atanh().tanh(), c)); - } - - // sinh(z) = (e^z - e^(-z))/2 - assert!(close((c.exp() - c.exp().inv()).unscale(2.0), c.sinh())); - // cosh(z) = (e^z + e^(-z))/2 - assert!(close((c.exp() + c.exp().inv()).unscale(2.0), c.cosh())); - // tanh(z) = ( e^(2z) - 1)/(e^(2z) + 1) - assert!(close( - (c.scale(2.0).exp() - _1_0i) / (c.scale(2.0).exp() + _1_0i), - c.tanh() - )); - } - } - } - - // Test both a + b and a += b - macro_rules! test_a_op_b { - ($a:ident + $b:expr, $answer:expr) => { - assert_eq!($a + $b, $answer); - assert_eq!( - { - let mut x = $a; - x += $b; - x - }, - $answer - ); - }; - ($a:ident - $b:expr, $answer:expr) => { - assert_eq!($a - $b, $answer); - assert_eq!( - { - let mut x = $a; - x -= $b; - x - }, - $answer - ); - }; - ($a:ident * $b:expr, $answer:expr) => { - assert_eq!($a * $b, $answer); - assert_eq!( - { - let mut x = $a; - x *= $b; - x - }, - $answer - ); - }; - ($a:ident / $b:expr, $answer:expr) => { - assert_eq!($a / $b, $answer); - assert_eq!( - { - let mut x = $a; - x /= $b; - x - }, - $answer - ); - }; - ($a:ident % $b:expr, $answer:expr) => { - assert_eq!($a % $b, $answer); - assert_eq!( - { - let mut x = $a; - x %= $b; - x - }, - $answer - ); - }; - } - - // Test both a + b and a + &b - macro_rules! test_op { - ($a:ident $op:tt $b:expr, $answer:expr) => { - test_a_op_b!($a $op $b, $answer); - test_a_op_b!($a $op &$b, $answer); - }; - } - - mod complex_arithmetic { - use super::{_05_05i, _0_0i, _0_1i, _1_0i, _1_1i, _4_2i, _neg1_1i, all_consts}; - use num_traits::{MulAdd, MulAddAssign, Zero}; - - #[test] - fn test_add() { - test_op!(_05_05i + _05_05i, _1_1i); - test_op!(_0_1i + _1_0i, _1_1i); - test_op!(_1_0i + _neg1_1i, _0_1i); - - for &c in all_consts.iter() { - test_op!(_0_0i + c, c); - test_op!(c + _0_0i, c); - } - } - - #[test] - fn test_sub() { - test_op!(_05_05i - _05_05i, _0_0i); - test_op!(_0_1i - _1_0i, _neg1_1i); - test_op!(_0_1i - _neg1_1i, _1_0i); - - for &c in all_consts.iter() { - test_op!(c - _0_0i, c); - test_op!(c - c, _0_0i); - } - } - - #[test] - fn test_mul() { - test_op!(_05_05i * _05_05i, _0_1i.unscale(2.0)); - test_op!(_1_1i * _0_1i, _neg1_1i); - - // i^2 & i^4 - test_op!(_0_1i * _0_1i, -_1_0i); - assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i); - - for &c in all_consts.iter() { - test_op!(c * _1_0i, c); - test_op!(_1_0i * c, c); - } - } - - #[test] - #[cfg(any(feature = "std", feature = "libm"))] - fn test_mul_add_float() { - assert_eq!(_05_05i.mul_add(_05_05i, _0_0i), _05_05i * _05_05i + _0_0i); - assert_eq!(_05_05i * _05_05i + _0_0i, _05_05i.mul_add(_05_05i, _0_0i)); - assert_eq!(_0_1i.mul_add(_0_1i, _0_1i), _neg1_1i); - assert_eq!(_1_0i.mul_add(_1_0i, _1_0i), _1_0i * _1_0i + _1_0i); - assert_eq!(_1_0i * _1_0i + _1_0i, _1_0i.mul_add(_1_0i, _1_0i)); - - let mut x = _1_0i; - x.mul_add_assign(_1_0i, _1_0i); - assert_eq!(x, _1_0i * _1_0i + _1_0i); - - for &a in &all_consts { - for &b in &all_consts { - for &c in &all_consts { - let abc = a * b + c; - assert_eq!(a.mul_add(b, c), abc); - let mut x = a; - x.mul_add_assign(b, c); - assert_eq!(x, abc); - } - } - } - } - - #[test] - fn test_mul_add() { - use super::Complex; - const _0_0i: Complex = Complex { re: 0, im: 0 }; - const _1_0i: Complex = Complex { re: 1, im: 0 }; - const _1_1i: Complex = Complex { re: 1, im: 1 }; - const _0_1i: Complex = Complex { re: 0, im: 1 }; - const _neg1_1i: Complex = Complex { re: -1, im: 1 }; - const all_consts: [Complex; 5] = [_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i]; - - assert_eq!(_1_0i.mul_add(_1_0i, _0_0i), _1_0i * _1_0i + _0_0i); - assert_eq!(_1_0i * _1_0i + _0_0i, _1_0i.mul_add(_1_0i, _0_0i)); - assert_eq!(_0_1i.mul_add(_0_1i, _0_1i), _neg1_1i); - assert_eq!(_1_0i.mul_add(_1_0i, _1_0i), _1_0i * _1_0i + _1_0i); - assert_eq!(_1_0i * _1_0i + _1_0i, _1_0i.mul_add(_1_0i, _1_0i)); - - let mut x = _1_0i; - x.mul_add_assign(_1_0i, _1_0i); - assert_eq!(x, _1_0i * _1_0i + _1_0i); - - for &a in &all_consts { - for &b in &all_consts { - for &c in &all_consts { - let abc = a * b + c; - assert_eq!(a.mul_add(b, c), abc); - let mut x = a; - x.mul_add_assign(b, c); - assert_eq!(x, abc); - } - } - } - } - - #[test] - fn test_div() { - test_op!(_neg1_1i / _0_1i, _1_1i); - for &c in all_consts.iter() { - if c != Zero::zero() { - test_op!(c / c, _1_0i); - } - } - } - - #[test] - fn test_rem() { - test_op!(_neg1_1i % _0_1i, _0_0i); - test_op!(_4_2i % _0_1i, _0_0i); - test_op!(_05_05i % _0_1i, _05_05i); - test_op!(_05_05i % _1_1i, _05_05i); - assert_eq!((_4_2i + _05_05i) % _0_1i, _05_05i); - assert_eq!((_4_2i + _05_05i) % _1_1i, _05_05i); - } - - #[test] - fn test_neg() { - assert_eq!(-_1_0i + _0_1i, _neg1_1i); - assert_eq!((-_0_1i) * _0_1i, _1_0i); - for &c in all_consts.iter() { - assert_eq!(-(-c), c); - } - } - } - - mod real_arithmetic { - use super::super::Complex; - use super::{_4_2i, _neg1_1i}; - - #[test] - fn test_add() { - test_op!(_4_2i + 0.5, Complex::new(4.5, 2.0)); - assert_eq!(0.5 + _4_2i, Complex::new(4.5, 2.0)); - } - - #[test] - fn test_sub() { - test_op!(_4_2i - 0.5, Complex::new(3.5, 2.0)); - assert_eq!(0.5 - _4_2i, Complex::new(-3.5, -2.0)); - } - - #[test] - fn test_mul() { - assert_eq!(_4_2i * 0.5, Complex::new(2.0, 1.0)); - assert_eq!(0.5 * _4_2i, Complex::new(2.0, 1.0)); - } - - #[test] - fn test_div() { - assert_eq!(_4_2i / 0.5, Complex::new(8.0, 4.0)); - assert_eq!(0.5 / _4_2i, Complex::new(0.1, -0.05)); - } - - #[test] - fn test_rem() { - assert_eq!(_4_2i % 2.0, Complex::new(0.0, 0.0)); - assert_eq!(_4_2i % 3.0, Complex::new(1.0, 2.0)); - assert_eq!(3.0 % _4_2i, Complex::new(3.0, 0.0)); - assert_eq!(_neg1_1i % 2.0, _neg1_1i); - assert_eq!(-_4_2i % 3.0, Complex::new(-1.0, -2.0)); - } - - #[test] - fn test_div_rem_gaussian() { - // These would overflow with `norm_sqr` division. - let max = Complex::new(255u8, 255u8); - assert_eq!(max / 200, Complex::new(1, 1)); - assert_eq!(max % 200, Complex::new(55, 55)); - } - } - - #[test] - fn test_to_string() { - fn test(c: Complex64, s: String) { - assert_eq!(c.to_string(), s); - } - test(_0_0i, "0+0i".to_string()); - test(_1_0i, "1+0i".to_string()); - test(_0_1i, "0+1i".to_string()); - test(_1_1i, "1+1i".to_string()); - test(_neg1_1i, "-1+1i".to_string()); - test(-_neg1_1i, "1-1i".to_string()); - test(_05_05i, "0.5+0.5i".to_string()); - } - - #[test] - fn test_string_formatting() { - let a = Complex::new(1.23456, 123.456); - assert_eq!(format!("{}", a), "1.23456+123.456i"); - assert_eq!(format!("{:.2}", a), "1.23+123.46i"); - assert_eq!(format!("{:.2e}", a), "1.23e0+1.23e2i"); - assert_eq!(format!("{:+.2E}", a), "+1.23E0+1.23E2i"); - #[cfg(feature = "std")] - assert_eq!(format!("{:+20.2E}", a), " +1.23E0+1.23E2i"); - - let b = Complex::new(0x80, 0xff); - assert_eq!(format!("{:X}", b), "80+FFi"); - assert_eq!(format!("{:#x}", b), "0x80+0xffi"); - assert_eq!(format!("{:+#b}", b), "+0b10000000+0b11111111i"); - assert_eq!(format!("{:+#o}", b), "+0o200+0o377i"); - #[cfg(feature = "std")] - assert_eq!(format!("{:+#16o}", b), " +0o200+0o377i"); - - let c = Complex::new(-10, -10000); - assert_eq!(format!("{}", c), "-10-10000i"); - #[cfg(feature = "std")] - assert_eq!(format!("{:16}", c), " -10-10000i"); - } - - #[test] - fn test_hash() { - let a = Complex::new(0i32, 0i32); - let b = Complex::new(1i32, 0i32); - let c = Complex::new(0i32, 1i32); - assert!(crate::hash(&a) != crate::hash(&b)); - assert!(crate::hash(&b) != crate::hash(&c)); - assert!(crate::hash(&c) != crate::hash(&a)); - } - - #[test] - fn test_hashset() { - use std::collections::HashSet; - let a = Complex::new(0i32, 0i32); - let b = Complex::new(1i32, 0i32); - let c = Complex::new(0i32, 1i32); - - let set: HashSet<_> = [a, b, c].iter().cloned().collect(); - assert!(set.contains(&a)); - assert!(set.contains(&b)); - assert!(set.contains(&c)); - assert!(!set.contains(&(a + b + c))); - } - - #[test] - fn test_is_nan() { - assert!(!_1_1i.is_nan()); - let a = Complex::new(f64::NAN, f64::NAN); - assert!(a.is_nan()); - } - - #[test] - fn test_is_nan_special_cases() { - let a = Complex::new(0f64, f64::NAN); - let b = Complex::new(f64::NAN, 0f64); - assert!(a.is_nan()); - assert!(b.is_nan()); - } - - #[test] - fn test_is_infinite() { - let a = Complex::new(2f64, f64::INFINITY); - assert!(a.is_infinite()); - } - - #[test] - fn test_is_finite() { - assert!(_1_1i.is_finite()) - } - - #[test] - fn test_is_normal() { - let a = Complex::new(0f64, f64::NAN); - let b = Complex::new(2f64, f64::INFINITY); - assert!(!a.is_normal()); - assert!(!b.is_normal()); - assert!(_1_1i.is_normal()); - } - - #[test] - fn test_from_str() { - fn test(z: Complex64, s: &str) { - assert_eq!(FromStr::from_str(s), Ok(z)); - } - test(_0_0i, "0 + 0i"); - test(_0_0i, "0+0j"); - test(_0_0i, "0 - 0j"); - test(_0_0i, "0-0i"); - test(_0_0i, "0i + 0"); - test(_0_0i, "0"); - test(_0_0i, "-0"); - test(_0_0i, "0i"); - test(_0_0i, "0j"); - test(_0_0i, "+0j"); - test(_0_0i, "-0i"); - - test(_1_0i, "1 + 0i"); - test(_1_0i, "1+0j"); - test(_1_0i, "1 - 0j"); - test(_1_0i, "+1-0i"); - test(_1_0i, "-0j+1"); - test(_1_0i, "1"); - - test(_1_1i, "1 + i"); - test(_1_1i, "1+j"); - test(_1_1i, "1 + 1j"); - test(_1_1i, "1+1i"); - test(_1_1i, "i + 1"); - test(_1_1i, "1i+1"); - test(_1_1i, "+j+1"); - - test(_0_1i, "0 + i"); - test(_0_1i, "0+j"); - test(_0_1i, "-0 + j"); - test(_0_1i, "-0+i"); - test(_0_1i, "0 + 1i"); - test(_0_1i, "0+1j"); - test(_0_1i, "-0 + 1j"); - test(_0_1i, "-0+1i"); - test(_0_1i, "j + 0"); - test(_0_1i, "i"); - test(_0_1i, "j"); - test(_0_1i, "1j"); - - test(_neg1_1i, "-1 + i"); - test(_neg1_1i, "-1+j"); - test(_neg1_1i, "-1 + 1j"); - test(_neg1_1i, "-1+1i"); - test(_neg1_1i, "1i-1"); - test(_neg1_1i, "j + -1"); - - test(_05_05i, "0.5 + 0.5i"); - test(_05_05i, "0.5+0.5j"); - test(_05_05i, "5e-1+0.5j"); - test(_05_05i, "5E-1 + 0.5j"); - test(_05_05i, "5E-1i + 0.5"); - test(_05_05i, "0.05e+1j + 50E-2"); - } - - #[test] - fn test_from_str_radix() { - fn test(z: Complex64, s: &str, radix: u32) { - let res: Result::FromStrRadixErr> = - Num::from_str_radix(s, radix); - assert_eq!(res.unwrap(), z) - } - test(_4_2i, "4+2i", 10); - test(Complex::new(15.0, 32.0), "F+20i", 16); - test(Complex::new(15.0, 32.0), "1111+100000i", 2); - test(Complex::new(-15.0, -32.0), "-F-20i", 16); - test(Complex::new(-15.0, -32.0), "-1111-100000i", 2); - } - - #[test] - fn test_from_str_fail() { - fn test(s: &str) { - let complex: Result = FromStr::from_str(s); - assert!( - complex.is_err(), - "complex {:?} -> {:?} should be an error", - s, - complex - ); - } - test("foo"); - test("6E"); - test("0 + 2.718"); - test("1 - -2i"); - test("314e-2ij"); - test("4.3j - i"); - test("1i - 2i"); - test("+ 1 - 3.0i"); - } - - #[test] - fn test_sum() { - let v = vec![_0_1i, _1_0i]; - assert_eq!(v.iter().sum::(), _1_1i); - assert_eq!(v.into_iter().sum::(), _1_1i); - } - - #[test] - fn test_prod() { - let v = vec![_0_1i, _1_0i]; - assert_eq!(v.iter().product::(), _0_1i); - assert_eq!(v.into_iter().product::(), _0_1i); - } - - #[test] - fn test_zero() { - let zero = Complex64::zero(); - assert!(zero.is_zero()); - - let mut c = Complex::new(1.23, 4.56); - assert!(!c.is_zero()); - assert_eq!(c + zero, c); - - c.set_zero(); - assert!(c.is_zero()); - } - - #[test] - fn test_one() { - let one = Complex64::one(); - assert!(one.is_one()); - - let mut c = Complex::new(1.23, 4.56); - assert!(!c.is_one()); - assert_eq!(c * one, c); - - c.set_one(); - assert!(c.is_one()); - } - - #[test] - #[allow(clippy::float_cmp)] - fn test_const() { - const R: f64 = 12.3; - const I: f64 = -4.5; - const C: Complex64 = Complex::new(R, I); - - assert_eq!(C.re, 12.3); - assert_eq!(C.im, -4.5); - } -} diff --git a/third_party/rust/num-complex/src/pow.rs b/third_party/rust/num-complex/src/pow.rs deleted file mode 100644 index 569f01daa592..000000000000 --- a/third_party/rust/num-complex/src/pow.rs +++ /dev/null @@ -1,186 +0,0 @@ -use super::Complex; - -use core::ops::Neg; -#[cfg(any(feature = "std", feature = "libm"))] -use num_traits::Float; -use num_traits::{Num, One, Pow}; - -macro_rules! pow_impl { - ($U:ty, $S:ty) => { - impl<'a, T: Clone + Num> Pow<$U> for &'a Complex { - type Output = Complex; - - #[inline] - fn pow(self, mut exp: $U) -> Self::Output { - if exp == 0 { - return Complex::one(); - } - let mut base = self.clone(); - - while exp & 1 == 0 { - base = base.clone() * base; - exp >>= 1; - } - - if exp == 1 { - return base; - } - - let mut acc = base.clone(); - while exp > 1 { - exp >>= 1; - base = base.clone() * base; - if exp & 1 == 1 { - acc = acc * base.clone(); - } - } - acc - } - } - - impl<'a, 'b, T: Clone + Num> Pow<&'b $U> for &'a Complex { - type Output = Complex; - - #[inline] - fn pow(self, exp: &$U) -> Self::Output { - self.pow(*exp) - } - } - - impl<'a, T: Clone + Num + Neg> Pow<$S> for &'a Complex { - type Output = Complex; - - #[inline] - fn pow(self, exp: $S) -> Self::Output { - if exp < 0 { - Pow::pow(&self.inv(), exp.wrapping_neg() as $U) - } else { - Pow::pow(self, exp as $U) - } - } - } - - impl<'a, 'b, T: Clone + Num + Neg> Pow<&'b $S> for &'a Complex { - type Output = Complex; - - #[inline] - fn pow(self, exp: &$S) -> Self::Output { - self.pow(*exp) - } - } - }; -} - -pow_impl!(u8, i8); -pow_impl!(u16, i16); -pow_impl!(u32, i32); -pow_impl!(u64, i64); -pow_impl!(usize, isize); -pow_impl!(u128, i128); - -// Note: we can't add `impl Pow for Complex` because new blanket impls are a -// breaking change. Someone could already have their own `F` and `impl Pow for Complex` -// which would conflict. We can't even do this in a new semantic version, because we have to -// gate it on the "std" feature, and features can't add breaking changes either. - -macro_rules! powf_impl { - ($F:ty) => { - #[cfg(any(feature = "std", feature = "libm"))] - impl<'a, T: Float> Pow<$F> for &'a Complex - where - $F: Into, - { - type Output = Complex; - - #[inline] - fn pow(self, exp: $F) -> Self::Output { - self.powf(exp.into()) - } - } - - #[cfg(any(feature = "std", feature = "libm"))] - impl<'a, 'b, T: Float> Pow<&'b $F> for &'a Complex - where - $F: Into, - { - type Output = Complex; - - #[inline] - fn pow(self, &exp: &$F) -> Self::Output { - self.powf(exp.into()) - } - } - - #[cfg(any(feature = "std", feature = "libm"))] - impl Pow<$F> for Complex - where - $F: Into, - { - type Output = Complex; - - #[inline] - fn pow(self, exp: $F) -> Self::Output { - self.powf(exp.into()) - } - } - - #[cfg(any(feature = "std", feature = "libm"))] - impl<'b, T: Float> Pow<&'b $F> for Complex - where - $F: Into, - { - type Output = Complex; - - #[inline] - fn pow(self, &exp: &$F) -> Self::Output { - self.powf(exp.into()) - } - } - }; -} - -powf_impl!(f32); -powf_impl!(f64); - -// These blanket impls are OK, because both the target type and the trait parameter would be -// foreign to anyone else trying to implement something that would overlap, raising E0117. - -#[cfg(any(feature = "std", feature = "libm"))] -impl<'a, T: Float> Pow> for &'a Complex { - type Output = Complex; - - #[inline] - fn pow(self, exp: Complex) -> Self::Output { - self.powc(exp) - } -} - -#[cfg(any(feature = "std", feature = "libm"))] -impl<'a, 'b, T: Float> Pow<&'b Complex> for &'a Complex { - type Output = Complex; - - #[inline] - fn pow(self, &exp: &'b Complex) -> Self::Output { - self.powc(exp) - } -} - -#[cfg(any(feature = "std", feature = "libm"))] -impl Pow> for Complex { - type Output = Complex; - - #[inline] - fn pow(self, exp: Complex) -> Self::Output { - self.powc(exp) - } -} - -#[cfg(any(feature = "std", feature = "libm"))] -impl<'b, T: Float> Pow<&'b Complex> for Complex { - type Output = Complex; - - #[inline] - fn pow(self, &exp: &'b Complex) -> Self::Output { - self.powc(exp) - } -} diff --git a/third_party/rust/num-integer/.cargo-checksum.json b/third_party/rust/num-integer/.cargo-checksum.json index 135a6295d072..e8222de49dcd 100644 --- a/third_party/rust/num-integer/.cargo-checksum.json +++ b/third_party/rust/num-integer/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"df725a7c5780368b03dbe14ac170989ddd987e2e3c8a69bfb47d34025e0e06ec","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c49fdda3780903fa8c17bb5811ea3029e271e9e79a8f6c59aa3b2468eb9b203f","RELEASES.md":"756843fa25e29f642367b6b3fc161ce34a72d01ae0fb67d5531a280245d287c8","benches/average.rs":"2a30b4ccd8ece8663d17583ae2e3623e654b5f401babef90f1634722824e6c2b","benches/gcd.rs":"9b5c0ae8ccd6c7fc8f8384fb351d10cfdd0be5fbea9365f9ea925d8915b015bf","benches/roots.rs":"79b4ab2d8fe7bbf43fe65314d2e1bc206165bc4cb34b3ceaa899f9ea7af31c09","build.rs":"b4b2d0df90ca7570a339ca4d84a72e4ef00d9dced8927350424e666790c752d7","src/average.rs":"a66cf6a49f893e60697c17b2540258e69daa15ab97d8d444c6f2e8cac2f01ae9","src/lib.rs":"bf0ce9a09f92f606ca038288cde7a29670ccca480d42ec97e88f3c56b117e33c","src/roots.rs":"2a9b908bd3666b5cffc58c1b37d329e46ed02f71ad6d5deea1e8440c10660e1a","tests/average.rs":"5f26a31be042626e9af66f7b751798621561fa090da48b1ec5ab63e388288a91","tests/roots.rs":"a0caa4142899ec8cb806a7a0d3410c39d50de97cceadc4c2ceca707be91b1ddd"},"package":"8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"} \ No newline at end of file +{"files":{"Cargo.toml":"f491aec76f2252ca15a333dd3cfd18cfd91ebf841c7d607857dfa75c7080cb9a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7ad5fb625f7ef61595a2180f3b26715457552faa8bb08526c70b416da29b2533","RELEASES.md":"ebe114c148e4fc43b63c2523e13e9d903f07db139ab70f48320f9cb8c17ac9d8","benches/roots.rs":"df3554c0025d78235b5dca975b641f3bb10cae8d5ad3a79eb6cbd1a21475f133","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"16de2aa57e754fc1526d0400b5d87a3f771296705fca54601aa598b6f74ded8f","ci/rustup.sh":"2aa9e89e4af81ed9da86bdcf7cdabe512287c877248783b69eed1eccf09ad6bb","ci/test_full.sh":"fd4928a73c13905d939d009801bd448a7a9d2ca00a30260eedd1feb03fc88e11","src/lib.rs":"1e19a19aa0d414d7548e4bc9510f89bed122430564e044302edd4a21a1b83134","src/roots.rs":"51a994a5e0bf505911cf912954283f52e7aa582ce0cd1c483e6b2e4c09a47b9e","tests/roots.rs":"ef70f711cb1544311c343dbaf411ad2598432e82b6dfa3d166c1d99096991d9e"},"package":"e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"} \ No newline at end of file diff --git a/third_party/rust/num-integer/Cargo.toml b/third_party/rust/num-integer/Cargo.toml index 39d70f78905b..14400ad4951b 100644 --- a/third_party/rust/num-integer/Cargo.toml +++ b/third_party/rust/num-integer/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,10 +12,9 @@ [package] name = "num-integer" -version = "0.1.43" +version = "0.1.39" authors = ["The Rust Project Developers"] build = "build.rs" -exclude = ["/bors.toml", "/ci/*", "/.github/*"] description = "Integer traits and functions" homepage = "https://github.com/rust-num/num-integer" documentation = "https://docs.rs/num-integer" @@ -27,10 +26,8 @@ repository = "https://github.com/rust-num/num-integer" [package.metadata.docs.rs] features = ["std"] [dependencies.num-traits] -version = "0.2.11" +version = "0.2.4" default-features = false -[build-dependencies.autocfg] -version = "1" [features] default = ["std"] diff --git a/third_party/rust/num-integer/README.md b/third_party/rust/num-integer/README.md index 249d5f046170..4b3d42e7218d 100644 --- a/third_party/rust/num-integer/README.md +++ b/third_party/rust/num-integer/README.md @@ -2,8 +2,8 @@ [![crate](https://img.shields.io/crates/v/num-integer.svg)](https://crates.io/crates/num-integer) [![documentation](https://docs.rs/num-integer/badge.svg)](https://docs.rs/num-integer) -[![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num-integer/workflows/master/badge.svg)](https://github.com/rust-num/num-integer/actions) +![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg) +[![Travis status](https://travis-ci.org/rust-num/num-integer.svg?branch=master)](https://travis-ci.org/rust-num/num-integer) `Integer` trait and functions for Rust. diff --git a/third_party/rust/num-integer/RELEASES.md b/third_party/rust/num-integer/RELEASES.md index 727369661e58..b20dbcbf1b58 100644 --- a/third_party/rust/num-integer/RELEASES.md +++ b/third_party/rust/num-integer/RELEASES.md @@ -1,43 +1,4 @@ -# Release 0.1.43 (2020-06-11) - -- [The new `Average` trait][31] computes fast integer averages, rounded up or - down, without any risk of overflow. - -**Contributors**: @althonos, @cuviper - -[31]: https://github.com/rust-num/num-integer/pull/31 - -# Release 0.1.42 (2020-01-09) - -- [Updated the `autocfg` build dependency to 1.0][29]. - -**Contributors**: @cuviper, @dingelish - -[29]: https://github.com/rust-num/num-integer/pull/29 - -# Release 0.1.41 (2019-05-21) - -- [Fixed feature detection on `no_std` targets][25]. - -**Contributors**: @cuviper - -[25]: https://github.com/rust-num/num-integer/pull/25 - -# Release 0.1.40 (2019-05-20) - -- [Optimized primitive `gcd` by avoiding memory swaps][11]. -- [Fixed `lcm(0, 0)` to return `0`, rather than panicking][18]. -- [Added `Integer::div_ceil`, `next_multiple_of`, and `prev_multiple_of`][16]. -- [Added `Integer::gcd_lcm`, `extended_gcd`, and `extended_gcd_lcm`][19]. - -**Contributors**: @cuviper, @ignatenkobrain, @smarnach, @strake - -[11]: https://github.com/rust-num/num-integer/pull/11 -[16]: https://github.com/rust-num/num-integer/pull/16 -[18]: https://github.com/rust-num/num-integer/pull/18 -[19]: https://github.com/rust-num/num-integer/pull/19 - -# Release 0.1.39 (2018-06-20) +# Release 0.1.39 - [The new `Roots` trait provides `sqrt`, `cbrt`, and `nth_root` methods][9], calculating an `Integer`'s principal roots rounded toward zero. @@ -46,7 +7,7 @@ [9]: https://github.com/rust-num/num-integer/pull/9 -# Release 0.1.38 (2018-05-11) +# Release 0.1.38 - [Support for 128-bit integers is now automatically detected and enabled.][8] Setting the `i128` crate feature now causes the build script to panic if such @@ -56,7 +17,7 @@ [8]: https://github.com/rust-num/num-integer/pull/8 -# Release 0.1.37 (2018-05-10) +# Release 0.1.37 - [`Integer` is now implemented for `i128` and `u128`][7] starting with Rust 1.26, enabled by the new `i128` crate feature. @@ -65,7 +26,7 @@ [7]: https://github.com/rust-num/num-integer/pull/7 -# Release 0.1.36 (2018-02-06) +# Release 0.1.36 - [num-integer now has its own source repository][num-356] at [rust-num/num-integer][home]. - [Corrected the argument order documented in `Integer::is_multiple_of`][1] diff --git a/third_party/rust/num-integer/benches/average.rs b/third_party/rust/num-integer/benches/average.rs deleted file mode 100644 index 05d824c840ec..000000000000 --- a/third_party/rust/num-integer/benches/average.rs +++ /dev/null @@ -1,414 +0,0 @@ -//! Benchmark sqrt and cbrt - -#![feature(test)] - -extern crate num_integer; -extern crate num_traits; -extern crate test; - -use num_integer::Integer; -use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul}; -use std::cmp::{max, min}; -use std::fmt::Debug; -use test::{black_box, Bencher}; - -// --- Utilities for RNG ---------------------------------------------------- - -trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {} - -impl BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {} - -// Simple PRNG so we don't have to worry about rand compatibility -fn lcg(x: T) -> T -where - u32: AsPrimitive, - T: BenchInteger, -{ - // LCG parameters from Numerical Recipes - // (but we're applying it to arbitrary sizes) - const LCG_A: u32 = 1664525; - const LCG_C: u32 = 1013904223; - x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_()) -} - -// --- Alt. Implementations ------------------------------------------------- - -trait NaiveAverage { - fn naive_average_ceil(&self, other: &Self) -> Self; - fn naive_average_floor(&self, other: &Self) -> Self; -} - -trait UncheckedAverage { - fn unchecked_average_ceil(&self, other: &Self) -> Self; - fn unchecked_average_floor(&self, other: &Self) -> Self; -} - -trait ModuloAverage { - fn modulo_average_ceil(&self, other: &Self) -> Self; - fn modulo_average_floor(&self, other: &Self) -> Self; -} - -macro_rules! naive_average { - ($T:ident) => { - impl super::NaiveAverage for $T { - fn naive_average_floor(&self, other: &$T) -> $T { - match self.checked_add(*other) { - Some(z) => z.div_floor(&2), - None => { - if self > other { - let diff = self - other; - other + diff.div_floor(&2) - } else { - let diff = other - self; - self + diff.div_floor(&2) - } - } - } - } - fn naive_average_ceil(&self, other: &$T) -> $T { - match self.checked_add(*other) { - Some(z) => z.div_ceil(&2), - None => { - if self > other { - let diff = self - other; - self - diff.div_floor(&2) - } else { - let diff = other - self; - other - diff.div_floor(&2) - } - } - } - } - } - }; -} - -macro_rules! unchecked_average { - ($T:ident) => { - impl super::UncheckedAverage for $T { - fn unchecked_average_floor(&self, other: &$T) -> $T { - self.wrapping_add(*other) / 2 - } - fn unchecked_average_ceil(&self, other: &$T) -> $T { - (self.wrapping_add(*other) / 2).wrapping_add(1) - } - } - }; -} - -macro_rules! modulo_average { - ($T:ident) => { - impl super::ModuloAverage for $T { - fn modulo_average_ceil(&self, other: &$T) -> $T { - let (q1, r1) = self.div_mod_floor(&2); - let (q2, r2) = other.div_mod_floor(&2); - q1 + q2 + (r1 | r2) - } - fn modulo_average_floor(&self, other: &$T) -> $T { - let (q1, r1) = self.div_mod_floor(&2); - let (q2, r2) = other.div_mod_floor(&2); - q1 + q2 + (r1 * r2) - } - } - }; -} - -// --- Bench functions ------------------------------------------------------ - -fn bench_unchecked(b: &mut Bencher, v: &[(T, T)], f: F) -where - T: Integer + Debug + Copy, - F: Fn(&T, &T) -> T, -{ - b.iter(|| { - for (x, y) in v { - black_box(f(x, y)); - } - }); -} - -fn bench_ceil(b: &mut Bencher, v: &[(T, T)], f: F) -where - T: Integer + Debug + Copy, - F: Fn(&T, &T) -> T, -{ - for &(i, j) in v { - let rt = f(&i, &j); - let (a, b) = (min(i, j), max(i, j)); - // if both number are the same sign, check rt is in the middle - if (a < T::zero()) == (b < T::zero()) { - if (b - a).is_even() { - assert_eq!(rt - a, b - rt); - } else { - assert_eq!(rt - a, b - rt + T::one()); - } - // if both number have a different sign, - } else { - if (a + b).is_even() { - assert_eq!(rt, (a + b) / (T::one() + T::one())) - } else { - assert_eq!(rt, (a + b + T::one()) / (T::one() + T::one())) - } - } - } - bench_unchecked(b, v, f); -} - -fn bench_floor(b: &mut Bencher, v: &[(T, T)], f: F) -where - T: Integer + Debug + Copy, - F: Fn(&T, &T) -> T, -{ - for &(i, j) in v { - let rt = f(&i, &j); - let (a, b) = (min(i, j), max(i, j)); - // if both number are the same sign, check rt is in the middle - if (a < T::zero()) == (b < T::zero()) { - if (b - a).is_even() { - assert_eq!(rt - a, b - rt); - } else { - assert_eq!(rt - a + T::one(), b - rt); - } - // if both number have a different sign, - } else { - if (a + b).is_even() { - assert_eq!(rt, (a + b) / (T::one() + T::one())) - } else { - assert_eq!(rt, (a + b - T::one()) / (T::one() + T::one())) - } - } - } - bench_unchecked(b, v, f); -} - -// --- Bench implementation ------------------------------------------------- - -macro_rules! bench_average { - ($($T:ident),*) => {$( - mod $T { - use test::Bencher; - use num_integer::{Average, Integer}; - use super::{UncheckedAverage, NaiveAverage, ModuloAverage}; - use super::{bench_ceil, bench_floor, bench_unchecked}; - - naive_average!($T); - unchecked_average!($T); - modulo_average!($T); - - const SIZE: $T = 30; - - fn overflowing() -> Vec<($T, $T)> { - (($T::max_value()-SIZE)..$T::max_value()) - .flat_map(|x| -> Vec<_> { - (($T::max_value()-100)..($T::max_value()-100+SIZE)) - .map(|y| (x, y)) - .collect() - }) - .collect() - } - - fn small() -> Vec<($T, $T)> { - (0..SIZE) - .flat_map(|x| -> Vec<_> {(0..SIZE).map(|y| (x, y)).collect()}) - .collect() - } - - fn rand() -> Vec<($T, $T)> { - small() - .into_iter() - .map(|(x, y)| (super::lcg(x), super::lcg(y))) - .collect() - } - - mod ceil { - - use super::*; - - mod small { - - use super::*; - - #[bench] - fn optimized(b: &mut Bencher) { - let v = small(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.average_ceil(y)); - } - - #[bench] - fn naive(b: &mut Bencher) { - let v = small(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.naive_average_ceil(y)); - } - - #[bench] - fn unchecked(b: &mut Bencher) { - let v = small(); - bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_ceil(y)); - } - - #[bench] - fn modulo(b: &mut Bencher) { - let v = small(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.modulo_average_ceil(y)); - } - } - - mod overflowing { - - use super::*; - - #[bench] - fn optimized(b: &mut Bencher) { - let v = overflowing(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.average_ceil(y)); - } - - #[bench] - fn naive(b: &mut Bencher) { - let v = overflowing(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.naive_average_ceil(y)); - } - - #[bench] - fn unchecked(b: &mut Bencher) { - let v = overflowing(); - bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_ceil(y)); - } - - #[bench] - fn modulo(b: &mut Bencher) { - let v = overflowing(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.modulo_average_ceil(y)); - } - } - - mod rand { - - use super::*; - - #[bench] - fn optimized(b: &mut Bencher) { - let v = rand(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.average_ceil(y)); - } - - #[bench] - fn naive(b: &mut Bencher) { - let v = rand(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.naive_average_ceil(y)); - } - - #[bench] - fn unchecked(b: &mut Bencher) { - let v = rand(); - bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_ceil(y)); - } - - #[bench] - fn modulo(b: &mut Bencher) { - let v = rand(); - bench_ceil(b, &v, |x: &$T, y: &$T| x.modulo_average_ceil(y)); - } - } - - } - - mod floor { - - use super::*; - - mod small { - - use super::*; - - #[bench] - fn optimized(b: &mut Bencher) { - let v = small(); - bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y)); - } - - #[bench] - fn naive(b: &mut Bencher) { - let v = small(); - bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y)); - } - - #[bench] - fn unchecked(b: &mut Bencher) { - let v = small(); - bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y)); - } - - #[bench] - fn modulo(b: &mut Bencher) { - let v = small(); - bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y)); - } - } - - mod overflowing { - - use super::*; - - #[bench] - fn optimized(b: &mut Bencher) { - let v = overflowing(); - bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y)); - } - - #[bench] - fn naive(b: &mut Bencher) { - let v = overflowing(); - bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y)); - } - - #[bench] - fn unchecked(b: &mut Bencher) { - let v = overflowing(); - bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y)); - } - - #[bench] - fn modulo(b: &mut Bencher) { - let v = overflowing(); - bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y)); - } - } - - mod rand { - - use super::*; - - #[bench] - fn optimized(b: &mut Bencher) { - let v = rand(); - bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y)); - } - - #[bench] - fn naive(b: &mut Bencher) { - let v = rand(); - bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y)); - } - - #[bench] - fn unchecked(b: &mut Bencher) { - let v = rand(); - bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y)); - } - - #[bench] - fn modulo(b: &mut Bencher) { - let v = rand(); - bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y)); - } - } - - } - - } - )*} -} - -bench_average!(i8, i16, i32, i64, i128, isize); -bench_average!(u8, u16, u32, u64, u128, usize); diff --git a/third_party/rust/num-integer/benches/gcd.rs b/third_party/rust/num-integer/benches/gcd.rs deleted file mode 100644 index 082d5ee09d7b..000000000000 --- a/third_party/rust/num-integer/benches/gcd.rs +++ /dev/null @@ -1,176 +0,0 @@ -//! Benchmark comparing the current GCD implemtation against an older one. - -#![feature(test)] - -extern crate num_integer; -extern crate num_traits; -extern crate test; - -use num_integer::Integer; -use num_traits::{AsPrimitive, Bounded, Signed}; -use test::{black_box, Bencher}; - -trait GcdOld: Integer { - fn gcd_old(&self, other: &Self) -> Self; -} - -macro_rules! impl_gcd_old_for_isize { - ($T:ty) => { - impl GcdOld for $T { - /// Calculates the Greatest Common Divisor (GCD) of the number and - /// `other`. The result is always positive. - #[inline] - fn gcd_old(&self, other: &Self) -> Self { - // Use Stein's algorithm - let mut m = *self; - let mut n = *other; - if m == 0 || n == 0 { - return (m | n).abs(); - } - - // find common factors of 2 - let shift = (m | n).trailing_zeros(); - - // The algorithm needs positive numbers, but the minimum value - // can't be represented as a positive one. - // It's also a power of two, so the gcd can be - // calculated by bitshifting in that case - - // Assuming two's complement, the number created by the shift - // is positive for all numbers except gcd = abs(min value) - // The call to .abs() causes a panic in debug mode - if m == Self::min_value() || n == Self::min_value() { - return (1 << shift).abs(); - } - - // guaranteed to be positive now, rest like unsigned algorithm - m = m.abs(); - n = n.abs(); - - // divide n and m by 2 until odd - // m inside loop - n >>= n.trailing_zeros(); - - while m != 0 { - m >>= m.trailing_zeros(); - if n > m { - std::mem::swap(&mut n, &mut m) - } - m -= n; - } - - n << shift - } - } - }; -} - -impl_gcd_old_for_isize!(i8); -impl_gcd_old_for_isize!(i16); -impl_gcd_old_for_isize!(i32); -impl_gcd_old_for_isize!(i64); -impl_gcd_old_for_isize!(isize); -impl_gcd_old_for_isize!(i128); - -macro_rules! impl_gcd_old_for_usize { - ($T:ty) => { - impl GcdOld for $T { - /// Calculates the Greatest Common Divisor (GCD) of the number and - /// `other`. The result is always positive. - #[inline] - fn gcd_old(&self, other: &Self) -> Self { - // Use Stein's algorithm - let mut m = *self; - let mut n = *other; - if m == 0 || n == 0 { - return m | n; - } - - // find common factors of 2 - let shift = (m | n).trailing_zeros(); - - // divide n and m by 2 until odd - // m inside loop - n >>= n.trailing_zeros(); - - while m != 0 { - m >>= m.trailing_zeros(); - if n > m { - std::mem::swap(&mut n, &mut m) - } - m -= n; - } - - n << shift - } - } - }; -} - -impl_gcd_old_for_usize!(u8); -impl_gcd_old_for_usize!(u16); -impl_gcd_old_for_usize!(u32); -impl_gcd_old_for_usize!(u64); -impl_gcd_old_for_usize!(usize); -impl_gcd_old_for_usize!(u128); - -/// Return an iterator that yields all Fibonacci numbers fitting into a u128. -fn fibonacci() -> impl Iterator { - (0..185).scan((0, 1), |&mut (ref mut a, ref mut b), _| { - let tmp = *a; - *a = *b; - *b += tmp; - Some(*b) - }) -} - -fn run_bench(b: &mut Bencher, gcd: fn(&T, &T) -> T) -where - T: AsPrimitive, - u128: AsPrimitive, -{ - let max_value: u128 = T::max_value().as_(); - let pairs: Vec<(T, T)> = fibonacci() - .collect::>() - .windows(2) - .filter(|&pair| pair[0] <= max_value && pair[1] <= max_value) - .map(|pair| (pair[0].as_(), pair[1].as_())) - .collect(); - b.iter(|| { - for &(ref m, ref n) in &pairs { - black_box(gcd(m, n)); - } - }); -} - -macro_rules! bench_gcd { - ($T:ident) => { - mod $T { - use crate::{run_bench, GcdOld}; - use num_integer::Integer; - use test::Bencher; - - #[bench] - fn bench_gcd(b: &mut Bencher) { - run_bench(b, $T::gcd); - } - - #[bench] - fn bench_gcd_old(b: &mut Bencher) { - run_bench(b, $T::gcd_old); - } - } - }; -} - -bench_gcd!(u8); -bench_gcd!(u16); -bench_gcd!(u32); -bench_gcd!(u64); -bench_gcd!(u128); - -bench_gcd!(i8); -bench_gcd!(i16); -bench_gcd!(i32); -bench_gcd!(i64); -bench_gcd!(i128); diff --git a/third_party/rust/num-integer/benches/roots.rs b/third_party/rust/num-integer/benches/roots.rs index 7f672786a572..3ca801581577 100644 --- a/third_party/rust/num-integer/benches/roots.rs +++ b/third_party/rust/num-integer/benches/roots.rs @@ -13,7 +13,11 @@ use test::{black_box, Bencher}; trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {} -impl BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {} +impl BenchInteger for T +where + T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static, +{ +} fn bench(b: &mut Bencher, v: &[T], f: F, n: u32) where diff --git a/third_party/rust/num-rational-0.2.1/bors.toml b/third_party/rust/num-integer/bors.toml similarity index 100% rename from third_party/rust/num-rational-0.2.1/bors.toml rename to third_party/rust/num-integer/bors.toml diff --git a/third_party/rust/num-integer/build.rs b/third_party/rust/num-integer/build.rs index e483c15fd7f6..fd60866558c3 100644 --- a/third_party/rust/num-integer/build.rs +++ b/third_party/rust/num-integer/build.rs @@ -1,14 +1,35 @@ -extern crate autocfg; - use std::env; +use std::io::Write; +use std::process::{Command, Stdio}; fn main() { - let ac = autocfg::new(); - if ac.probe_type("i128") { + if probe("fn main() { 0i128; }") { println!("cargo:rustc-cfg=has_i128"); } else if env::var_os("CARGO_FEATURE_I128").is_some() { panic!("i128 support was not detected!"); } - - autocfg::rerun_path("build.rs"); +} + +/// Test if a code snippet can be compiled +fn probe(code: &str) -> bool { + let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); + let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR"); + + let mut child = Command::new(rustc) + .arg("--out-dir") + .arg(out_dir) + .arg("--emit=obj") + .arg("-") + .stdin(Stdio::piped()) + .spawn() + .expect("rustc probe"); + + child + .stdin + .as_mut() + .expect("rustc stdin") + .write_all(code.as_bytes()) + .expect("write rustc stdin"); + + child.wait().expect("rustc probe").success() } diff --git a/third_party/rust/num-integer/ci/rustup.sh b/third_party/rust/num-integer/ci/rustup.sh new file mode 100755 index 000000000000..e82ece76d7a6 --- /dev/null +++ b/third_party/rust/num-integer/ci/rustup.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Use rustup to locally run the same suite of tests as .travis.yml. +# (You should first install/update 1.8.0, stable, beta, and nightly.) + +set -ex + +export TRAVIS_RUST_VERSION +for TRAVIS_RUST_VERSION in 1.8.0 1.15.0 1.20.0 stable beta nightly; do + run="rustup run $TRAVIS_RUST_VERSION" + $run cargo build --verbose + $run $PWD/ci/test_full.sh +done diff --git a/third_party/rust/num-integer/ci/test_full.sh b/third_party/rust/num-integer/ci/test_full.sh new file mode 100755 index 000000000000..e7c2549e8da0 --- /dev/null +++ b/third_party/rust/num-integer/ci/test_full.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -ex + +echo Testing num-integer on rustc ${TRAVIS_RUST_VERSION} + +# num-integer should build and test everywhere. +cargo build --verbose +cargo test --verbose + +# test `no_std` +cargo build --verbose --no-default-features +cargo test --verbose --no-default-features + +# test `i128` +if [[ "$TRAVIS_RUST_VERSION" =~ ^(nightly|beta|stable)$ ]]; then + cargo build --verbose --features=i128 + cargo test --verbose --features=i128 +fi + +if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then + cargo test --verbose --all-features --benches +fi diff --git a/third_party/rust/num-integer/src/average.rs b/third_party/rust/num-integer/src/average.rs deleted file mode 100644 index 29cd11e3fec6..000000000000 --- a/third_party/rust/num-integer/src/average.rs +++ /dev/null @@ -1,78 +0,0 @@ -use core::ops::{BitAnd, BitOr, BitXor, Shr}; -use Integer; - -/// Provides methods to compute the average of two integers, without overflows. -pub trait Average: Integer { - /// Returns the ceiling value of the average of `self` and `other`. - /// -- `⌈(self + other)/2⌉` - /// - /// # Examples - /// - /// ``` - /// use num_integer::Average; - /// - /// assert_eq!(( 3).average_ceil(&10), 7); - /// assert_eq!((-2).average_ceil(&-5), -3); - /// assert_eq!(( 4).average_ceil(& 4), 4); - /// - /// assert_eq!(u8::max_value().average_ceil(&2), 129); - /// assert_eq!(i8::min_value().average_ceil(&-1), -64); - /// assert_eq!(i8::min_value().average_ceil(&i8::max_value()), 0); - /// ``` - /// - fn average_ceil(&self, other: &Self) -> Self; - - /// Returns the floor value of the average of `self` and `other`. - /// -- `⌊(self + other)/2⌋` - /// - /// # Examples - /// - /// ``` - /// use num_integer::Average; - /// - /// assert_eq!(( 3).average_floor(&10), 6); - /// assert_eq!((-2).average_floor(&-5), -4); - /// assert_eq!(( 4).average_floor(& 4), 4); - /// - /// assert_eq!(u8::max_value().average_floor(&2), 128); - /// assert_eq!(i8::min_value().average_floor(&-1), -65); - /// assert_eq!(i8::min_value().average_floor(&i8::max_value()), -1); - /// ``` - /// - fn average_floor(&self, other: &Self) -> Self; -} - -impl Average for I -where - I: Integer + Shr, - for<'a, 'b> &'a I: - BitAnd<&'b I, Output = I> + BitOr<&'b I, Output = I> + BitXor<&'b I, Output = I>, -{ - // The Henry Gordon Dietz implementation as shown in the Hacker's Delight, - // see http://aggregate.org/MAGIC/#Average%20of%20Integers - - /// Returns the floor value of the average of `self` and `other`. - #[inline] - fn average_floor(&self, other: &I) -> I { - (self & other) + ((self ^ other) >> 1) - } - - /// Returns the ceil value of the average of `self` and `other`. - #[inline] - fn average_ceil(&self, other: &I) -> I { - (self | other) - ((self ^ other) >> 1) - } -} - -/// Returns the floor value of the average of `x` and `y` -- -/// see [Average::average_floor](trait.Average.html#tymethod.average_floor). -#[inline] -pub fn average_floor(x: T, y: T) -> T { - x.average_floor(&y) -} -/// Returns the ceiling value of the average of `x` and `y` -- -/// see [Average::average_ceil](trait.Average.html#tymethod.average_ceil). -#[inline] -pub fn average_ceil(x: T, y: T) -> T { - x.average_ceil(&y) -} diff --git a/third_party/rust/num-integer/src/lib.rs b/third_party/rust/num-integer/src/lib.rs index 02819541b958..57f4c855d035 100644 --- a/third_party/rust/num-integer/src/lib.rs +++ b/third_party/rust/num-integer/src/lib.rs @@ -15,24 +15,21 @@ //! The `num-integer` crate is tested for rustc 1.8 and greater. #![doc(html_root_url = "https://docs.rs/num-integer/0.1")] + #![no_std] #[cfg(feature = "std")] extern crate std; extern crate num_traits as traits; -use core::mem; use core::ops::Add; +use core::mem; -use traits::{Num, Signed, Zero}; +use traits::{Num, Signed}; mod roots; pub use roots::Roots; -pub use roots::{cbrt, nth_root, sqrt}; - -mod average; -pub use average::Average; -pub use average::{average_ceil, average_floor}; +pub use roots::{sqrt, cbrt, nth_root}; pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// Floored integer division. @@ -77,31 +74,6 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// ~~~ fn mod_floor(&self, other: &Self) -> Self; - /// Ceiled integer division. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(( 8).div_ceil( &3), 3); - /// assert_eq!(( 8).div_ceil(&-3), -2); - /// assert_eq!((-8).div_ceil( &3), -2); - /// assert_eq!((-8).div_ceil(&-3), 3); - /// - /// assert_eq!(( 1).div_ceil( &2), 1); - /// assert_eq!(( 1).div_ceil(&-2), 0); - /// assert_eq!((-1).div_ceil( &2), 0); - /// assert_eq!((-1).div_ceil(&-2), 1); - /// ~~~ - fn div_ceil(&self, other: &Self) -> Self { - let (q, r) = self.div_mod_floor(other); - if r.is_zero() { - q - } else { - q + Self::one() - } - } - /// Greatest Common Divisor (GCD). /// /// # Examples @@ -121,93 +93,9 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// # use num_integer::Integer; /// assert_eq!(7.lcm(&3), 21); /// assert_eq!(2.lcm(&4), 4); - /// assert_eq!(0.lcm(&0), 0); /// ~~~ fn lcm(&self, other: &Self) -> Self; - /// Greatest Common Divisor (GCD) and - /// Lowest Common Multiple (LCM) together. - /// - /// Potentially more efficient than calling `gcd` and `lcm` - /// individually for identical inputs. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(10.gcd_lcm(&4), (2, 20)); - /// assert_eq!(8.gcd_lcm(&9), (1, 72)); - /// ~~~ - #[inline] - fn gcd_lcm(&self, other: &Self) -> (Self, Self) { - (self.gcd(other), self.lcm(other)) - } - - /// Greatest common divisor and Bézout coefficients. - /// - /// # Examples - /// - /// ~~~ - /// # extern crate num_integer; - /// # extern crate num_traits; - /// # fn main() { - /// # use num_integer::{ExtendedGcd, Integer}; - /// # use num_traits::NumAssign; - /// fn check(a: A, b: A) -> bool { - /// let ExtendedGcd { gcd, x, y, .. } = a.extended_gcd(&b); - /// gcd == x * a + y * b - /// } - /// assert!(check(10isize, 4isize)); - /// assert!(check(8isize, 9isize)); - /// # } - /// ~~~ - #[inline] - fn extended_gcd(&self, other: &Self) -> ExtendedGcd - where - Self: Clone, - { - let mut s = (Self::zero(), Self::one()); - let mut t = (Self::one(), Self::zero()); - let mut r = (other.clone(), self.clone()); - - while !r.0.is_zero() { - let q = r.1.clone() / r.0.clone(); - let f = |mut r: (Self, Self)| { - mem::swap(&mut r.0, &mut r.1); - r.0 = r.0 - q.clone() * r.1.clone(); - r - }; - r = f(r); - s = f(s); - t = f(t); - } - - if r.1 >= Self::zero() { - ExtendedGcd { - gcd: r.1, - x: s.1, - y: t.1, - _hidden: (), - } - } else { - ExtendedGcd { - gcd: Self::zero() - r.1, - x: Self::zero() - s.1, - y: Self::zero() - t.1, - _hidden: (), - } - } - } - - /// Greatest common divisor, least common multiple, and Bézout coefficients. - #[inline] - fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) - where - Self: Clone + Signed, - { - (self.extended_gcd(other), self.lcm(other)) - } - /// Deprecated, use `is_multiple_of` instead. fn divides(&self, other: &Self) -> bool; @@ -261,6 +149,7 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// assert_eq!((-1).div_rem( &2), ( 0, -1)); /// assert_eq!((-1).div_rem(&-2), ( 0, -1)); /// ~~~ + #[inline] fn div_rem(&self, other: &Self) -> (Self, Self); /// Simultaneous floored integer division and modulus. @@ -283,80 +172,6 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { fn div_mod_floor(&self, other: &Self) -> (Self, Self) { (self.div_floor(other), self.mod_floor(other)) } - - /// Rounds up to nearest multiple of argument. - /// - /// # Notes - /// - /// For signed types, `a.next_multiple_of(b) = a.prev_multiple_of(b.neg())`. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(( 16).next_multiple_of(& 8), 16); - /// assert_eq!(( 23).next_multiple_of(& 8), 24); - /// assert_eq!(( 16).next_multiple_of(&-8), 16); - /// assert_eq!(( 23).next_multiple_of(&-8), 16); - /// assert_eq!((-16).next_multiple_of(& 8), -16); - /// assert_eq!((-23).next_multiple_of(& 8), -16); - /// assert_eq!((-16).next_multiple_of(&-8), -16); - /// assert_eq!((-23).next_multiple_of(&-8), -24); - /// ~~~ - #[inline] - fn next_multiple_of(&self, other: &Self) -> Self - where - Self: Clone, - { - let m = self.mod_floor(other); - self.clone() - + if m.is_zero() { - Self::zero() - } else { - other.clone() - m - } - } - - /// Rounds down to nearest multiple of argument. - /// - /// # Notes - /// - /// For signed types, `a.prev_multiple_of(b) = a.next_multiple_of(b.neg())`. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(( 16).prev_multiple_of(& 8), 16); - /// assert_eq!(( 23).prev_multiple_of(& 8), 16); - /// assert_eq!(( 16).prev_multiple_of(&-8), 16); - /// assert_eq!(( 23).prev_multiple_of(&-8), 24); - /// assert_eq!((-16).prev_multiple_of(& 8), -16); - /// assert_eq!((-23).prev_multiple_of(& 8), -24); - /// assert_eq!((-16).prev_multiple_of(&-8), -16); - /// assert_eq!((-23).prev_multiple_of(&-8), -16); - /// ~~~ - #[inline] - fn prev_multiple_of(&self, other: &Self) -> Self - where - Self: Clone, - { - self.clone() - self.mod_floor(other) - } -} - -/// Greatest common divisor and Bézout coefficients -/// -/// ```no_build -/// let e = isize::extended_gcd(a, b); -/// assert_eq!(e.gcd, e.x*a + e.y*b); -/// ``` -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct ExtendedGcd { - pub gcd: A, - pub x: A, - pub y: A, - _hidden: (), } /// Simultaneous integer division and modulus @@ -379,11 +194,6 @@ pub fn mod_floor(x: T, y: T) -> T { pub fn div_mod_floor(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) } -/// Ceiled integer division -#[inline] -pub fn div_ceil(x: T, y: T) -> T { - x.div_ceil(&y) -} /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The /// result is always positive. @@ -397,26 +207,18 @@ pub fn lcm(x: T, y: T) -> T { x.lcm(&y) } -/// Calculates the Greatest Common Divisor (GCD) and -/// Lowest Common Multiple (LCM) of the number and `other`. -#[inline(always)] -pub fn gcd_lcm(x: T, y: T) -> (T, T) { - x.gcd_lcm(&y) -} - macro_rules! impl_integer_for_isize { - ($T:ty, $test_mod:ident) => { + ($T:ty, $test_mod:ident) => ( impl Integer for $T { /// Floored integer division #[inline] fn div_floor(&self, other: &Self) -> Self { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - let (d, r) = self.div_rem(other); - if (r > 0 && *other < 0) || (r < 0 && *other > 0) { - d - 1 - } else { - d + match self.div_rem(other) { + (d, r) if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => d - 1, + (d, _) => d, } } @@ -425,11 +227,10 @@ macro_rules! impl_integer_for_isize { fn mod_floor(&self, other: &Self) -> Self { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - let r = *self % *other; - if (r > 0 && *other < 0) || (r < 0 && *other > 0) { - r + *other - } else { - r + match *self % *other { + r if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => r + *other, + r => r, } } @@ -438,21 +239,10 @@ macro_rules! impl_integer_for_isize { fn div_mod_floor(&self, other: &Self) -> (Self, Self) { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - let (d, r) = self.div_rem(other); - if (r > 0 && *other < 0) || (r < 0 && *other > 0) { - (d - 1, r + *other) - } else { - (d, r) - } - } - - #[inline] - fn div_ceil(&self, other: &Self) -> Self { - let (d, r) = self.div_rem(other); - if (r > 0 && *other > 0) || (r < 0 && *other < 0) { - d + 1 - } else { - d + match self.div_rem(other) { + (d, r) if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => (d - 1, r + *other), + (d, r) => (d, r), } } @@ -463,9 +253,7 @@ macro_rules! impl_integer_for_isize { // Use Stein's algorithm let mut m = *self; let mut n = *other; - if m == 0 || n == 0 { - return (m | n).abs(); - } + if m == 0 || n == 0 { return (m | n).abs() } // find common factors of 2 let shift = (m | n).trailing_zeros(); @@ -479,7 +267,7 @@ macro_rules! impl_integer_for_isize { // is positive for all numbers except gcd = abs(min value) // The call to .abs() causes a panic in debug mode if m == Self::min_value() || n == Self::min_value() { - return (1 << shift).abs(); + return (1 << shift).abs() } // guaranteed to be positive now, rest like unsigned algorithm @@ -487,51 +275,24 @@ macro_rules! impl_integer_for_isize { n = n.abs(); // divide n and m by 2 until odd - m >>= m.trailing_zeros(); + // m inside loop n >>= n.trailing_zeros(); - while m != n { - if m > n { - m -= n; - m >>= m.trailing_zeros(); - } else { - n -= m; - n >>= n.trailing_zeros(); - } + while m != 0 { + m >>= m.trailing_zeros(); + if n > m { mem::swap(&mut n, &mut m) } + m -= n; } - m << shift - } - #[inline] - fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) { - let egcd = self.extended_gcd(other); - // should not have to recalculate abs - let lcm = if egcd.gcd.is_zero() { - Self::zero() - } else { - (*self * (*other / egcd.gcd)).abs() - }; - (egcd, lcm) + n << shift } /// Calculates the Lowest Common Multiple (LCM) of the number and /// `other`. #[inline] fn lcm(&self, other: &Self) -> Self { - self.gcd_lcm(other).1 - } - - /// Calculates the Greatest Common Divisor (GCD) and - /// Lowest Common Multiple (LCM) of the number and `other`. - #[inline] - fn gcd_lcm(&self, other: &Self) -> (Self, Self) { - if self.is_zero() && other.is_zero() { - return (Self::zero(), Self::zero()); - } - let gcd = self.gcd(other); // should not have to recalculate abs - let lcm = (*self * (*other / gcd)).abs(); - (gcd, lcm) + (*self * (*other / self.gcd(other))).abs() } /// Deprecated, use `is_multiple_of` instead. @@ -548,15 +309,11 @@ macro_rules! impl_integer_for_isize { /// Returns `true` if the number is divisible by `2` #[inline] - fn is_even(&self) -> bool { - (*self) & 1 == 0 - } + fn is_even(&self) -> bool { (*self) & 1 == 0 } /// Returns `true` if the number is not divisible by `2` #[inline] - fn is_odd(&self) -> bool { - !self.is_even() - } + fn is_odd(&self) -> bool { !self.is_even() } /// Simultaneous truncated integer division and modulus. #[inline] @@ -567,8 +324,8 @@ macro_rules! impl_integer_for_isize { #[cfg(test)] mod $test_mod { - use core::mem; use Integer; + use core::mem; /// Checks that the division rule holds for: /// @@ -576,14 +333,14 @@ macro_rules! impl_integer_for_isize { /// - `d`: denominator (divisor) /// - `qr`: quotient and remainder #[cfg(test)] - fn test_division_rule((n, d): ($T, $T), (q, r): ($T, $T)) { + fn test_division_rule((n,d): ($T, $T), (q,r): ($T, $T)) { assert_eq!(d * q + r, n); } #[test] fn test_div_rem() { - fn test_nd_dr(nd: ($T, $T), qr: ($T, $T)) { - let (n, d) = nd; + fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) { + let (n,d) = nd; let separate_div_rem = (n / d, n % d); let combined_div_rem = n.div_rem(&d); @@ -594,21 +351,21 @@ macro_rules! impl_integer_for_isize { test_division_rule(nd, combined_div_rem); } - test_nd_dr((8, 3), (2, 2)); - test_nd_dr((8, -3), (-2, 2)); - test_nd_dr((-8, 3), (-2, -2)); - test_nd_dr((-8, -3), (2, -2)); + test_nd_dr(( 8, 3), ( 2, 2)); + test_nd_dr(( 8, -3), (-2, 2)); + test_nd_dr((-8, 3), (-2, -2)); + test_nd_dr((-8, -3), ( 2, -2)); - test_nd_dr((1, 2), (0, 1)); - test_nd_dr((1, -2), (0, 1)); - test_nd_dr((-1, 2), (0, -1)); - test_nd_dr((-1, -2), (0, -1)); + test_nd_dr(( 1, 2), ( 0, 1)); + test_nd_dr(( 1, -2), ( 0, 1)); + test_nd_dr((-1, 2), ( 0, -1)); + test_nd_dr((-1, -2), ( 0, -1)); } #[test] fn test_div_mod_floor() { - fn test_nd_dm(nd: ($T, $T), dm: ($T, $T)) { - let (n, d) = nd; + fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) { + let (n,d) = nd; let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d)); let combined_div_mod_floor = n.div_mod_floor(&d); @@ -619,15 +376,15 @@ macro_rules! impl_integer_for_isize { test_division_rule(nd, combined_div_mod_floor); } - test_nd_dm((8, 3), (2, 2)); - test_nd_dm((8, -3), (-3, -1)); - test_nd_dm((-8, 3), (-3, 1)); - test_nd_dm((-8, -3), (2, -2)); + test_nd_dm(( 8, 3), ( 2, 2)); + test_nd_dm(( 8, -3), (-3, -1)); + test_nd_dm((-8, 3), (-3, 1)); + test_nd_dm((-8, -3), ( 2, -2)); - test_nd_dm((1, 2), (0, 1)); - test_nd_dm((1, -2), (-1, -1)); - test_nd_dm((-1, 2), (-1, 1)); - test_nd_dm((-1, -2), (0, -1)); + test_nd_dm(( 1, 2), ( 0, 1)); + test_nd_dm(( 1, -2), (-1, -1)); + test_nd_dm((-1, 2), (-1, 1)); + test_nd_dm((-1, -2), ( 0, -1)); } #[test] @@ -657,7 +414,7 @@ macro_rules! impl_integer_for_isize { // for i8 for i in -127..127 { for j in -127..127 { - assert_eq!(euclidean_gcd(i, j), i.gcd(&j)); + assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); } } @@ -665,7 +422,7 @@ macro_rules! impl_integer_for_isize { // FIXME: Use inclusive ranges for above loop when implemented let i = 127; for j in -127..127 { - assert_eq!(euclidean_gcd(i, j), i.gcd(&j)); + assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); } assert_eq!(127.gcd(&127), 127); } @@ -716,49 +473,6 @@ macro_rules! impl_integer_for_isize { assert_eq!((11 as $T).lcm(&5), 55 as $T); } - #[test] - fn test_gcd_lcm() { - use core::iter::once; - for i in once(0) - .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) - .chain(once(-128)) - { - for j in once(0) - .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) - .chain(once(-128)) - { - assert_eq!(i.gcd_lcm(&j), (i.gcd(&j), i.lcm(&j))); - } - } - } - - #[test] - fn test_extended_gcd_lcm() { - use core::fmt::Debug; - use traits::NumAssign; - use ExtendedGcd; - - fn check(a: A, b: A) { - let ExtendedGcd { gcd, x, y, .. } = a.extended_gcd(&b); - assert_eq!(gcd, x * a + y * b); - } - - use core::iter::once; - for i in once(0) - .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) - .chain(once(-128)) - { - for j in once(0) - .chain((1..).take(127).flat_map(|a| once(a).chain(once(-a)))) - .chain(once(-128)) - { - check(i, j); - let (ExtendedGcd { gcd, .. }, lcm) = i.extended_gcd_lcm(&j); - assert_eq!((gcd, lcm), (i.gcd(&j), i.lcm(&j))); - } - } - } - #[test] fn test_even() { assert_eq!((-4 as $T).is_even(), true); @@ -785,7 +499,7 @@ macro_rules! impl_integer_for_isize { assert_eq!((4 as $T).is_odd(), false); } } - }; + ) } impl_integer_for_isize!(i8, test_integer_i8); @@ -797,7 +511,7 @@ impl_integer_for_isize!(isize, test_integer_isize); impl_integer_for_isize!(i128, test_integer_i128); macro_rules! impl_integer_for_usize { - ($T:ty, $test_mod:ident) => { + ($T:ty, $test_mod:ident) => ( impl Integer for $T { /// Unsigned integer division. Returns the same result as `div` (`/`). #[inline] @@ -811,68 +525,34 @@ macro_rules! impl_integer_for_usize { *self % *other } - #[inline] - fn div_ceil(&self, other: &Self) -> Self { - *self / *other + (0 != *self % *other) as Self - } - /// Calculates the Greatest Common Divisor (GCD) of the number and `other` #[inline] fn gcd(&self, other: &Self) -> Self { // Use Stein's algorithm let mut m = *self; let mut n = *other; - if m == 0 || n == 0 { - return m | n; - } + if m == 0 || n == 0 { return m | n } // find common factors of 2 let shift = (m | n).trailing_zeros(); // divide n and m by 2 until odd - m >>= m.trailing_zeros(); + // m inside loop n >>= n.trailing_zeros(); - while m != n { - if m > n { - m -= n; - m >>= m.trailing_zeros(); - } else { - n -= m; - n >>= n.trailing_zeros(); - } + while m != 0 { + m >>= m.trailing_zeros(); + if n > m { mem::swap(&mut n, &mut m) } + m -= n; } - m << shift - } - #[inline] - fn extended_gcd_lcm(&self, other: &Self) -> (ExtendedGcd, Self) { - let egcd = self.extended_gcd(other); - // should not have to recalculate abs - let lcm = if egcd.gcd.is_zero() { - Self::zero() - } else { - *self * (*other / egcd.gcd) - }; - (egcd, lcm) + n << shift } /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn lcm(&self, other: &Self) -> Self { - self.gcd_lcm(other).1 - } - - /// Calculates the Greatest Common Divisor (GCD) and - /// Lowest Common Multiple (LCM) of the number and `other`. - #[inline] - fn gcd_lcm(&self, other: &Self) -> (Self, Self) { - if self.is_zero() && other.is_zero() { - return (Self::zero(), Self::zero()); - } - let gcd = self.gcd(other); - let lcm = *self * (*other / gcd); - (gcd, lcm) + *self * (*other / self.gcd(other)) } /// Deprecated, use `is_multiple_of` instead. @@ -908,8 +588,8 @@ macro_rules! impl_integer_for_usize { #[cfg(test)] mod $test_mod { - use core::mem; use Integer; + use core::mem; #[test] fn test_div_mod_floor() { @@ -945,7 +625,7 @@ macro_rules! impl_integer_for_usize { for i in 0..255 { for j in 0..255 { - assert_eq!(euclidean_gcd(i, j), i.gcd(&j)); + assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); } } @@ -953,7 +633,7 @@ macro_rules! impl_integer_for_usize { // FIXME: Use inclusive ranges for above loop when implemented let i = 255; for j in 0..255 { - assert_eq!(euclidean_gcd(i, j), i.gcd(&j)); + assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); } assert_eq!(255.gcd(&255), 255); } @@ -968,15 +648,6 @@ macro_rules! impl_integer_for_usize { assert_eq!((15 as $T).lcm(&17), 255 as $T); } - #[test] - fn test_gcd_lcm() { - for i in (0..).take(256) { - for j in (0..).take(256) { - assert_eq!(i.gcd_lcm(&j), (i.gcd(&j), i.lcm(&j))); - } - } - } - #[test] fn test_is_multiple_of() { assert!((6 as $T).is_multiple_of(&(6 as $T))); @@ -1002,7 +673,7 @@ macro_rules! impl_integer_for_usize { assert_eq!((4 as $T).is_odd(), false); } } - }; + ) } impl_integer_for_usize!(u8, test_integer_u8); @@ -1021,8 +692,7 @@ pub struct IterBinomial { } impl IterBinomial -where - T: Integer, + where T: Integer, { /// For a given n, iterate over all binomial coefficients binomial(n, k), for k=0...n. /// @@ -1044,16 +714,13 @@ where /// For larger n, `T` should be a bigint type. pub fn new(n: T) -> IterBinomial { IterBinomial { - k: T::zero(), - a: T::one(), - n: n, + k: T::zero(), a: T::one(), n: n } } } impl Iterator for IterBinomial -where - T: Integer + Clone, + where T: Integer + Clone { type Item = T; @@ -1065,7 +732,7 @@ where multiply_and_divide( self.a.clone(), self.n.clone() - self.k.clone() + T::one(), - self.k.clone(), + self.k.clone() ) } else { T::one() @@ -1081,7 +748,7 @@ where fn multiply_and_divide(r: T, a: T, b: T) -> T { // See http://blog.plover.com/math/choose-2.html for the idea. let g = gcd(r.clone(), b.clone()); - r / g.clone() * (a / (b / g)) + r/g.clone() * (a / (b/g)) } /// Calculate the binomial coefficient. @@ -1125,8 +792,7 @@ pub fn binomial(mut n: T, k: T) -> T { /// Calculate the multinomial coefficient. pub fn multinomial(k: &[T]) -> T -where - for<'a> T: Add<&'a T, Output = T>, + where for<'a> T: Add<&'a T, Output = T> { let mut r = T::one(); let mut p = T::zero(); @@ -1140,20 +806,16 @@ where #[test] fn test_lcm_overflow() { macro_rules! check { - ($t:ty, $x:expr, $y:expr, $r:expr) => {{ + ($t:ty, $x:expr, $y:expr, $r:expr) => { { let x: $t = $x; let y: $t = $y; let o = x.checked_mul(y); - assert!( - o.is_none(), - "sanity checking that {} input {} * {} overflows", - stringify!($t), - x, - y - ); + assert!(o.is_none(), + "sanity checking that {} input {} * {} overflows", + stringify!($t), x, y); assert_eq!(x.lcm(&y), $r); assert_eq!(y.lcm(&x), $r); - }}; + } } } // Original bug (Issue #166) @@ -1172,13 +834,13 @@ fn test_lcm_overflow() { #[test] fn test_iter_binomial() { macro_rules! check_simple { - ($t:ty) => {{ + ($t:ty) => { { let n: $t = 3; let expected = [1, 3, 3, 1]; for (b, &e) in IterBinomial::new(n).zip(&expected) { assert_eq!(b, e); } - }}; + } } } check_simple!(u8); @@ -1191,14 +853,14 @@ fn test_iter_binomial() { check_simple!(i64); macro_rules! check_binomial { - ($t:ty, $n:expr) => {{ + ($t:ty, $n:expr) => { { let n: $t = $n; let mut k: $t = 0; for b in IterBinomial::new(n) { assert_eq!(b, binomial(n, k)); k += 1; } - }}; + } } } // Check the largest n for which there is no overflow. @@ -1215,7 +877,7 @@ fn test_iter_binomial() { #[test] fn test_binomial() { macro_rules! check { - ($t:ty, $x:expr, $y:expr, $r:expr) => {{ + ($t:ty, $x:expr, $y:expr, $r:expr) => { { let x: $t = $x; let y: $t = $y; let expected: $t = $r; @@ -1223,7 +885,7 @@ fn test_binomial() { if y <= x { assert_eq!(binomial(x, x - y), expected); } - }}; + } } } check!(u8, 9, 4, 126); check!(u8, 0, 0, 1); @@ -1271,12 +933,12 @@ fn test_binomial() { #[test] fn test_multinomial() { macro_rules! check_binomial { - ($t:ty, $k:expr) => {{ + ($t:ty, $k:expr) => { { let n: $t = $k.iter().fold(0, |acc, &x| acc + x); let k: &[$t] = $k; assert_eq!(k.len(), 2); assert_eq!(multinomial(k), binomial(n, k[0])); - }}; + } } } check_binomial!(u8, &[4, 5]); @@ -1306,11 +968,11 @@ fn test_multinomial() { check_binomial!(i64, &[4, 10]); macro_rules! check_multinomial { - ($t:ty, $k:expr, $r:expr) => {{ + ($t:ty, $k:expr, $r:expr) => { { let k: &[$t] = $k; let expected: $t = $r; assert_eq!(multinomial(k), expected); - }}; + } } } check_multinomial!(u8, &[2, 1, 2], 30); diff --git a/third_party/rust/num-integer/src/roots.rs b/third_party/rust/num-integer/src/roots.rs index a9eec1a93cbe..9bad31f9d78a 100644 --- a/third_party/rust/num-integer/src/roots.rs +++ b/third_party/rust/num-integer/src/roots.rs @@ -202,181 +202,170 @@ fn log2(x: T) -> u32 { macro_rules! unsigned_roots { ($T:ident) => { impl Roots for $T { - #[inline] fn nth_root(&self, n: u32) -> Self { - fn go(a: $T, n: u32) -> $T { - // Specialize small roots - match n { - 0 => panic!("can't find a root of degree 0!"), - 1 => return a, - 2 => return a.sqrt(), - 3 => return a.cbrt(), - _ => (), - } + // Specialize small roots + match n { + 0 => panic!("can't find a root of degree 0!"), + 1 => return *self, + 2 => return self.sqrt(), + 3 => return self.cbrt(), + _ => (), + } - // The root of values less than 2ⁿ can only be 0 or 1. - if bits::<$T>() <= n || a < (1 << n) { - return (a > 0) as $T; - } + // The root of values less than 2ⁿ can only be 0 or 1. + if bits::<$T>() <= n || *self < (1 << n) { + return (*self > 0) as $T; + } - if bits::<$T>() > 64 { - // 128-bit division is slow, so do a bitwise `nth_root` until it's small enough. - return if a <= core::u64::MAX as $T { - (a as u64).nth_root(n) as $T - } else { - let lo = (a >> n).nth_root(n) << 1; - let hi = lo + 1; - // 128-bit `checked_mul` also involves division, but we can't always - // compute `hiⁿ` without risking overflow. Try to avoid it though... - if hi.next_power_of_two().trailing_zeros() * n >= bits::<$T>() { - match checked_pow(hi, n as usize) { - Some(x) if x <= a => hi, - _ => lo, - } - } else { - if hi.pow(n) <= a { - hi - } else { - lo - } + if bits::<$T>() > 64 { + // 128-bit division is slow, so do a bitwise `nth_root` until it's small enough. + return if *self <= core::u64::MAX as $T { + (*self as u64).nth_root(n) as $T + } else { + let lo = (self >> n).nth_root(n) << 1; + let hi = lo + 1; + // 128-bit `checked_mul` also involves division, but we can't always + // compute `hiⁿ` without risking overflow. Try to avoid it though... + if hi.next_power_of_two().trailing_zeros() * n >= bits::<$T>() { + match checked_pow(hi, n as usize) { + Some(x) if x <= *self => hi, + _ => lo, } - }; - } - - #[cfg(feature = "std")] - #[inline] - fn guess(x: $T, n: u32) -> $T { - // for smaller inputs, `f64` doesn't justify its cost. - if bits::<$T>() <= 32 || x <= core::u32::MAX as $T { - 1 << ((log2(x) + n - 1) / n) } else { - ((x as f64).ln() / f64::from(n)).exp() as $T + if hi.pow(n) <= *self { + hi + } else { + lo + } } - } - - #[cfg(not(feature = "std"))] - #[inline] - fn guess(x: $T, n: u32) -> $T { - 1 << ((log2(x) + n - 1) / n) - } - - // https://en.wikipedia.org/wiki/Nth_root_algorithm - let n1 = n - 1; - let next = |x: $T| { - let y = match checked_pow(x, n1 as usize) { - Some(ax) => a / ax, - None => 0, - }; - (y + x * n1 as $T) / n as $T }; - fixpoint(guess(a, n), next) } - go(*self, n) + + #[cfg(feature = "std")] + #[inline] + fn guess(x: $T, n: u32) -> $T { + // for smaller inputs, `f64` doesn't justify its cost. + if bits::<$T>() <= 32 || x <= core::u32::MAX as $T { + 1 << ((log2(x) + n - 1) / n) + } else { + ((x as f64).ln() / f64::from(n)).exp() as $T + } + } + + #[cfg(not(feature = "std"))] + #[inline] + fn guess(x: $T, n: u32) -> $T { + 1 << ((log2(x) + n - 1) / n) + } + + // https://en.wikipedia.org/wiki/Nth_root_algorithm + let n1 = n - 1; + let next = |x: $T| { + let y = match checked_pow(x, n1 as usize) { + Some(ax) => self / ax, + None => 0, + }; + (y + x * n1 as $T) / n as $T + }; + fixpoint(guess(*self, n), next) } - #[inline] fn sqrt(&self) -> Self { - fn go(a: $T) -> $T { - if bits::<$T>() > 64 { - // 128-bit division is slow, so do a bitwise `sqrt` until it's small enough. - return if a <= core::u64::MAX as $T { - (a as u64).sqrt() as $T + if bits::<$T>() > 64 { + // 128-bit division is slow, so do a bitwise `sqrt` until it's small enough. + // https://en.wikipedia.org/wiki/Integer_square_root#Using_bitwise_operations + return if *self <= core::u64::MAX as $T { + (*self as u64).sqrt() as $T + } else { + let lo = (self >> 2u32).sqrt() << 1; + let hi = lo + 1; + if hi * hi <= *self { + hi } else { - let lo = (a >> 2u32).sqrt() << 1; - let hi = lo + 1; - if hi * hi <= a { - hi - } else { - lo - } - }; - } - - if a < 4 { - return (a > 0) as $T; - } - - #[cfg(feature = "std")] - #[inline] - fn guess(x: $T) -> $T { - (x as f64).sqrt() as $T - } - - #[cfg(not(feature = "std"))] - #[inline] - fn guess(x: $T) -> $T { - 1 << ((log2(x) + 1) / 2) - } - - // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method - let next = |x: $T| (a / x + x) >> 1; - fixpoint(guess(a), next) + lo + } + }; } - go(*self) + + if *self < 4 { + return (*self > 0) as Self; + } + + #[cfg(feature = "std")] + #[inline] + fn guess(x: $T) -> $T { + (x as f64).sqrt() as $T + } + + #[cfg(not(feature = "std"))] + #[inline] + fn guess(x: $T) -> $T { + 1 << ((log2(x) + 1) / 2) + } + + // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method + let next = |x: $T| (self / x + x) >> 1; + fixpoint(guess(*self), next) } - #[inline] fn cbrt(&self) -> Self { - fn go(a: $T) -> $T { - if bits::<$T>() > 64 { - // 128-bit division is slow, so do a bitwise `cbrt` until it's small enough. - return if a <= core::u64::MAX as $T { - (a as u64).cbrt() as $T + if bits::<$T>() > 64 { + // 128-bit division is slow, so do a bitwise `cbrt` until it's small enough. + return if *self <= core::u64::MAX as $T { + (*self as u64).cbrt() as $T + } else { + let lo = (self >> 3u32).cbrt() << 1; + let hi = lo + 1; + if hi * hi * hi <= *self { + hi } else { - let lo = (a >> 3u32).cbrt() << 1; - let hi = lo + 1; - if hi * hi * hi <= a { - hi - } else { - lo - } - }; - } - - if bits::<$T>() <= 32 { - // Implementation based on Hacker's Delight `icbrt2` - let mut x = a; - let mut y2 = 0; - let mut y = 0; - let smax = bits::<$T>() / 3; - for s in (0..smax + 1).rev() { - let s = s * 3; - y2 *= 4; - y *= 2; - let b = 3 * (y2 + y) + 1; - if x >> s >= b { - x -= b << s; - y2 += 2 * y + 1; - y += 1; - } + lo } - return y; - } - - if a < 8 { - return (a > 0) as $T; - } - if a <= core::u32::MAX as $T { - return (a as u32).cbrt() as $T; - } - - #[cfg(feature = "std")] - #[inline] - fn guess(x: $T) -> $T { - (x as f64).cbrt() as $T - } - - #[cfg(not(feature = "std"))] - #[inline] - fn guess(x: $T) -> $T { - 1 << ((log2(x) + 2) / 3) - } - - // https://en.wikipedia.org/wiki/Cube_root#Numerical_methods - let next = |x: $T| (a / (x * x) + x * 2) / 3; - fixpoint(guess(a), next) + }; } - go(*self) + + if bits::<$T>() <= 32 { + // Implementation based on Hacker's Delight `icbrt2` + let mut x = *self; + let mut y2 = 0; + let mut y = 0; + let smax = bits::<$T>() / 3; + for s in (0..smax + 1).rev() { + let s = s * 3; + y2 *= 4; + y *= 2; + let b = 3 * (y2 + y) + 1; + if x >> s >= b { + x -= b << s; + y2 += 2 * y + 1; + y += 1; + } + } + return y; + } + + if *self < 8 { + return (*self > 0) as Self; + } + if *self <= core::u32::MAX as $T { + return (*self as u32).cbrt() as $T; + } + + #[cfg(feature = "std")] + #[inline] + fn guess(x: $T) -> $T { + (x as f64).cbrt() as $T + } + + #[cfg(not(feature = "std"))] + #[inline] + fn guess(x: $T) -> $T { + 1 << ((log2(x) + 2) / 3) + } + + // https://en.wikipedia.org/wiki/Cube_root#Numerical_methods + let next = |x: $T| (self / (x * x) + x * 2) / 3; + fixpoint(guess(*self), next) } } }; diff --git a/third_party/rust/num-integer/tests/average.rs b/third_party/rust/num-integer/tests/average.rs deleted file mode 100644 index 9fd8cf18f4ea..000000000000 --- a/third_party/rust/num-integer/tests/average.rs +++ /dev/null @@ -1,100 +0,0 @@ -extern crate num_integer; -extern crate num_traits; - -macro_rules! test_average { - ($I:ident, $U:ident) => { - mod $I { - mod ceil { - use num_integer::Average; - - #[test] - fn same_sign() { - assert_eq!((14 as $I).average_ceil(&16), 15 as $I); - assert_eq!((14 as $I).average_ceil(&17), 16 as $I); - - let max = $crate::std::$I::MAX; - assert_eq!((max - 3).average_ceil(&(max - 1)), max - 2); - assert_eq!((max - 3).average_ceil(&(max - 2)), max - 2); - } - - #[test] - fn different_sign() { - assert_eq!((14 as $I).average_ceil(&-4), 5 as $I); - assert_eq!((14 as $I).average_ceil(&-5), 5 as $I); - - let min = $crate::std::$I::MIN; - let max = $crate::std::$I::MAX; - assert_eq!(min.average_ceil(&max), 0 as $I); - } - } - - mod floor { - use num_integer::Average; - - #[test] - fn same_sign() { - assert_eq!((14 as $I).average_floor(&16), 15 as $I); - assert_eq!((14 as $I).average_floor(&17), 15 as $I); - - let max = $crate::std::$I::MAX; - assert_eq!((max - 3).average_floor(&(max - 1)), max - 2); - assert_eq!((max - 3).average_floor(&(max - 2)), max - 3); - } - - #[test] - fn different_sign() { - assert_eq!((14 as $I).average_floor(&-4), 5 as $I); - assert_eq!((14 as $I).average_floor(&-5), 4 as $I); - - let min = $crate::std::$I::MIN; - let max = $crate::std::$I::MAX; - assert_eq!(min.average_floor(&max), -1 as $I); - } - } - } - - mod $U { - mod ceil { - use num_integer::Average; - - #[test] - fn bounded() { - assert_eq!((14 as $U).average_ceil(&16), 15 as $U); - assert_eq!((14 as $U).average_ceil(&17), 16 as $U); - } - - #[test] - fn overflow() { - let max = $crate::std::$U::MAX; - assert_eq!((max - 3).average_ceil(&(max - 1)), max - 2); - assert_eq!((max - 3).average_ceil(&(max - 2)), max - 2); - } - } - - mod floor { - use num_integer::Average; - - #[test] - fn bounded() { - assert_eq!((14 as $U).average_floor(&16), 15 as $U); - assert_eq!((14 as $U).average_floor(&17), 15 as $U); - } - - #[test] - fn overflow() { - let max = $crate::std::$U::MAX; - assert_eq!((max - 3).average_floor(&(max - 1)), max - 2); - assert_eq!((max - 3).average_floor(&(max - 2)), max - 3); - } - } - } - }; -} - -test_average!(i8, u8); -test_average!(i16, u16); -test_average!(i32, u32); -test_average!(i64, u64); -#[cfg(has_i128)] -test_average!(i128, u128); -test_average!(isize, usize); diff --git a/third_party/rust/num-integer/tests/roots.rs b/third_party/rust/num-integer/tests/roots.rs index f85f9e021143..85e97f327285 100644 --- a/third_party/rust/num-integer/tests/roots.rs +++ b/third_party/rust/num-integer/tests/roots.rs @@ -10,7 +10,11 @@ use std::mem; trait TestInteger: Roots + PrimInt + Debug + AsPrimitive + 'static {} -impl TestInteger for T where T: Roots + PrimInt + Debug + AsPrimitive + 'static {} +impl TestInteger for T +where + T: Roots + PrimInt + Debug + AsPrimitive + 'static, +{ +} /// Check that each root is correct /// diff --git a/third_party/rust/num-iter/.cargo-checksum.json b/third_party/rust/num-iter/.cargo-checksum.json index 7b1837842e0c..ec53015f36ad 100644 --- a/third_party/rust/num-iter/.cargo-checksum.json +++ b/third_party/rust/num-iter/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"a4d2d0bbd05ab5a51970062722652bacf4d4e30cff0fcca1fd923939fec2b274","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"57d78cdbd4b4adfac543cc95afb88d34b2415bf074eb1081631210f84cca54f3","RELEASES.md":"f947644ec5b4a6d5e25497dfa3dbdd0d14983b9593e41dad7e12d1218559b4fa","build.rs":"b4b2d0df90ca7570a339ca4d84a72e4ef00d9dced8927350424e666790c752d7","src/lib.rs":"7baa9cfcc89c27a6d16a4be0fe53c0488f3c1c424812219fc47be0918a197d9b"},"package":"7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f"} \ No newline at end of file +{"files":{"Cargo.toml":"c13da0848b07a604569216fdb430f87d43b83252055ab1f6e237fc4020897b2b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"f3be0ace34d626865f124c492483c30cadc3362c17aabefed45fa2686c67a070","RELEASES.md":"1031b964f47fd9c33e0249d1343b3292c830d7e2e6c8d88931dcbc25a20a0337","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"16de2aa57e754fc1526d0400b5d87a3f771296705fca54601aa598b6f74ded8f","ci/rustup.sh":"2aa9e89e4af81ed9da86bdcf7cdabe512287c877248783b69eed1eccf09ad6bb","ci/test_full.sh":"22ab0d413456c350a8a0e62e3614da628dad06eb4c923b4d162aef4cb47b9dd2","src/lib.rs":"e6b0f870ab6e741f15293b76b11e5bc01193aa8e08c13f5f67e2f85c3808636f"},"package":"af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"} \ No newline at end of file diff --git a/third_party/rust/num-iter/Cargo.toml b/third_party/rust/num-iter/Cargo.toml index 1064ec694529..3f01499a4ac9 100644 --- a/third_party/rust/num-iter/Cargo.toml +++ b/third_party/rust/num-iter/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -12,10 +12,9 @@ [package] name = "num-iter" -version = "0.1.41" +version = "0.1.37" authors = ["The Rust Project Developers"] build = "build.rs" -exclude = ["/bors.toml", "/ci/*", "/.github/*"] description = "External iterators for generic mathematics" homepage = "https://github.com/rust-num/num-iter" documentation = "https://docs.rs/num-iter" @@ -27,14 +26,12 @@ repository = "https://github.com/rust-num/num-iter" [package.metadata.docs.rs] features = ["std"] [dependencies.num-integer] -version = "0.1.42" +version = "0.1.38" default-features = false [dependencies.num-traits] -version = "0.2.11" +version = "0.2.4" default-features = false -[build-dependencies.autocfg] -version = "1" [features] default = ["std"] diff --git a/third_party/rust/num-iter/README.md b/third_party/rust/num-iter/README.md index 5abd89661f67..3d0362e09e09 100644 --- a/third_party/rust/num-iter/README.md +++ b/third_party/rust/num-iter/README.md @@ -2,8 +2,8 @@ [![crate](https://img.shields.io/crates/v/num-iter.svg)](https://crates.io/crates/num-iter) [![documentation](https://docs.rs/num-iter/badge.svg)](https://docs.rs/num-iter) -[![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num-iter/workflows/master/badge.svg)](https://github.com/rust-num/num-iter/actions) +![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg) +[![Travis status](https://travis-ci.org/rust-num/num-iter.svg?branch=master)](https://travis-ci.org/rust-num/num-iter) Generic `Range` iterators for Rust. diff --git a/third_party/rust/num-iter/RELEASES.md b/third_party/rust/num-iter/RELEASES.md index 5fcc53238e76..c54fe521cead 100644 --- a/third_party/rust/num-iter/RELEASES.md +++ b/third_party/rust/num-iter/RELEASES.md @@ -1,35 +1,4 @@ -# Release 0.1.41 (2020-06-11) - -- [The new `RangeFrom` and `RangeFromStep` iterators][18] will count from a - given starting value, without any terminating value. - -**Contributors**: @cuviper, @sollyucko - -[18]: https://github.com/rust-num/num-iter/pull/18 - -# Release 0.1.40 (2020-01-09) - -- [Updated the `autocfg` build dependency to 1.0][14]. - -**Contributors**: @cuviper, @dingelish - -[14]: https://github.com/rust-num/num-iter/pull/14 - -# Release 0.1.39 (2019-05-21) - -- [Fixed feature detection on `no_std` targets][11]. - -**Contributors**: @cuviper - -[11]: https://github.com/rust-num/num-iter/pull/11 - -# Release 0.1.38 (2019-05-20) - -- Maintenance update -- no functional changes. - -**Contributors**: @cuviper, @ignatenkobrain - -# Release 0.1.37 (2018-05-11) +# Release 0.1.37 - [Support for 128-bit integers is now automatically detected and enabled.][5] Setting the `i128` crate feature now causes the build script to panic if such @@ -39,7 +8,7 @@ [5]: https://github.com/rust-num/num-iter/pull/5 -# Release 0.1.36 (2018-05-10) +# Release 0.1.36 - [The iterators are now implemented for `i128` and `u128`][7] starting with Rust 1.26, enabled by the new `i128` crate feature. @@ -48,7 +17,7 @@ [4]: https://github.com/rust-num/num-iter/pull/4 -# Release 0.1.35 (2018-02-06) +# Release 0.1.35 - [num-iter now has its own source repository][num-356] at [rust-num/num-iter][home]. - [There is now a `std` feature][2], enabled by default, along with the implication diff --git a/third_party/rust/num-iter/bors.toml b/third_party/rust/num-iter/bors.toml new file mode 100644 index 000000000000..ca08e818bf3e --- /dev/null +++ b/third_party/rust/num-iter/bors.toml @@ -0,0 +1,3 @@ +status = [ + "continuous-integration/travis-ci/push", +] diff --git a/third_party/rust/num-iter/build.rs b/third_party/rust/num-iter/build.rs index e483c15fd7f6..fd60866558c3 100644 --- a/third_party/rust/num-iter/build.rs +++ b/third_party/rust/num-iter/build.rs @@ -1,14 +1,35 @@ -extern crate autocfg; - use std::env; +use std::io::Write; +use std::process::{Command, Stdio}; fn main() { - let ac = autocfg::new(); - if ac.probe_type("i128") { + if probe("fn main() { 0i128; }") { println!("cargo:rustc-cfg=has_i128"); } else if env::var_os("CARGO_FEATURE_I128").is_some() { panic!("i128 support was not detected!"); } - - autocfg::rerun_path("build.rs"); +} + +/// Test if a code snippet can be compiled +fn probe(code: &str) -> bool { + let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); + let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR"); + + let mut child = Command::new(rustc) + .arg("--out-dir") + .arg(out_dir) + .arg("--emit=obj") + .arg("-") + .stdin(Stdio::piped()) + .spawn() + .expect("rustc probe"); + + child + .stdin + .as_mut() + .expect("rustc stdin") + .write_all(code.as_bytes()) + .expect("write rustc stdin"); + + child.wait().expect("rustc probe").success() } diff --git a/third_party/rust/num-iter/ci/rustup.sh b/third_party/rust/num-iter/ci/rustup.sh new file mode 100755 index 000000000000..e82ece76d7a6 --- /dev/null +++ b/third_party/rust/num-iter/ci/rustup.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Use rustup to locally run the same suite of tests as .travis.yml. +# (You should first install/update 1.8.0, stable, beta, and nightly.) + +set -ex + +export TRAVIS_RUST_VERSION +for TRAVIS_RUST_VERSION in 1.8.0 1.15.0 1.20.0 stable beta nightly; do + run="rustup run $TRAVIS_RUST_VERSION" + $run cargo build --verbose + $run $PWD/ci/test_full.sh +done diff --git a/third_party/rust/num-iter/ci/test_full.sh b/third_party/rust/num-iter/ci/test_full.sh new file mode 100755 index 000000000000..2c5325eda85d --- /dev/null +++ b/third_party/rust/num-iter/ci/test_full.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -ex + +echo Testing num-iter on rustc ${TRAVIS_RUST_VERSION} + +# num-iter should build and test everywhere. +cargo build --verbose +cargo test --verbose + +# test `no_std` +cargo build --verbose --no-default-features +cargo test --verbose --no-default-features + +# test `i128` +if [[ "$TRAVIS_RUST_VERSION" =~ ^(nightly|beta|stable)$ ]]; then + cargo build --verbose --features=i128 + cargo test --verbose --features=i128 +fi diff --git a/third_party/rust/num-iter/src/lib.rs b/third_party/rust/num-iter/src/lib.rs index 9dc835426826..f4bac547fb25 100644 --- a/third_party/rust/num-iter/src/lib.rs +++ b/third_party/rust/num-iter/src/lib.rs @@ -15,24 +15,25 @@ //! The `num-iter` crate is tested for rustc 1.8 and greater. #![doc(html_root_url = "https://docs.rs/num-iter/0.1")] + #![no_std] #[cfg(feature = "std")] extern crate std; -extern crate num_integer as integer; extern crate num_traits as traits; +extern crate num_integer as integer; +use integer::Integer; +use traits::{Zero, One, CheckedAdd, ToPrimitive}; use core::ops::{Add, Sub}; use core::usize; -use integer::Integer; -use traits::{CheckedAdd, One, ToPrimitive, Zero}; /// An iterator over the range [start, stop) #[derive(Clone)] pub struct Range { state: A, stop: A, - one: A, + one: A } /// Returns an iterator over the given range [start, stop) (that is, starting @@ -50,14 +51,9 @@ pub struct Range { /// ``` #[inline] pub fn range(start: A, stop: A) -> Range -where - A: Add + PartialOrd + Clone + One, + where A: Add + PartialOrd + Clone + One { - Range { - state: start, - stop: stop, - one: One::one(), - } + Range{state: start, stop: stop, one: One::one()} } #[inline] @@ -86,8 +82,7 @@ fn unsigned(x: &T) -> Option { // FIXME: rust-lang/rust#10414: Unfortunate type bound impl Iterator for Range -where - A: Add + PartialOrd + Clone + ToPrimitive, + where A: Add + PartialOrd + Clone + ToPrimitive { type Item = A; @@ -118,7 +113,7 @@ where return match b.wrapping_sub(a).to_usize() { Some(len) => (len, Some(len)), None => (usize::MAX, None), - }; + } } } @@ -130,8 +125,7 @@ where /// `Integer` is required to ensure the range will be the same regardless of /// the direction it is consumed. impl DoubleEndedIterator for Range -where - A: Integer + Clone + ToPrimitive, + where A: Integer + Clone + ToPrimitive { #[inline] fn next_back(&mut self) -> Option { @@ -154,18 +148,13 @@ pub struct RangeInclusive { /// Return an iterator over the range [start, stop] #[inline] pub fn range_inclusive(start: A, stop: A) -> RangeInclusive -where - A: Add + PartialOrd + Clone + One, + where A: Add + PartialOrd + Clone + One { - RangeInclusive { - range: range(start, stop), - done: false, - } + RangeInclusive{range: range(start, stop), done: false} } impl Iterator for RangeInclusive -where - A: Add + PartialOrd + Clone + ToPrimitive, + where A: Add + PartialOrd + Clone + ToPrimitive { type Item = A; @@ -193,7 +182,7 @@ where let lo = lo.saturating_add(1); let hi = match hi { Some(x) => x.checked_add(1), - None => None, + None => None }; (lo, hi) } @@ -201,8 +190,7 @@ where } impl DoubleEndedIterator for RangeInclusive -where - A: Sub + Integer + Clone + ToPrimitive, + where A: Sub + Integer + Clone + ToPrimitive { #[inline] fn next_back(&mut self) -> Option { @@ -231,21 +219,14 @@ pub struct RangeStep { /// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. #[inline] pub fn range_step(start: A, stop: A, step: A) -> RangeStep -where - A: CheckedAdd + PartialOrd + Clone + Zero, + where A: CheckedAdd + PartialOrd + Clone + Zero { let rev = step < Zero::zero(); - RangeStep { - state: start, - stop: stop, - step: step, - rev: rev, - } + RangeStep{state: start, stop: stop, step: step, rev: rev} } impl Iterator for RangeStep -where - A: CheckedAdd + PartialOrd + Clone, + where A: CheckedAdd + PartialOrd + Clone { type Item = A; @@ -255,7 +236,7 @@ where let result = self.state.clone(); match self.state.checked_add(&self.step) { Some(x) => self.state = x, - None => self.state = self.stop.clone(), + None => self.state = self.stop.clone() } Some(result) } else { @@ -277,34 +258,25 @@ pub struct RangeStepInclusive { /// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. #[inline] pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive -where - A: CheckedAdd + PartialOrd + Clone + Zero, + where A: CheckedAdd + PartialOrd + Clone + Zero { let rev = step < Zero::zero(); - RangeStepInclusive { - state: start, - stop: stop, - step: step, - rev: rev, - done: false, - } + RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} } impl Iterator for RangeStepInclusive -where - A: CheckedAdd + PartialOrd + Clone + PartialEq, + where A: CheckedAdd + PartialOrd + Clone + PartialEq { type Item = A; #[inline] fn next(&mut self) -> Option { - if !self.done - && ((self.rev && self.state >= self.stop) || (!self.rev && self.state <= self.stop)) - { + if !self.done && ((self.rev && self.state >= self.stop) || + (!self.rev && self.state <= self.stop)) { let result = self.state.clone(); match self.state.checked_add(&self.step) { Some(x) => self.state = x, - None => self.done = true, + None => self.done = true } Some(result) } else { @@ -313,98 +285,12 @@ where } } -/// An iterator over the infinite range starting at `start` -#[derive(Clone)] -pub struct RangeFrom { - state: A, - one: A, -} - -/// Return an iterator over the infinite range starting at `start` and continuing forever. -/// -/// *Note*: Currently, the `Iterator` implementation is not checked for overflow. -/// If you use a finite-sized integer type and the integer overflows, -/// it might panic in debug mode or wrap around in release mode. -/// **This behavior is not guaranteed and may change at any time.** -#[inline] -pub fn range_from(start: A) -> RangeFrom -where - A: Add + Clone + One, -{ - RangeFrom { - state: start, - one: One::one(), - } -} - -impl Iterator for RangeFrom -where - A: Add + Clone, -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let result = self.state.clone(); - self.state = self.state.clone() + self.one.clone(); - Some(result) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) - } -} - -/// An iterator over the infinite range starting at `start` by `step` -#[derive(Clone)] -pub struct RangeStepFrom { - state: A, - step: A, -} - -/// Return an iterator over the infinite range starting at `start` and continuing forever by `step`. -/// -/// *Note*: Currently, the `Iterator` implementation is not checked for overflow. -/// If you use a finite-sized integer type and the integer overflows, -/// it might panic in debug mode or wrap around in release mode. -/// **This behavior is not guaranteed and may change at any time.** -#[inline] -pub fn range_step_from(start: A, step: A) -> RangeStepFrom -where - A: Add + Clone, -{ - RangeStepFrom { - state: start, - step: step, - } -} - -impl Iterator for RangeStepFrom -where - A: Add + Clone, -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - let result = self.state.clone(); - self.state = self.state.clone() + self.step.clone(); - Some(result) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) - } -} - #[cfg(test)] mod tests { + use core::{isize, usize}; + use core::ops::{Add, Mul}; use core::cmp::Ordering; use core::iter; - use core::ops::{Add, Mul}; - use core::{isize, usize}; use traits::{One, ToPrimitive}; #[test] @@ -413,12 +299,8 @@ mod tests { struct Foo; impl ToPrimitive for Foo { - fn to_i64(&self) -> Option { - None - } - fn to_u64(&self) -> Option { - None - } + fn to_i64(&self) -> Option { None } + fn to_u64(&self) -> Option { None } } impl Add for Foo { @@ -461,9 +343,12 @@ mod tests { } } - assert!(super::range(0, 5).eq([0, 1, 2, 3, 4].iter().cloned())); - assert!(super::range(-10, -1).eq([-10, -9, -8, -7, -6, -5, -4, -3, -2].iter().cloned())); - assert!(super::range(0, 5).rev().eq([4, 3, 2, 1, 0].iter().cloned())); + assert!(super::range(0, 5) + .eq([0, 1, 2, 3, 4].iter().cloned())); + assert!(super::range(-10, -1) + .eq([-10, -9, -8, -7, -6, -5, -4, -3, -2].iter().cloned())); + assert!(super::range(0, 5).rev() + .eq([4, 3, 2, 1, 0].iter().cloned())); assert_eq!(super::range(200, -5).count(), 0); assert_eq!(super::range(200, -5).rev().count(), 0); assert_eq!(super::range(200, 200).count(), 0); @@ -471,15 +356,9 @@ mod tests { assert_eq!(super::range(0, 100).size_hint(), (100, Some(100))); // this test is only meaningful when sizeof usize < sizeof u64 - assert_eq!( - super::range(usize::MAX - 1, usize::MAX).size_hint(), - (1, Some(1)) - ); + assert_eq!(super::range(usize::MAX - 1, usize::MAX).size_hint(), (1, Some(1))); assert_eq!(super::range(-10, -1).size_hint(), (9, Some(9))); - assert_eq!( - super::range(isize::MIN, isize::MAX).size_hint(), - (usize::MAX, Some(usize::MAX)) - ); + assert_eq!(super::range(isize::MIN, isize::MAX).size_hint(), (usize::MAX, Some(usize::MAX))); } #[test] @@ -487,58 +366,39 @@ mod tests { fn test_range_128() { use core::{i128, u128}; - assert!(super::range(0i128, 5).eq([0, 1, 2, 3, 4].iter().cloned())); - assert!(super::range(-10i128, -1).eq([-10, -9, -8, -7, -6, -5, -4, -3, -2].iter().cloned())); - assert!(super::range(0u128, 5) - .rev() - .eq([4, 3, 2, 1, 0].iter().cloned())); + assert!(super::range(0i128, 5) + .eq([0, 1, 2, 3, 4].iter().cloned())); + assert!(super::range(-10i128, -1) + .eq([-10, -9, -8, -7, -6, -5, -4, -3, -2].iter().cloned())); + assert!(super::range(0u128, 5).rev() + .eq([4, 3, 2, 1, 0].iter().cloned())); - assert_eq!( - super::range(i128::MIN, i128::MIN + 1).size_hint(), - (1, Some(1)) - ); - assert_eq!( - super::range(i128::MAX - 1, i128::MAX).size_hint(), - (1, Some(1)) - ); - assert_eq!( - super::range(i128::MIN, i128::MAX).size_hint(), - (usize::MAX, None) - ); + assert_eq!(super::range(i128::MIN, i128::MIN+1).size_hint(), (1, Some(1))); + assert_eq!(super::range(i128::MAX - 1, i128::MAX).size_hint(), (1, Some(1))); + assert_eq!(super::range(i128::MIN, i128::MAX).size_hint(), (usize::MAX, None)); - assert_eq!( - super::range(u128::MAX - 1, u128::MAX).size_hint(), - (1, Some(1)) - ); - assert_eq!( - super::range(0, usize::MAX as u128).size_hint(), - (usize::MAX, Some(usize::MAX)) - ); - assert_eq!( - super::range(0, usize::MAX as u128 + 1).size_hint(), - (usize::MAX, None) - ); + assert_eq!(super::range(u128::MAX - 1, u128::MAX).size_hint(), (1, Some(1))); + assert_eq!(super::range(0, usize::MAX as u128).size_hint(), (usize::MAX, Some(usize::MAX))); + assert_eq!(super::range(0, usize::MAX as u128 + 1).size_hint(), (usize::MAX, None)); assert_eq!(super::range(0, i128::MAX).size_hint(), (usize::MAX, None)); } #[test] fn test_range_inclusive() { - assert!(super::range_inclusive(0, 5).eq([0, 1, 2, 3, 4, 5].iter().cloned())); assert!(super::range_inclusive(0, 5) - .rev() - .eq([5, 4, 3, 2, 1, 0].iter().cloned())); + .eq([0, 1, 2, 3, 4, 5].iter().cloned())); + assert!(super::range_inclusive(0, 5).rev() + .eq([5, 4, 3, 2, 1, 0].iter().cloned())); assert_eq!(super::range_inclusive(200, -5).count(), 0); assert_eq!(super::range_inclusive(200, -5).rev().count(), 0); - assert!(super::range_inclusive(200, 200).eq(iter::once(200))); - assert!(super::range_inclusive(200, 200).rev().eq(iter::once(200))); - assert_eq!( - super::range_inclusive(isize::MIN, isize::MAX - 1).size_hint(), - (usize::MAX, Some(usize::MAX)) - ); - assert_eq!( - super::range_inclusive(isize::MIN, isize::MAX).size_hint(), - (usize::MAX, None) - ); + assert!(super::range_inclusive(200, 200) + .eq(iter::once(200))); + assert!(super::range_inclusive(200, 200).rev() + .eq(iter::once(200))); + assert_eq!(super::range_inclusive(isize::MIN, isize::MAX - 1).size_hint(), + (usize::MAX, Some(usize::MAX))); + assert_eq!(super::range_inclusive(isize::MIN, isize::MAX).size_hint(), + (usize::MAX, None)); } #[test] @@ -546,42 +406,40 @@ mod tests { fn test_range_inclusive_128() { use core::i128; - assert!(super::range_inclusive(0u128, 5).eq([0, 1, 2, 3, 4, 5].iter().cloned())); assert!(super::range_inclusive(0u128, 5) - .rev() - .eq([5, 4, 3, 2, 1, 0].iter().cloned())); + .eq([0, 1, 2, 3, 4, 5].iter().cloned())); + assert!(super::range_inclusive(0u128, 5).rev() + .eq([5, 4, 3, 2, 1, 0].iter().cloned())); assert_eq!(super::range_inclusive(200i128, -5).count(), 0); assert_eq!(super::range_inclusive(200i128, -5).rev().count(), 0); - assert!(super::range_inclusive(200u128, 200).eq(iter::once(200))); assert!(super::range_inclusive(200u128, 200) - .rev() - .eq(iter::once(200))); - assert_eq!( - super::range_inclusive(isize::MIN as i128, isize::MAX as i128 - 1).size_hint(), - (usize::MAX, Some(usize::MAX)) - ); - assert_eq!( - super::range_inclusive(isize::MIN as i128, isize::MAX as i128).size_hint(), - (usize::MAX, None) - ); - assert_eq!( - super::range_inclusive(isize::MIN as i128, isize::MAX as i128 + 1).size_hint(), - (usize::MAX, None) - ); - assert_eq!( - super::range_inclusive(i128::MIN, i128::MAX).size_hint(), - (usize::MAX, None) - ); + .eq(iter::once(200))); + assert!(super::range_inclusive(200u128, 200).rev() + .eq(iter::once(200))); + assert_eq!(super::range_inclusive(isize::MIN as i128, isize::MAX as i128 - 1).size_hint(), + (usize::MAX, Some(usize::MAX))); + assert_eq!(super::range_inclusive(isize::MIN as i128, isize::MAX as i128).size_hint(), + (usize::MAX, None)); + assert_eq!(super::range_inclusive(isize::MIN as i128, isize::MAX as i128 + 1).size_hint(), + (usize::MAX, None)); + assert_eq!(super::range_inclusive(i128::MIN, i128::MAX).size_hint(), + (usize::MAX, None)); } #[test] fn test_range_step() { - assert!(super::range_step(0, 20, 5).eq([0, 5, 10, 15].iter().cloned())); - assert!(super::range_step(20, 0, -5).eq([20, 15, 10, 5].iter().cloned())); - assert!(super::range_step(20, 0, -6).eq([20, 14, 8, 2].iter().cloned())); - assert!(super::range_step(200u8, 255, 50).eq([200u8, 250].iter().cloned())); - assert!(super::range_step(200, -5, 1).eq(iter::empty())); - assert!(super::range_step(200, 200, 1).eq(iter::empty())); + assert!(super::range_step(0, 20, 5) + .eq([0, 5, 10, 15].iter().cloned())); + assert!(super::range_step(20, 0, -5) + .eq([20, 15, 10, 5].iter().cloned())); + assert!(super::range_step(20, 0, -6) + .eq([20, 14, 8, 2].iter().cloned())); + assert!(super::range_step(200u8, 255, 50) + .eq([200u8, 250].iter().cloned())); + assert!(super::range_step(200, -5, 1) + .eq(iter::empty())); + assert!(super::range_step(200, 200, 1) + .eq(iter::empty())); } #[test] @@ -589,22 +447,34 @@ mod tests { fn test_range_step_128() { use core::u128::MAX as UMAX; - assert!(super::range_step(0u128, 20, 5).eq([0, 5, 10, 15].iter().cloned())); - assert!(super::range_step(20i128, 0, -5).eq([20, 15, 10, 5].iter().cloned())); - assert!(super::range_step(20i128, 0, -6).eq([20, 14, 8, 2].iter().cloned())); - assert!(super::range_step(UMAX - 55, UMAX, 50).eq([UMAX - 55, UMAX - 5].iter().cloned())); - assert!(super::range_step(200i128, -5, 1).eq(iter::empty())); - assert!(super::range_step(200i128, 200, 1).eq(iter::empty())); + assert!(super::range_step(0u128, 20, 5) + .eq([0, 5, 10, 15].iter().cloned())); + assert!(super::range_step(20i128, 0, -5) + .eq([20, 15, 10, 5].iter().cloned())); + assert!(super::range_step(20i128, 0, -6) + .eq([20, 14, 8, 2].iter().cloned())); + assert!(super::range_step(UMAX - 55, UMAX, 50) + .eq([UMAX - 55, UMAX - 5].iter().cloned())); + assert!(super::range_step(200i128, -5, 1) + .eq(iter::empty())); + assert!(super::range_step(200i128, 200, 1) + .eq(iter::empty())); } #[test] fn test_range_step_inclusive() { - assert!(super::range_step_inclusive(0, 20, 5).eq([0, 5, 10, 15, 20].iter().cloned())); - assert!(super::range_step_inclusive(20, 0, -5).eq([20, 15, 10, 5, 0].iter().cloned())); - assert!(super::range_step_inclusive(20, 0, -6).eq([20, 14, 8, 2].iter().cloned())); - assert!(super::range_step_inclusive(200u8, 255, 50).eq([200u8, 250].iter().cloned())); - assert!(super::range_step_inclusive(200, -5, 1).eq(iter::empty())); - assert!(super::range_step_inclusive(200, 200, 1).eq(iter::once(200))); + assert!(super::range_step_inclusive(0, 20, 5) + .eq([0, 5, 10, 15, 20].iter().cloned())); + assert!(super::range_step_inclusive(20, 0, -5) + .eq([20, 15, 10, 5, 0].iter().cloned())); + assert!(super::range_step_inclusive(20, 0, -6) + .eq([20, 14, 8, 2].iter().cloned())); + assert!(super::range_step_inclusive(200u8, 255, 50) + .eq([200u8, 250].iter().cloned())); + assert!(super::range_step_inclusive(200, -5, 1) + .eq(iter::empty())); + assert!(super::range_step_inclusive(200, 200, 1) + .eq(iter::once(200))); } #[test] @@ -612,87 +482,17 @@ mod tests { fn test_range_step_inclusive_128() { use core::u128::MAX as UMAX; - assert!(super::range_step_inclusive(0u128, 20, 5).eq([0, 5, 10, 15, 20].iter().cloned())); - assert!(super::range_step_inclusive(20i128, 0, -5).eq([20, 15, 10, 5, 0].iter().cloned())); - assert!(super::range_step_inclusive(20i128, 0, -6).eq([20, 14, 8, 2].iter().cloned())); + assert!(super::range_step_inclusive(0u128, 20, 5) + .eq([0, 5, 10, 15, 20].iter().cloned())); + assert!(super::range_step_inclusive(20i128, 0, -5) + .eq([20, 15, 10, 5, 0].iter().cloned())); + assert!(super::range_step_inclusive(20i128, 0, -6) + .eq([20, 14, 8, 2].iter().cloned())); assert!(super::range_step_inclusive(UMAX - 55, UMAX, 50) - .eq([UMAX - 55, UMAX - 5].iter().cloned())); - assert!(super::range_step_inclusive(200i128, -5, 1).eq(iter::empty())); - assert!(super::range_step_inclusive(200i128, 200, 1).eq(iter::once(200))); - } - - #[test] - fn test_range_from() { - assert!(super::range_from(10u8) - .take(5) - .eq([10, 11, 12, 13, 14].iter().cloned())); - assert_eq!(super::range_from(10u8).size_hint(), (usize::MAX, None)); - } - - #[test] - fn test_range_step_from() { - assert!(super::range_step_from(10u8, 2u8) - .take(5) - .eq([10, 12, 14, 16, 18].iter().cloned())); - assert_eq!( - super::range_step_from(10u8, 2u8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10u8, 1u8) - .take(5) - .eq([10, 11, 12, 13, 14].iter().cloned())); - assert_eq!( - super::range_step_from(10u8, 1u8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10u8, 0u8) - .take(5) - .eq([10, 10, 10, 10, 10].iter().cloned())); - assert_eq!( - super::range_step_from(10u8, 0u8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10i8, 2i8) - .take(5) - .eq([10, 12, 14, 16, 18].iter().cloned())); - assert_eq!( - super::range_step_from(10i8, 2i8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10i8, 1i8) - .take(5) - .eq([10, 11, 12, 13, 14].iter().cloned())); - assert_eq!( - super::range_step_from(10i8, 1i8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10i8, 0i8) - .take(5) - .eq([10, 10, 10, 10, 10].iter().cloned())); - assert_eq!( - super::range_step_from(10i8, 0i8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10i8, -1i8) - .take(5) - .eq([10, 9, 8, 7, 6].iter().cloned())); - assert_eq!( - super::range_step_from(10i8, -1i8).size_hint(), - (usize::MAX, None) - ); - - assert!(super::range_step_from(10i8, -2i8) - .take(5) - .eq([10, 8, 6, 4, 2].iter().cloned())); - assert_eq!( - super::range_step_from(10i8, -2i8).size_hint(), - (usize::MAX, None) - ); + .eq([UMAX - 55, UMAX - 5].iter().cloned())); + assert!(super::range_step_inclusive(200i128, -5, 1) + .eq(iter::empty())); + assert!(super::range_step_inclusive(200i128, 200, 1) + .eq(iter::once(200))); } } diff --git a/third_party/rust/num-rational-0.2.1/.cargo-checksum.json b/third_party/rust/num-rational-0.2.1/.cargo-checksum.json deleted file mode 100644 index a092a8a9f3de..000000000000 --- a/third_party/rust/num-rational-0.2.1/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"0955835c06d82075c9e70941ba0a923c918d3ecb0baadbd0bfb14a6503b47fed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"07973a21c5e6cbc14fb304f32d51f8df7c538b3b6c1837b5c5c19e83e316cc9e","RELEASES.md":"8bc9a6e43749b87a6b01002ea45dc7b9ef34b27c905fc7c822b2256603aae3f1","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"16de2aa57e754fc1526d0400b5d87a3f771296705fca54601aa598b6f74ded8f","ci/rustup.sh":"bc6270c57c9fc72ab407336bb8b7d9027dd08502c9c08105c3848d1f796ed6eb","ci/test_full.sh":"051ecff898e891c50356b17d7da0350541d14e83fa753737e61b67d7e5eb9a0e","src/lib.rs":"cfdf09d8d5f7df2cdaea25e548bc2050dfc339afcd8d6f3bfc5ccce068850541"},"package":"4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"} \ No newline at end of file diff --git a/third_party/rust/num-rational-0.2.1/Cargo.toml b/third_party/rust/num-rational-0.2.1/Cargo.toml deleted file mode 100644 index def7033f5800..000000000000 --- a/third_party/rust/num-rational-0.2.1/Cargo.toml +++ /dev/null @@ -1,51 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "num-rational" -version = "0.2.1" -authors = ["The Rust Project Developers"] -build = "build.rs" -description = "Rational numbers implementation for Rust" -homepage = "https://github.com/rust-num/num-rational" -documentation = "https://docs.rs/num-rational" -readme = "README.md" -keywords = ["mathematics", "numerics"] -categories = ["algorithms", "data-structures", "science", "no-std"] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num-rational" -[package.metadata.docs.rs] -features = ["std", "bigint-std", "serde"] -[dependencies.num-bigint] -version = "0.2.0" -optional = true -default-features = false - -[dependencies.num-integer] -version = "0.1.38" -default-features = false - -[dependencies.num-traits] -version = "0.2.4" -default-features = false - -[dependencies.serde] -version = "1.0.0" -optional = true -default-features = false - -[features] -bigint = ["num-bigint"] -bigint-std = ["bigint", "num-bigint/std"] -default = ["bigint-std", "std"] -i128 = ["num-integer/i128", "num-traits/i128"] -std = ["num-integer/std", "num-traits/std"] diff --git a/third_party/rust/num-rational-0.2.1/LICENSE-APACHE b/third_party/rust/num-rational-0.2.1/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/third_party/rust/num-rational-0.2.1/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/third_party/rust/num-rational-0.2.1/LICENSE-MIT b/third_party/rust/num-rational-0.2.1/LICENSE-MIT deleted file mode 100644 index 39d4bdb5acd3..000000000000 --- a/third_party/rust/num-rational-0.2.1/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/num-rational-0.2.1/README.md b/third_party/rust/num-rational-0.2.1/README.md deleted file mode 100644 index ebd0f314f9fb..000000000000 --- a/third_party/rust/num-rational-0.2.1/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# num-rational - -[![crate](https://img.shields.io/crates/v/num-rational.svg)](https://crates.io/crates/num-rational) -[![documentation](https://docs.rs/num-rational/badge.svg)](https://docs.rs/num-rational) -![minimum rustc 1.15](https://img.shields.io/badge/rustc-1.15+-red.svg) -[![Travis status](https://travis-ci.org/rust-num/num-rational.svg?branch=master)](https://travis-ci.org/rust-num/num-rational) - -Generic `Rational` numbers for Rust. - -## Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] -num-rational = "0.2" -``` - -and this to your crate root: - -```rust -extern crate num_rational; -``` - -## Features - -This crate can be used without the standard library (`#![no_std]`) by disabling -the default `std` feature. Use this in `Cargo.toml`: - -```toml -[dependencies.num-rational] -version = "0.2" -default-features = false -``` - -Implementations for `i128` and `u128` are only available with Rust 1.26 and -later. The build script automatically detects this, but you can make it -mandatory by enabling the `i128` crate feature. - -## Releases - -Release notes are available in [RELEASES.md](RELEASES.md). - -## Compatibility - -The `num-rational` crate is tested for rustc 1.15 and greater. diff --git a/third_party/rust/num-rational-0.2.1/RELEASES.md b/third_party/rust/num-rational-0.2.1/RELEASES.md deleted file mode 100644 index c427db3ac3c4..000000000000 --- a/third_party/rust/num-rational-0.2.1/RELEASES.md +++ /dev/null @@ -1,63 +0,0 @@ -# Release 0.2.1 (2018-06-22) - -- Maintenance release to fix `html_root_url`. - -# Release 0.2.0 (2018-06-19) - -### Enhancements - -- [`Ratio` now implements `One::is_one` and the `Inv` trait][19]. -- [`Ratio` now implements `Sum` and `Product`][25]. -- [`Ratio` now supports `i128` and `u128` components][29] with Rust 1.26+. -- [`Ratio` now implements the `Pow` trait][21]. - -### Breaking Changes - -- [`num-rational` now requires rustc 1.15 or greater][18]. -- [There is now a `std` feature][23], enabled by default, along with the - implication that building *without* this feature makes this a `#![no_std]` - crate. A few methods now require `FloatCore` instead of `Float`. -- [The `serde` dependency has been updated to 1.0][24], and `rustc-serialize` - is no longer supported by `num-complex`. -- The optional `num-bigint` dependency has been updated to 0.2, and should be - enabled using the `bigint-std` feature. In the future, it may be possible - to use the `bigint` feature with `no_std`. - -**Contributors**: @clarcharr, @cuviper, @Emerentius, @robomancer-or, @vks - -[18]: https://github.com/rust-num/num-rational/pull/18 -[19]: https://github.com/rust-num/num-rational/pull/19 -[21]: https://github.com/rust-num/num-rational/pull/21 -[23]: https://github.com/rust-num/num-rational/pull/23 -[24]: https://github.com/rust-num/num-rational/pull/24 -[25]: https://github.com/rust-num/num-rational/pull/25 -[29]: https://github.com/rust-num/num-rational/pull/29 - - -# Release 0.1.42 (2018-02-08) - -- Maintenance release to update dependencies. - - -# Release 0.1.41 (2018-01-26) - -- [num-rational now has its own source repository][num-356] at [rust-num/num-rational][home]. -- [`Ratio` now implements `CheckedAdd`, `CheckedSub`, `CheckedMul`, and `CheckedDiv`][11]. -- [`Ratio` now implements `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, and `RemAssign`][12] - with either `Ratio` or an integer on the right side. The non-assignment operators now also - accept integers as an operand. -- [`Ratio` operators now make fewer `clone()` calls][14]. - -Thanks to @c410-f3r, @cuviper, and @psimonyi for their contributions! - -[home]: https://github.com/rust-num/num-rational -[num-356]: https://github.com/rust-num/num/pull/356 -[11]: https://github.com/rust-num/num-rational/pull/11 -[12]: https://github.com/rust-num/num-rational/pull/12 -[14]: https://github.com/rust-num/num-rational/pull/14 - - -# Prior releases - -No prior release notes were kept. Thanks all the same to the many -contributors that have made this crate what it is! diff --git a/third_party/rust/num-rational-0.2.1/build.rs b/third_party/rust/num-rational-0.2.1/build.rs deleted file mode 100644 index fd60866558c3..000000000000 --- a/third_party/rust/num-rational-0.2.1/build.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::env; -use std::io::Write; -use std::process::{Command, Stdio}; - -fn main() { - if probe("fn main() { 0i128; }") { - println!("cargo:rustc-cfg=has_i128"); - } else if env::var_os("CARGO_FEATURE_I128").is_some() { - panic!("i128 support was not detected!"); - } -} - -/// Test if a code snippet can be compiled -fn probe(code: &str) -> bool { - let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); - let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR"); - - let mut child = Command::new(rustc) - .arg("--out-dir") - .arg(out_dir) - .arg("--emit=obj") - .arg("-") - .stdin(Stdio::piped()) - .spawn() - .expect("rustc probe"); - - child - .stdin - .as_mut() - .expect("rustc stdin") - .write_all(code.as_bytes()) - .expect("write rustc stdin"); - - child.wait().expect("rustc probe").success() -} diff --git a/third_party/rust/num-rational-0.2.1/src/lib.rs b/third_party/rust/num-rational-0.2.1/src/lib.rs deleted file mode 100644 index a49d712b692f..000000000000 --- a/third_party/rust/num-rational-0.2.1/src/lib.rs +++ /dev/null @@ -1,1927 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Rational numbers -//! -//! ## Compatibility -//! -//! The `num-rational` crate is tested for rustc 1.15 and greater. - -#![doc(html_root_url = "https://docs.rs/num-rational/0.2")] - -#![no_std] - -#[cfg(feature = "serde")] -extern crate serde; -#[cfg(feature = "bigint")] -extern crate num_bigint as bigint; - -extern crate num_traits as traits; -extern crate num_integer as integer; - -#[cfg(feature = "std")] -#[cfg_attr(test, macro_use)] -extern crate std; - -use core::cmp; -#[cfg(feature = "std")] -use std::error::Error; -use core::fmt; -use core::hash::{Hash, Hasher}; -use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; -use core::str::FromStr; - -#[cfg(feature = "bigint")] -use bigint::{BigInt, BigUint, Sign}; - -use integer::Integer; -use traits::float::FloatCore; -use traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Inv, Num, - NumCast, One, Pow, Signed, Zero}; - -/// Represents the ratio between two numbers. -#[derive(Copy, Clone, Debug)] -#[allow(missing_docs)] -pub struct Ratio { - /// Numerator. - numer: T, - /// Denominator. - denom: T, -} - -/// Alias for a `Ratio` of machine-sized integers. -pub type Rational = Ratio; -/// Alias for a `Ratio` of 32-bit-sized integers. -pub type Rational32 = Ratio; -/// Alias for a `Ratio` of 64-bit-sized integers. -pub type Rational64 = Ratio; - -#[cfg(feature = "bigint")] -/// Alias for arbitrary precision rationals. -pub type BigRational = Ratio; - -impl Ratio { - /// Creates a new `Ratio`. Fails if `denom` is zero. - #[inline] - pub fn new(numer: T, denom: T) -> Ratio { - if denom.is_zero() { - panic!("denominator == 0"); - } - let mut ret = Ratio::new_raw(numer, denom); - ret.reduce(); - ret - } - - /// Creates a `Ratio` representing the integer `t`. - #[inline] - pub fn from_integer(t: T) -> Ratio { - Ratio::new_raw(t, One::one()) - } - - /// Creates a `Ratio` without checking for `denom == 0` or reducing. - #[inline] - pub fn new_raw(numer: T, denom: T) -> Ratio { - Ratio { - numer: numer, - denom: denom, - } - } - - /// Converts to an integer, rounding towards zero. - #[inline] - pub fn to_integer(&self) -> T { - self.trunc().numer - } - - /// Gets an immutable reference to the numerator. - #[inline] - pub fn numer<'a>(&'a self) -> &'a T { - &self.numer - } - - /// Gets an immutable reference to the denominator. - #[inline] - pub fn denom<'a>(&'a self) -> &'a T { - &self.denom - } - - /// Returns true if the rational number is an integer (denominator is 1). - #[inline] - pub fn is_integer(&self) -> bool { - self.denom.is_one() - } - - /// Puts self into lowest terms, with denom > 0. - fn reduce(&mut self) { - let g: T = self.numer.gcd(&self.denom); - - // FIXME(#5992): assignment operator overloads - // self.numer /= g; - // T: Clone + Integer != T: Clone + NumAssign - self.numer = self.numer.clone() / g.clone(); - // FIXME(#5992): assignment operator overloads - // self.denom /= g; - // T: Clone + Integer != T: Clone + NumAssign - self.denom = self.denom.clone() / g; - - // keep denom positive! - if self.denom < T::zero() { - self.numer = T::zero() - self.numer.clone(); - self.denom = T::zero() - self.denom.clone(); - } - } - - /// Returns a reduced copy of self. - /// - /// In general, it is not necessary to use this method, as the only - /// method of procuring a non-reduced fraction is through `new_raw`. - pub fn reduced(&self) -> Ratio { - let mut ret = self.clone(); - ret.reduce(); - ret - } - - /// Returns the reciprocal. - /// - /// Fails if the `Ratio` is zero. - #[inline] - pub fn recip(&self) -> Ratio { - match self.numer.cmp(&T::zero()) { - cmp::Ordering::Equal => panic!("numerator == 0"), - cmp::Ordering::Greater => Ratio::new_raw(self.denom.clone(), self.numer.clone()), - cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom.clone(), - T::zero() - self.numer.clone()) - } - } - - /// Rounds towards minus infinity. - #[inline] - pub fn floor(&self) -> Ratio { - if *self < Zero::zero() { - let one: T = One::one(); - Ratio::from_integer((self.numer.clone() - self.denom.clone() + one) / - self.denom.clone()) - } else { - Ratio::from_integer(self.numer.clone() / self.denom.clone()) - } - } - - /// Rounds towards plus infinity. - #[inline] - pub fn ceil(&self) -> Ratio { - if *self < Zero::zero() { - Ratio::from_integer(self.numer.clone() / self.denom.clone()) - } else { - let one: T = One::one(); - Ratio::from_integer((self.numer.clone() + self.denom.clone() - one) / - self.denom.clone()) - } - } - - /// Rounds to the nearest integer. Rounds half-way cases away from zero. - #[inline] - pub fn round(&self) -> Ratio { - let zero: Ratio = Zero::zero(); - let one: T = One::one(); - let two: T = one.clone() + one.clone(); - - // Find unsigned fractional part of rational number - let mut fractional = self.fract(); - if fractional < zero { - fractional = zero - fractional - }; - - // The algorithm compares the unsigned fractional part with 1/2, that - // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use - // a >= (b/2)+1. This avoids overflow issues. - let half_or_larger = if fractional.denom().is_even() { - *fractional.numer() >= fractional.denom().clone() / two.clone() - } else { - *fractional.numer() >= (fractional.denom().clone() / two.clone()) + one.clone() - }; - - if half_or_larger { - let one: Ratio = One::one(); - if *self >= Zero::zero() { - self.trunc() + one - } else { - self.trunc() - one - } - } else { - self.trunc() - } - } - - /// Rounds towards zero. - #[inline] - pub fn trunc(&self) -> Ratio { - Ratio::from_integer(self.numer.clone() / self.denom.clone()) - } - - /// Returns the fractional part of a number, with division rounded towards zero. - /// - /// Satisfies `self == self.trunc() + self.fract()`. - #[inline] - pub fn fract(&self) -> Ratio { - Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone()) - } -} - -impl> Ratio { - /// Raises the `Ratio` to the power of an exponent. - #[inline] - pub fn pow(&self, expon: i32) -> Ratio { - Pow::pow(self, expon) - } -} - -macro_rules! pow_impl { - ($exp: ty) => { - pow_impl!($exp, $exp); - }; - ($exp: ty, $unsigned: ty) => { - impl> Pow<$exp> for Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: $exp) -> Ratio { - match expon.cmp(&0) { - cmp::Ordering::Equal => One::one(), - cmp::Ordering::Less => { - let expon = expon.wrapping_abs() as $unsigned; - Ratio::new_raw( - Pow::pow(self.denom, expon), - Pow::pow(self.numer, expon), - ) - }, - cmp::Ordering::Greater => { - Ratio::new_raw( - Pow::pow(self.numer, expon as $unsigned), - Pow::pow(self.denom, expon as $unsigned), - ) - } - } - } - } - impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for &'a Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: $exp) -> Ratio { - Pow::pow(self.clone(), expon) - } - } - impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'a $exp) -> Ratio { - Pow::pow(self, *expon) - } - } - impl<'a, 'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for &'b Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'a $exp) -> Ratio { - Pow::pow(self.clone(), *expon) - } - } - }; -} - -// this is solely to make `pow_impl!` work -trait WrappingAbs: Sized { - fn wrapping_abs(self) -> Self { - self - } -} -impl WrappingAbs for u8 {} -impl WrappingAbs for u16 {} -impl WrappingAbs for u32 {} -impl WrappingAbs for u64 {} -impl WrappingAbs for usize {} - -pow_impl!(i8, u8); -pow_impl!(i16, u16); -pow_impl!(i32, u32); -pow_impl!(i64, u64); -pow_impl!(isize, usize); -pow_impl!(u8); -pow_impl!(u16); -pow_impl!(u32); -pow_impl!(u64); -pow_impl!(usize); - -// TODO: pow_impl!(BigUint) and pow_impl!(BigInt, BigUint) - -#[cfg(feature = "bigint")] -impl Ratio { - /// Converts a float into a rational number. - pub fn from_float(f: T) -> Option { - if !f.is_finite() { - return None; - } - let (mantissa, exponent, sign) = f.integer_decode(); - let bigint_sign = if sign == 1 { - Sign::Plus - } else { - Sign::Minus - }; - if exponent < 0 { - let one: BigInt = One::one(); - let denom: BigInt = one << ((-exponent) as usize); - let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap(); - Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom)) - } else { - let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap(); - numer = numer << (exponent as usize); - Some(Ratio::from_integer(BigInt::from_biguint(bigint_sign, numer))) - } - } -} - -// From integer -impl From for Ratio where T: Clone + Integer { - fn from(x: T) -> Ratio { - Ratio::from_integer(x) - } -} - -// From pair (through the `new` constructor) -impl From<(T, T)> for Ratio where T: Clone + Integer { - fn from(pair: (T, T)) -> Ratio { - Ratio::new(pair.0, pair.1) - } -} - -// Comparisons - -// Mathematically, comparing a/b and c/d is the same as comparing a*d and b*c, but it's very easy -// for those multiplications to overflow fixed-size integers, so we need to take care. - -impl Ord for Ratio { - #[inline] - fn cmp(&self, other: &Self) -> cmp::Ordering { - // With equal denominators, the numerators can be directly compared - if self.denom == other.denom { - let ord = self.numer.cmp(&other.numer); - return if self.denom < T::zero() { - ord.reverse() - } else { - ord - }; - } - - // With equal numerators, the denominators can be inversely compared - if self.numer == other.numer { - let ord = self.denom.cmp(&other.denom); - return if self.numer < T::zero() { - ord - } else { - ord.reverse() - }; - } - - // Unfortunately, we don't have CheckedMul to try. That could sometimes avoid all the - // division below, or even always avoid it for BigInt and BigUint. - // FIXME- future breaking change to add Checked* to Integer? - - // Compare as floored integers and remainders - let (self_int, self_rem) = self.numer.div_mod_floor(&self.denom); - let (other_int, other_rem) = other.numer.div_mod_floor(&other.denom); - match self_int.cmp(&other_int) { - cmp::Ordering::Greater => cmp::Ordering::Greater, - cmp::Ordering::Less => cmp::Ordering::Less, - cmp::Ordering::Equal => { - match (self_rem.is_zero(), other_rem.is_zero()) { - (true, true) => cmp::Ordering::Equal, - (true, false) => cmp::Ordering::Less, - (false, true) => cmp::Ordering::Greater, - (false, false) => { - // Compare the reciprocals of the remaining fractions in reverse - let self_recip = Ratio::new_raw(self.denom.clone(), self_rem); - let other_recip = Ratio::new_raw(other.denom.clone(), other_rem); - self_recip.cmp(&other_recip).reverse() - } - } - } - } - } -} - -impl PartialOrd for Ratio { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for Ratio { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == cmp::Ordering::Equal - } -} - -impl Eq for Ratio {} - -// NB: We can't just `#[derive(Hash)]`, because it needs to agree -// with `Eq` even for non-reduced ratios. -impl Hash for Ratio { - fn hash(&self, state: &mut H) { - recurse(&self.numer, &self.denom, state); - - fn recurse(numer: &T, denom: &T, state: &mut H) { - if !denom.is_zero() { - let (int, rem) = numer.div_mod_floor(denom); - int.hash(state); - recurse(denom, &rem, state); - } else { - denom.hash(state); - } - } - } -} - -mod iter_sum_product { - use ::core::iter::{Sum, Product}; - use Ratio; - use integer::Integer; - use traits::{Zero, One}; - - impl Sum for Ratio { - fn sum(iter: I) -> Self - where - I: Iterator> - { - iter.fold(Self::zero(), |sum, num| sum + num) - } - } - - impl<'a, T: Integer + Clone> Sum<&'a Ratio> for Ratio { - fn sum(iter: I) -> Self - where - I: Iterator> - { - iter.fold(Self::zero(), |sum, num| sum + num) - } - } - - impl Product for Ratio { - fn product(iter: I) -> Self - where - I: Iterator> - { - iter.fold(Self::one(), |prod, num| prod * num) - } - } - - impl<'a, T: Integer + Clone> Product<&'a Ratio> for Ratio { - fn product(iter: I) -> Self - where - I: Iterator> - { - iter.fold(Self::one(), |prod, num| prod * num) - } - } -} - -mod opassign { - use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; - - use Ratio; - use integer::Integer; - use traits::NumAssign; - - impl AddAssign for Ratio { - fn add_assign(&mut self, other: Ratio) { - self.numer *= other.denom.clone(); - self.numer += self.denom.clone() * other.numer; - self.denom *= other.denom; - self.reduce(); - } - } - - impl DivAssign for Ratio { - fn div_assign(&mut self, other: Ratio) { - self.numer *= other.denom; - self.denom *= other.numer; - self.reduce(); - } - } - - impl MulAssign for Ratio { - fn mul_assign(&mut self, other: Ratio) { - self.numer *= other.numer; - self.denom *= other.denom; - self.reduce(); - } - } - - impl RemAssign for Ratio { - fn rem_assign(&mut self, other: Ratio) { - self.numer *= other.denom.clone(); - self.numer %= self.denom.clone() * other.numer; - self.denom *= other.denom; - self.reduce(); - } - } - - impl SubAssign for Ratio { - fn sub_assign(&mut self, other: Ratio) { - self.numer *= other.denom.clone(); - self.numer -= self.denom.clone() * other.numer; - self.denom *= other.denom; - self.reduce(); - } - } - - // a/b + c/1 = (a*1 + b*c) / (b*1) = (a + b*c) / b - impl AddAssign for Ratio { - fn add_assign(&mut self, other: T) { - self.numer += self.denom.clone() * other; - self.reduce(); - } - } - - impl DivAssign for Ratio { - fn div_assign(&mut self, other: T) { - self.denom *= other; - self.reduce(); - } - } - - impl MulAssign for Ratio { - fn mul_assign(&mut self, other: T) { - self.numer *= other; - self.reduce(); - } - } - - // a/b % c/1 = (a*1 % b*c) / (b*1) = (a % b*c) / b - impl RemAssign for Ratio { - fn rem_assign(&mut self, other: T) { - self.numer %= self.denom.clone() * other; - self.reduce(); - } - } - - // a/b - c/1 = (a*1 - b*c) / (b*1) = (a - b*c) / b - impl SubAssign for Ratio { - fn sub_assign(&mut self, other: T) { - self.numer -= self.denom.clone() * other; - self.reduce(); - } - } - - macro_rules! forward_op_assign { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + Integer + NumAssign> $imp<&'a Ratio> for Ratio { - #[inline] - fn $method(&mut self, other: &Ratio) { - self.$method(other.clone()) - } - } - impl<'a, T: Clone + Integer + NumAssign> $imp<&'a T> for Ratio { - #[inline] - fn $method(&mut self, other: &T) { - self.$method(other.clone()) - } - } - } - } - - forward_op_assign!(impl AddAssign, add_assign); - forward_op_assign!(impl DivAssign, div_assign); - forward_op_assign!(impl MulAssign, mul_assign); - forward_op_assign!(impl RemAssign, rem_assign); - forward_op_assign!(impl SubAssign, sub_assign); -} - -macro_rules! forward_ref_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, 'b, T: Clone + Integer> $imp<&'b Ratio> for &'a Ratio { - type Output = Ratio; - - #[inline] - fn $method(self, other: &'b Ratio) -> Ratio { - self.clone().$method(other.clone()) - } - } - impl<'a, 'b, T: Clone + Integer> $imp<&'b T> for &'a Ratio { - type Output = Ratio; - - #[inline] - fn $method(self, other: &'b T) -> Ratio { - self.clone().$method(other.clone()) - } - } - } -} - -macro_rules! forward_ref_val_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T> $imp> for &'a Ratio where - T: Clone + Integer - { - type Output = Ratio; - - #[inline] - fn $method(self, other: Ratio) -> Ratio { - self.clone().$method(other) - } - } - impl<'a, T> $imp for &'a Ratio where - T: Clone + Integer - { - type Output = Ratio; - - #[inline] - fn $method(self, other: T) -> Ratio { - self.clone().$method(other) - } - } - } -} - -macro_rules! forward_val_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T> $imp<&'a Ratio> for Ratio where - T: Clone + Integer - { - type Output = Ratio; - - #[inline] - fn $method(self, other: &Ratio) -> Ratio { - self.$method(other.clone()) - } - } - impl<'a, T> $imp<&'a T> for Ratio where - T: Clone + Integer - { - type Output = Ratio; - - #[inline] - fn $method(self, other: &T) -> Ratio { - self.$method(other.clone()) - } - } - } -} - -macro_rules! forward_all_binop { - (impl $imp:ident, $method:ident) => { - forward_ref_ref_binop!(impl $imp, $method); - forward_ref_val_binop!(impl $imp, $method); - forward_val_ref_binop!(impl $imp, $method); - }; -} - -// Arithmetic -forward_all_binop!(impl Mul, mul); -// a/b * c/d = (a*c)/(b*d) -impl Mul> for Ratio - where T: Clone + Integer -{ - type Output = Ratio; - #[inline] - fn mul(self, rhs: Ratio) -> Ratio { - Ratio::new(self.numer * rhs.numer, - self.denom * rhs.denom) - } -} -// a/b * c/1 = (a*c) / (b*1) = (a*c) / b -impl Mul for Ratio - where T: Clone + Integer -{ - type Output = Ratio; - #[inline] - fn mul(self, rhs: T) -> Ratio { - Ratio::new(self.numer * rhs, - self.denom) - } -} - -forward_all_binop!(impl Div, div); -// (a/b) / (c/d) = (a*d) / (b*c) -impl Div> for Ratio - where T: Clone + Integer -{ - type Output = Ratio; - - #[inline] - fn div(self, rhs: Ratio) -> Ratio { - Ratio::new(self.numer * rhs.denom, - self.denom * rhs.numer) - } -} -// (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c) -impl Div for Ratio - where T: Clone + Integer -{ - type Output = Ratio; - - #[inline] - fn div(self, rhs: T) -> Ratio { - Ratio::new(self.numer, - self.denom * rhs) - } -} - -macro_rules! arith_impl { - (impl $imp:ident, $method:ident) => { - forward_all_binop!(impl $imp, $method); - // Abstracts the a/b `op` c/d = (a*d `op` b*c) / (b*d) pattern - impl $imp> for Ratio { - type Output = Ratio; - #[inline] - fn $method(self, rhs: Ratio) -> Ratio { - Ratio::new((self.numer * rhs.denom.clone()).$method(self.denom.clone() * rhs.numer), - self.denom * rhs.denom) - } - } - // Abstracts the a/b `op` c/1 = (a*1 `op` b*c) / (b*1) = (a `op` b*c) / b pattern - impl $imp for Ratio { - type Output = Ratio; - #[inline] - fn $method(self, rhs: T) -> Ratio { - Ratio::new(self.numer.$method(self.denom.clone() * rhs), - self.denom) - } - } - } -} - -arith_impl!(impl Add, add); -arith_impl!(impl Sub, sub); -arith_impl!(impl Rem, rem); - -// Like `std::try!` for Option, unwrap the value or early-return None. -// Since Rust 1.22 this can be replaced by the `?` operator. -macro_rules! otry { - ($expr:expr) => (match $expr { - Some(val) => val, - None => return None, - }) -} - -// a/b * c/d = (a*c)/(b*d) -impl CheckedMul for Ratio - where T: Clone + Integer + CheckedMul -{ - #[inline] - fn checked_mul(&self, rhs: &Ratio) -> Option> { - Some(Ratio::new(otry!(self.numer.checked_mul(&rhs.numer)), - otry!(self.denom.checked_mul(&rhs.denom)))) - } -} - -// (a/b) / (c/d) = (a*d)/(b*c) -impl CheckedDiv for Ratio - where T: Clone + Integer + CheckedMul -{ - #[inline] - fn checked_div(&self, rhs: &Ratio) -> Option> { - let bc = otry!(self.denom.checked_mul(&rhs.numer)); - if bc.is_zero() { - None - } else { - Some(Ratio::new(otry!(self.numer.checked_mul(&rhs.denom)), bc)) - } - } -} - -// As arith_impl! but for Checked{Add,Sub} traits -macro_rules! checked_arith_impl { - (impl $imp:ident, $method:ident) => { - impl $imp for Ratio { - #[inline] - fn $method(&self, rhs: &Ratio) -> Option> { - let ad = otry!(self.numer.checked_mul(&rhs.denom)); - let bc = otry!(self.denom.checked_mul(&rhs.numer)); - let bd = otry!(self.denom.checked_mul(&rhs.denom)); - Some(Ratio::new(otry!(ad.$method(&bc)), bd)) - } - } - } -} - -// a/b + c/d = (a*d + b*c)/(b*d) -checked_arith_impl!(impl CheckedAdd, checked_add); - -// a/b - c/d = (a*d - b*c)/(b*d) -checked_arith_impl!(impl CheckedSub, checked_sub); - -impl Neg for Ratio - where T: Clone + Integer + Neg -{ - type Output = Ratio; - - #[inline] - fn neg(self) -> Ratio { - Ratio::new_raw(-self.numer, self.denom) - } -} - -impl<'a, T> Neg for &'a Ratio - where T: Clone + Integer + Neg -{ - type Output = Ratio; - - #[inline] - fn neg(self) -> Ratio { - -self.clone() - } -} - -impl Inv for Ratio - where T: Clone + Integer -{ - type Output = Ratio; - - #[inline] - fn inv(self) -> Ratio { - self.recip() - } -} - -impl<'a, T> Inv for &'a Ratio - where T: Clone + Integer -{ - type Output = Ratio; - - #[inline] - fn inv(self) -> Ratio { - self.recip() - } -} - -// Constants -impl Zero for Ratio { - #[inline] - fn zero() -> Ratio { - Ratio::new_raw(Zero::zero(), One::one()) - } - - #[inline] - fn is_zero(&self) -> bool { - self.numer.is_zero() - } -} - -impl One for Ratio { - #[inline] - fn one() -> Ratio { - Ratio::new_raw(One::one(), One::one()) - } - - #[inline] - fn is_one(&self) -> bool { - self.numer == self.denom - } -} - -impl Num for Ratio { - type FromStrRadixErr = ParseRatioError; - - /// Parses `numer/denom` where the numbers are in base `radix`. - fn from_str_radix(s: &str, radix: u32) -> Result, ParseRatioError> { - if s.splitn(2, '/').count() == 2 { - let mut parts = s.splitn(2, '/').map(|ss| T::from_str_radix(ss, radix).map_err(|_| { - ParseRatioError { kind: RatioErrorKind::ParseError } - })); - let numer: T = parts.next().unwrap()?; - let denom: T = parts.next().unwrap()?; - if denom.is_zero() { - Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator }) - } else { - Ok(Ratio::new(numer, denom)) - } - } else { - Err(ParseRatioError { kind: RatioErrorKind::ParseError }) - } - } -} - -impl Signed for Ratio { - #[inline] - fn abs(&self) -> Ratio { - if self.is_negative() { - -self.clone() - } else { - self.clone() - } - } - - #[inline] - fn abs_sub(&self, other: &Ratio) -> Ratio { - if *self <= *other { - Zero::zero() - } else { - self - other - } - } - - #[inline] - fn signum(&self) -> Ratio { - if self.is_positive() { - Self::one() - } else if self.is_zero() { - Self::zero() - } else { - -Self::one() - } - } - - #[inline] - fn is_positive(&self) -> bool { - (self.numer.is_positive() && self.denom.is_positive()) || - (self.numer.is_negative() && self.denom.is_negative()) - } - - #[inline] - fn is_negative(&self) -> bool { - (self.numer.is_negative() && self.denom.is_positive()) || - (self.numer.is_positive() && self.denom.is_negative()) - } -} - -// String conversions -impl fmt::Display for Ratio - where T: fmt::Display + Eq + One -{ - /// Renders as `numer/denom`. If denom=1, renders as numer. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.denom.is_one() { - write!(f, "{}", self.numer) - } else { - write!(f, "{}/{}", self.numer, self.denom) - } - } -} - -impl FromStr for Ratio { - type Err = ParseRatioError; - - /// Parses `numer/denom` or just `numer`. - fn from_str(s: &str) -> Result, ParseRatioError> { - let mut split = s.splitn(2, '/'); - - let n = try!(split.next().ok_or(ParseRatioError { kind: RatioErrorKind::ParseError })); - let num = try!(FromStr::from_str(n) - .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError })); - - let d = split.next().unwrap_or("1"); - let den = try!(FromStr::from_str(d) - .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError })); - - if Zero::is_zero(&den) { - Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator }) - } else { - Ok(Ratio::new(num, den)) - } - } -} - -impl Into<(T, T)> for Ratio { - fn into(self) -> (T, T) { - (self.numer, self.denom) - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Ratio - where T: serde::Serialize + Clone + Integer + PartialOrd -{ - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer - { - (self.numer(), self.denom()).serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de, T> serde::Deserialize<'de> for Ratio - where T: serde::Deserialize<'de> + Clone + Integer + PartialOrd -{ - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'de> - { - use serde::de::Unexpected; - use serde::de::Error; - let (numer, denom): (T,T) = try!(serde::Deserialize::deserialize(deserializer)); - if denom.is_zero() { - Err(Error::invalid_value(Unexpected::Signed(0), &"a ratio with non-zero denominator")) - } else { - Ok(Ratio::new_raw(numer, denom)) - } - } -} - -// FIXME: Bubble up specific errors -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct ParseRatioError { - kind: RatioErrorKind, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -enum RatioErrorKind { - ParseError, - ZeroDenominator, -} - -impl fmt::Display for ParseRatioError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.kind.description().fmt(f) - } -} - -#[cfg(feature = "std")] -impl Error for ParseRatioError { - fn description(&self) -> &str { - self.kind.description() - } -} - -impl RatioErrorKind { - fn description(&self) -> &'static str { - match *self { - RatioErrorKind::ParseError => "failed to parse integer", - RatioErrorKind::ZeroDenominator => "zero value denominator", - } - } -} - -#[cfg(feature = "bigint")] -impl FromPrimitive for Ratio { - fn from_i64(n: i64) -> Option { - Some(Ratio::from_integer(n.into())) - } - - #[cfg(has_i128)] - fn from_i128(n: i128) -> Option { - Some(Ratio::from_integer(n.into())) - } - - fn from_u64(n: u64) -> Option { - Some(Ratio::from_integer(n.into())) - } - - #[cfg(has_i128)] - fn from_u128(n: u128) -> Option { - Some(Ratio::from_integer(n.into())) - } - - fn from_f32(n: f32) -> Option { - Ratio::from_float(n) - } - - fn from_f64(n: f64) -> Option { - Ratio::from_float(n) - } -} - -macro_rules! from_primitive_integer { - ($typ:ty, $approx:ident) => { - impl FromPrimitive for Ratio<$typ> { - fn from_i64(n: i64) -> Option { - <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer) - } - - #[cfg(has_i128)] - fn from_i128(n: i128) -> Option { - <$typ as FromPrimitive>::from_i128(n).map(Ratio::from_integer) - } - - fn from_u64(n: u64) -> Option { - <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer) - } - - #[cfg(has_i128)] - fn from_u128(n: u128) -> Option { - <$typ as FromPrimitive>::from_u128(n).map(Ratio::from_integer) - } - - fn from_f32(n: f32) -> Option { - $approx(n, 10e-20, 30) - } - - fn from_f64(n: f64) -> Option { - $approx(n, 10e-20, 30) - } - } - } -} - -from_primitive_integer!(i8, approximate_float); -from_primitive_integer!(i16, approximate_float); -from_primitive_integer!(i32, approximate_float); -from_primitive_integer!(i64, approximate_float); -#[cfg(has_i128)] -from_primitive_integer!(i128, approximate_float); -from_primitive_integer!(isize, approximate_float); - -from_primitive_integer!(u8, approximate_float_unsigned); -from_primitive_integer!(u16, approximate_float_unsigned); -from_primitive_integer!(u32, approximate_float_unsigned); -from_primitive_integer!(u64, approximate_float_unsigned); -#[cfg(has_i128)] -from_primitive_integer!(u128, approximate_float_unsigned); -from_primitive_integer!(usize, approximate_float_unsigned); - -impl Ratio { - pub fn approximate_float(f: F) -> Option> { - // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems - // to work well. Might want to choose something based on the types in the future, e.g. - // T::max().recip() and T::bits() or something similar. - let epsilon = ::from(10e-20).expect("Can't convert 10e-20"); - approximate_float(f, epsilon, 30) - } -} - -fn approximate_float(val: F, max_error: F, max_iterations: usize) -> Option> - where T: Integer + Signed + Bounded + NumCast + Clone, - F: FloatCore + NumCast -{ - let negative = val.is_sign_negative(); - let abs_val = val.abs(); - - let r = approximate_float_unsigned(abs_val, max_error, max_iterations); - - // Make negative again if needed - if negative { - r.map(|r| r.neg()) - } else { - r - } -} - -// No Unsigned constraint because this also works on positive integers and is called -// like that, see above -fn approximate_float_unsigned(val: F, max_error: F, max_iterations: usize) -> Option> - where T: Integer + Bounded + NumCast + Clone, - F: FloatCore + NumCast -{ - // Continued fractions algorithm - // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac - - if val < F::zero() || val.is_nan() { - return None; - } - - let mut q = val; - let mut n0 = T::zero(); - let mut d0 = T::one(); - let mut n1 = T::one(); - let mut d1 = T::zero(); - - let t_max = T::max_value(); - let t_max_f = match ::from(t_max.clone()) { - None => return None, - Some(t_max_f) => t_max_f, - }; - - // 1/epsilon > T::MAX - let epsilon = t_max_f.recip(); - - // Overflow - if q > t_max_f { - return None; - } - - for _ in 0..max_iterations { - let a = match ::from(q) { - None => break, - Some(a) => a, - }; - - let a_f = match ::from(a.clone()) { - None => break, - Some(a_f) => a_f, - }; - let f = q - a_f; - - // Prevent overflow - if !a.is_zero() && - (n1 > t_max.clone() / a.clone() || - d1 > t_max.clone() / a.clone() || - a.clone() * n1.clone() > t_max.clone() - n0.clone() || - a.clone() * d1.clone() > t_max.clone() - d0.clone()) { - break; - } - - let n = a.clone() * n1.clone() + n0.clone(); - let d = a.clone() * d1.clone() + d0.clone(); - - n0 = n1; - d0 = d1; - n1 = n.clone(); - d1 = d.clone(); - - // Simplify fraction. Doing so here instead of at the end - // allows us to get closer to the target value without overflows - let g = Integer::gcd(&n1, &d1); - if !g.is_zero() { - n1 = n1 / g.clone(); - d1 = d1 / g.clone(); - } - - // Close enough? - let (n_f, d_f) = match (::from(n), ::from(d)) { - (Some(n_f), Some(d_f)) => (n_f, d_f), - _ => break, - }; - if (n_f / d_f - val).abs() < max_error { - break; - } - - // Prevent division by ~0 - if f < epsilon { - break; - } - q = f.recip(); - } - - // Overflow - if d1.is_zero() { - return None; - } - - Some(Ratio::new(n1, d1)) -} - -#[cfg(test)] -#[cfg(feature = "std")] -fn hash(x: &T) -> u64 { - use std::hash::BuildHasher; - use std::collections::hash_map::RandomState; - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[cfg(test)] -mod test { - use super::{Ratio, Rational}; - #[cfg(feature = "bigint")] - use super::BigRational; - - use core::str::FromStr; - use core::i32; - use core::f64; - use traits::{Zero, One, Signed, FromPrimitive, Pow}; - use integer::Integer; - - pub const _0: Rational = Ratio { - numer: 0, - denom: 1, - }; - pub const _1: Rational = Ratio { - numer: 1, - denom: 1, - }; - pub const _2: Rational = Ratio { - numer: 2, - denom: 1, - }; - pub const _NEG2: Rational = Ratio { - numer: -2, - denom: 1, - }; - pub const _1_2: Rational = Ratio { - numer: 1, - denom: 2, - }; - pub const _3_2: Rational = Ratio { - numer: 3, - denom: 2, - }; - pub const _NEG1_2: Rational = Ratio { - numer: -1, - denom: 2, - }; - pub const _1_NEG2: Rational = Ratio { - numer: 1, - denom: -2, - }; - pub const _NEG1_NEG2: Rational = Ratio { - numer: -1, - denom: -2, - }; - pub const _1_3: Rational = Ratio { - numer: 1, - denom: 3, - }; - pub const _NEG1_3: Rational = Ratio { - numer: -1, - denom: 3, - }; - pub const _2_3: Rational = Ratio { - numer: 2, - denom: 3, - }; - pub const _NEG2_3: Rational = Ratio { - numer: -2, - denom: 3, - }; - - #[cfg(feature = "bigint")] - pub fn to_big(n: Rational) -> BigRational { - Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(), - FromPrimitive::from_isize(n.denom).unwrap()) - } - #[cfg(not(feature = "bigint"))] - pub fn to_big(n: Rational) -> Rational { - Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(), - FromPrimitive::from_isize(n.denom).unwrap()) - } - - #[test] - fn test_test_constants() { - // check our constants are what Ratio::new etc. would make. - assert_eq!(_0, Zero::zero()); - assert_eq!(_1, One::one()); - assert_eq!(_2, Ratio::from_integer(2)); - assert_eq!(_1_2, Ratio::new(1, 2)); - assert_eq!(_3_2, Ratio::new(3, 2)); - assert_eq!(_NEG1_2, Ratio::new(-1, 2)); - assert_eq!(_2, From::from(2)); - } - - #[test] - fn test_new_reduce() { - let one22 = Ratio::new(2, 2); - - assert_eq!(one22, One::one()); - } - #[test] - #[should_panic] - fn test_new_zero() { - let _a = Ratio::new(1, 0); - } - - #[test] - fn test_approximate_float() { - assert_eq!(Ratio::from_f32(0.5f32), Some(Ratio::new(1i64, 2))); - assert_eq!(Ratio::from_f64(0.5f64), Some(Ratio::new(1i32, 2))); - assert_eq!(Ratio::from_f32(5f32), Some(Ratio::new(5i64, 1))); - assert_eq!(Ratio::from_f64(5f64), Some(Ratio::new(5i32, 1))); - assert_eq!(Ratio::from_f32(29.97f32), Some(Ratio::new(2997i64, 100))); - assert_eq!(Ratio::from_f32(-29.97f32), Some(Ratio::new(-2997i64, 100))); - - assert_eq!(Ratio::::from_f32(63.5f32), Some(Ratio::new(127i8, 2))); - assert_eq!(Ratio::::from_f32(126.5f32), Some(Ratio::new(126i8, 1))); - assert_eq!(Ratio::::from_f32(127.0f32), Some(Ratio::new(127i8, 1))); - assert_eq!(Ratio::::from_f32(127.5f32), None); - assert_eq!(Ratio::::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2))); - assert_eq!(Ratio::::from_f32(-126.5f32), Some(Ratio::new(-126i8, 1))); - assert_eq!(Ratio::::from_f32(-127.0f32), Some(Ratio::new(-127i8, 1))); - assert_eq!(Ratio::::from_f32(-127.5f32), None); - - assert_eq!(Ratio::::from_f32(-127f32), None); - assert_eq!(Ratio::::from_f32(127f32), Some(Ratio::new(127u8, 1))); - assert_eq!(Ratio::::from_f32(127.5f32), Some(Ratio::new(255u8, 2))); - assert_eq!(Ratio::::from_f32(256f32), None); - - assert_eq!(Ratio::::from_f64(-10e200), None); - assert_eq!(Ratio::::from_f64(10e200), None); - assert_eq!(Ratio::::from_f64(f64::INFINITY), None); - assert_eq!(Ratio::::from_f64(f64::NEG_INFINITY), None); - assert_eq!(Ratio::::from_f64(f64::NAN), None); - assert_eq!(Ratio::::from_f64(f64::EPSILON), Some(Ratio::new(1, 4503599627370496))); - assert_eq!(Ratio::::from_f64(0.0), Some(Ratio::new(0, 1))); - assert_eq!(Ratio::::from_f64(-0.0), Some(Ratio::new(0, 1))); - } - - #[test] - fn test_cmp() { - assert!(_0 == _0 && _1 == _1); - assert!(_0 != _1 && _1 != _0); - assert!(_0 < _1 && !(_1 < _0)); - assert!(_1 > _0 && !(_0 > _1)); - - assert!(_0 <= _0 && _1 <= _1); - assert!(_0 <= _1 && !(_1 <= _0)); - - assert!(_0 >= _0 && _1 >= _1); - assert!(_1 >= _0 && !(_0 >= _1)); - } - - #[test] - fn test_cmp_overflow() { - use core::cmp::Ordering; - - // issue #7 example: - let big = Ratio::new(128u8, 1); - let small = big.recip(); - assert!(big > small); - - // try a few that are closer together - // (some matching numer, some matching denom, some neither) - let ratios = [ - Ratio::new(125_i8, 127_i8), - Ratio::new(63_i8, 64_i8), - Ratio::new(124_i8, 125_i8), - Ratio::new(125_i8, 126_i8), - Ratio::new(126_i8, 127_i8), - Ratio::new(127_i8, 126_i8), - ]; - - fn check_cmp(a: Ratio, b: Ratio, ord: Ordering) { - #[cfg(feature = "std")] - println!("comparing {} and {}", a, b); - assert_eq!(a.cmp(&b), ord); - assert_eq!(b.cmp(&a), ord.reverse()); - } - - for (i, &a) in ratios.iter().enumerate() { - check_cmp(a, a, Ordering::Equal); - check_cmp(-a, a, Ordering::Less); - for &b in &ratios[i + 1..] { - check_cmp(a, b, Ordering::Less); - check_cmp(-a, -b, Ordering::Greater); - check_cmp(a.recip(), b.recip(), Ordering::Greater); - check_cmp(-a.recip(), -b.recip(), Ordering::Less); - } - } - } - - #[test] - fn test_to_integer() { - assert_eq!(_0.to_integer(), 0); - assert_eq!(_1.to_integer(), 1); - assert_eq!(_2.to_integer(), 2); - assert_eq!(_1_2.to_integer(), 0); - assert_eq!(_3_2.to_integer(), 1); - assert_eq!(_NEG1_2.to_integer(), 0); - } - - - #[test] - fn test_numer() { - assert_eq!(_0.numer(), &0); - assert_eq!(_1.numer(), &1); - assert_eq!(_2.numer(), &2); - assert_eq!(_1_2.numer(), &1); - assert_eq!(_3_2.numer(), &3); - assert_eq!(_NEG1_2.numer(), &(-1)); - } - #[test] - fn test_denom() { - assert_eq!(_0.denom(), &1); - assert_eq!(_1.denom(), &1); - assert_eq!(_2.denom(), &1); - assert_eq!(_1_2.denom(), &2); - assert_eq!(_3_2.denom(), &2); - assert_eq!(_NEG1_2.denom(), &2); - } - - - #[test] - fn test_is_integer() { - assert!(_0.is_integer()); - assert!(_1.is_integer()); - assert!(_2.is_integer()); - assert!(!_1_2.is_integer()); - assert!(!_3_2.is_integer()); - assert!(!_NEG1_2.is_integer()); - } - - #[test] - #[cfg(feature = "std")] - fn test_show() { - use std::string::ToString; - assert_eq!(format!("{}", _2), "2".to_string()); - assert_eq!(format!("{}", _1_2), "1/2".to_string()); - assert_eq!(format!("{}", _0), "0".to_string()); - assert_eq!(format!("{}", Ratio::from_integer(-2)), "-2".to_string()); - } - - mod arith { - use super::{_0, _1, _2, _1_2, _3_2, _NEG1_2, to_big}; - use super::super::{Ratio, Rational}; - use traits::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv}; - - #[test] - fn test_add() { - fn test(a: Rational, b: Rational, c: Rational) { - assert_eq!(a + b, c); - assert_eq!({ let mut x = a; x += b; x}, c); - assert_eq!(to_big(a) + to_big(b), to_big(c)); - assert_eq!(a.checked_add(&b), Some(c)); - assert_eq!(to_big(a).checked_add(&to_big(b)), Some(to_big(c))); - } - fn test_assign(a: Rational, b: isize, c: Rational) { - assert_eq!(a + b, c); - assert_eq!({ let mut x = a; x += b; x}, c); - } - - test(_1, _1_2, _3_2); - test(_1, _1, _2); - test(_1_2, _3_2, _2); - test(_1_2, _NEG1_2, _0); - test_assign(_1_2, 1, _3_2); - } - - #[test] - fn test_sub() { - fn test(a: Rational, b: Rational, c: Rational) { - assert_eq!(a - b, c); - assert_eq!({ let mut x = a; x -= b; x}, c); - assert_eq!(to_big(a) - to_big(b), to_big(c)); - assert_eq!(a.checked_sub(&b), Some(c)); - assert_eq!(to_big(a).checked_sub(&to_big(b)), Some(to_big(c))); - } - fn test_assign(a: Rational, b: isize, c: Rational) { - assert_eq!(a - b, c); - assert_eq!({ let mut x = a; x -= b; x}, c); - } - - test(_1, _1_2, _1_2); - test(_3_2, _1_2, _1); - test(_1, _NEG1_2, _3_2); - test_assign(_1_2, 1, _NEG1_2); - } - - #[test] - fn test_mul() { - fn test(a: Rational, b: Rational, c: Rational) { - assert_eq!(a * b, c); - assert_eq!({ let mut x = a; x *= b; x}, c); - assert_eq!(to_big(a) * to_big(b), to_big(c)); - assert_eq!(a.checked_mul(&b), Some(c)); - assert_eq!(to_big(a).checked_mul(&to_big(b)), Some(to_big(c))); - } - fn test_assign(a: Rational, b: isize, c: Rational) { - assert_eq!(a * b, c); - assert_eq!({ let mut x = a; x *= b; x}, c); - } - - test(_1, _1_2, _1_2); - test(_1_2, _3_2, Ratio::new(3, 4)); - test(_1_2, _NEG1_2, Ratio::new(-1, 4)); - test_assign(_1_2, 2, _1); - } - - #[test] - fn test_div() { - fn test(a: Rational, b: Rational, c: Rational) { - assert_eq!(a / b, c); - assert_eq!({ let mut x = a; x /= b; x}, c); - assert_eq!(to_big(a) / to_big(b), to_big(c)); - assert_eq!(a.checked_div(&b), Some(c)); - assert_eq!(to_big(a).checked_div(&to_big(b)), Some(to_big(c))); - } - fn test_assign(a: Rational, b: isize, c: Rational) { - assert_eq!(a / b, c); - assert_eq!({ let mut x = a; x /= b; x}, c); - } - - test(_1, _1_2, _2); - test(_3_2, _1_2, _1 + _2); - test(_1, _NEG1_2, _NEG1_2 + _NEG1_2 + _NEG1_2 + _NEG1_2); - test_assign(_1, 2, _1_2); - } - - #[test] - fn test_rem() { - fn test(a: Rational, b: Rational, c: Rational) { - assert_eq!(a % b, c); - assert_eq!({ let mut x = a; x %= b; x}, c); - assert_eq!(to_big(a) % to_big(b), to_big(c)) - } - fn test_assign(a: Rational, b: isize, c: Rational) { - assert_eq!(a % b, c); - assert_eq!({ let mut x = a; x %= b; x}, c); - } - - test(_3_2, _1, _1_2); - test(_2, _NEG1_2, _0); - test(_1_2, _2, _1_2); - test_assign(_3_2, 1, _1_2); - } - - #[test] - fn test_neg() { - fn test(a: Rational, b: Rational) { - assert_eq!(-a, b); - assert_eq!(-to_big(a), to_big(b)) - } - - test(_0, _0); - test(_1_2, _NEG1_2); - test(-_1, _1); - } - #[test] - fn test_zero() { - assert_eq!(_0 + _0, _0); - assert_eq!(_0 * _0, _0); - assert_eq!(_0 * _1, _0); - assert_eq!(_0 / _NEG1_2, _0); - assert_eq!(_0 - _0, _0); - } - #[test] - #[should_panic] - fn test_div_0() { - let _a = _1 / _0; - } - - #[test] - fn test_checked_failures() { - let big = Ratio::new(128u8, 1); - let small = Ratio::new(1, 128u8); - assert_eq!(big.checked_add(&big), None); - assert_eq!(small.checked_sub(&big), None); - assert_eq!(big.checked_mul(&big), None); - assert_eq!(small.checked_div(&big), None); - assert_eq!(_1.checked_div(&_0), None); - } - } - - #[test] - fn test_round() { - assert_eq!(_1_3.ceil(), _1); - assert_eq!(_1_3.floor(), _0); - assert_eq!(_1_3.round(), _0); - assert_eq!(_1_3.trunc(), _0); - - assert_eq!(_NEG1_3.ceil(), _0); - assert_eq!(_NEG1_3.floor(), -_1); - assert_eq!(_NEG1_3.round(), _0); - assert_eq!(_NEG1_3.trunc(), _0); - - assert_eq!(_2_3.ceil(), _1); - assert_eq!(_2_3.floor(), _0); - assert_eq!(_2_3.round(), _1); - assert_eq!(_2_3.trunc(), _0); - - assert_eq!(_NEG2_3.ceil(), _0); - assert_eq!(_NEG2_3.floor(), -_1); - assert_eq!(_NEG2_3.round(), -_1); - assert_eq!(_NEG2_3.trunc(), _0); - - assert_eq!(_1_2.ceil(), _1); - assert_eq!(_1_2.floor(), _0); - assert_eq!(_1_2.round(), _1); - assert_eq!(_1_2.trunc(), _0); - - assert_eq!(_NEG1_2.ceil(), _0); - assert_eq!(_NEG1_2.floor(), -_1); - assert_eq!(_NEG1_2.round(), -_1); - assert_eq!(_NEG1_2.trunc(), _0); - - assert_eq!(_1.ceil(), _1); - assert_eq!(_1.floor(), _1); - assert_eq!(_1.round(), _1); - assert_eq!(_1.trunc(), _1); - - // Overflow checks - - let _neg1 = Ratio::from_integer(-1); - let _large_rat1 = Ratio::new(i32::MAX, i32::MAX - 1); - let _large_rat2 = Ratio::new(i32::MAX - 1, i32::MAX); - let _large_rat3 = Ratio::new(i32::MIN + 2, i32::MIN + 1); - let _large_rat4 = Ratio::new(i32::MIN + 1, i32::MIN + 2); - let _large_rat5 = Ratio::new(i32::MIN + 2, i32::MAX); - let _large_rat6 = Ratio::new(i32::MAX, i32::MIN + 2); - let _large_rat7 = Ratio::new(1, i32::MIN + 1); - let _large_rat8 = Ratio::new(1, i32::MAX); - - assert_eq!(_large_rat1.round(), One::one()); - assert_eq!(_large_rat2.round(), One::one()); - assert_eq!(_large_rat3.round(), One::one()); - assert_eq!(_large_rat4.round(), One::one()); - assert_eq!(_large_rat5.round(), _neg1); - assert_eq!(_large_rat6.round(), _neg1); - assert_eq!(_large_rat7.round(), Zero::zero()); - assert_eq!(_large_rat8.round(), Zero::zero()); - } - - #[test] - fn test_fract() { - assert_eq!(_1.fract(), _0); - assert_eq!(_NEG1_2.fract(), _NEG1_2); - assert_eq!(_1_2.fract(), _1_2); - assert_eq!(_3_2.fract(), _1_2); - } - - #[test] - fn test_recip() { - assert_eq!(_1 * _1.recip(), _1); - assert_eq!(_2 * _2.recip(), _1); - assert_eq!(_1_2 * _1_2.recip(), _1); - assert_eq!(_3_2 * _3_2.recip(), _1); - assert_eq!(_NEG1_2 * _NEG1_2.recip(), _1); - - assert_eq!(_3_2.recip(), _2_3); - assert_eq!(_NEG1_2.recip(), _NEG2); - assert_eq!(_NEG1_2.recip().denom(), &1); - } - - #[test] - #[should_panic(expected = "== 0")] - fn test_recip_fail() { - let _a = Ratio::new(0, 1).recip(); - } - - #[test] - fn test_pow() { - fn test(r: Rational, e: i32, expected: Rational) { - assert_eq!(r.pow(e), expected); - assert_eq!(Pow::pow(r, e), expected); - assert_eq!(Pow::pow(r, &e), expected); - assert_eq!(Pow::pow(&r, e), expected); - assert_eq!(Pow::pow(&r, &e), expected); - } - - test(_1_2, 2, Ratio::new(1, 4)); - test(_1_2, -2, Ratio::new(4, 1)); - test(_1, 1, _1); - test(_1, i32::MAX, _1); - test(_1, i32::MIN, _1); - test(_NEG1_2, 2, _1_2.pow(2i32)); - test(_NEG1_2, 3, -_1_2.pow(3i32)); - test(_3_2, 0, _1); - test(_3_2, -1, _3_2.recip()); - test(_3_2, 3, Ratio::new(27, 8)); - } - - #[test] - #[cfg(feature = "std")] - fn test_to_from_str() { - use std::string::{String, ToString}; - fn test(r: Rational, s: String) { - assert_eq!(FromStr::from_str(&s), Ok(r)); - assert_eq!(r.to_string(), s); - } - test(_1, "1".to_string()); - test(_0, "0".to_string()); - test(_1_2, "1/2".to_string()); - test(_3_2, "3/2".to_string()); - test(_2, "2".to_string()); - test(_NEG1_2, "-1/2".to_string()); - } - #[test] - fn test_from_str_fail() { - fn test(s: &str) { - let rational: Result = FromStr::from_str(s); - assert!(rational.is_err()); - } - - let xs = ["0 /1", "abc", "", "1/", "--1/2", "3/2/1", "1/0"]; - for &s in xs.iter() { - test(s); - } - } - - #[cfg(feature = "bigint")] - #[test] - fn test_from_float() { - use traits::float::FloatCore; - fn test(given: T, (numer, denom): (&str, &str)) { - let ratio: BigRational = Ratio::from_float(given).unwrap(); - assert_eq!(ratio, - Ratio::new(FromStr::from_str(numer).unwrap(), - FromStr::from_str(denom).unwrap())); - } - - // f32 - test(3.14159265359f32, ("13176795", "4194304")); - test(2f32.powf(100.), ("1267650600228229401496703205376", "1")); - test(-2f32.powf(100.), ("-1267650600228229401496703205376", "1")); - test(1.0 / 2f32.powf(100.), - ("1", "1267650600228229401496703205376")); - test(684729.48391f32, ("1369459", "2")); - test(-8573.5918555f32, ("-4389679", "512")); - - // f64 - test(3.14159265359f64, ("3537118876014453", "1125899906842624")); - test(2f64.powf(100.), ("1267650600228229401496703205376", "1")); - test(-2f64.powf(100.), ("-1267650600228229401496703205376", "1")); - test(684729.48391f64, ("367611342500051", "536870912")); - test(-8573.5918555f64, ("-4713381968463931", "549755813888")); - test(1.0 / 2f64.powf(100.), - ("1", "1267650600228229401496703205376")); - } - - #[cfg(feature = "bigint")] - #[test] - fn test_from_float_fail() { - use core::{f32, f64}; - - assert_eq!(Ratio::from_float(f32::NAN), None); - assert_eq!(Ratio::from_float(f32::INFINITY), None); - assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None); - assert_eq!(Ratio::from_float(f64::NAN), None); - assert_eq!(Ratio::from_float(f64::INFINITY), None); - assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None); - } - - #[test] - fn test_signed() { - assert_eq!(_NEG1_2.abs(), _1_2); - assert_eq!(_3_2.abs_sub(&_1_2), _1); - assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero()); - assert_eq!(_1_2.signum(), One::one()); - assert_eq!(_NEG1_2.signum(), ->::one()); - assert_eq!(_0.signum(), Zero::zero()); - assert!(_NEG1_2.is_negative()); - assert!(_1_NEG2.is_negative()); - assert!(!_NEG1_2.is_positive()); - assert!(!_1_NEG2.is_positive()); - assert!(_1_2.is_positive()); - assert!(_NEG1_NEG2.is_positive()); - assert!(!_1_2.is_negative()); - assert!(!_NEG1_NEG2.is_negative()); - assert!(!_0.is_positive()); - assert!(!_0.is_negative()); - } - - #[test] - #[cfg(feature = "std")] - fn test_hash() { - assert!(::hash(&_0) != ::hash(&_1)); - assert!(::hash(&_0) != ::hash(&_3_2)); - - // a == b -> hash(a) == hash(b) - let a = Rational::new_raw(4, 2); - let b = Rational::new_raw(6, 3); - assert_eq!(a, b); - assert_eq!(::hash(&a), ::hash(&b)); - - let a = Rational::new_raw(123456789, 1000); - let b = Rational::new_raw(123456789 * 5, 5000); - assert_eq!(a, b); - assert_eq!(::hash(&a), ::hash(&b)); - } - - #[test] - fn test_into_pair() { - assert_eq! ((0, 1), _0.into()); - assert_eq! ((-2, 1), _NEG2.into()); - assert_eq! ((1, -2), _1_NEG2.into()); - } - - #[test] - fn test_from_pair() { - assert_eq! (_0, Ratio::from ((0, 1))); - assert_eq! (_1, Ratio::from ((1, 1))); - assert_eq! (_NEG2, Ratio::from ((-2, 1))); - assert_eq! (_1_NEG2, Ratio::from ((1, -2))); - } - - #[test] - fn ratio_iter_sum() { - // generic function to assure the iter method can be called - // for any Iterator with Item = Ratio or Ratio<&impl Integer> - fn iter_sums(slice: &[Ratio]) -> [Ratio; 3] { - let mut manual_sum = Ratio::new(T::zero(), T::one()); - for ratio in slice { - manual_sum = manual_sum + ratio; - } - [ - manual_sum, - slice.iter().sum(), - slice.iter().cloned().sum() - ] - } - // collect into array so test works on no_std - let mut nums = [Ratio::new(0,1); 1000]; - for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() { - nums[i] = r; - } - let sums = iter_sums(&nums[..]); - assert_eq!(sums[0], sums[1]); - assert_eq!(sums[0], sums[2]); - } - - #[test] - fn ratio_iter_product() { - // generic function to assure the iter method can be called - // for any Iterator with Item = Ratio or Ratio<&impl Integer> - fn iter_products(slice: &[Ratio]) -> [Ratio; 3] { - let mut manual_prod = Ratio::new(T::one(), T::one()); - for ratio in slice { - manual_prod = manual_prod * ratio; - } - [ - manual_prod, - slice.iter().product(), - slice.iter().cloned().product() - ] - } - - // collect into array so test works on no_std - let mut nums = [Ratio::new(0,1); 1000]; - for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() { - nums[i] = r; - } - let products = iter_products(&nums[..]); - assert_eq!(products[0], products[1]); - assert_eq!(products[0], products[2]); - } -} diff --git a/third_party/rust/num-rational/.cargo-checksum.json b/third_party/rust/num-rational/.cargo-checksum.json index 4a7679e9b925..a092a8a9f3de 100644 --- a/third_party/rust/num-rational/.cargo-checksum.json +++ b/third_party/rust/num-rational/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"23e8f81e9618cd7087ddc7718ac09d72350bbcf831f48b2e5f017a82ae59c945","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"f793cf497bf0589bb7acf04b1e9a0b784bfe61b9e48c4794f205d0888e63cd97","RELEASES.md":"8f02dc6441c8962dcb6811046a898b2f659fbcbaeac515b2089260769912c5a7","build.rs":"254c248fc8824e2cf6329cf0c313b6eb44059ab7a69e7bf1acb036e55cc3e2ff","src/lib.rs":"5a41b5257c2079a6a423b225903648ca791091755fcf7f3343b445c52ad1941b","src/pow.rs":"c38cabc61e75e99425ee4fea7ac5b0712a648baa0635a2c40a6215edd43ae4a3"},"package":"a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138"} \ No newline at end of file +{"files":{"Cargo.toml":"0955835c06d82075c9e70941ba0a923c918d3ecb0baadbd0bfb14a6503b47fed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"07973a21c5e6cbc14fb304f32d51f8df7c538b3b6c1837b5c5c19e83e316cc9e","RELEASES.md":"8bc9a6e43749b87a6b01002ea45dc7b9ef34b27c905fc7c822b2256603aae3f1","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"16de2aa57e754fc1526d0400b5d87a3f771296705fca54601aa598b6f74ded8f","ci/rustup.sh":"bc6270c57c9fc72ab407336bb8b7d9027dd08502c9c08105c3848d1f796ed6eb","ci/test_full.sh":"051ecff898e891c50356b17d7da0350541d14e83fa753737e61b67d7e5eb9a0e","src/lib.rs":"cfdf09d8d5f7df2cdaea25e548bc2050dfc339afcd8d6f3bfc5ccce068850541"},"package":"4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"} \ No newline at end of file diff --git a/third_party/rust/num-rational/Cargo.toml b/third_party/rust/num-rational/Cargo.toml index d17542ac6ac0..def7033f5800 100644 --- a/third_party/rust/num-rational/Cargo.toml +++ b/third_party/rust/num-rational/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,44 +11,41 @@ # will likely look very different (and much more reasonable) [package] -edition = "2018" name = "num-rational" -version = "0.3.0" +version = "0.2.1" authors = ["The Rust Project Developers"] -exclude = ["/bors.toml", "/ci/*", "/.github/*"] +build = "build.rs" description = "Rational numbers implementation for Rust" homepage = "https://github.com/rust-num/num-rational" documentation = "https://docs.rs/num-rational" readme = "README.md" -keywords = ["mathematics", "numerics", "fractions"] +keywords = ["mathematics", "numerics"] categories = ["algorithms", "data-structures", "science", "no-std"] license = "MIT/Apache-2.0" repository = "https://github.com/rust-num/num-rational" [package.metadata.docs.rs] -features = ["std", "num-bigint-std", "serde"] +features = ["std", "bigint-std", "serde"] [dependencies.num-bigint] -version = "0.3.0" +version = "0.2.0" optional = true default-features = false [dependencies.num-integer] -version = "0.1.42" -features = ["i128"] +version = "0.1.38" default-features = false [dependencies.num-traits] -version = "0.2.11" -features = ["i128"] +version = "0.2.4" default-features = false [dependencies.serde] version = "1.0.0" optional = true default-features = false -[build-dependencies.autocfg] -version = "1.0.0" [features] -default = ["num-bigint-std", "std"] -num-bigint-std = ["num-bigint/std"] +bigint = ["num-bigint"] +bigint-std = ["bigint", "num-bigint/std"] +default = ["bigint-std", "std"] +i128 = ["num-integer/i128", "num-traits/i128"] std = ["num-integer/std", "num-traits/std"] diff --git a/third_party/rust/num-rational/README.md b/third_party/rust/num-rational/README.md index d6e1ebb9c785..ebd0f314f9fb 100644 --- a/third_party/rust/num-rational/README.md +++ b/third_party/rust/num-rational/README.md @@ -2,10 +2,10 @@ [![crate](https://img.shields.io/crates/v/num-rational.svg)](https://crates.io/crates/num-rational) [![documentation](https://docs.rs/num-rational/badge.svg)](https://docs.rs/num-rational) -[![minimum rustc 1.31](https://img.shields.io/badge/rustc-1.31+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num-rational/workflows/master/badge.svg)](https://github.com/rust-num/num-rational/actions) +![minimum rustc 1.15](https://img.shields.io/badge/rustc-1.15+-red.svg) +[![Travis status](https://travis-ci.org/rust-num/num-rational.svg?branch=master)](https://travis-ci.org/rust-num/num-rational) -Generic `Rational` numbers (aka fractions) for Rust. +Generic `Rational` numbers for Rust. ## Usage @@ -13,7 +13,13 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -num-rational = "0.3" +num-rational = "0.2" +``` + +and this to your crate root: + +```rust +extern crate num_rational; ``` ## Features @@ -23,14 +29,18 @@ the default `std` feature. Use this in `Cargo.toml`: ```toml [dependencies.num-rational] -version = "0.3" +version = "0.2" default-features = false ``` +Implementations for `i128` and `u128` are only available with Rust 1.26 and +later. The build script automatically detects this, but you can make it +mandatory by enabling the `i128` crate feature. + ## Releases Release notes are available in [RELEASES.md](RELEASES.md). ## Compatibility -The `num-rational` crate is tested for rustc 1.31 and greater. +The `num-rational` crate is tested for rustc 1.15 and greater. diff --git a/third_party/rust/num-rational/RELEASES.md b/third_party/rust/num-rational/RELEASES.md index 13b5f2921615..c427db3ac3c4 100644 --- a/third_party/rust/num-rational/RELEASES.md +++ b/third_party/rust/num-rational/RELEASES.md @@ -1,58 +1,3 @@ -# Release 0.3.0 (2020-06-13) - -### Enhancements - -- [`Ratio` now implements `ToPrimitive`][52]. -- [`Ratio` now implements additional formatting traits][56]: - - `Binary`, `Octal`, `LowerHex`, `UpperHex`, `LowerExp`, `UpperExp` -- [The `Pow` implementations have been expanded][70]. - - `Pow` and `Pow` are now implemented. - - `Pow<_> for &Ratio` now uses `&T: Pow`. - - The inherent `pow` method now uses `&T: Pow`. - -### Breaking Changes - -- [`num-rational` now requires Rust 1.31 or greater][66]. - - The "i128" opt-in feature was removed, now always available. -- [The "num-bigint-std" feature replaces "bigint" with `std` enabled][80]. - - The "num-bigint" feature without `std` uses `alloc` on Rust 1.36+. - -**Contributors**: @cuviper, @MattX, @maxbla - -[52]: https://github.com/rust-num/num-rational/pull/52 -[56]: https://github.com/rust-num/num-rational/pull/56 -[66]: https://github.com/rust-num/num-rational/pull/66 -[70]: https://github.com/rust-num/num-rational/pull/70 -[80]: https://github.com/rust-num/num-rational/pull/80 - -# Release 0.2.4 (2020-03-17) - -- [Fixed `CheckedDiv` when both dividend and divisor are 0][74]. -- [Fixed `CheckedDiv` with `min_value()` numerators][76]. - -[74]: https://github.com/rust-num/num-rational/pull/74 -[76]: https://github.com/rust-num/num-rational/pull/76 - -# Release 0.2.3 (2020-01-09) - -- [`Ratio` now performs earlier reductions to avoid overflow with `+-*/%` operators][42]. -- [`Ratio::{new_raw, numer, denom}` are now `const fn` for Rust 1.31 and later][48]. -- [Updated the `autocfg` build dependency to 1.0][63]. - -**Contributors**: @cuviper, @dingelish, @jimbo1qaz, @maxbla - -[42]: https://github.com/rust-num/num-rational/pull/42 -[48]: https://github.com/rust-num/num-rational/pull/48 -[63]: https://github.com/rust-num/num-rational/pull/63 - -# Release 0.2.2 (2019-06-10) - -- [`Ratio` now implements `Zero::set_zero` and `One::set_one`][47]. - -**Contributors**: @cuviper, @ignatenkobrain, @vks - -[47]: https://github.com/rust-num/num-rational/pull/47 - # Release 0.2.1 (2018-06-22) - Maintenance release to fix `html_root_url`. @@ -73,7 +18,7 @@ implication that building *without* this feature makes this a `#![no_std]` crate. A few methods now require `FloatCore` instead of `Float`. - [The `serde` dependency has been updated to 1.0][24], and `rustc-serialize` - is no longer supported by `num-rational`. + is no longer supported by `num-complex`. - The optional `num-bigint` dependency has been updated to 0.2, and should be enabled using the `bigint-std` feature. In the future, it may be possible to use the `bigint` feature with `no_std`. diff --git a/third_party/rust/num-rational/bors.toml b/third_party/rust/num-rational/bors.toml new file mode 100644 index 000000000000..ca08e818bf3e --- /dev/null +++ b/third_party/rust/num-rational/bors.toml @@ -0,0 +1,3 @@ +status = [ + "continuous-integration/travis-ci/push", +] diff --git a/third_party/rust/num-rational/build.rs b/third_party/rust/num-rational/build.rs index f8290880ada3..fd60866558c3 100644 --- a/third_party/rust/num-rational/build.rs +++ b/third_party/rust/num-rational/build.rs @@ -1,8 +1,35 @@ -fn main() { - let ac = autocfg::new(); - if ac.probe_expression("format!(\"{:e}\", 0_isize)") { - println!("cargo:rustc-cfg=has_int_exp_fmt"); - } +use std::env; +use std::io::Write; +use std::process::{Command, Stdio}; - autocfg::rerun_path(file!()); +fn main() { + if probe("fn main() { 0i128; }") { + println!("cargo:rustc-cfg=has_i128"); + } else if env::var_os("CARGO_FEATURE_I128").is_some() { + panic!("i128 support was not detected!"); + } +} + +/// Test if a code snippet can be compiled +fn probe(code: &str) -> bool { + let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); + let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR"); + + let mut child = Command::new(rustc) + .arg("--out-dir") + .arg(out_dir) + .arg("--emit=obj") + .arg("-") + .stdin(Stdio::piped()) + .spawn() + .expect("rustc probe"); + + child + .stdin + .as_mut() + .expect("rustc stdin") + .write_all(code.as_bytes()) + .expect("write rustc stdin"); + + child.wait().expect("rustc probe").success() } diff --git a/third_party/rust/num-rational-0.2.1/ci/rustup.sh b/third_party/rust/num-rational/ci/rustup.sh similarity index 100% rename from third_party/rust/num-rational-0.2.1/ci/rustup.sh rename to third_party/rust/num-rational/ci/rustup.sh diff --git a/third_party/rust/num-rational-0.2.1/ci/test_full.sh b/third_party/rust/num-rational/ci/test_full.sh similarity index 100% rename from third_party/rust/num-rational-0.2.1/ci/test_full.sh rename to third_party/rust/num-rational/ci/test_full.sh diff --git a/third_party/rust/num-rational/src/lib.rs b/third_party/rust/num-rational/src/lib.rs index 37c62284ed6e..a49d712b692f 100644 --- a/third_party/rust/num-rational/src/lib.rs +++ b/third_party/rust/num-rational/src/lib.rs @@ -12,39 +12,39 @@ //! //! ## Compatibility //! -//! The `num-rational` crate is tested for rustc 1.31 and greater. +//! The `num-rational` crate is tested for rustc 1.15 and greater. + +#![doc(html_root_url = "https://docs.rs/num-rational/0.2")] -#![doc(html_root_url = "https://docs.rs/num-rational/0.3")] #![no_std] -// Ratio ops often use other "suspicious" ops -#![allow(clippy::suspicious_arithmetic_impl)] -#![allow(clippy::suspicious_op_assign_impl)] + +#[cfg(feature = "serde")] +extern crate serde; +#[cfg(feature = "bigint")] +extern crate num_bigint as bigint; + +extern crate num_traits as traits; +extern crate num_integer as integer; #[cfg(feature = "std")] -#[macro_use] +#[cfg_attr(test, macro_use)] extern crate std; use core::cmp; -use core::fmt; -use core::fmt::{Binary, Display, Formatter, LowerExp, LowerHex, Octal, UpperExp, UpperHex}; -use core::hash::{Hash, Hasher}; -use core::ops::{Add, Div, Mul, Neg, Rem, ShlAssign, Sub}; -use core::str::FromStr; #[cfg(feature = "std")] use std::error::Error; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; +use core::str::FromStr; -#[cfg(feature = "num-bigint")] -use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; +#[cfg(feature = "bigint")] +use bigint::{BigInt, BigUint, Sign}; -use num_integer::Integer; -use num_traits::float::FloatCore; -use num_traits::ToPrimitive; -use num_traits::{ - Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Inv, Num, NumCast, One, - Pow, Signed, Zero, -}; - -mod pow; +use integer::Integer; +use traits::float::FloatCore; +use traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Inv, Num, + NumCast, One, Pow, Signed, Zero}; /// Represents the ratio between two numbers. #[derive(Copy, Clone, Debug)] @@ -63,35 +63,17 @@ pub type Rational32 = Ratio; /// Alias for a `Ratio` of 64-bit-sized integers. pub type Rational64 = Ratio; -#[cfg(feature = "num-bigint")] +#[cfg(feature = "bigint")] /// Alias for arbitrary precision rationals. pub type BigRational = Ratio; -/// These method are `const` for Rust 1.31 and later. -impl Ratio { - /// Creates a `Ratio` without checking for `denom == 0` or reducing. - #[inline] - pub const fn new_raw(numer: T, denom: T) -> Ratio { - Ratio { numer, denom } - } - - /// Gets an immutable reference to the numerator. - #[inline] - pub const fn numer(&self) -> &T { - &self.numer - } - - /// Gets an immutable reference to the denominator. - #[inline] - pub const fn denom(&self) -> &T { - &self.denom - } -} - impl Ratio { /// Creates a new `Ratio`. Fails if `denom` is zero. #[inline] pub fn new(numer: T, denom: T) -> Ratio { + if denom.is_zero() { + panic!("denominator == 0"); + } let mut ret = Ratio::new_raw(numer, denom); ret.reduce(); ret @@ -103,12 +85,33 @@ impl Ratio { Ratio::new_raw(t, One::one()) } + /// Creates a `Ratio` without checking for `denom == 0` or reducing. + #[inline] + pub fn new_raw(numer: T, denom: T) -> Ratio { + Ratio { + numer: numer, + denom: denom, + } + } + /// Converts to an integer, rounding towards zero. #[inline] pub fn to_integer(&self) -> T { self.trunc().numer } + /// Gets an immutable reference to the numerator. + #[inline] + pub fn numer<'a>(&'a self) -> &'a T { + &self.numer + } + + /// Gets an immutable reference to the denominator. + #[inline] + pub fn denom<'a>(&'a self) -> &'a T { + &self.denom + } + /// Returns true if the rational number is an integer (denominator is 1). #[inline] pub fn is_integer(&self) -> bool { @@ -117,17 +120,6 @@ impl Ratio { /// Puts self into lowest terms, with denom > 0. fn reduce(&mut self) { - if self.denom.is_zero() { - panic!("denominator == 0"); - } - if self.numer.is_zero() { - self.denom.set_one(); - return; - } - if self.numer == self.denom { - self.set_one(); - return; - } let g: T = self.numer.gcd(&self.denom); // FIXME(#5992): assignment operator overloads @@ -161,15 +153,11 @@ impl Ratio { /// Fails if the `Ratio` is zero. #[inline] pub fn recip(&self) -> Ratio { - self.clone().into_recip() - } - - #[inline] - fn into_recip(self) -> Ratio { match self.numer.cmp(&T::zero()) { - cmp::Ordering::Equal => panic!("division by zero"), - cmp::Ordering::Greater => Ratio::new_raw(self.denom, self.numer), - cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom, T::zero() - self.numer), + cmp::Ordering::Equal => panic!("numerator == 0"), + cmp::Ordering::Greater => Ratio::new_raw(self.denom.clone(), self.numer.clone()), + cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom.clone(), + T::zero() - self.numer.clone()) } } @@ -178,9 +166,8 @@ impl Ratio { pub fn floor(&self) -> Ratio { if *self < Zero::zero() { let one: T = One::one(); - Ratio::from_integer( - (self.numer.clone() - self.denom.clone() + one) / self.denom.clone(), - ) + Ratio::from_integer((self.numer.clone() - self.denom.clone() + one) / + self.denom.clone()) } else { Ratio::from_integer(self.numer.clone() / self.denom.clone()) } @@ -193,9 +180,8 @@ impl Ratio { Ratio::from_integer(self.numer.clone() / self.denom.clone()) } else { let one: T = One::one(); - Ratio::from_integer( - (self.numer.clone() + self.denom.clone() - one) / self.denom.clone(), - ) + Ratio::from_integer((self.numer.clone() + self.denom.clone() - one) / + self.denom.clone()) } } @@ -215,10 +201,10 @@ impl Ratio { // The algorithm compares the unsigned fractional part with 1/2, that // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use // a >= (b/2)+1. This avoids overflow issues. - let half_or_larger = if fractional.denom.is_even() { - fractional.numer >= fractional.denom / two + let half_or_larger = if fractional.denom().is_even() { + *fractional.numer() >= fractional.denom().clone() / two.clone() } else { - fractional.numer >= (fractional.denom / two) + one + *fractional.numer() >= (fractional.denom().clone() / two.clone()) + one.clone() }; if half_or_larger { @@ -246,18 +232,93 @@ impl Ratio { pub fn fract(&self) -> Ratio { Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone()) } +} +impl> Ratio { /// Raises the `Ratio` to the power of an exponent. #[inline] - pub fn pow(&self, expon: i32) -> Ratio - where - for<'a> &'a T: Pow, - { + pub fn pow(&self, expon: i32) -> Ratio { Pow::pow(self, expon) } } -#[cfg(feature = "num-bigint")] +macro_rules! pow_impl { + ($exp: ty) => { + pow_impl!($exp, $exp); + }; + ($exp: ty, $unsigned: ty) => { + impl> Pow<$exp> for Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: $exp) -> Ratio { + match expon.cmp(&0) { + cmp::Ordering::Equal => One::one(), + cmp::Ordering::Less => { + let expon = expon.wrapping_abs() as $unsigned; + Ratio::new_raw( + Pow::pow(self.denom, expon), + Pow::pow(self.numer, expon), + ) + }, + cmp::Ordering::Greater => { + Ratio::new_raw( + Pow::pow(self.numer, expon as $unsigned), + Pow::pow(self.denom, expon as $unsigned), + ) + } + } + } + } + impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for &'a Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: $exp) -> Ratio { + Pow::pow(self.clone(), expon) + } + } + impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'a $exp) -> Ratio { + Pow::pow(self, *expon) + } + } + impl<'a, 'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for &'b Ratio { + type Output = Ratio; + #[inline] + fn pow(self, expon: &'a $exp) -> Ratio { + Pow::pow(self.clone(), *expon) + } + } + }; +} + +// this is solely to make `pow_impl!` work +trait WrappingAbs: Sized { + fn wrapping_abs(self) -> Self { + self + } +} +impl WrappingAbs for u8 {} +impl WrappingAbs for u16 {} +impl WrappingAbs for u32 {} +impl WrappingAbs for u64 {} +impl WrappingAbs for usize {} + +pow_impl!(i8, u8); +pow_impl!(i16, u16); +pow_impl!(i32, u32); +pow_impl!(i64, u64); +pow_impl!(isize, usize); +pow_impl!(u8); +pow_impl!(u16); +pow_impl!(u32); +pow_impl!(u64); +pow_impl!(usize); + +// TODO: pow_impl!(BigUint) and pow_impl!(BigInt, BigUint) + +#[cfg(feature = "bigint")] impl Ratio { /// Converts a float into a rational number. pub fn from_float(f: T) -> Option { @@ -265,7 +326,11 @@ impl Ratio { return None; } let (mantissa, exponent, sign) = f.integer_decode(); - let bigint_sign = if sign == 1 { Sign::Plus } else { Sign::Minus }; + let bigint_sign = if sign == 1 { + Sign::Plus + } else { + Sign::Minus + }; if exponent < 0 { let one: BigInt = One::one(); let denom: BigInt = one << ((-exponent) as usize); @@ -273,30 +338,21 @@ impl Ratio { Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom)) } else { let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap(); - numer <<= exponent as usize; - Some(Ratio::from_integer(BigInt::from_biguint( - bigint_sign, - numer, - ))) + numer = numer << (exponent as usize); + Some(Ratio::from_integer(BigInt::from_biguint(bigint_sign, numer))) } } } // From integer -impl From for Ratio -where - T: Clone + Integer, -{ +impl From for Ratio where T: Clone + Integer { fn from(x: T) -> Ratio { Ratio::from_integer(x) } } // From pair (through the `new` constructor) -impl From<(T, T)> for Ratio -where - T: Clone + Integer, -{ +impl From<(T, T)> for Ratio where T: Clone + Integer { fn from(pair: (T, T)) -> Ratio { Ratio::new(pair.0, pair.1) } @@ -322,9 +378,6 @@ impl Ord for Ratio { // With equal numerators, the denominators can be inversely compared if self.numer == other.numer { - if self.numer.is_zero() { - return cmp::Ordering::Equal; - } let ord = self.denom.cmp(&other.denom); return if self.numer < T::zero() { ord @@ -395,15 +448,15 @@ impl Hash for Ratio { } mod iter_sum_product { - use crate::Ratio; - use core::iter::{Product, Sum}; - use num_integer::Integer; - use num_traits::{One, Zero}; + use ::core::iter::{Sum, Product}; + use Ratio; + use integer::Integer; + use traits::{Zero, One}; impl Sum for Ratio { fn sum(iter: I) -> Self where - I: Iterator>, + I: Iterator> { iter.fold(Self::zero(), |sum, num| sum + num) } @@ -412,7 +465,7 @@ mod iter_sum_product { impl<'a, T: Integer + Clone> Sum<&'a Ratio> for Ratio { fn sum(iter: I) -> Self where - I: Iterator>, + I: Iterator> { iter.fold(Self::zero(), |sum, num| sum + num) } @@ -421,7 +474,7 @@ mod iter_sum_product { impl Product for Ratio { fn product(iter: I) -> Self where - I: Iterator>, + I: Iterator> { iter.fold(Self::one(), |prod, num| prod * num) } @@ -430,7 +483,7 @@ mod iter_sum_product { impl<'a, T: Integer + Clone> Product<&'a Ratio> for Ratio { fn product(iter: I) -> Self where - I: Iterator>, + I: Iterator> { iter.fold(Self::one(), |prod, num| prod * num) } @@ -438,79 +491,51 @@ mod iter_sum_product { } mod opassign { - use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; + use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; - use crate::Ratio; - use num_integer::Integer; - use num_traits::NumAssign; + use Ratio; + use integer::Integer; + use traits::NumAssign; impl AddAssign for Ratio { fn add_assign(&mut self, other: Ratio) { - if self.denom == other.denom { - self.numer += other.numer - } else { - let lcm = self.denom.lcm(&other.denom); - let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone()); - let rhs_numer = other.numer * (lcm.clone() / other.denom); - self.numer = lhs_numer + rhs_numer; - self.denom = lcm; - } + self.numer *= other.denom.clone(); + self.numer += self.denom.clone() * other.numer; + self.denom *= other.denom; self.reduce(); } } - // (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd)) impl DivAssign for Ratio { fn div_assign(&mut self, other: Ratio) { - let gcd_ac = self.numer.gcd(&other.numer); - let gcd_bd = self.denom.gcd(&other.denom); - self.numer /= gcd_ac.clone(); - self.numer *= other.denom / gcd_bd.clone(); - self.denom /= gcd_bd; - self.denom *= other.numer / gcd_ac; - self.reduce(); //TODO: remove this line. see #8. + self.numer *= other.denom; + self.denom *= other.numer; + self.reduce(); } } - // a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc)) impl MulAssign for Ratio { fn mul_assign(&mut self, other: Ratio) { - let gcd_ad = self.numer.gcd(&other.denom); - let gcd_bc = self.denom.gcd(&other.numer); - self.numer /= gcd_ad.clone(); - self.numer *= other.numer / gcd_bc.clone(); - self.denom /= gcd_bc; - self.denom *= other.denom / gcd_ad; - self.reduce(); //TODO: remove this line. see #8. + self.numer *= other.numer; + self.denom *= other.denom; + self.reduce(); } } impl RemAssign for Ratio { fn rem_assign(&mut self, other: Ratio) { - if self.denom == other.denom { - self.numer %= other.numer - } else { - let lcm = self.denom.lcm(&other.denom); - let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone()); - let rhs_numer = other.numer * (lcm.clone() / other.denom); - self.numer = lhs_numer % rhs_numer; - self.denom = lcm; - } + self.numer *= other.denom.clone(); + self.numer %= self.denom.clone() * other.numer; + self.denom *= other.denom; self.reduce(); } } impl SubAssign for Ratio { fn sub_assign(&mut self, other: Ratio) { - if self.denom == other.denom { - self.numer -= other.numer - } else { - let lcm = self.denom.lcm(&other.denom); - let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone()); - let rhs_numer = other.numer * (lcm.clone() / other.denom); - self.numer = lhs_numer - rhs_numer; - self.denom = lcm; - } + self.numer *= other.denom.clone(); + self.numer -= self.denom.clone() * other.numer; + self.denom *= other.denom; self.reduce(); } } @@ -525,19 +550,15 @@ mod opassign { impl DivAssign for Ratio { fn div_assign(&mut self, other: T) { - let gcd = self.numer.gcd(&other); - self.numer /= gcd.clone(); - self.denom *= other / gcd; - self.reduce(); //TODO: remove this line. see #8. + self.denom *= other; + self.reduce(); } } impl MulAssign for Ratio { fn mul_assign(&mut self, other: T) { - let gcd = self.denom.gcd(&other); - self.denom /= gcd.clone(); - self.numer *= other / gcd; - self.reduce(); //TODO: remove this line. see #8. + self.numer *= other; + self.reduce(); } } @@ -571,7 +592,7 @@ mod opassign { self.$method(other.clone()) } } - }; + } } forward_op_assign!(impl AddAssign, add_assign); @@ -599,14 +620,13 @@ macro_rules! forward_ref_ref_binop { self.clone().$method(other.clone()) } } - }; + } } macro_rules! forward_ref_val_binop { (impl $imp:ident, $method:ident) => { - impl<'a, T> $imp> for &'a Ratio - where - T: Clone + Integer, + impl<'a, T> $imp> for &'a Ratio where + T: Clone + Integer { type Output = Ratio; @@ -615,9 +635,8 @@ macro_rules! forward_ref_val_binop { self.clone().$method(other) } } - impl<'a, T> $imp for &'a Ratio - where - T: Clone + Integer, + impl<'a, T> $imp for &'a Ratio where + T: Clone + Integer { type Output = Ratio; @@ -626,14 +645,13 @@ macro_rules! forward_ref_val_binop { self.clone().$method(other) } } - }; + } } macro_rules! forward_val_ref_binop { (impl $imp:ident, $method:ident) => { - impl<'a, T> $imp<&'a Ratio> for Ratio - where - T: Clone + Integer, + impl<'a, T> $imp<&'a Ratio> for Ratio where + T: Clone + Integer { type Output = Ratio; @@ -642,9 +660,8 @@ macro_rules! forward_val_ref_binop { self.$method(other.clone()) } } - impl<'a, T> $imp<&'a T> for Ratio - where - T: Clone + Integer, + impl<'a, T> $imp<&'a T> for Ratio where + T: Clone + Integer { type Output = Ratio; @@ -653,7 +670,7 @@ macro_rules! forward_val_ref_binop { self.$method(other.clone()) } } - }; + } } macro_rules! forward_all_binop { @@ -666,82 +683,65 @@ macro_rules! forward_all_binop { // Arithmetic forward_all_binop!(impl Mul, mul); -// a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc)) +// a/b * c/d = (a*c)/(b*d) impl Mul> for Ratio -where - T: Clone + Integer, + where T: Clone + Integer { type Output = Ratio; #[inline] fn mul(self, rhs: Ratio) -> Ratio { - let gcd_ad = self.numer.gcd(&rhs.denom); - let gcd_bc = self.denom.gcd(&rhs.numer); - Ratio::new( - self.numer / gcd_ad.clone() * (rhs.numer / gcd_bc.clone()), - self.denom / gcd_bc * (rhs.denom / gcd_ad), - ) + Ratio::new(self.numer * rhs.numer, + self.denom * rhs.denom) } } // a/b * c/1 = (a*c) / (b*1) = (a*c) / b impl Mul for Ratio -where - T: Clone + Integer, + where T: Clone + Integer { type Output = Ratio; #[inline] fn mul(self, rhs: T) -> Ratio { - let gcd = self.denom.gcd(&rhs); - Ratio::new(self.numer * (rhs / gcd.clone()), self.denom / gcd) + Ratio::new(self.numer * rhs, + self.denom) } } forward_all_binop!(impl Div, div); -// (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd)) +// (a/b) / (c/d) = (a*d) / (b*c) impl Div> for Ratio -where - T: Clone + Integer, + where T: Clone + Integer { type Output = Ratio; #[inline] fn div(self, rhs: Ratio) -> Ratio { - let gcd_ac = self.numer.gcd(&rhs.numer); - let gcd_bd = self.denom.gcd(&rhs.denom); - Ratio::new( - self.numer / gcd_ac.clone() * (rhs.denom / gcd_bd.clone()), - self.denom / gcd_bd * (rhs.numer / gcd_ac), - ) + Ratio::new(self.numer * rhs.denom, + self.denom * rhs.numer) } } // (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c) impl Div for Ratio -where - T: Clone + Integer, + where T: Clone + Integer { type Output = Ratio; #[inline] fn div(self, rhs: T) -> Ratio { - let gcd = self.numer.gcd(&rhs); - Ratio::new(self.numer / gcd.clone(), self.denom * (rhs / gcd)) + Ratio::new(self.numer, + self.denom * rhs) } } macro_rules! arith_impl { (impl $imp:ident, $method:ident) => { forward_all_binop!(impl $imp, $method); - // Abstracts a/b `op` c/d = (a*lcm/b `op` c*lcm/d)/lcm where lcm = lcm(b,d) + // Abstracts the a/b `op` c/d = (a*d `op` b*c) / (b*d) pattern impl $imp> for Ratio { type Output = Ratio; #[inline] fn $method(self, rhs: Ratio) -> Ratio { - if self.denom == rhs.denom { - return Ratio::new(self.numer.$method(rhs.numer), rhs.denom); - } - let lcm = self.denom.lcm(&rhs.denom); - let lhs_numer = self.numer * (lcm.clone() / self.denom); - let rhs_numer = rhs.numer * (lcm.clone() / rhs.denom); - Ratio::new(lhs_numer.$method(rhs_numer), lcm) + Ratio::new((self.numer * rhs.denom.clone()).$method(self.denom.clone() * rhs.numer), + self.denom * rhs.denom) } } // Abstracts the a/b `op` c/1 = (a*1 `op` b*c) / (b*1) = (a `op` b*c) / b pattern @@ -749,76 +749,48 @@ macro_rules! arith_impl { type Output = Ratio; #[inline] fn $method(self, rhs: T) -> Ratio { - Ratio::new(self.numer.$method(self.denom.clone() * rhs), self.denom) + Ratio::new(self.numer.$method(self.denom.clone() * rhs), + self.denom) } } - }; + } } arith_impl!(impl Add, add); arith_impl!(impl Sub, sub); arith_impl!(impl Rem, rem); +// Like `std::try!` for Option, unwrap the value or early-return None. +// Since Rust 1.22 this can be replaced by the `?` operator. +macro_rules! otry { + ($expr:expr) => (match $expr { + Some(val) => val, + None => return None, + }) +} + // a/b * c/d = (a*c)/(b*d) impl CheckedMul for Ratio -where - T: Clone + Integer + CheckedMul, + where T: Clone + Integer + CheckedMul { #[inline] fn checked_mul(&self, rhs: &Ratio) -> Option> { - let gcd_ad = self.numer.gcd(&rhs.denom); - let gcd_bc = self.denom.gcd(&rhs.numer); - Some(Ratio::new( - (self.numer.clone() / gcd_ad.clone()) - .checked_mul(&(rhs.numer.clone() / gcd_bc.clone()))?, - (self.denom.clone() / gcd_bc).checked_mul(&(rhs.denom.clone() / gcd_ad))?, - )) + Some(Ratio::new(otry!(self.numer.checked_mul(&rhs.numer)), + otry!(self.denom.checked_mul(&rhs.denom)))) } } // (a/b) / (c/d) = (a*d)/(b*c) impl CheckedDiv for Ratio -where - T: Clone + Integer + CheckedMul, + where T: Clone + Integer + CheckedMul { #[inline] fn checked_div(&self, rhs: &Ratio) -> Option> { - if rhs.is_zero() { - return None; - } - let (numer, denom) = if self.denom == rhs.denom { - (self.numer.clone(), rhs.numer.clone()) - } else if self.numer == rhs.numer { - (rhs.denom.clone(), self.denom.clone()) - } else { - let gcd_ac = self.numer.gcd(&rhs.numer); - let gcd_bd = self.denom.gcd(&rhs.denom); - ( - (self.numer.clone() / gcd_ac.clone()) - .checked_mul(&(rhs.denom.clone() / gcd_bd.clone()))?, - (self.denom.clone() / gcd_bd).checked_mul(&(rhs.numer.clone() / gcd_ac))?, - ) - }; - // Manual `reduce()`, avoiding sharp edges - if denom.is_zero() { + let bc = otry!(self.denom.checked_mul(&rhs.numer)); + if bc.is_zero() { None - } else if numer.is_zero() { - Some(Self::zero()) - } else if numer == denom { - Some(Self::one()) } else { - let g = numer.gcd(&denom); - let numer = numer / g.clone(); - let denom = denom / g; - let raw = if denom < T::zero() { - // We need to keep denom positive, but 2's-complement MIN may - // overflow negation -- instead we can check multiplying -1. - let n1 = T::zero() - T::one(); - Ratio::new_raw(numer.checked_mul(&n1)?, denom.checked_mul(&n1)?) - } else { - Ratio::new_raw(numer, denom) - }; - Some(raw) + Some(Ratio::new(otry!(self.numer.checked_mul(&rhs.denom)), bc)) } } } @@ -829,25 +801,23 @@ macro_rules! checked_arith_impl { impl $imp for Ratio { #[inline] fn $method(&self, rhs: &Ratio) -> Option> { - let gcd = self.denom.clone().gcd(&rhs.denom); - let lcm = (self.denom.clone() / gcd.clone()).checked_mul(&rhs.denom)?; - let lhs_numer = (lcm.clone() / self.denom.clone()).checked_mul(&self.numer)?; - let rhs_numer = (lcm.clone() / rhs.denom.clone()).checked_mul(&rhs.numer)?; - Some(Ratio::new(lhs_numer.$method(&rhs_numer)?, lcm)) + let ad = otry!(self.numer.checked_mul(&rhs.denom)); + let bc = otry!(self.denom.checked_mul(&rhs.numer)); + let bd = otry!(self.denom.checked_mul(&rhs.denom)); + Some(Ratio::new(otry!(ad.$method(&bc)), bd)) } } - }; + } } -// a/b + c/d = (lcm/b*a + lcm/d*c)/lcm, where lcm = lcm(b,d) +// a/b + c/d = (a*d + b*c)/(b*d) checked_arith_impl!(impl CheckedAdd, checked_add); -// a/b - c/d = (lcm/b*a - lcm/d*c)/lcm, where lcm = lcm(b,d) +// a/b - c/d = (a*d - b*c)/(b*d) checked_arith_impl!(impl CheckedSub, checked_sub); impl Neg for Ratio -where - T: Clone + Integer + Neg, + where T: Clone + Integer + Neg { type Output = Ratio; @@ -858,8 +828,7 @@ where } impl<'a, T> Neg for &'a Ratio -where - T: Clone + Integer + Neg, + where T: Clone + Integer + Neg { type Output = Ratio; @@ -870,8 +839,7 @@ where } impl Inv for Ratio -where - T: Clone + Integer, + where T: Clone + Integer { type Output = Ratio; @@ -882,8 +850,7 @@ where } impl<'a, T> Inv for &'a Ratio -where - T: Clone + Integer, + where T: Clone + Integer { type Output = Ratio; @@ -904,12 +871,6 @@ impl Zero for Ratio { fn is_zero(&self) -> bool { self.numer.is_zero() } - - #[inline] - fn set_zero(&mut self) { - self.numer.set_zero(); - self.denom.set_one(); - } } impl One for Ratio { @@ -922,12 +883,6 @@ impl One for Ratio { fn is_one(&self) -> bool { self.numer == self.denom } - - #[inline] - fn set_one(&mut self) { - self.numer.set_one(); - self.denom.set_one(); - } } impl Num for Ratio { @@ -936,24 +891,18 @@ impl Num for Ratio { /// Parses `numer/denom` where the numbers are in base `radix`. fn from_str_radix(s: &str, radix: u32) -> Result, ParseRatioError> { if s.splitn(2, '/').count() == 2 { - let mut parts = s.splitn(2, '/').map(|ss| { - T::from_str_radix(ss, radix).map_err(|_| ParseRatioError { - kind: RatioErrorKind::ParseError, - }) - }); + let mut parts = s.splitn(2, '/').map(|ss| T::from_str_radix(ss, radix).map_err(|_| { + ParseRatioError { kind: RatioErrorKind::ParseError } + })); let numer: T = parts.next().unwrap()?; let denom: T = parts.next().unwrap()?; if denom.is_zero() { - Err(ParseRatioError { - kind: RatioErrorKind::ZeroDenominator, - }) + Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator }) } else { Ok(Ratio::new(numer, denom)) } } else { - Err(ParseRatioError { - kind: RatioErrorKind::ParseError, - }) + Err(ParseRatioError { kind: RatioErrorKind::ParseError }) } } } @@ -990,83 +939,31 @@ impl Signed for Ratio { #[inline] fn is_positive(&self) -> bool { - (self.numer.is_positive() && self.denom.is_positive()) - || (self.numer.is_negative() && self.denom.is_negative()) + (self.numer.is_positive() && self.denom.is_positive()) || + (self.numer.is_negative() && self.denom.is_negative()) } #[inline] fn is_negative(&self) -> bool { - (self.numer.is_negative() && self.denom.is_positive()) - || (self.numer.is_positive() && self.denom.is_negative()) + (self.numer.is_negative() && self.denom.is_positive()) || + (self.numer.is_positive() && self.denom.is_negative()) } } // String conversions -macro_rules! impl_formatting { - ($fmt_trait:ident, $prefix:expr, $fmt_str:expr, $fmt_alt:expr) => { - impl $fmt_trait for Ratio { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let pre_pad = if self.denom.is_one() { - format!($fmt_str, self.numer) - } else { - if f.alternate() { - format!(concat!($fmt_str, "/", $fmt_alt), self.numer, self.denom) - } else { - format!(concat!($fmt_str, "/", $fmt_str), self.numer, self.denom) - } - }; - //TODO: replace with strip_prefix, when stabalized - let (pre_pad, non_negative) = { - if pre_pad.starts_with("-") { - (&pre_pad[1..], false) - } else { - (&pre_pad[..], true) - } - }; - f.pad_integral(non_negative, $prefix, pre_pad) - } - #[cfg(not(feature = "std"))] - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let plus = if f.sign_plus() && self.numer >= T::zero() { - "+" - } else { - "" - }; - if self.denom.is_one() { - if f.alternate() { - write!(f, concat!("{}", $fmt_alt), plus, self.numer) - } else { - write!(f, concat!("{}", $fmt_str), plus, self.numer) - } - } else { - if f.alternate() { - write!( - f, - concat!("{}", $fmt_alt, "/", $fmt_alt), - plus, self.numer, self.denom - ) - } else { - write!( - f, - concat!("{}", $fmt_str, "/", $fmt_str), - plus, self.numer, self.denom - ) - } - } - } +impl fmt::Display for Ratio + where T: fmt::Display + Eq + One +{ + /// Renders as `numer/denom`. If denom=1, renders as numer. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.denom.is_one() { + write!(f, "{}", self.numer) + } else { + write!(f, "{}/{}", self.numer, self.denom) } - }; + } } -impl_formatting!(Display, "", "{}", "{:#}"); -impl_formatting!(Octal, "0o", "{:o}", "{:#o}"); -impl_formatting!(Binary, "0b", "{:b}", "{:#b}"); -impl_formatting!(LowerHex, "0x", "{:x}", "{:#x}"); -impl_formatting!(UpperHex, "0x", "{:X}", "{:#X}"); -impl_formatting!(LowerExp, "", "{:e}", "{:#e}"); -impl_formatting!(UpperExp, "", "{:E}", "{:#E}"); - impl FromStr for Ratio { type Err = ParseRatioError; @@ -1074,22 +971,16 @@ impl FromStr for Ratio { fn from_str(s: &str) -> Result, ParseRatioError> { let mut split = s.splitn(2, '/'); - let n = split.next().ok_or(ParseRatioError { - kind: RatioErrorKind::ParseError, - })?; - let num = FromStr::from_str(n).map_err(|_| ParseRatioError { - kind: RatioErrorKind::ParseError, - })?; + let n = try!(split.next().ok_or(ParseRatioError { kind: RatioErrorKind::ParseError })); + let num = try!(FromStr::from_str(n) + .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError })); let d = split.next().unwrap_or("1"); - let den = FromStr::from_str(d).map_err(|_| ParseRatioError { - kind: RatioErrorKind::ParseError, - })?; + let den = try!(FromStr::from_str(d) + .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError })); if Zero::is_zero(&den) { - Err(ParseRatioError { - kind: RatioErrorKind::ZeroDenominator, - }) + Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator }) } else { Ok(Ratio::new(num, den)) } @@ -1104,12 +995,10 @@ impl Into<(T, T)> for Ratio { #[cfg(feature = "serde")] impl serde::Serialize for Ratio -where - T: serde::Serialize + Clone + Integer + PartialOrd, + where T: serde::Serialize + Clone + Integer + PartialOrd { fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, + where S: serde::Serializer { (self.numer(), self.denom()).serialize(serializer) } @@ -1117,21 +1006,16 @@ where #[cfg(feature = "serde")] impl<'de, T> serde::Deserialize<'de> for Ratio -where - T: serde::Deserialize<'de> + Clone + Integer + PartialOrd, + where T: serde::Deserialize<'de> + Clone + Integer + PartialOrd { fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, + where D: serde::Deserializer<'de> { - use serde::de::Error; use serde::de::Unexpected; - let (numer, denom): (T, T) = serde::Deserialize::deserialize(deserializer)?; + use serde::de::Error; + let (numer, denom): (T,T) = try!(serde::Deserialize::deserialize(deserializer)); if denom.is_zero() { - Err(Error::invalid_value( - Unexpected::Signed(0), - &"a ratio with non-zero denominator", - )) + Err(Error::invalid_value(Unexpected::Signed(0), &"a ratio with non-zero denominator")) } else { Ok(Ratio::new_raw(numer, denom)) } @@ -1151,14 +1035,13 @@ enum RatioErrorKind { } impl fmt::Display for ParseRatioError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.kind.description().fmt(f) } } #[cfg(feature = "std")] impl Error for ParseRatioError { - #[allow(deprecated)] fn description(&self) -> &str { self.kind.description() } @@ -1173,12 +1056,13 @@ impl RatioErrorKind { } } -#[cfg(feature = "num-bigint")] +#[cfg(feature = "bigint")] impl FromPrimitive for Ratio { fn from_i64(n: i64) -> Option { Some(Ratio::from_integer(n.into())) } + #[cfg(has_i128)] fn from_i128(n: i128) -> Option { Some(Ratio::from_integer(n.into())) } @@ -1187,6 +1071,7 @@ impl FromPrimitive for Ratio { Some(Ratio::from_integer(n.into())) } + #[cfg(has_i128)] fn from_u128(n: u128) -> Option { Some(Ratio::from_integer(n.into())) } @@ -1207,6 +1092,7 @@ macro_rules! from_primitive_integer { <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer) } + #[cfg(has_i128)] fn from_i128(n: i128) -> Option { <$typ as FromPrimitive>::from_i128(n).map(Ratio::from_integer) } @@ -1215,6 +1101,7 @@ macro_rules! from_primitive_integer { <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer) } + #[cfg(has_i128)] fn from_u128(n: u128) -> Option { <$typ as FromPrimitive>::from_u128(n).map(Ratio::from_integer) } @@ -1227,13 +1114,14 @@ macro_rules! from_primitive_integer { $approx(n, 10e-20, 30) } } - }; + } } from_primitive_integer!(i8, approximate_float); from_primitive_integer!(i16, approximate_float); from_primitive_integer!(i32, approximate_float); from_primitive_integer!(i64, approximate_float); +#[cfg(has_i128)] from_primitive_integer!(i128, approximate_float); from_primitive_integer!(isize, approximate_float); @@ -1241,6 +1129,7 @@ from_primitive_integer!(u8, approximate_float_unsigned); from_primitive_integer!(u16, approximate_float_unsigned); from_primitive_integer!(u32, approximate_float_unsigned); from_primitive_integer!(u64, approximate_float_unsigned); +#[cfg(has_i128)] from_primitive_integer!(u128, approximate_float_unsigned); from_primitive_integer!(usize, approximate_float_unsigned); @@ -1255,25 +1144,27 @@ impl Ratio { } fn approximate_float(val: F, max_error: F, max_iterations: usize) -> Option> -where - T: Integer + Signed + Bounded + NumCast + Clone, - F: FloatCore + NumCast, + where T: Integer + Signed + Bounded + NumCast + Clone, + F: FloatCore + NumCast { let negative = val.is_sign_negative(); let abs_val = val.abs(); - let r = approximate_float_unsigned(abs_val, max_error, max_iterations)?; + let r = approximate_float_unsigned(abs_val, max_error, max_iterations); // Make negative again if needed - Some(if negative { r.neg() } else { r }) + if negative { + r.map(|r| r.neg()) + } else { + r + } } // No Unsigned constraint because this also works on positive integers and is called // like that, see above fn approximate_float_unsigned(val: F, max_error: F, max_iterations: usize) -> Option> -where - T: Integer + Bounded + NumCast + Clone, - F: FloatCore + NumCast, + where T: Integer + Bounded + NumCast + Clone, + F: FloatCore + NumCast { // Continued fractions algorithm // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac @@ -1289,7 +1180,10 @@ where let mut d1 = T::zero(); let t_max = T::max_value(); - let t_max_f = ::from(t_max.clone())?; + let t_max_f = match ::from(t_max.clone()) { + None => return None, + Some(t_max_f) => t_max_f, + }; // 1/epsilon > T::MAX let epsilon = t_max_f.recip(); @@ -1312,12 +1206,11 @@ where let f = q - a_f; // Prevent overflow - if !a.is_zero() - && (n1 > t_max.clone() / a.clone() - || d1 > t_max.clone() / a.clone() - || a.clone() * n1.clone() > t_max.clone() - n0.clone() - || a.clone() * d1.clone() > t_max.clone() - d0.clone()) - { + if !a.is_zero() && + (n1 > t_max.clone() / a.clone() || + d1 > t_max.clone() / a.clone() || + a.clone() * n1.clone() > t_max.clone() - n0.clone() || + a.clone() * d1.clone() > t_max.clone() - d0.clone()) { break; } @@ -1361,228 +1254,11 @@ where Some(Ratio::new(n1, d1)) } -#[cfg(not(feature = "num-bigint"))] -macro_rules! to_primitive_small { - ($($type_name:ty)*) => ($( - impl ToPrimitive for Ratio<$type_name> { - fn to_i64(&self) -> Option { - self.to_integer().to_i64() - } - - fn to_i128(&self) -> Option { - self.to_integer().to_i128() - } - - fn to_u64(&self) -> Option { - self.to_integer().to_u64() - } - - fn to_u128(&self) -> Option { - self.to_integer().to_u128() - } - - fn to_f64(&self) -> Option { - Some(self.numer.to_f64().unwrap() / self.denom.to_f64().unwrap()) - } - } - )*) -} - -#[cfg(not(feature = "num-bigint"))] -to_primitive_small!(u8 i8 u16 i16 u32 i32); - -#[cfg(all(target_pointer_width = "32", not(feature = "num-bigint")))] -to_primitive_small!(usize isize); - -#[cfg(not(feature = "num-bigint"))] -macro_rules! to_primitive_64 { - ($($type_name:ty)*) => ($( - impl ToPrimitive for Ratio<$type_name> { - fn to_i64(&self) -> Option { - self.to_integer().to_i64() - } - - fn to_i128(&self) -> Option { - self.to_integer().to_i128() - } - - fn to_u64(&self) -> Option { - self.to_integer().to_u64() - } - - fn to_u128(&self) -> Option { - self.to_integer().to_u128() - } - - fn to_f64(&self) -> Option { - Some(ratio_to_f64( - self.numer as i128, - self.denom as i128 - )) - } - } - )*) -} - -#[cfg(not(feature = "num-bigint"))] -to_primitive_64!(u64 i64); - -#[cfg(all(target_pointer_width = "64", not(feature = "num-bigint")))] -to_primitive_64!(usize isize); - -#[cfg(feature = "num-bigint")] -impl ToPrimitive for Ratio { - fn to_i64(&self) -> Option { - self.to_integer().to_i64() - } - - fn to_i128(&self) -> Option { - self.to_integer().to_i128() - } - - fn to_u64(&self) -> Option { - self.to_integer().to_u64() - } - - fn to_u128(&self) -> Option { - self.to_integer().to_u128() - } - - fn to_f64(&self) -> Option { - match (self.numer.to_i64(), self.denom.to_i64()) { - (Some(numer), Some(denom)) => Some(ratio_to_f64( - >::from(numer), - >::from(denom), - )), - _ => { - let numer: BigInt = self.numer.to_bigint()?; - let denom: BigInt = self.denom.to_bigint()?; - Some(ratio_to_f64(numer, denom)) - } - } - } -} - -trait Bits { - fn bits(&self) -> u64; -} - -#[cfg(feature = "num-bigint")] -impl Bits for BigInt { - fn bits(&self) -> u64 { - self.bits() - } -} - -impl Bits for i128 { - fn bits(&self) -> u64 { - (128 - self.wrapping_abs().leading_zeros()).into() - } -} - -/// Converts a ratio of `T` to an f64. -/// -/// In addition to stated trait bounds, `T` must be able to hold numbers 56 bits larger than -/// the largest of `numer` and `denom`. This is automatically true if `T` is `BigInt`. -fn ratio_to_f64 + ToPrimitive>( - numer: T, - denom: T, -) -> f64 { - assert_eq!( - core::f64::RADIX, - 2, - "only floating point implementations with radix 2 are supported" - ); - - // Inclusive upper and lower bounds to the range of exactly-representable ints in an f64. - const MAX_EXACT_INT: i64 = 1i64 << core::f64::MANTISSA_DIGITS; - const MIN_EXACT_INT: i64 = -MAX_EXACT_INT; - - let flo_sign = numer.signum().to_f64().unwrap() * denom.signum().to_f64().unwrap(); - - if numer.is_zero() { - return 0.0 * flo_sign; - } - - // Fast track: both sides can losslessly be converted to f64s. In this case, letting the - // FPU do the job is faster and easier. In any other case, converting to f64s may lead - // to an inexact result: https://stackoverflow.com/questions/56641441/. - if let (Some(n), Some(d)) = (numer.to_i64(), denom.to_i64()) { - if MIN_EXACT_INT <= n && n <= MAX_EXACT_INT && MIN_EXACT_INT <= d && d <= MAX_EXACT_INT { - return n.to_f64().unwrap() / d.to_f64().unwrap(); - } - } - - // Otherwise, the goal is to obtain a quotient with at least 55 bits. 53 of these bits will - // be used as the mantissa of the resulting float, and the remaining two are for rounding. - // There's an error of up to 1 on the number of resulting bits, so we may get either 55 or - // 56 bits. - let mut numer = numer.abs(); - let mut denom = denom.abs(); - let (is_diff_positive, absolute_diff) = match numer.bits().checked_sub(denom.bits()) { - Some(diff) => (true, diff), - None => (false, denom.bits() - numer.bits()), - }; - - // Filter out overflows and underflows. After this step, the signed difference fits in an - // isize. - if is_diff_positive && absolute_diff > core::f64::MAX_EXP as u64 { - return core::f64::INFINITY * flo_sign; - } - if !is_diff_positive - && absolute_diff > -core::f64::MIN_EXP as u64 + core::f64::MANTISSA_DIGITS as u64 + 1 - { - return 0.0 * flo_sign; - } - let diff = if is_diff_positive { - absolute_diff.to_isize().unwrap() - } else { - -absolute_diff.to_isize().unwrap() - }; - - // Shift is chosen so that the quotient will have 55 or 56 bits. The exception is if the - // quotient is going to be subnormal, in which case it may have fewer bits. - let shift: isize = - diff.max(core::f64::MIN_EXP as isize) - core::f64::MANTISSA_DIGITS as isize - 2; - if shift >= 0 { - denom <<= shift as usize - } else { - numer <<= -shift as usize - }; - - let (quotient, remainder) = numer.div_rem(&denom); - - // This is guaranteed to fit since we've set up quotient to be at most 56 bits. - let mut quotient = quotient.to_u64().unwrap(); - let n_rounding_bits = { - let quotient_bits = 64 - quotient.leading_zeros() as isize; - let subnormal_bits = core::f64::MIN_EXP as isize - shift; - quotient_bits.max(subnormal_bits) - core::f64::MANTISSA_DIGITS as isize - } as usize; - debug_assert!(n_rounding_bits == 2 || n_rounding_bits == 3); - let rounding_bit_mask = (1u64 << n_rounding_bits) - 1; - - // Round to 53 bits with round-to-even. For rounding, we need to take into account both - // our rounding bits and the division's remainder. - let ls_bit = quotient & (1u64 << n_rounding_bits) != 0; - let ms_rounding_bit = quotient & (1u64 << (n_rounding_bits - 1)) != 0; - let ls_rounding_bits = quotient & (rounding_bit_mask >> 1) != 0; - if ms_rounding_bit && (ls_bit || ls_rounding_bits || !remainder.is_zero()) { - quotient += 1u64 << n_rounding_bits; - } - quotient &= !rounding_bit_mask; - - // The quotient is guaranteed to be exactly representable as it's now 53 bits + 2 or 3 - // trailing zeros, so there is no risk of a rounding error here. - let q_float = quotient as f64; - q_float * 2f64.powi(shift as i32) * flo_sign -} - #[cfg(test)] #[cfg(feature = "std")] fn hash(x: &T) -> u64 { - use std::collections::hash_map::RandomState; use std::hash::BuildHasher; + use std::collections::hash_map::RandomState; let mut hasher = ::Hasher::new(); x.hash(&mut hasher); hasher.finish() @@ -1590,49 +1266,40 @@ fn hash(x: &T) -> u64 { #[cfg(test)] mod test { - #[cfg(all(feature = "num-bigint"))] - use super::BigInt; - #[cfg(feature = "num-bigint")] + use super::{Ratio, Rational}; + #[cfg(feature = "bigint")] use super::BigRational; - use super::{Ratio, Rational, Rational64}; - use core::f64; - use core::i32; - use core::isize; use core::str::FromStr; - use num_integer::Integer; - use num_traits::ToPrimitive; - use num_traits::{FromPrimitive, One, Pow, Signed, Zero}; + use core::i32; + use core::f64; + use traits::{Zero, One, Signed, FromPrimitive, Pow}; + use integer::Integer; - pub const _0: Rational = Ratio { numer: 0, denom: 1 }; - pub const _1: Rational = Ratio { numer: 1, denom: 1 }; - pub const _2: Rational = Ratio { numer: 2, denom: 1 }; + pub const _0: Rational = Ratio { + numer: 0, + denom: 1, + }; + pub const _1: Rational = Ratio { + numer: 1, + denom: 1, + }; + pub const _2: Rational = Ratio { + numer: 2, + denom: 1, + }; pub const _NEG2: Rational = Ratio { numer: -2, denom: 1, }; - pub const _8: Rational = Ratio { numer: 8, denom: 1 }; - pub const _15: Rational = Ratio { - numer: 15, - denom: 1, - }; - pub const _16: Rational = Ratio { - numer: 16, - denom: 1, - }; - - pub const _1_2: Rational = Ratio { numer: 1, denom: 2 }; - pub const _1_8: Rational = Ratio { numer: 1, denom: 8 }; - pub const _1_15: Rational = Ratio { + pub const _1_2: Rational = Ratio { numer: 1, - denom: 15, + denom: 2, }; - pub const _1_16: Rational = Ratio { - numer: 1, - denom: 16, + pub const _3_2: Rational = Ratio { + numer: 3, + denom: 2, }; - pub const _3_2: Rational = Ratio { numer: 3, denom: 2 }; - pub const _5_2: Rational = Ratio { numer: 5, denom: 2 }; pub const _NEG1_2: Rational = Ratio { numer: -1, denom: 2, @@ -1645,50 +1312,32 @@ mod test { numer: -1, denom: -2, }; - pub const _1_3: Rational = Ratio { numer: 1, denom: 3 }; + pub const _1_3: Rational = Ratio { + numer: 1, + denom: 3, + }; pub const _NEG1_3: Rational = Ratio { numer: -1, denom: 3, }; - pub const _2_3: Rational = Ratio { numer: 2, denom: 3 }; + pub const _2_3: Rational = Ratio { + numer: 2, + denom: 3, + }; pub const _NEG2_3: Rational = Ratio { numer: -2, denom: 3, }; - pub const _MIN: Rational = Ratio { - numer: isize::MIN, - denom: 1, - }; - pub const _MIN_P1: Rational = Ratio { - numer: isize::MIN + 1, - denom: 1, - }; - pub const _MAX: Rational = Ratio { - numer: isize::MAX, - denom: 1, - }; - pub const _MAX_M1: Rational = Ratio { - numer: isize::MAX - 1, - denom: 1, - }; - pub const _BILLION: Rational = Ratio { - numer: 1_000_000_000, - denom: 1, - }; - #[cfg(feature = "num-bigint")] + #[cfg(feature = "bigint")] pub fn to_big(n: Rational) -> BigRational { - Ratio::new( - FromPrimitive::from_isize(n.numer).unwrap(), - FromPrimitive::from_isize(n.denom).unwrap(), - ) + Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(), + FromPrimitive::from_isize(n.denom).unwrap()) } - #[cfg(not(feature = "num-bigint"))] + #[cfg(not(feature = "bigint"))] pub fn to_big(n: Rational) -> Rational { - Ratio::new( - FromPrimitive::from_isize(n.numer).unwrap(), - FromPrimitive::from_isize(n.denom).unwrap(), - ) + Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(), + FromPrimitive::from_isize(n.denom).unwrap()) } #[test] @@ -1705,9 +1354,9 @@ mod test { #[test] fn test_new_reduce() { - assert_eq!(Ratio::new(2, 2), One::one()); - assert_eq!(Ratio::new(0, i32::MIN), Zero::zero()); - assert_eq!(Ratio::new(i32::MIN, i32::MIN), One::one()); + let one22 = Ratio::new(2, 2); + + assert_eq!(one22, One::one()); } #[test] #[should_panic] @@ -1729,14 +1378,8 @@ mod test { assert_eq!(Ratio::::from_f32(127.0f32), Some(Ratio::new(127i8, 1))); assert_eq!(Ratio::::from_f32(127.5f32), None); assert_eq!(Ratio::::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2))); - assert_eq!( - Ratio::::from_f32(-126.5f32), - Some(Ratio::new(-126i8, 1)) - ); - assert_eq!( - Ratio::::from_f32(-127.0f32), - Some(Ratio::new(-127i8, 1)) - ); + assert_eq!(Ratio::::from_f32(-126.5f32), Some(Ratio::new(-126i8, 1))); + assert_eq!(Ratio::::from_f32(-127.0f32), Some(Ratio::new(-127i8, 1))); assert_eq!(Ratio::::from_f32(-127.5f32), None); assert_eq!(Ratio::::from_f32(-127f32), None); @@ -1749,16 +1392,12 @@ mod test { assert_eq!(Ratio::::from_f64(f64::INFINITY), None); assert_eq!(Ratio::::from_f64(f64::NEG_INFINITY), None); assert_eq!(Ratio::::from_f64(f64::NAN), None); - assert_eq!( - Ratio::::from_f64(f64::EPSILON), - Some(Ratio::new(1, 4503599627370496)) - ); + assert_eq!(Ratio::::from_f64(f64::EPSILON), Some(Ratio::new(1, 4503599627370496))); assert_eq!(Ratio::::from_f64(0.0), Some(Ratio::new(0, 1))); assert_eq!(Ratio::::from_f64(-0.0), Some(Ratio::new(0, 1))); } #[test] - #[allow(clippy::eq_op)] fn test_cmp() { assert!(_0 == _0 && _1 == _1); assert!(_0 != _1 && _1 != _0); @@ -1770,9 +1409,6 @@ mod test { assert!(_0 >= _0 && _1 >= _1); assert!(_1 >= _0 && !(_0 >= _1)); - - let _0_2: Rational = Ratio::new_raw(0, 2); - assert_eq!(_0, _0_2); } #[test] @@ -1824,6 +1460,7 @@ mod test { assert_eq!(_NEG1_2.to_integer(), 0); } + #[test] fn test_numer() { assert_eq!(_0.numer(), &0); @@ -1843,6 +1480,7 @@ mod test { assert_eq!(_NEG1_2.denom(), &2); } + #[test] fn test_is_integer() { assert!(_0.is_integer()); @@ -1853,200 +1491,33 @@ mod test { assert!(!_NEG1_2.is_integer()); } - #[cfg(not(feature = "std"))] - use core::fmt::{self, Write}; - #[cfg(not(feature = "std"))] - #[derive(Debug)] - struct NoStdTester { - cursor: usize, - buf: [u8; NoStdTester::BUF_SIZE], - } - - #[cfg(not(feature = "std"))] - impl NoStdTester { - fn new() -> NoStdTester { - NoStdTester { - buf: [0; Self::BUF_SIZE], - cursor: 0, - } - } - - fn clear(&mut self) { - self.buf = [0; Self::BUF_SIZE]; - self.cursor = 0; - } - - const WRITE_ERR: &'static str = "Formatted output too long"; - const BUF_SIZE: usize = 32; - } - - #[cfg(not(feature = "std"))] - impl Write for NoStdTester { - fn write_str(&mut self, s: &str) -> fmt::Result { - for byte in s.bytes() { - self.buf[self.cursor] = byte; - self.cursor += 1; - if self.cursor >= self.buf.len() { - return Err(fmt::Error {}); - } - } - Ok(()) - } - } - - #[cfg(not(feature = "std"))] - impl PartialEq for NoStdTester { - fn eq(&self, other: &str) -> bool { - let other = other.as_bytes(); - for index in 0..self.cursor { - if self.buf.get(index) != other.get(index) { - return false; - } - } - true - } - } - - macro_rules! assert_fmt_eq { - ($fmt_args:expr, $string:expr) => { - #[cfg(not(feature = "std"))] - { - let mut tester = NoStdTester::new(); - write!(tester, "{}", $fmt_args).expect(NoStdTester::WRITE_ERR); - assert_eq!(tester, *$string); - tester.clear(); - } - #[cfg(feature = "std")] - { - assert_eq!(std::fmt::format($fmt_args), $string); - } - }; - } - #[test] + #[cfg(feature = "std")] fn test_show() { - // Test: - // :b :o :x, :X, :? - // alternate or not (#) - // positive and negative - // padding - // does not test precision (i.e. truncation) - assert_fmt_eq!(format_args!("{}", _2), "2"); - assert_fmt_eq!(format_args!("{:+}", _2), "+2"); - assert_fmt_eq!(format_args!("{:-}", _2), "2"); - assert_fmt_eq!(format_args!("{}", _1_2), "1/2"); - assert_fmt_eq!(format_args!("{}", -_1_2), "-1/2"); // test negatives - assert_fmt_eq!(format_args!("{}", _0), "0"); - assert_fmt_eq!(format_args!("{}", -_2), "-2"); - assert_fmt_eq!(format_args!("{:+}", -_2), "-2"); - assert_fmt_eq!(format_args!("{:b}", _2), "10"); - assert_fmt_eq!(format_args!("{:#b}", _2), "0b10"); - assert_fmt_eq!(format_args!("{:b}", _1_2), "1/10"); - assert_fmt_eq!(format_args!("{:+b}", _1_2), "+1/10"); - assert_fmt_eq!(format_args!("{:-b}", _1_2), "1/10"); - assert_fmt_eq!(format_args!("{:b}", _0), "0"); - assert_fmt_eq!(format_args!("{:#b}", _1_2), "0b1/0b10"); - //no std does not support padding - #[cfg(feature = "std")] - assert_eq!(&format!("{:010b}", _1_2), "0000001/10"); - #[cfg(feature = "std")] - assert_eq!(&format!("{:#010b}", _1_2), "0b001/0b10"); - let half_i8: Ratio = Ratio::new(1_i8, 2_i8); - assert_fmt_eq!(format_args!("{:b}", -half_i8), "11111111/10"); - assert_fmt_eq!(format_args!("{:#b}", -half_i8), "0b11111111/0b10"); - #[cfg(feature = "std")] - assert_eq!(&format!("{:05}", Ratio::new(-1_i8, 1_i8)), "-0001"); - - assert_fmt_eq!(format_args!("{:o}", _8), "10"); - assert_fmt_eq!(format_args!("{:o}", _1_8), "1/10"); - assert_fmt_eq!(format_args!("{:o}", _0), "0"); - assert_fmt_eq!(format_args!("{:#o}", _1_8), "0o1/0o10"); - #[cfg(feature = "std")] - assert_eq!(&format!("{:010o}", _1_8), "0000001/10"); - #[cfg(feature = "std")] - assert_eq!(&format!("{:#010o}", _1_8), "0o001/0o10"); - assert_fmt_eq!(format_args!("{:o}", -half_i8), "377/2"); - assert_fmt_eq!(format_args!("{:#o}", -half_i8), "0o377/0o2"); - - assert_fmt_eq!(format_args!("{:x}", _16), "10"); - assert_fmt_eq!(format_args!("{:x}", _15), "f"); - assert_fmt_eq!(format_args!("{:x}", _1_16), "1/10"); - assert_fmt_eq!(format_args!("{:x}", _1_15), "1/f"); - assert_fmt_eq!(format_args!("{:x}", _0), "0"); - assert_fmt_eq!(format_args!("{:#x}", _1_16), "0x1/0x10"); - #[cfg(feature = "std")] - assert_eq!(&format!("{:010x}", _1_16), "0000001/10"); - #[cfg(feature = "std")] - assert_eq!(&format!("{:#010x}", _1_16), "0x001/0x10"); - assert_fmt_eq!(format_args!("{:x}", -half_i8), "ff/2"); - assert_fmt_eq!(format_args!("{:#x}", -half_i8), "0xff/0x2"); - - assert_fmt_eq!(format_args!("{:X}", _16), "10"); - assert_fmt_eq!(format_args!("{:X}", _15), "F"); - assert_fmt_eq!(format_args!("{:X}", _1_16), "1/10"); - assert_fmt_eq!(format_args!("{:X}", _1_15), "1/F"); - assert_fmt_eq!(format_args!("{:X}", _0), "0"); - assert_fmt_eq!(format_args!("{:#X}", _1_16), "0x1/0x10"); - #[cfg(feature = "std")] - assert_eq!(format!("{:010X}", _1_16), "0000001/10"); - #[cfg(feature = "std")] - assert_eq!(format!("{:#010X}", _1_16), "0x001/0x10"); - assert_fmt_eq!(format_args!("{:X}", -half_i8), "FF/2"); - assert_fmt_eq!(format_args!("{:#X}", -half_i8), "0xFF/0x2"); - - #[cfg(has_int_exp_fmt)] - { - assert_fmt_eq!(format_args!("{:e}", -_2), "-2e0"); - assert_fmt_eq!(format_args!("{:#e}", -_2), "-2e0"); - assert_fmt_eq!(format_args!("{:+e}", -_2), "-2e0"); - assert_fmt_eq!(format_args!("{:e}", _BILLION), "1e9"); - assert_fmt_eq!(format_args!("{:+e}", _BILLION), "+1e9"); - assert_fmt_eq!(format_args!("{:e}", _BILLION.recip()), "1e0/1e9"); - assert_fmt_eq!(format_args!("{:+e}", _BILLION.recip()), "+1e0/1e9"); - - assert_fmt_eq!(format_args!("{:E}", -_2), "-2E0"); - assert_fmt_eq!(format_args!("{:#E}", -_2), "-2E0"); - assert_fmt_eq!(format_args!("{:+E}", -_2), "-2E0"); - assert_fmt_eq!(format_args!("{:E}", _BILLION), "1E9"); - assert_fmt_eq!(format_args!("{:+E}", _BILLION), "+1E9"); - assert_fmt_eq!(format_args!("{:E}", _BILLION.recip()), "1E0/1E9"); - assert_fmt_eq!(format_args!("{:+E}", _BILLION.recip()), "+1E0/1E9"); - } + use std::string::ToString; + assert_eq!(format!("{}", _2), "2".to_string()); + assert_eq!(format!("{}", _1_2), "1/2".to_string()); + assert_eq!(format!("{}", _0), "0".to_string()); + assert_eq!(format!("{}", Ratio::from_integer(-2)), "-2".to_string()); } mod arith { + use super::{_0, _1, _2, _1_2, _3_2, _NEG1_2, to_big}; use super::super::{Ratio, Rational}; - use super::{to_big, _0, _1, _1_2, _2, _3_2, _5_2, _MAX, _MAX_M1, _MIN, _MIN_P1, _NEG1_2}; - use core::fmt::Debug; - use num_integer::Integer; - use num_traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, NumAssign}; + use traits::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv}; #[test] fn test_add() { fn test(a: Rational, b: Rational, c: Rational) { assert_eq!(a + b, c); - assert_eq!( - { - let mut x = a; - x += b; - x - }, - c - ); + assert_eq!({ let mut x = a; x += b; x}, c); assert_eq!(to_big(a) + to_big(b), to_big(c)); assert_eq!(a.checked_add(&b), Some(c)); assert_eq!(to_big(a).checked_add(&to_big(b)), Some(to_big(c))); } - fn test_assign(a: Rational, b: isize, c: Rational) { + fn test_assign(a: Rational, b: isize, c: Rational) { assert_eq!(a + b, c); - assert_eq!( - { - let mut x = a; - x += b; - x - }, - c - ); + assert_eq!({ let mut x = a; x += b; x}, c); } test(_1, _1_2, _3_2); @@ -2056,68 +1527,18 @@ mod test { test_assign(_1_2, 1, _3_2); } - #[test] - fn test_add_overflow() { - // compares Ratio(1, T::max_value()) + Ratio(1, T::max_value()) - // to Ratio(1+1, T::max_value()) for each integer type. - // Previously, this calculation would overflow. - fn test_add_typed_overflow() - where - T: Integer + Bounded + Clone + Debug + NumAssign, - { - let _1_max = Ratio::new(T::one(), T::max_value()); - let _2_max = Ratio::new(T::one() + T::one(), T::max_value()); - assert_eq!(_1_max.clone() + _1_max.clone(), _2_max); - assert_eq!( - { - let mut tmp = _1_max.clone(); - tmp += _1_max; - tmp - }, - _2_max - ); - } - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - test_add_typed_overflow::(); - } - #[test] fn test_sub() { fn test(a: Rational, b: Rational, c: Rational) { assert_eq!(a - b, c); - assert_eq!( - { - let mut x = a; - x -= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x -= b; x}, c); assert_eq!(to_big(a) - to_big(b), to_big(c)); assert_eq!(a.checked_sub(&b), Some(c)); assert_eq!(to_big(a).checked_sub(&to_big(b)), Some(to_big(c))); } fn test_assign(a: Rational, b: isize, c: Rational) { assert_eq!(a - b, c); - assert_eq!( - { - let mut x = a; - x -= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x -= b; x}, c); } test(_1, _1_2, _1_2); @@ -2126,63 +1547,18 @@ mod test { test_assign(_1_2, 1, _NEG1_2); } - #[test] - fn test_sub_overflow() { - // compares Ratio(1, T::max_value()) - Ratio(1, T::max_value()) to T::zero() - // for each integer type. Previously, this calculation would overflow. - fn test_sub_typed_overflow() - where - T: Integer + Bounded + Clone + Debug + NumAssign, - { - let _1_max: Ratio = Ratio::new(T::one(), T::max_value()); - assert!(T::is_zero(&(_1_max.clone() - _1_max.clone()).numer)); - { - let mut tmp: Ratio = _1_max.clone(); - tmp -= _1_max; - assert!(T::is_zero(&tmp.numer)); - } - } - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - test_sub_typed_overflow::(); - } - #[test] fn test_mul() { fn test(a: Rational, b: Rational, c: Rational) { assert_eq!(a * b, c); - assert_eq!( - { - let mut x = a; - x *= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x *= b; x}, c); assert_eq!(to_big(a) * to_big(b), to_big(c)); assert_eq!(a.checked_mul(&b), Some(c)); assert_eq!(to_big(a).checked_mul(&to_big(b)), Some(to_big(c))); } fn test_assign(a: Rational, b: isize, c: Rational) { assert_eq!(a * b, c); - assert_eq!( - { - let mut x = a; - x *= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x *= b; x}, c); } test(_1, _1_2, _1_2); @@ -2191,87 +1567,18 @@ mod test { test_assign(_1_2, 2, _1); } - #[test] - fn test_mul_overflow() { - fn test_mul_typed_overflow() - where - T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul, - { - let two = T::one() + T::one(); - let _3 = T::one() + T::one() + T::one(); - - // 1/big * 2/3 = 1/(max/4*3), where big is max/2 - // make big = max/2, but also divisible by 2 - let big = T::max_value() / two.clone() / two.clone() * two.clone(); - let _1_big: Ratio = Ratio::new(T::one(), big.clone()); - let _2_3: Ratio = Ratio::new(two.clone(), _3.clone()); - assert_eq!(None, big.clone().checked_mul(&_3.clone())); - let expected = Ratio::new(T::one(), big / two.clone() * _3.clone()); - assert_eq!(expected.clone(), _1_big.clone() * _2_3.clone()); - assert_eq!( - Some(expected.clone()), - _1_big.clone().checked_mul(&_2_3.clone()) - ); - assert_eq!(expected, { - let mut tmp = _1_big; - tmp *= _2_3; - tmp - }); - - // big/3 * 3 = big/1 - // make big = max/2, but make it indivisible by 3 - let big = T::max_value() / two / _3.clone() * _3.clone() + T::one(); - assert_eq!(None, big.clone().checked_mul(&_3.clone())); - let big_3 = Ratio::new(big.clone(), _3.clone()); - let expected = Ratio::new(big, T::one()); - assert_eq!(expected, big_3.clone() * _3.clone()); - assert_eq!(expected, { - let mut tmp = big_3; - tmp *= _3; - tmp - }); - } - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - test_mul_typed_overflow::(); - } - #[test] fn test_div() { fn test(a: Rational, b: Rational, c: Rational) { assert_eq!(a / b, c); - assert_eq!( - { - let mut x = a; - x /= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x /= b; x}, c); assert_eq!(to_big(a) / to_big(b), to_big(c)); assert_eq!(a.checked_div(&b), Some(c)); assert_eq!(to_big(a).checked_div(&to_big(b)), Some(to_big(c))); } fn test_assign(a: Rational, b: isize, c: Rational) { assert_eq!(a / b, c); - assert_eq!( - { - let mut x = a; - x /= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x /= b; x}, c); } test(_1, _1_2, _2); @@ -2280,130 +1587,24 @@ mod test { test_assign(_1, 2, _1_2); } - #[test] - fn test_div_overflow() { - fn test_div_typed_overflow() - where - T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul, - { - let two = T::one() + T::one(); - let _3 = T::one() + T::one() + T::one(); - - // 1/big / 3/2 = 1/(max/4*3), where big is max/2 - // big ~ max/2, and big is divisible by 2 - let big = T::max_value() / two.clone() / two.clone() * two.clone(); - assert_eq!(None, big.clone().checked_mul(&_3.clone())); - let _1_big: Ratio = Ratio::new(T::one(), big.clone()); - let _3_two: Ratio = Ratio::new(_3.clone(), two.clone()); - let expected = Ratio::new(T::one(), big / two.clone() * _3.clone()); - assert_eq!(expected.clone(), _1_big.clone() / _3_two.clone()); - assert_eq!( - Some(expected.clone()), - _1_big.clone().checked_div(&_3_two.clone()) - ); - assert_eq!(expected, { - let mut tmp = _1_big; - tmp /= _3_two; - tmp - }); - - // 3/big / 3 = 1/big where big is max/2 - // big ~ max/2, and big is not divisible by 3 - let big = T::max_value() / two / _3.clone() * _3.clone() + T::one(); - assert_eq!(None, big.clone().checked_mul(&_3.clone())); - let _3_big = Ratio::new(_3.clone(), big.clone()); - let expected = Ratio::new(T::one(), big); - assert_eq!(expected, _3_big.clone() / _3.clone()); - assert_eq!(expected, { - let mut tmp = _3_big; - tmp /= _3; - tmp - }); - } - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - test_div_typed_overflow::(); - } - #[test] fn test_rem() { fn test(a: Rational, b: Rational, c: Rational) { assert_eq!(a % b, c); - assert_eq!( - { - let mut x = a; - x %= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x %= b; x}, c); assert_eq!(to_big(a) % to_big(b), to_big(c)) } fn test_assign(a: Rational, b: isize, c: Rational) { assert_eq!(a % b, c); - assert_eq!( - { - let mut x = a; - x %= b; - x - }, - c - ); + assert_eq!({ let mut x = a; x %= b; x}, c); } test(_3_2, _1, _1_2); - test(_3_2, _1_2, _0); - test(_5_2, _3_2, _1); test(_2, _NEG1_2, _0); test(_1_2, _2, _1_2); test_assign(_3_2, 1, _1_2); } - #[test] - fn test_rem_overflow() { - // tests that Ratio(1,2) % Ratio(1, T::max_value()) equals 0 - // for each integer type. Previously, this calculation would overflow. - fn test_rem_typed_overflow() - where - T: Integer + Bounded + Clone + Debug + NumAssign, - { - let two = T::one() + T::one(); - //value near to maximum, but divisible by two - let max_div2 = T::max_value() / two.clone() * two.clone(); - let _1_max: Ratio = Ratio::new(T::one(), max_div2); - let _1_two: Ratio = Ratio::new(T::one(), two); - assert!(T::is_zero(&(_1_two.clone() % _1_max.clone()).numer)); - { - let mut tmp: Ratio = _1_two; - tmp %= _1_max; - assert!(T::is_zero(&tmp.numer)); - } - } - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - test_rem_typed_overflow::(); - } - #[test] fn test_neg() { fn test(a: Rational, b: Rational) { @@ -2416,7 +1617,6 @@ mod test { test(-_1, _1); } #[test] - #[allow(clippy::eq_op)] fn test_zero() { assert_eq!(_0 + _0, _0); assert_eq!(_0 * _0, _0); @@ -2440,77 +1640,6 @@ mod test { assert_eq!(small.checked_div(&big), None); assert_eq!(_1.checked_div(&_0), None); } - - #[test] - fn test_checked_zeros() { - assert_eq!(_0.checked_add(&_0), Some(_0)); - assert_eq!(_0.checked_sub(&_0), Some(_0)); - assert_eq!(_0.checked_mul(&_0), Some(_0)); - assert_eq!(_0.checked_div(&_0), None); - } - - #[test] - fn test_checked_min() { - assert_eq!(_MIN.checked_add(&_MIN), None); - assert_eq!(_MIN.checked_sub(&_MIN), Some(_0)); - assert_eq!(_MIN.checked_mul(&_MIN), None); - assert_eq!(_MIN.checked_div(&_MIN), Some(_1)); - assert_eq!(_0.checked_add(&_MIN), Some(_MIN)); - assert_eq!(_0.checked_sub(&_MIN), None); - assert_eq!(_0.checked_mul(&_MIN), Some(_0)); - assert_eq!(_0.checked_div(&_MIN), Some(_0)); - assert_eq!(_1.checked_add(&_MIN), Some(_MIN_P1)); - assert_eq!(_1.checked_sub(&_MIN), None); - assert_eq!(_1.checked_mul(&_MIN), Some(_MIN)); - assert_eq!(_1.checked_div(&_MIN), None); - assert_eq!(_MIN.checked_add(&_0), Some(_MIN)); - assert_eq!(_MIN.checked_sub(&_0), Some(_MIN)); - assert_eq!(_MIN.checked_mul(&_0), Some(_0)); - assert_eq!(_MIN.checked_div(&_0), None); - assert_eq!(_MIN.checked_add(&_1), Some(_MIN_P1)); - assert_eq!(_MIN.checked_sub(&_1), None); - assert_eq!(_MIN.checked_mul(&_1), Some(_MIN)); - assert_eq!(_MIN.checked_div(&_1), Some(_MIN)); - } - - #[test] - fn test_checked_max() { - assert_eq!(_MAX.checked_add(&_MAX), None); - assert_eq!(_MAX.checked_sub(&_MAX), Some(_0)); - assert_eq!(_MAX.checked_mul(&_MAX), None); - assert_eq!(_MAX.checked_div(&_MAX), Some(_1)); - assert_eq!(_0.checked_add(&_MAX), Some(_MAX)); - assert_eq!(_0.checked_sub(&_MAX), Some(_MIN_P1)); - assert_eq!(_0.checked_mul(&_MAX), Some(_0)); - assert_eq!(_0.checked_div(&_MAX), Some(_0)); - assert_eq!(_1.checked_add(&_MAX), None); - assert_eq!(_1.checked_sub(&_MAX), Some(-_MAX_M1)); - assert_eq!(_1.checked_mul(&_MAX), Some(_MAX)); - assert_eq!(_1.checked_div(&_MAX), Some(_MAX.recip())); - assert_eq!(_MAX.checked_add(&_0), Some(_MAX)); - assert_eq!(_MAX.checked_sub(&_0), Some(_MAX)); - assert_eq!(_MAX.checked_mul(&_0), Some(_0)); - assert_eq!(_MAX.checked_div(&_0), None); - assert_eq!(_MAX.checked_add(&_1), None); - assert_eq!(_MAX.checked_sub(&_1), Some(_MAX_M1)); - assert_eq!(_MAX.checked_mul(&_1), Some(_MAX)); - assert_eq!(_MAX.checked_div(&_1), Some(_MAX)); - } - - #[test] - fn test_checked_min_max() { - assert_eq!(_MIN.checked_add(&_MAX), Some(-_1)); - assert_eq!(_MIN.checked_sub(&_MAX), None); - assert_eq!(_MIN.checked_mul(&_MAX), None); - assert_eq!( - _MIN.checked_div(&_MAX), - Some(Ratio::new(_MIN.numer, _MAX.numer)) - ); - assert_eq!(_MAX.checked_add(&_MIN), Some(-_1)); - assert_eq!(_MAX.checked_sub(&_MIN), None); - assert_eq!(_MAX.checked_mul(&_MIN), None); - assert_eq!(_MAX.checked_div(&_MIN), None); - } } #[test] @@ -2594,7 +1723,7 @@ mod test { } #[test] - #[should_panic(expected = "division by zero")] + #[should_panic(expected = "== 0")] fn test_recip_fail() { let _a = Ratio::new(0, 1).recip(); } @@ -2607,19 +1736,6 @@ mod test { assert_eq!(Pow::pow(r, &e), expected); assert_eq!(Pow::pow(&r, e), expected); assert_eq!(Pow::pow(&r, &e), expected); - #[cfg(feature = "num-bigint")] - test_big(r, e, expected); - } - - #[cfg(feature = "num-bigint")] - fn test_big(r: Rational, e: i32, expected: Rational) { - let r = BigRational::new_raw(r.numer.into(), r.denom.into()); - let expected = BigRational::new_raw(expected.numer.into(), expected.denom.into()); - assert_eq!((&r).pow(e), expected); - assert_eq!(Pow::pow(r.clone(), e), expected); - assert_eq!(Pow::pow(r.clone(), &e), expected); - assert_eq!(Pow::pow(&r, e), expected); - assert_eq!(Pow::pow(&r, &e), expected); } test(_1_2, 2, Ratio::new(1, 4)); @@ -2662,54 +1778,37 @@ mod test { } } - #[cfg(feature = "num-bigint")] + #[cfg(feature = "bigint")] #[test] fn test_from_float() { - use num_traits::float::FloatCore; + use traits::float::FloatCore; fn test(given: T, (numer, denom): (&str, &str)) { let ratio: BigRational = Ratio::from_float(given).unwrap(); - assert_eq!( - ratio, - Ratio::new( - FromStr::from_str(numer).unwrap(), - FromStr::from_str(denom).unwrap() - ) - ); + assert_eq!(ratio, + Ratio::new(FromStr::from_str(numer).unwrap(), + FromStr::from_str(denom).unwrap())); } // f32 - test(core::f32::consts::PI, ("13176795", "4194304")); + test(3.14159265359f32, ("13176795", "4194304")); test(2f32.powf(100.), ("1267650600228229401496703205376", "1")); - test( - -(2f32.powf(100.)), - ("-1267650600228229401496703205376", "1"), - ); - test( - 1.0 / 2f32.powf(100.), - ("1", "1267650600228229401496703205376"), - ); + test(-2f32.powf(100.), ("-1267650600228229401496703205376", "1")); + test(1.0 / 2f32.powf(100.), + ("1", "1267650600228229401496703205376")); test(684729.48391f32, ("1369459", "2")); test(-8573.5918555f32, ("-4389679", "512")); // f64 - test( - core::f64::consts::PI, - ("884279719003555", "281474976710656"), - ); + test(3.14159265359f64, ("3537118876014453", "1125899906842624")); test(2f64.powf(100.), ("1267650600228229401496703205376", "1")); - test( - -(2f64.powf(100.)), - ("-1267650600228229401496703205376", "1"), - ); + test(-2f64.powf(100.), ("-1267650600228229401496703205376", "1")); test(684729.48391f64, ("367611342500051", "536870912")); test(-8573.5918555f64, ("-4713381968463931", "549755813888")); - test( - 1.0 / 2f64.powf(100.), - ("1", "1267650600228229401496703205376"), - ); + test(1.0 / 2f64.powf(100.), + ("1", "1267650600228229401496703205376")); } - #[cfg(feature = "num-bigint")] + #[cfg(feature = "bigint")] #[test] fn test_from_float_fail() { use core::{f32, f64}; @@ -2745,34 +1844,34 @@ mod test { #[test] #[cfg(feature = "std")] fn test_hash() { - assert!(crate::hash(&_0) != crate::hash(&_1)); - assert!(crate::hash(&_0) != crate::hash(&_3_2)); + assert!(::hash(&_0) != ::hash(&_1)); + assert!(::hash(&_0) != ::hash(&_3_2)); // a == b -> hash(a) == hash(b) let a = Rational::new_raw(4, 2); let b = Rational::new_raw(6, 3); assert_eq!(a, b); - assert_eq!(crate::hash(&a), crate::hash(&b)); + assert_eq!(::hash(&a), ::hash(&b)); let a = Rational::new_raw(123456789, 1000); let b = Rational::new_raw(123456789 * 5, 5000); assert_eq!(a, b); - assert_eq!(crate::hash(&a), crate::hash(&b)); + assert_eq!(::hash(&a), ::hash(&b)); } #[test] fn test_into_pair() { - assert_eq!((0, 1), _0.into()); - assert_eq!((-2, 1), _NEG2.into()); - assert_eq!((1, -2), _1_NEG2.into()); + assert_eq! ((0, 1), _0.into()); + assert_eq! ((-2, 1), _NEG2.into()); + assert_eq! ((1, -2), _1_NEG2.into()); } #[test] fn test_from_pair() { - assert_eq!(_0, Ratio::from((0, 1))); - assert_eq!(_1, Ratio::from((1, 1))); - assert_eq!(_NEG2, Ratio::from((-2, 1))); - assert_eq!(_1_NEG2, Ratio::from((1, -2))); + assert_eq! (_0, Ratio::from ((0, 1))); + assert_eq! (_1, Ratio::from ((1, 1))); + assert_eq! (_NEG2, Ratio::from ((-2, 1))); + assert_eq! (_1_NEG2, Ratio::from ((1, -2))); } #[test] @@ -2784,10 +1883,14 @@ mod test { for ratio in slice { manual_sum = manual_sum + ratio; } - [manual_sum, slice.iter().sum(), slice.iter().cloned().sum()] + [ + manual_sum, + slice.iter().sum(), + slice.iter().cloned().sum() + ] } // collect into array so test works on no_std - let mut nums = [Ratio::new(0, 1); 1000]; + let mut nums = [Ratio::new(0,1); 1000]; for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() { nums[i] = r; } @@ -2808,12 +1911,12 @@ mod test { [ manual_prod, slice.iter().product(), - slice.iter().cloned().product(), + slice.iter().cloned().product() ] } // collect into array so test works on no_std - let mut nums = [Ratio::new(0, 1); 1000]; + let mut nums = [Ratio::new(0,1); 1000]; for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() { nums[i] = r; } @@ -2821,116 +1924,4 @@ mod test { assert_eq!(products[0], products[1]); assert_eq!(products[0], products[2]); } - - #[test] - fn test_num_zero() { - let zero = Rational64::zero(); - assert!(zero.is_zero()); - - let mut r = Rational64::new(123, 456); - assert!(!r.is_zero()); - assert_eq!(r + zero, r); - - r.set_zero(); - assert!(r.is_zero()); - } - - #[test] - fn test_num_one() { - let one = Rational64::one(); - assert!(one.is_one()); - - let mut r = Rational64::new(123, 456); - assert!(!r.is_one()); - assert_eq!(r * one, r); - - r.set_one(); - assert!(r.is_one()); - } - - #[test] - fn test_const() { - const N: Ratio = Ratio::new_raw(123, 456); - const N_NUMER: &i32 = N.numer(); - const N_DENOM: &i32 = N.denom(); - - assert_eq!(N_NUMER, &123); - assert_eq!(N_DENOM, &456); - - let r = N.reduced(); - assert_eq!(r.numer(), &(123 / 3)); - assert_eq!(r.denom(), &(456 / 3)); - } - - #[test] - fn test_ratio_to_i64() { - assert_eq!(5, Rational64::new(70, 14).to_u64().unwrap()); - assert_eq!(-3, Rational64::new(-31, 8).to_i64().unwrap()); - assert_eq!(None, Rational64::new(-31, 8).to_u64()); - } - - #[test] - #[cfg(feature = "num-bigint")] - fn test_ratio_to_i128() { - assert_eq!( - 1i128 << 70, - Ratio::::new(1i128 << 77, 1i128 << 7) - .to_i128() - .unwrap() - ); - } - - #[test] - #[cfg(feature = "num-bigint")] - fn test_big_ratio_to_f64() { - assert_eq!( - BigRational::new( - "1234567890987654321234567890987654321234567890" - .parse() - .unwrap(), - "3".parse().unwrap() - ) - .to_f64() - .unwrap(), - 411522630329218100000000000000000000000000000f64 - ); - assert_eq!( - BigRational::new(1.into(), BigInt::one() << 1050,) - .to_f64() - .unwrap(), - 0f64 - ); - assert_eq!( - BigRational::new( - "1234567890987654321234567890".parse().unwrap(), - "987654321234567890987654321".parse().unwrap() - ) - .to_f64() - .unwrap(), - 1.2499999893125f64 - ); - } - - #[test] - fn test_ratio_to_f64() { - assert_eq!(0.5f64, Ratio::::new(1, 2).to_f64().unwrap()); - assert_eq!(0.5f64, Rational64::new(1, 2).to_f64().unwrap()); - assert_eq!(-0.5f64, Rational64::new(1, -2).to_f64().unwrap()); - assert_eq!(0.0f64, Rational64::new(0, 2).to_f64().unwrap()); - assert_eq!(-0.0f64, Rational64::new(0, -2).to_f64().unwrap()); - assert_eq!( - 8f64, - Rational64::new((1 << 57) + 1, 1 << 54).to_f64().unwrap() - ); - assert_eq!( - 1.0000000000000002f64, - Rational64::new((1 << 52) + 1, 1 << 52).to_f64().unwrap() - ); - assert_eq!( - 1.0000000000000002f64, - Rational64::new((1 << 60) + (1 << 8), 1 << 60) - .to_f64() - .unwrap() - ); - } } diff --git a/third_party/rust/num-rational/src/pow.rs b/third_party/rust/num-rational/src/pow.rs deleted file mode 100644 index 33253320e7df..000000000000 --- a/third_party/rust/num-rational/src/pow.rs +++ /dev/null @@ -1,173 +0,0 @@ -use crate::Ratio; - -use core::cmp; -use num_integer::Integer; -use num_traits::{One, Pow}; - -macro_rules! pow_unsigned_impl { - (@ $exp:ty) => { - type Output = Ratio; - #[inline] - fn pow(self, expon: $exp) -> Ratio { - Ratio::new_raw(self.numer.pow(expon), self.denom.pow(expon)) - } - }; - ($exp:ty) => { - impl> Pow<$exp> for Ratio { - pow_unsigned_impl!(@ $exp); - } - impl<'a, T: Clone + Integer> Pow<$exp> for &'a Ratio - where - &'a T: Pow<$exp, Output = T>, - { - pow_unsigned_impl!(@ $exp); - } - impl<'b, T: Clone + Integer + Pow<$exp, Output = T>> Pow<&'b $exp> for Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'b $exp) -> Ratio { - Pow::pow(self, *expon) - } - } - impl<'a, 'b, T: Clone + Integer> Pow<&'b $exp> for &'a Ratio - where - &'a T: Pow<$exp, Output = T>, - { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'b $exp) -> Ratio { - Pow::pow(self, *expon) - } - } - }; -} -pow_unsigned_impl!(u8); -pow_unsigned_impl!(u16); -pow_unsigned_impl!(u32); -pow_unsigned_impl!(u64); -pow_unsigned_impl!(u128); -pow_unsigned_impl!(usize); - -macro_rules! pow_signed_impl { - (@ &'b BigInt, BigUint) => { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'b BigInt) -> Ratio { - match expon.sign() { - Sign::NoSign => One::one(), - Sign::Minus => { - Pow::pow(self, expon.magnitude()).into_recip() - } - Sign::Plus => Pow::pow(self, expon.magnitude()), - } - } - }; - (@ $exp:ty, $unsigned:ty) => { - type Output = Ratio; - #[inline] - fn pow(self, expon: $exp) -> Ratio { - match expon.cmp(&0) { - cmp::Ordering::Equal => One::one(), - cmp::Ordering::Less => { - let expon = expon.wrapping_abs() as $unsigned; - Pow::pow(self, expon).into_recip() - } - cmp::Ordering::Greater => Pow::pow(self, expon as $unsigned), - } - } - }; - ($exp:ty, $unsigned:ty) => { - impl> Pow<$exp> for Ratio { - pow_signed_impl!(@ $exp, $unsigned); - } - impl<'a, T: Clone + Integer> Pow<$exp> for &'a Ratio - where - &'a T: Pow<$unsigned, Output = T>, - { - pow_signed_impl!(@ $exp, $unsigned); - } - impl<'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'b $exp> for Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'b $exp) -> Ratio { - Pow::pow(self, *expon) - } - } - impl<'a, 'b, T: Clone + Integer> Pow<&'b $exp> for &'a Ratio - where - &'a T: Pow<$unsigned, Output = T>, - { - type Output = Ratio; - #[inline] - fn pow(self, expon: &'b $exp) -> Ratio { - Pow::pow(self, *expon) - } - } - }; -} -pow_signed_impl!(i8, u8); -pow_signed_impl!(i16, u16); -pow_signed_impl!(i32, u32); -pow_signed_impl!(i64, u64); -pow_signed_impl!(i128, u128); -pow_signed_impl!(isize, usize); - -#[cfg(feature = "num-bigint")] -mod bigint { - use super::*; - use num_bigint::{BigInt, BigUint, Sign}; - - impl Pow<&'b BigUint, Output = T>> Pow for Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: BigUint) -> Ratio { - Pow::pow(self, &expon) - } - } - impl<'a, T: Clone + Integer> Pow for &'a Ratio - where - &'a T: for<'b> Pow<&'b BigUint, Output = T>, - { - type Output = Ratio; - #[inline] - fn pow(self, expon: BigUint) -> Ratio { - Pow::pow(self, &expon) - } - } - impl<'b, T: Clone + Integer + Pow<&'b BigUint, Output = T>> Pow<&'b BigUint> for Ratio { - pow_unsigned_impl!(@ &'b BigUint); - } - impl<'a, 'b, T: Clone + Integer> Pow<&'b BigUint> for &'a Ratio - where - &'a T: Pow<&'b BigUint, Output = T>, - { - pow_unsigned_impl!(@ &'b BigUint); - } - - impl Pow<&'b BigUint, Output = T>> Pow for Ratio { - type Output = Ratio; - #[inline] - fn pow(self, expon: BigInt) -> Ratio { - Pow::pow(self, &expon) - } - } - impl<'a, T: Clone + Integer> Pow for &'a Ratio - where - &'a T: for<'b> Pow<&'b BigUint, Output = T>, - { - type Output = Ratio; - #[inline] - fn pow(self, expon: BigInt) -> Ratio { - Pow::pow(self, &expon) - } - } - impl<'b, T: Clone + Integer + Pow<&'b BigUint, Output = T>> Pow<&'b BigInt> for Ratio { - pow_signed_impl!(@ &'b BigInt, BigUint); - } - impl<'a, 'b, T: Clone + Integer> Pow<&'b BigInt> for &'a Ratio - where - &'a T: Pow<&'b BigUint, Output = T>, - { - pow_signed_impl!(@ &'b BigInt, BigUint); - } -} diff --git a/third_party/rust/num-traits/.cargo-checksum.json b/third_party/rust/num-traits/.cargo-checksum.json index 79d9eed9b6e0..9338f632f4c1 100644 --- a/third_party/rust/num-traits/.cargo-checksum.json +++ b/third_party/rust/num-traits/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"2dba1df8f54451f64f9e009cfe450da952b776e7ef501e7ac486a3b8777ef5a8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"198b40fa52bedfc43a9d77f6e66b53f3772550a4c1baf1140d72f44c1c8787c5","RELEASES.md":"a35240d247d49d53a59c1a9ffb17755746c01f06d7e759b2b26b2c15076bbd8c","build.rs":"8be12f3d765000d72bae7604e9e129c830dcfd5dea8d4541eccc81f2aa8d5beb","src/bounds.rs":"4fbc6bf3550e4da7ef55c9eb96466c6e0aee7f7542d7c85cfd742f16e3b4729f","src/cast.rs":"78adc1d0c015138bc96c18d75972b57ad5e9bc627070af8b7cde7e0613902652","src/float.rs":"73cc27228e7578d537c00b9b46e124e365c569a53a7e160fe0d1ad1dacf54fc8","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"c6e042ac4614529f07b0009271a6b97378451d6d3998e1dc407e76f9a050aa2d","src/lib.rs":"4a48c6674e95d77361da4578b4659b5119bdaf9d31b1add6cb1a6701fbc17c93","src/macros.rs":"b589a98c2468ca98131c641a058601964c4e82d75129b1c16fdc17aca8779eca","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"036b2a1900dc8e7295a91060e660184b2bd98f33b5db81a62b08cf8d3df726cf","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/saturating.rs":"6fb4b2a2c78d9202152a84586d7b068444b78d3caed4b293980832672a234d4b","src/ops/wrapping.rs":"0acf88c0e5fc81a3c6790b31986ab9be5b16c720c9e27461fe5d69b710ffcaba","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"81b1116300b5787546852d9d04f0375fa24342f85c34f5bc1ce5360b53fa411a","tests/cast.rs":"2c4b4f2185ec0d687e1bde292731dbc5efec527ab393478b5adf26f6e1352231"},"package":"ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"} \ No newline at end of file +{"files":{"Cargo.toml":"35c48122af67e382695600a6af69d73c0dd907afb31914aee049eebc88c871a5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"b442afb73953744a9d2134442845d3e960984ac5be2a058e5064ae851624d67f","RELEASES.md":"683c12fd04a3185fcbfa1915d1fbce8051077c5bdf07c3bfade4606bdd92d0e4","build.rs":"b4b2d0df90ca7570a339ca4d84a72e4ef00d9dced8927350424e666790c752d7","src/bounds.rs":"4fbc6bf3550e4da7ef55c9eb96466c6e0aee7f7542d7c85cfd742f16e3b4729f","src/cast.rs":"2eae0873cbe11fa0d1a012e304f48dea6a0802c0ee738dc25683779cf15b18fb","src/float.rs":"5c1a11e4218d376cd531aff0d6546c2b590d687bda5825f8c27dc6d6f974fb9b","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"bbc014a02998848170430abf60ab80fa46d7835be3a5e8bf7d28e1c5318068ae","src/lib.rs":"beb207aa3f791811b043d7aa0daa34a2f8f3a52e0555bda8eb32e3359203a129","src/macros.rs":"b589a98c2468ca98131c641a058601964c4e82d75129b1c16fdc17aca8779eca","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"036b2a1900dc8e7295a91060e660184b2bd98f33b5db81a62b08cf8d3df726cf","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/saturating.rs":"81c34038ec88fe49f4286e6e1213a1da831c5e66caac651f0a61506a4534c9ce","src/ops/wrapping.rs":"8d334dd2b8128e640bff6c3e93ea301182241987b3ed1fc158268292827bbd0c","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"81b1116300b5787546852d9d04f0375fa24342f85c34f5bc1ce5360b53fa411a","tests/cast.rs":"2c4b4f2185ec0d687e1bde292731dbc5efec527ab393478b5adf26f6e1352231"},"package":"d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"} \ No newline at end of file diff --git a/third_party/rust/num-traits/Cargo.toml b/third_party/rust/num-traits/Cargo.toml index 30e0dd317c55..5b7b0ada1e7a 100644 --- a/third_party/rust/num-traits/Cargo.toml +++ b/third_party/rust/num-traits/Cargo.toml @@ -12,10 +12,10 @@ [package] name = "num-traits" -version = "0.2.12" +version = "0.2.10" authors = ["The Rust Project Developers"] build = "build.rs" -exclude = ["/bors.toml", "/ci/*", "/.github/*"] +exclude = ["/ci/*", "/.travis.yml", "/bors.toml"] description = "Numeric traits for generic mathematics" homepage = "https://github.com/rust-num/num-traits" documentation = "https://docs.rs/num-traits" @@ -30,7 +30,7 @@ features = ["std"] version = "0.2.0" optional = true [build-dependencies.autocfg] -version = "1" +version = "0.1.3" [features] default = ["std"] diff --git a/third_party/rust/num-traits/README.md b/third_party/rust/num-traits/README.md index 114c04430be4..43335b1341bf 100644 --- a/third_party/rust/num-traits/README.md +++ b/third_party/rust/num-traits/README.md @@ -2,8 +2,8 @@ [![crate](https://img.shields.io/crates/v/num-traits.svg)](https://crates.io/crates/num-traits) [![documentation](https://docs.rs/num-traits/badge.svg)](https://docs.rs/num-traits) -[![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num-traits/workflows/master/badge.svg)](https://github.com/rust-num/num-traits/actions) +![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg) +[![Travis status](https://travis-ci.org/rust-num/num-traits.svg?branch=master)](https://travis-ci.org/rust-num/num-traits) Numeric traits for generic mathematics in Rust. diff --git a/third_party/rust/num-traits/RELEASES.md b/third_party/rust/num-traits/RELEASES.md index 75a74f915dfa..18879d8a5e55 100644 --- a/third_party/rust/num-traits/RELEASES.md +++ b/third_party/rust/num-traits/RELEASES.md @@ -1,29 +1,3 @@ -# Release 0.2.12 (2020-06-11) - -- [The new `WrappingNeg` trait][153] will wrap the result if it exceeds the - boundary of the type, e.g. `i32::MIN.wrapping_neg() == i32::MIN`. -- [The new `SaturatingAdd`, `SaturatingSub`, and `SaturatingMul` traits][165] - will saturate at the numeric bounds if the operation would overflow. These - soft-deprecate the existing `Saturating` trait that only has addition and - subtraction methods. -- [Added new constants for logarithms, `FloatConst::{LOG10_2, LOG2_10}`][171]. - -**Contributors**: @cuviper, @ocstl, @trepetti, @vallentin - -[153]: https://github.com/rust-num/num-traits/pull/153 -[165]: https://github.com/rust-num/num-traits/pull/165 -[171]: https://github.com/rust-num/num-traits/pull/171 - -# Release 0.2.11 (2020-01-09) - -- [Added the full circle constant τ as `FloatConst::TAU`][145]. -- [Updated the `autocfg` build dependency to 1.0][148]. - -**Contributors**: @cuviper, @m-ou-se - -[145]: https://github.com/rust-num/num-traits/pull/145 -[148]: https://github.com/rust-num/num-traits/pull/148 - # Release 0.2.10 (2019-11-22) - [Updated the `libm` dependency to 0.2][144]. diff --git a/third_party/rust/num-traits/build.rs b/third_party/rust/num-traits/build.rs index 891fa09b199e..e483c15fd7f6 100644 --- a/third_party/rust/num-traits/build.rs +++ b/third_party/rust/num-traits/build.rs @@ -9,10 +9,6 @@ fn main() { } else if env::var_os("CARGO_FEATURE_I128").is_some() { panic!("i128 support was not detected!"); } - ac.emit_expression_cfg( - "unsafe { 1f64.to_int_unchecked::() }", - "has_to_int_unchecked", - ); autocfg::rerun_path("build.rs"); } diff --git a/third_party/rust/num-traits/src/cast.rs b/third_party/rust/num-traits/src/cast.rs index b33f1a19f40b..cd66ae964ffc 100644 --- a/third_party/rust/num-traits/src/cast.rs +++ b/third_party/rust/num-traits/src/cast.rs @@ -284,22 +284,6 @@ macro_rules! impl_to_primitive_float_to_float { )*} } -#[cfg(has_to_int_unchecked)] -macro_rules! float_to_int_unchecked { - // SAFETY: Must not be NaN or infinite; must be representable as the integer after truncating. - // We already checked that the float is in the exclusive range `(MIN-1, MAX+1)`. - ($float:expr => $int:ty) => { - unsafe { $float.to_int_unchecked::<$int>() } - }; -} - -#[cfg(not(has_to_int_unchecked))] -macro_rules! float_to_int_unchecked { - ($float:expr => $int:ty) => { - $float as $int - }; -} - macro_rules! impl_to_primitive_float_to_signed_int { ($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$( #[inline] @@ -312,7 +296,7 @@ macro_rules! impl_to_primitive_float_to_signed_int { const MIN_M1: $f = $i::MIN as $f - 1.0; const MAX_P1: $f = $i::MAX as $f + 1.0; if *self > MIN_M1 && *self < MAX_P1 { - return Some(float_to_int_unchecked!(*self => $i)); + return Some(*self as $i); } } else { // We can't represent `MIN-1` exactly, but there's no fractional part @@ -322,7 +306,7 @@ macro_rules! impl_to_primitive_float_to_signed_int { // `MAX+1` (a power of two) when we cast it. const MAX_P1: $f = $i::MAX as $f; if *self >= MIN && *self < MAX_P1 { - return Some(float_to_int_unchecked!(*self => $i)); + return Some(*self as $i); } } None @@ -341,7 +325,7 @@ macro_rules! impl_to_primitive_float_to_unsigned_int { // With a larger size, we can represent the range exactly. const MAX_P1: $f = $u::MAX as $f + 1.0; if *self > -1.0 && *self < MAX_P1 { - return Some(float_to_int_unchecked!(*self => $u)); + return Some(*self as $u); } } else { // We can't represent `MAX` exactly, but it will round up to exactly @@ -349,7 +333,7 @@ macro_rules! impl_to_primitive_float_to_unsigned_int { // (`u128::MAX as f32` is infinity, but this is still ok.) const MAX_P1: $f = $u::MAX as $f; if *self > -1.0 && *self < MAX_P1 { - return Some(float_to_int_unchecked!(*self => $u)); + return Some(*self as $u); } } None diff --git a/third_party/rust/num-traits/src/float.rs b/third_party/rust/num-traits/src/float.rs index 0e7b9db357f5..dd14bbe4ed94 100644 --- a/third_party/rust/num-traits/src/float.rs +++ b/third_party/rust/num-traits/src/float.rs @@ -1,6 +1,6 @@ use core::mem; use core::num::FpCategory; -use core::ops::{Add, Div, Neg}; +use core::ops::Neg; use core::f32; use core::f64; @@ -606,8 +606,8 @@ pub trait FloatCore: Num + NumCast + Neg + PartialOrd + Copy { /// use num_traits::float::FloatCore; /// use std::{f32, f64}; /// - /// fn check(x: T, y: T, max: T) { - /// assert!(x.max(y) == max); + /// fn check(x: T, y: T, min: T) { + /// assert!(x.max(y) == min); /// } /// /// check(1.0f32, 2.0, 2.0); @@ -2247,21 +2247,6 @@ macro_rules! float_const_impl { #[allow(non_snake_case)] pub trait FloatConst { $(#[$doc] fn $constant() -> Self;)+ - #[doc = "Return the full circle constant `τ`."] - #[inline] - fn TAU() -> Self where Self: Sized + Add { - Self::PI() + Self::PI() - } - #[doc = "Return `log10(2.0)`."] - #[inline] - fn LOG10_2() -> Self where Self: Sized + Div { - Self::LN_2() / Self::LN_10() - } - #[doc = "Return `log2(10.0)`."] - #[inline] - fn LOG2_10() -> Self where Self: Sized + Div { - Self::LN_10() / Self::LN_2() - } } float_const_impl! { @float f32, $($constant,)+ } float_const_impl! { @float f64, $($constant,)+ } @@ -2270,9 +2255,6 @@ macro_rules! float_const_impl { impl FloatConst for $T { constant! { $( $constant() -> $T::consts::$constant; )+ - TAU() -> 6.28318530717958647692528676655900577; - LOG10_2() -> 0.301029995663981195213738894724493027; - LOG2_10() -> 3.32192809488736234787031942948939018; } } ); @@ -2307,7 +2289,7 @@ float_const_impl! { LOG10_E, #[doc = "Return `log2(e)`."] LOG2_E, - #[doc = "Return Archimedes’ constant `π`."] + #[doc = "Return Archimedes’ constant."] PI, #[doc = "Return `sqrt(2.0)`."] SQRT_2, @@ -2368,23 +2350,4 @@ mod tests { 57.2957795130823208767981548141051703 ); } - - #[test] - #[cfg(any(feature = "std", feature = "libm"))] - fn extra_logs() { - use float::{Float, FloatConst}; - - fn check(diff: F) { - let _2 = F::from(2.0).unwrap(); - assert!((F::LOG10_2() - F::log10(_2)).abs() < diff); - assert!((F::LOG10_2() - F::LN_2() / F::LN_10()).abs() < diff); - - let _10 = F::from(10.0).unwrap(); - assert!((F::LOG2_10() - F::log2(_10)).abs() < diff); - assert!((F::LOG2_10() - F::LN_10() / F::LN_2()).abs() < diff); - } - - check::(1e-6); - check::(1e-12); - } } diff --git a/third_party/rust/num-traits/src/int.rs b/third_party/rust/num-traits/src/int.rs index 10e751a9d4fd..26d5a9a3970a 100644 --- a/third_party/rust/num-traits/src/int.rs +++ b/third_party/rust/num-traits/src/int.rs @@ -106,7 +106,7 @@ pub trait PrimInt: /// ``` fn trailing_zeros(self) -> u32; - /// Shifts the bits to the left by a specified amount, `n`, wrapping + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping /// the truncated bits to the end of the resulting integer. /// /// # Examples @@ -121,7 +121,7 @@ pub trait PrimInt: /// ``` fn rotate_left(self, n: u32) -> Self; - /// Shifts the bits to the right by a specified amount, `n`, wrapping + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping /// the truncated bits to the beginning of the resulting integer. /// /// # Examples @@ -136,7 +136,7 @@ pub trait PrimInt: /// ``` fn rotate_right(self, n: u32) -> Self; - /// Shifts the bits to the left by a specified amount, `n`, filling + /// Shifts the bits to the left by a specified amount amount, `n`, filling /// zeros in the least significant bits. /// /// This is bitwise equivalent to signed `Shl`. @@ -153,7 +153,7 @@ pub trait PrimInt: /// ``` fn signed_shl(self, n: u32) -> Self; - /// Shifts the bits to the right by a specified amount, `n`, copying + /// Shifts the bits to the right by a specified amount amount, `n`, copying /// the "sign bit" in the most significant bits even for unsigned types. /// /// This is bitwise equivalent to signed `Shr`. @@ -170,7 +170,7 @@ pub trait PrimInt: /// ``` fn signed_shr(self, n: u32) -> Self; - /// Shifts the bits to the left by a specified amount, `n`, filling + /// Shifts the bits to the left by a specified amount amount, `n`, filling /// zeros in the least significant bits. /// /// This is bitwise equivalent to unsigned `Shl`. @@ -187,7 +187,7 @@ pub trait PrimInt: /// ``` fn unsigned_shl(self, n: u32) -> Self; - /// Shifts the bits to the right by a specified amount, `n`, filling + /// Shifts the bits to the right by a specified amount amount, `n`, filling /// zeros in the most significant bits. /// /// This is bitwise equivalent to unsigned `Shr`. diff --git a/third_party/rust/num-traits/src/lib.rs b/third_party/rust/num-traits/src/lib.rs index d9989467eb8f..559a18cdf8f8 100644 --- a/third_party/rust/num-traits/src/lib.rs +++ b/third_party/rust/num-traits/src/lib.rs @@ -42,10 +42,8 @@ pub use ops::checked::{ }; pub use ops::inv::Inv; pub use ops::mul_add::{MulAdd, MulAddAssign}; -pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}; -pub use ops::wrapping::{ - WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub, -}; +pub use ops::saturating::Saturating; +pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingShl, WrappingShr, WrappingSub}; pub use pow::{checked_pow, pow, Pow}; pub use sign::{abs, abs_sub, signum, Signed, Unsigned}; diff --git a/third_party/rust/num-traits/src/ops/saturating.rs b/third_party/rust/num-traits/src/ops/saturating.rs index e39cfd7b6c1a..fdce18977c06 100644 --- a/third_party/rust/num-traits/src/ops/saturating.rs +++ b/third_party/rust/num-traits/src/ops/saturating.rs @@ -1,7 +1,4 @@ -use core::ops::{Add, Mul, Sub}; - -/// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and -/// `SaturatingMul` instead. +/// Saturating math operations pub trait Saturating { /// Saturating addition operator. /// Returns a+b, saturating at the numeric bounds instead of overflowing. @@ -12,7 +9,7 @@ pub trait Saturating { fn saturating_sub(self, v: Self) -> Self; } -macro_rules! deprecated_saturating_impl { +macro_rules! saturating_impl { ($trait_name:ident for $($t:ty)*) => {$( impl $trait_name for $t { #[inline] @@ -28,110 +25,6 @@ macro_rules! deprecated_saturating_impl { )*} } -deprecated_saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64); +saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64); #[cfg(has_i128)] -deprecated_saturating_impl!(Saturating for i128 u128); - -macro_rules! saturating_impl { - ($trait_name:ident, $method:ident, $t:ty) => { - impl $trait_name for $t { - #[inline] - fn $method(&self, v: &Self) -> Self { - <$t>::$method(*self, *v) - } - } - }; -} - -/// Performs addition that saturates at the numeric bounds instead of overflowing. -pub trait SaturatingAdd: Sized + Add { - /// Saturating addition. Computes `self + other`, saturating at the relevant high or low boundary of - /// the type. - fn saturating_add(&self, v: &Self) -> Self; -} - -saturating_impl!(SaturatingAdd, saturating_add, u8); -saturating_impl!(SaturatingAdd, saturating_add, u16); -saturating_impl!(SaturatingAdd, saturating_add, u32); -saturating_impl!(SaturatingAdd, saturating_add, u64); -saturating_impl!(SaturatingAdd, saturating_add, usize); -#[cfg(has_i128)] -saturating_impl!(SaturatingAdd, saturating_add, u128); - -saturating_impl!(SaturatingAdd, saturating_add, i8); -saturating_impl!(SaturatingAdd, saturating_add, i16); -saturating_impl!(SaturatingAdd, saturating_add, i32); -saturating_impl!(SaturatingAdd, saturating_add, i64); -saturating_impl!(SaturatingAdd, saturating_add, isize); -#[cfg(has_i128)] -saturating_impl!(SaturatingAdd, saturating_add, i128); - -/// Performs subtraction that saturates at the numeric bounds instead of overflowing. -pub trait SaturatingSub: Sized + Sub { - /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low boundary of - /// the type. - fn saturating_sub(&self, v: &Self) -> Self; -} - -saturating_impl!(SaturatingSub, saturating_sub, u8); -saturating_impl!(SaturatingSub, saturating_sub, u16); -saturating_impl!(SaturatingSub, saturating_sub, u32); -saturating_impl!(SaturatingSub, saturating_sub, u64); -saturating_impl!(SaturatingSub, saturating_sub, usize); -#[cfg(has_i128)] -saturating_impl!(SaturatingSub, saturating_sub, u128); - -saturating_impl!(SaturatingSub, saturating_sub, i8); -saturating_impl!(SaturatingSub, saturating_sub, i16); -saturating_impl!(SaturatingSub, saturating_sub, i32); -saturating_impl!(SaturatingSub, saturating_sub, i64); -saturating_impl!(SaturatingSub, saturating_sub, isize); -#[cfg(has_i128)] -saturating_impl!(SaturatingSub, saturating_sub, i128); - -/// Performs multiplication that saturates at the numeric bounds instead of overflowing. -pub trait SaturatingMul: Sized + Mul { - /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low boundary of - /// the type. - fn saturating_mul(&self, v: &Self) -> Self; -} - -saturating_impl!(SaturatingMul, saturating_mul, u8); -saturating_impl!(SaturatingMul, saturating_mul, u16); -saturating_impl!(SaturatingMul, saturating_mul, u32); -saturating_impl!(SaturatingMul, saturating_mul, u64); -saturating_impl!(SaturatingMul, saturating_mul, usize); -#[cfg(has_i128)] -saturating_impl!(SaturatingMul, saturating_mul, u128); - -saturating_impl!(SaturatingMul, saturating_mul, i8); -saturating_impl!(SaturatingMul, saturating_mul, i16); -saturating_impl!(SaturatingMul, saturating_mul, i32); -saturating_impl!(SaturatingMul, saturating_mul, i64); -saturating_impl!(SaturatingMul, saturating_mul, isize); -#[cfg(has_i128)] -saturating_impl!(SaturatingMul, saturating_mul, i128); - -// TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable. - -#[test] -fn test_saturating_traits() { - fn saturating_add(a: T, b: T) -> T { - a.saturating_add(&b) - } - fn saturating_sub(a: T, b: T) -> T { - a.saturating_sub(&b) - } - fn saturating_mul(a: T, b: T) -> T { - a.saturating_mul(&b) - } - assert_eq!(saturating_add(255, 1), 255u8); - assert_eq!(saturating_add(127, 1), 127i8); - assert_eq!(saturating_add(-128, -1), -128i8); - assert_eq!(saturating_sub(0, 1), 0u8); - assert_eq!(saturating_sub(-128, 1), -128i8); - assert_eq!(saturating_sub(127, -1), 127i8); - assert_eq!(saturating_mul(255, 2), 255u8); - assert_eq!(saturating_mul(127, 2), 127i8); - assert_eq!(saturating_mul(-128, 2), -128i8); -} +saturating_impl!(Saturating for i128 u128); diff --git a/third_party/rust/num-traits/src/ops/wrapping.rs b/third_party/rust/num-traits/src/ops/wrapping.rs index 265b8f3bbc98..5ce16af53fad 100644 --- a/third_party/rust/num-traits/src/ops/wrapping.rs +++ b/third_party/rust/num-traits/src/ops/wrapping.rs @@ -1,5 +1,5 @@ use core::num::Wrapping; -use core::ops::{Add, Mul, Neg, Shl, Shr, Sub}; +use core::ops::{Add, Mul, Shl, Shr, Sub}; macro_rules! wrapping_impl { ($trait_name:ident, $method:ident, $t:ty) => { @@ -89,54 +89,6 @@ wrapping_impl!(WrappingMul, wrapping_mul, isize); #[cfg(has_i128)] wrapping_impl!(WrappingMul, wrapping_mul, i128); -macro_rules! wrapping_unary_impl { - ($trait_name:ident, $method:ident, $t:ty) => { - impl $trait_name for $t { - #[inline] - fn $method(&self) -> $t { - <$t>::$method(*self) - } - } - }; -} - -/// Performs a negation that does not panic. -pub trait WrappingNeg: Sized { - /// Wrapping (modular) negation. Computes `-self`, - /// wrapping around at the boundary of the type. - /// - /// Since unsigned types do not have negative equivalents - /// all applications of this function will wrap (except for `-0`). - /// For values smaller than the corresponding signed type's maximum - /// the result is the same as casting the corresponding signed value. - /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where - /// `MAX` is the corresponding signed type's maximum. - /// - /// ``` - /// use num_traits::WrappingNeg; - /// - /// assert_eq!(100i8.wrapping_neg(), -100); - /// assert_eq!((-100i8).wrapping_neg(), 100); - /// assert_eq!((-128i8).wrapping_neg(), -128); // wrapped! - /// ``` - fn wrapping_neg(&self) -> Self; -} - -wrapping_unary_impl!(WrappingNeg, wrapping_neg, u8); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, u16); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, u32); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, u64); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, usize); -#[cfg(has_i128)] -wrapping_unary_impl!(WrappingNeg, wrapping_neg, u128); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, i8); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, i16); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, i32); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, i64); -wrapping_unary_impl!(WrappingNeg, wrapping_neg, isize); -#[cfg(has_i128)] -wrapping_unary_impl!(WrappingNeg, wrapping_neg, i128); - macro_rules! wrapping_shift_impl { ($trait_name:ident, $method:ident, $t:ty) => { impl $trait_name for $t { @@ -243,14 +195,6 @@ where Wrapping(self.0.wrapping_mul(&v.0)) } } -impl WrappingNeg for Wrapping -where - Wrapping: Neg>, -{ - fn wrapping_neg(&self) -> Self { - Wrapping(self.0.wrapping_neg()) - } -} impl WrappingShl for Wrapping where Wrapping: Shl>, @@ -279,9 +223,6 @@ fn test_wrapping_traits() { fn wrapping_mul(a: T, b: T) -> T { a.wrapping_mul(&b) } - fn wrapping_neg(a: T) -> T { - a.wrapping_neg() - } fn wrapping_shl(a: T, b: u32) -> T { a.wrapping_shl(b) } @@ -291,14 +232,11 @@ fn test_wrapping_traits() { assert_eq!(wrapping_add(255, 1), 0u8); assert_eq!(wrapping_sub(0, 1), 255u8); assert_eq!(wrapping_mul(255, 2), 254u8); - assert_eq!(wrapping_neg(255), 1u8); assert_eq!(wrapping_shl(255, 8), 255u8); assert_eq!(wrapping_shr(255, 8), 255u8); assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0); assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0); assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0); - // TODO: Test for Wrapping::Neg. Not possible yet since core::ops::Neg was - // only added to core::num::Wrapping<_> in Rust 1.10. assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0); assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0); } @@ -321,9 +259,6 @@ fn wrapping_is_wrappingmul() { require_wrappingmul(&Wrapping(42)); } -// TODO: Test for Wrapping::Neg. Not possible yet since core::ops::Neg was -// only added to core::num::Wrapping<_> in Rust 1.10. - #[test] fn wrapping_is_wrappingshl() { fn require_wrappingshl(_: &T) {} diff --git a/third_party/rust/num/.cargo-checksum.json b/third_party/rust/num/.cargo-checksum.json deleted file mode 100644 index 32aecf0fade3..000000000000 --- a/third_party/rust/num/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"2fcbacbf0e55576b0a29fb8aee872a48552243a8a113a4d13a3e72152e08b591","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"499859368204a8cbcdf8eedaa71c3ce5affe5e8ecd82926a6af02d4c48b7a6d2","RELEASES.md":"155c834a2ee31d45919320fda55ecb68d99b771a50cd0f7af14bed3f1fcd13fe","src/lib.rs":"d38f1f3714dc176d85666c7b8a253a57535442fbd27310596c3ad44b9803ca85"},"package":"ab3e176191bc4faad357e3122c4747aa098ac880e88b168f106386128736cf4a"} \ No newline at end of file diff --git a/third_party/rust/num/Cargo.toml b/third_party/rust/num/Cargo.toml deleted file mode 100644 index fbb46af8bb78..000000000000 --- a/third_party/rust/num/Cargo.toml +++ /dev/null @@ -1,67 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -edition = "2018" -name = "num" -version = "0.3.0" -authors = ["The Rust Project Developers"] -exclude = ["/bors.toml", "/ci/*", "/.github/*"] -description = "A collection of numeric types and traits for Rust, including bigint,\ncomplex, rational, range iterators, generic integers, and more!\n" -homepage = "https://github.com/rust-num/num" -documentation = "https://docs.rs/num" -readme = "README.md" -keywords = ["mathematics", "numerics", "bignum"] -categories = ["algorithms", "data-structures", "science", "no-std"] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num" -[package.metadata.docs.rs] -features = ["std", "serde", "rand"] -[dependencies.num-bigint] -version = "0.3.0" -optional = true -default-features = false - -[dependencies.num-complex] -version = "0.3.0" -default-features = false - -[dependencies.num-integer] -version = "0.1.43" -features = ["i128"] -default-features = false - -[dependencies.num-iter] -version = "0.1.41" -features = ["i128"] -default-features = false - -[dependencies.num-rational] -version = "0.3.0" -default-features = false - -[dependencies.num-traits] -version = "0.2.12" -features = ["i128"] -default-features = false - -[dev-dependencies] - -[features] -alloc = ["num-bigint", "num-rational/num-bigint"] -default = ["std"] -libm = ["num-complex/libm", "num-traits/libm"] -rand = ["num-bigint/rand", "num-complex/rand"] -serde = ["num-bigint/serde", "num-complex/serde", "num-rational/serde"] -std = ["num-bigint/std", "num-complex/std", "num-integer/std", "num-iter/std", "num-rational/std", "num-rational/num-bigint-std", "num-traits/std"] -[badges.travis-ci] -repository = "rust-num/num" diff --git a/third_party/rust/num/LICENSE-APACHE b/third_party/rust/num/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/third_party/rust/num/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/third_party/rust/num/LICENSE-MIT b/third_party/rust/num/LICENSE-MIT deleted file mode 100644 index 39d4bdb5acd3..000000000000 --- a/third_party/rust/num/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/num/README.md b/third_party/rust/num/README.md deleted file mode 100644 index 13b58f889f2c..000000000000 --- a/third_party/rust/num/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# num - -[![crate](https://img.shields.io/crates/v/num.svg)](https://crates.io/crates/num) -[![documentation](https://docs.rs/num/badge.svg)](https://docs.rs/num) -[![minimum rustc 1.31](https://img.shields.io/badge/rustc-1.31+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) -[![build status](https://github.com/rust-num/num/workflows/master/badge.svg)](https://github.com/rust-num/num/actions) - -A collection of numeric types and traits for Rust. - -This includes new types for big integers, rationals (aka fractions), and complex numbers, -new traits for generic programming on numeric properties like `Integer`, -and generic range iterators. - -`num` is a meta-crate, re-exporting items from these sub-crates: - -| Repository | Crate | Documentation | -| ---------- | ----- | ------------- | -| [`num-bigint`] | [![crate][bigint-cb]][bigint-c] | [![documentation][bigint-db]][bigint-d] -| [`num-complex`] | [![crate][complex-cb]][complex-c] | [![documentation][complex-db]][complex-d] -| [`num-integer`] | [![crate][integer-cb]][integer-c] | [![documentation][integer-db]][integer-d] -| [`num-iter`] | [![crate][iter-cb]][iter-c] | [![documentation][iter-db]][iter-d] -| [`num-rational`] | [![crate][rational-cb]][rational-c] | [![documentation][rational-db]][rational-d] -| [`num-traits`] | [![crate][traits-cb]][traits-c] | [![documentation][traits-db]][traits-d] -| ([`num-derive`]) | [![crate][derive-cb]][derive-c] | [![documentation][derive-db]][derive-d] - -Note: `num-derive` is listed here for reference, but it's not directly included -in `num`. This is a `proc-macro` crate for deriving some of `num`'s traits. - -## Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] -num = "0.3" -``` - -## Features - -This crate can be used without the standard library (`#![no_std]`) by disabling -the default `std` feature. Use this in `Cargo.toml`: - -```toml -[dependencies.num] -version = "0.3" -default-features = false -``` - -The `num-bigint` crate requires the `std` feature, or the `alloc` feature may -be used instead with Rust 1.36 and later. Other sub-crates may also have -limited functionality when used without `std`. - -The `libm` feature uses pure-Rust floating point implementations in `no_std` -builds, enabling the `Float` trait and related `Complex` methods. - -The `rand` feature enables randomization traits in `num-bigint` and -`num-complex`. - -The `serde` feature enables serialization for types in `num-bigint`, -`num-complex`, and `num-rational`. - -The `num` meta-crate no longer supports features to toggle the inclusion of -the individual sub-crates. If you need such control, you are recommended to -directly depend on your required crates instead. - -## Releases - -Release notes are available in [RELEASES.md](RELEASES.md). - -## Compatibility - -The `num` crate as a whole is tested for rustc 1.31 and greater. - -The `num-traits`, `num-integer`, and `num-iter` crates are individually tested -for rustc 1.8 and greater, if you require such older compatibility. - - -[`num-bigint`]: https://github.com/rust-num/num-bigint -[bigint-c]: https://crates.io/crates/num-bigint -[bigint-cb]: https://img.shields.io/crates/v/num-bigint.svg -[bigint-d]: https://docs.rs/num-bigint/ -[bigint-db]: https://docs.rs/num-bigint/badge.svg - -[`num-complex`]: https://github.com/rust-num/num-complex -[complex-c]: https://crates.io/crates/num-complex -[complex-cb]: https://img.shields.io/crates/v/num-complex.svg -[complex-d]: https://docs.rs/num-complex/ -[complex-db]: https://docs.rs/num-complex/badge.svg - -[`num-derive`]: https://github.com/rust-num/num-derive -[derive-c]: https://crates.io/crates/num-derive -[derive-cb]: https://img.shields.io/crates/v/num-derive.svg -[derive-d]: https://docs.rs/num-derive/ -[derive-db]: https://docs.rs/num-derive/badge.svg - -[`num-integer`]: https://github.com/rust-num/num-integer -[integer-c]: https://crates.io/crates/num-integer -[integer-cb]: https://img.shields.io/crates/v/num-integer.svg -[integer-d]: https://docs.rs/num-integer/ -[integer-db]: https://docs.rs/num-integer/badge.svg - -[`num-iter`]: https://github.com/rust-num/num-iter -[iter-c]: https://crates.io/crates/num-iter -[iter-cb]: https://img.shields.io/crates/v/num-iter.svg -[iter-d]: https://docs.rs/num-iter/ -[iter-db]: https://docs.rs/num-iter/badge.svg - -[`num-rational`]: https://github.com/rust-num/num-rational -[rational-c]: https://crates.io/crates/num-rational -[rational-cb]: https://img.shields.io/crates/v/num-rational.svg -[rational-d]: https://docs.rs/num-rational/ -[rational-db]: https://docs.rs/num-rational/badge.svg - -[`num-traits`]: https://github.com/rust-num/num-traits -[traits-c]: https://crates.io/crates/num-traits -[traits-cb]: https://img.shields.io/crates/v/num-traits.svg -[traits-d]: https://docs.rs/num-traits/ -[traits-db]: https://docs.rs/num-traits/badge.svg diff --git a/third_party/rust/num/RELEASES.md b/third_party/rust/num/RELEASES.md deleted file mode 100644 index 20401decd1be..000000000000 --- a/third_party/rust/num/RELEASES.md +++ /dev/null @@ -1,86 +0,0 @@ -# Release 0.3.0 (2020-06-13) - -All items exported from `num-integer`, `num-iter`, and `num-traits` are still -semver-compatible with those exported by `num` 0.1 and 0.2. If you have these -as public dependencies in your own crates, it is not a breaking change to move -to `num` 0.3. However, this is not true of `num-bigint`, `num-complex`, or -`num-rational`, as those exported items are distinct in this release. - -### Enhancements - -- Updates to `num-integer`, `num-iter`, and `num-traits` are still compatible - with `num` 0.1 and 0.2. -- The "alloc" feature enables `bigint` without `std` on Rust 1.36+. -- The "libm" feature enables `Float` without `std` in `traits` and `complex`. -- Please see the release notes of the individual sub-crates for details. - -### Breaking Changes - -- `num` now requires rustc 1.31 or greater. - - The "i128" opt-in feature was removed, now always available. -- `rand` support has been updated to 0.7, requiring Rust 1.32. - -**Contributors**: @cuviper - -# Release 0.2.1 (2019-01-09) - -- Updated all sub-crates to their latest versions. - -**Contributors**: @cuviper, @ignatenkobrain, @jimbo1qaz - -# Release 0.2.0 (2018-06-29) - -All items exported from `num-integer`, `num-iter`, and `num-traits` are still -semver-compatible with those exported by `num` 0.1. If you have these as public -dependencies in your own crates, it is not a breaking change to move to `num` -0.2. However, this is not true of `num-bigint`, `num-complex`, or -`num-rational`, as those exported items are distinct in this release. - -A few common changes are listed below, but most of the development happens in -the individual sub-crates. Please consult their release notes for more details -about recent changes: -[`num-bigint`](https://github.com/rust-num/num-bigint/blob/master/RELEASES.md), -[`num-complex`](https://github.com/rust-num/num-complex/blob/master/RELEASES.md), -[`num-integer`](https://github.com/rust-num/num-integer/blob/master/RELEASES.md), -[`num-iter`](https://github.com/rust-num/num-iter/blob/master/RELEASES.md), -[`num-rational`](https://github.com/rust-num/num-rational/blob/master/RELEASES.md), -and [`num-traits`](https://github.com/rust-num/num-traits/blob/master/RELEASES.md). - -### Enhancements - -- Updates to `num-integer`, `num-iter`, and `num-traits` are still compatible - with `num` 0.1. -- 128-bit integers are supported with Rust 1.26 and later. -- `BigInt`, `BigUint`, `Complex`, and `Ratio` all implement `Sum` and `Product`. - -### Breaking Changes - -- `num` now requires rustc 1.15 or greater. -- `num-bigint`, `num-complex`, and `num-rational` have all been updated to 0.2. -- It's no longer possible to toggle individual `num-*` sub-crates using cargo - features. If you need that control, please use those crates directly. -- There is now a `std` feature, enabled by default, along with the implication - that building *without* this feature makes this a `#![no_std]` crate. - `num::bigint` is not available without `std`, and the other sub-crates may - have limited functionality. -- The `serde` dependency has been updated to 1.0, still disabled by default. - The `rustc-serialize` crate is no longer supported by `num`. -- The `rand` dependency has been updated to 0.5, now disabled by default. This - requires rustc 1.22 or greater for `rand`'s own requirement. - -**Contributors**: @CAD97, @cuviper, and the many sub-crate contributors! - -# Release 0.1.42 (2018-02-08) - -- [All of the num sub-crates now have their own source repositories][num-356]. -- Updated num sub-crates to their latest versions. - -**Contributors**: @cuviper - -[num-356]: https://github.com/rust-num/num/pull/356 - - -# Prior releases - -No prior release notes were kept. Thanks all the same to the many -contributors that have made this crate what it is! diff --git a/third_party/rust/num/src/lib.rs b/third_party/rust/num/src/lib.rs deleted file mode 100644 index 27dd1968c4cf..000000000000 --- a/third_party/rust/num/src/lib.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A collection of numeric types and traits for Rust. -//! -//! This includes new types for big integers, rationals, and complex numbers, -//! new traits for generic programming on numeric properties like `Integer`, -//! and generic range iterators. -//! -//! ## Example -//! -//! This example uses the BigRational type and [Newton's method][newt] to -//! approximate a square root to arbitrary precision: -//! -//! ``` -//! # #[cfg(any(feature = "alloc", feature = "std"))] -//! # mod test { -//! -//! use num::FromPrimitive; -//! use num::bigint::BigInt; -//! use num::rational::{Ratio, BigRational}; -//! -//! # pub -//! fn approx_sqrt(number: u64, iterations: usize) -> BigRational { -//! let start: Ratio = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap()); -//! let mut approx = start.clone(); -//! -//! for _ in 0..iterations { -//! approx = (&approx + (&start / &approx)) / -//! Ratio::from_integer(FromPrimitive::from_u64(2).unwrap()); -//! } -//! -//! approx -//! } -//! # } -//! # #[cfg(not(any(feature = "alloc", feature = "std")))] -//! # mod test { pub fn approx_sqrt(n: u64, _: usize) -> u64 { n } } -//! # use crate::test::approx_sqrt; -//! -//! fn main() { -//! println!("{}", approx_sqrt(10, 4)); // prints 4057691201/1283082416 -//! } -//! -//! ``` -//! -//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method -//! -//! ## Compatibility -//! -//! The `num` crate is tested for rustc 1.31 and greater. - -#![doc(html_root_url = "https://docs.rs/num/0.3")] -#![no_std] - -#[cfg(any(feature = "alloc", feature = "std"))] -pub use num_bigint::{BigInt, BigUint}; - -pub use num_complex::Complex; - -#[cfg(any(feature = "alloc", feature = "std"))] -pub use num_rational::BigRational; -pub use num_rational::Rational; - -pub use num_integer::Integer; - -pub use num_iter::{range, range_inclusive, range_step, range_step_inclusive}; - -#[cfg(any(feature = "libm", feature = "std"))] -pub use num_traits::Float; -pub use num_traits::{ - abs, abs_sub, cast, checked_pow, clamp, one, pow, signum, zero, Bounded, CheckedAdd, - CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, NumCast, One, PrimInt, Saturating, - Signed, ToPrimitive, Unsigned, Zero, -}; - -#[cfg(any(feature = "alloc", feature = "std"))] -pub mod bigint { - pub use num_bigint::*; -} - -pub mod complex { - pub use num_complex::*; -} - -pub mod integer { - pub use num_integer::*; -} - -pub mod iter { - pub use num_iter::*; -} - -pub mod traits { - pub use num_traits::*; -} - -pub mod rational { - pub use num_rational::*; -} diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml index b416a87eefbd..55f7eb0fdd0d 100644 --- a/toolkit/library/rust/shared/Cargo.toml +++ b/toolkit/library/rust/shared/Cargo.toml @@ -9,7 +9,7 @@ description = "Shared Rust code for libxul" geckoservo = { path = "../../../../servo/ports/geckolib" } kvstore = { path = "../../../components/kvstore" } lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] } -mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "6ebb531e1b0381c7a5980279637ef6ae7a3b6bc2" } +mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "63325444ae3388599f2f222775eebdde4c2f9f30" } nserror = { path = "../../../../xpcom/rust/nserror" } nsstring = { path = "../../../../xpcom/rust/nsstring" } netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }