From d71a92391258ec645802477f6a2ac1eda858cf45 Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Wed, 17 May 2017 09:10:41 -0500 Subject: [PATCH 1/7] Adds quickcheck impls for BigInt, BigUint. --- Cargo.toml | 5 +++ bigint/Cargo.toml | 4 ++ bigint/src/lib.rs | 5 +++ bigint/src/quickcheck_impls.rs | 82 ++++++++++++++++++++++++++++++++++ complex/Cargo.toml | 4 ++ rational/Cargo.toml | 4 ++ 6 files changed, 104 insertions(+) create mode 100644 bigint/src/quickcheck_impls.rs diff --git a/Cargo.toml b/Cargo.toml index 662348368b..0a6621761f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,11 @@ complex = ["num-complex"] rational = ["num-rational"] default = ["bigint", "complex", "rational", "rustc-serialize"] +quickcheck = [ + "num-bigint/quickcheck", + "num-complex/quickcheck", + "num-rational/quickcheck" +] serde = [ "num-bigint/serde", "num-complex/serde", diff --git a/bigint/Cargo.toml b/bigint/Cargo.toml index 31725fe19c..38361536d4 100644 --- a/bigint/Cargo.toml +++ b/bigint/Cargo.toml @@ -19,6 +19,10 @@ version = "0.1.32" path = "../traits" version = "0.1.32" +[dependencies.quickcheck] +optional = true +version = "0.4.1" + [dependencies.rand] optional = true version = "0.3.14" diff --git a/bigint/src/lib.rs b/bigint/src/lib.rs index 586eeec3bf..0173e44d14 100644 --- a/bigint/src/lib.rs +++ b/bigint/src/lib.rs @@ -76,6 +76,8 @@ #[cfg(any(feature = "rand", test))] extern crate rand; +#[cfg(feature = "quickcheck")] +extern crate quickcheck; #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; #[cfg(feature = "serde")] @@ -133,6 +135,9 @@ mod macros; mod biguint; mod bigint; +#[cfg(feature = "quickcheck")] +mod quickcheck_impls; + pub use biguint::BigUint; pub use biguint::ToBigUint; pub use biguint::big_digit; diff --git a/bigint/src/quickcheck_impls.rs b/bigint/src/quickcheck_impls.rs new file mode 100644 index 0000000000..208e50fb4d --- /dev/null +++ b/bigint/src/quickcheck_impls.rs @@ -0,0 +1,82 @@ +use bigint::{BigInt, Sign}; +use biguint::BigUint; +use quickcheck::{Arbitrary, empty_shrinker, Gen}; +use std::iter::once; +use traits::{FromPrimitive, Signed, Zero}; + +impl Arbitrary for BigInt { + fn arbitrary(g: &mut G) -> Self { + let sign = if g.gen() { + Sign::Plus + } else { + Sign::Minus + }; + Self::new(sign, Arbitrary::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + /// Based on the SignedShrinker for primitive types in quickcheck + /// itself. + struct Iter(BigInt, BigInt); + impl Iterator for Iter { + type Item = BigInt; + + fn next(&mut self) -> Option { + if (self.0.clone() - &self.1).abs() < self.0.abs() { + let result = Some(self.0.clone() - &self.1); + // TODO This would benefit from in-place `/=`. + self.1 = self.1.clone() / BigInt::from_usize(2).unwrap(); + result + } else { + None + } + } + } + + if self.is_zero() { + empty_shrinker() + } else { + let two = BigInt::from_usize(2).unwrap(); + let shrinker = Iter(self.clone(), self.clone() / two); + let mut items = vec![Self::zero()]; + if shrinker.1.is_negative() { + items.push(shrinker.0.abs()); + } + Box::new(items.into_iter().chain(shrinker)) + } + } +} + +impl Arbitrary for BigUint { + fn arbitrary(g: &mut G) -> Self { + Self::new(Arbitrary::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + /// Based on the UnsignedShrinker for primitive types in quickcheck + /// itself. + struct Iter(BigUint, BigUint); + impl Iterator for Iter { + type Item = BigUint; + + fn next(&mut self) -> Option { + if (self.0.clone() - &self.1) < self.0 { + let result = Some(self.0.clone() - &self.1); + // TODO This would benefit from in-place `/=`. + self.1 = self.1.clone() / BigUint::from_usize(2).unwrap(); + result + } else { + None + } + } + } + + if self.is_zero() { + empty_shrinker() + } else { + let two = BigUint::from_usize(2).unwrap(); + let shrinker = Iter(self.clone(), self.clone() / two); + Box::new(once(Self::zero()).chain(shrinker)) + } + } +} diff --git a/complex/Cargo.toml b/complex/Cargo.toml index 29f7fe82e9..d3c6666d5c 100644 --- a/complex/Cargo.toml +++ b/complex/Cargo.toml @@ -16,6 +16,10 @@ optional = false path = "../traits" version = "0.1.32" +[dependencies.quickcheck] +optional = true +version = "0.4.1" + [dependencies.rustc-serialize] optional = true version = "0.3.19" diff --git a/rational/Cargo.toml b/rational/Cargo.toml index 6340171579..cbc47d2e40 100644 --- a/rational/Cargo.toml +++ b/rational/Cargo.toml @@ -24,6 +24,10 @@ version = "0.1.32" path = "../traits" version = "0.1.32" +[dependencies.quickcheck] +optional = true +version = "0.4.1" + [dependencies.rustc-serialize] optional = true version = "0.3.19" From e0ed21175eabc5059968b5035e87e098285c942e Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Wed, 17 May 2017 19:12:14 -0500 Subject: [PATCH 2/7] Adds complex quickcheck implementation. --- complex/src/lib.rs | 6 ++++ complex/src/quickcheck_impls.rs | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 complex/src/quickcheck_impls.rs diff --git a/complex/src/lib.rs b/complex/src/lib.rs index cb605a2c28..a92d818947 100644 --- a/complex/src/lib.rs +++ b/complex/src/lib.rs @@ -16,12 +16,18 @@ extern crate num_traits as traits; +#[cfg(feature = "quickcheck")] +extern crate quickcheck; + #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; #[cfg(feature = "serde")] extern crate serde; +#[cfg(feature = "quickcheck")] +mod quickcheck_impls; + use std::fmt; #[cfg(test)] use std::hash; diff --git a/complex/src/quickcheck_impls.rs b/complex/src/quickcheck_impls.rs new file mode 100644 index 0000000000..38d742679e --- /dev/null +++ b/complex/src/quickcheck_impls.rs @@ -0,0 +1,58 @@ +use Complex; +use quickcheck::{Arbitrary, Gen}; +use traits::Num; + +impl Arbitrary for Complex { + fn arbitrary(g: &mut G) -> Self { + Complex::new(T::arbitrary(g), T::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + Box::new(Shrinker::new(self.re.clone(), self.im.clone())) + } +} + +struct Shrinker { + mode: bool, + re: T, + im: T, + re_iter: Option>>, + im_iter: Option>>, +} + +impl Shrinker { + fn new(re: T, im: T) -> Self { + Shrinker { + mode: true, + re: re.clone(), + im: im, + re_iter: Some(re.shrink()), + im_iter: None, + } + } +} + +impl Iterator for Shrinker { + type Item = Complex; + + fn next(&mut self) -> Option> { + match self.mode { + true => if let Some(re) = self.re_iter.as_mut().unwrap().next() { + Some(Complex::new(re, self.im.clone())) + } else { + self.mode = false; + self.re_iter = None; + self.im_iter = Some(self.im.clone().shrink()); + self.next() + }, + false => if let Some(im) = self.im_iter.as_mut().unwrap().next() { + Some(Complex::new(self.re.clone(), im)) + } else if let Some(re) = self.re_iter.as_mut().unwrap().next() { + self.re = re; + self.next() + } else { + None + } + } + } +} From e7ca838c06baa89d83c24f72894ba2a282113a81 Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Wed, 17 May 2017 19:19:06 -0500 Subject: [PATCH 3/7] Adds Arbitrary impl for Rationals. --- rational/src/lib.rs | 5 +++ rational/src/quickcheck_impls.rs | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 rational/src/quickcheck_impls.rs diff --git a/rational/src/lib.rs b/rational/src/lib.rs index e12b987ed3..9bccb195fc 100644 --- a/rational/src/lib.rs +++ b/rational/src/lib.rs @@ -14,6 +14,8 @@ html_root_url = "https://rust-num.github.io/num/", html_playground_url = "http://play.integer32.com/")] +#[cfg(feature = "quickcheck")] +extern crate quickcheck; #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; #[cfg(feature = "serde")] @@ -24,6 +26,9 @@ extern crate num_bigint as bigint; extern crate num_traits as traits; extern crate num_integer as integer; +#[cfg(feature = "quickcheck")] +mod quickcheck_impls; + use std::cmp; use std::error::Error; use std::fmt; diff --git a/rational/src/quickcheck_impls.rs b/rational/src/quickcheck_impls.rs new file mode 100644 index 0000000000..6ccd06f4c2 --- /dev/null +++ b/rational/src/quickcheck_impls.rs @@ -0,0 +1,58 @@ +use Ratio; +use integer::Integer; +use quickcheck::{Arbitrary, Gen}; + +impl Arbitrary for Ratio { + fn arbitrary(g: &mut G) -> Self { + Ratio::new(T::arbitrary(g), T::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + Box::new(Shrinker::new(self.numer.clone(), self.denom.clone())) + } +} + +struct Shrinker { + mode: bool, + numer: T, + denom: T, + numer_iter: Option>>, + denom_iter: Option>>, +} + +impl Shrinker { + fn new(numer: T, denom: T) -> Self { + Shrinker { + mode: true, + numer: numer.clone(), + denom: denom, + numer_iter: Some(numer.shrink()), + denom_iter: None, + } + } +} + +impl Iterator for Shrinker { + type Item = Ratio; + + fn next(&mut self) -> Option> { + match self.mode { + true => if let Some(numer) = self.numer_iter.as_mut().unwrap().next() { + Some(Ratio::new(numer, self.denom.clone())) + } else { + self.mode = false; + self.numer_iter = None; + self.denom_iter = Some(self.denom.clone().shrink()); + self.next() + }, + false => if let Some(denom) = self.denom_iter.as_mut().unwrap().next() { + Some(Ratio::new(self.numer.clone(), denom)) + } else if let Some(numer) = self.numer_iter.as_mut().unwrap().next() { + self.numer = numer; + self.next() + } else { + None + } + } + } +} From d4bc2c5529f614e70e1395906907ef693a5d8fd9 Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Wed, 17 May 2017 21:57:11 -0500 Subject: [PATCH 4/7] Adds Travis testing for the quickcheck feature. --- ci/test_full.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test_full.sh b/ci/test_full.sh index b750b71874..4e3a47257f 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -11,7 +11,7 @@ for package in bigint complex integer iter rational traits; do done # Each isolated feature should also work everywhere. -for feature in '' bigint rational complex; do +for feature in '' bigint rational complex quickcheck; do cargo build --verbose --no-default-features --features="$feature" cargo test --verbose --no-default-features --features="$feature" done From 0ba676bcd35d63443e65979cf15c65d1400d12ba Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Wed, 17 May 2017 22:10:36 -0500 Subject: [PATCH 5/7] quickcheck requires Rust version 1.9.0 or later. --- ci/test_full.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ci/test_full.sh b/ci/test_full.sh index 4e3a47257f..3cbf6e31b6 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -11,7 +11,7 @@ for package in bigint complex integer iter rational traits; do done # Each isolated feature should also work everywhere. -for feature in '' bigint rational complex quickcheck; do +for feature in '' bigint rational complex; do cargo build --verbose --no-default-features --features="$feature" cargo test --verbose --no-default-features --features="$feature" done @@ -26,6 +26,10 @@ cargo build --verbose --features "serde" if [ "$TRAVIS_RUST_VERSION" = 1.8.0 ]; then exit; fi +# Build test for the quickcheck feature. +cargo build --verbose --features=quickcheck +cargo test --verbose --features=quickcheck + # num-derive should build on 1.15.0+ cargo build --verbose --manifest-path=derive/Cargo.toml From d090c25075ee9ca898c556b7f7aea6cdd9be7088 Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Wed, 17 May 2017 23:03:52 -0500 Subject: [PATCH 6/7] Makes quickcheck_impls public (whoops) --- bigint/src/lib.rs | 2 +- complex/src/lib.rs | 2 +- rational/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bigint/src/lib.rs b/bigint/src/lib.rs index 0173e44d14..61f699e769 100644 --- a/bigint/src/lib.rs +++ b/bigint/src/lib.rs @@ -136,7 +136,7 @@ mod biguint; mod bigint; #[cfg(feature = "quickcheck")] -mod quickcheck_impls; +pub mod quickcheck_impls; pub use biguint::BigUint; pub use biguint::ToBigUint; diff --git a/complex/src/lib.rs b/complex/src/lib.rs index a92d818947..e6423200c9 100644 --- a/complex/src/lib.rs +++ b/complex/src/lib.rs @@ -26,7 +26,7 @@ extern crate rustc_serialize; extern crate serde; #[cfg(feature = "quickcheck")] -mod quickcheck_impls; +pub mod quickcheck_impls; use std::fmt; #[cfg(test)] diff --git a/rational/src/lib.rs b/rational/src/lib.rs index 9bccb195fc..9fe1353f58 100644 --- a/rational/src/lib.rs +++ b/rational/src/lib.rs @@ -27,7 +27,7 @@ extern crate num_traits as traits; extern crate num_integer as integer; #[cfg(feature = "quickcheck")] -mod quickcheck_impls; +pub mod quickcheck_impls; use std::cmp; use std::error::Error; From 9ab6b2431432ca1b91d621efea31d54e283b4618 Mon Sep 17 00:00:00 2001 From: Nathaniel Ringo Date: Mon, 22 May 2017 01:07:52 -0500 Subject: [PATCH 7/7] Fixes dumb mistake. --- bigint/src/bigint.rs | 52 ++++++++++++++++++++ bigint/src/biguint.rs | 43 +++++++++++++++++ bigint/src/lib.rs | 3 -- bigint/src/quickcheck_impls.rs | 82 -------------------------------- complex/src/lib.rs | 61 ++++++++++++++++++++++-- complex/src/quickcheck_impls.rs | 58 ---------------------- rational/src/lib.rs | 61 ++++++++++++++++++++++-- rational/src/quickcheck_impls.rs | 58 ---------------------- 8 files changed, 211 insertions(+), 207 deletions(-) delete mode 100644 bigint/src/quickcheck_impls.rs delete mode 100644 complex/src/quickcheck_impls.rs delete mode 100644 rational/src/quickcheck_impls.rs diff --git a/bigint/src/bigint.rs b/bigint/src/bigint.rs index 32a44419ef..73b22a85e7 100644 --- a/bigint/src/bigint.rs +++ b/bigint/src/bigint.rs @@ -6,6 +6,9 @@ use std::cmp::Ordering::{self, Less, Greater, Equal}; use std::{i64, u64}; use std::ascii::AsciiExt; +#[cfg(feature = "quickcheck")] +use quickcheck; + #[cfg(feature = "serde")] use serde; @@ -751,6 +754,55 @@ impl From for BigInt { } } +#[cfg(feature = "quickcheck")] +impl quickcheck::Arbitrary for BigInt { + fn arbitrary(g: &mut G) -> Self { + use quickcheck::Arbitrary; + + let sign = if g.gen() { + Sign::Plus + } else { + Sign::Minus + }; + + Self::new(sign, Arbitrary::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + use quickcheck::empty_shrinker; + + /// Based on the SignedShrinker for primitive types in quickcheck + /// itself. + struct Iter(BigInt, BigInt); + impl Iterator for Iter { + type Item = BigInt; + + fn next(&mut self) -> Option { + if (self.0.clone() - &self.1).abs() < self.0.abs() { + let result = Some(self.0.clone() - &self.1); + // TODO This would benefit from in-place `/=`. + self.1 = self.1.clone() / BigInt::from_usize(2).unwrap(); + result + } else { + None + } + } + } + + if self.is_zero() { + empty_shrinker() + } else { + let two = BigInt::from_usize(2).unwrap(); + let shrinker = Iter(self.clone(), self.clone() / two); + let mut items = vec![Self::zero()]; + if shrinker.1.is_negative() { + items.push(shrinker.0.abs()); + } + Box::new(items.into_iter().chain(shrinker)) + } + } +} + #[cfg(feature = "serde")] impl serde::Serialize for BigInt { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 00877c8258..bb2ac01b36 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -10,6 +10,9 @@ use std::{f32, f64}; use std::{u8, u64}; use std::ascii::AsciiExt; +#[cfg(feature = "quickcheck")] +use quickcheck; + #[cfg(feature = "serde")] use serde; @@ -1071,6 +1074,46 @@ impl BigUint { } } +#[cfg(feature = "quickcheck")] +impl quickcheck::Arbitrary for BigUint { + fn arbitrary(g: &mut G) -> Self { + use quickcheck::Arbitrary; + + Self::new(Arbitrary::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + use quickcheck::empty_shrinker; + use std::iter::once; + + /// Based on the UnsignedShrinker for primitive types in quickcheck + /// itself. + struct Iter(BigUint, BigUint); + impl Iterator for Iter { + type Item = BigUint; + + fn next(&mut self) -> Option { + if (self.0.clone() - &self.1) < self.0 { + let result = Some(self.0.clone() - &self.1); + // TODO This would benefit from in-place `/=`. + self.1 = self.1.clone() / BigUint::from_usize(2).unwrap(); + result + } else { + None + } + } + } + + if self.is_zero() { + empty_shrinker() + } else { + let two = BigUint::from_usize(2).unwrap(); + let shrinker = Iter(self.clone(), self.clone() / two); + Box::new(once(Self::zero()).chain(shrinker)) + } + } +} + #[cfg(feature = "serde")] impl serde::Serialize for BigUint { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> diff --git a/bigint/src/lib.rs b/bigint/src/lib.rs index 61f699e769..cff7c823c4 100644 --- a/bigint/src/lib.rs +++ b/bigint/src/lib.rs @@ -135,9 +135,6 @@ mod macros; mod biguint; mod bigint; -#[cfg(feature = "quickcheck")] -pub mod quickcheck_impls; - pub use biguint::BigUint; pub use biguint::ToBigUint; pub use biguint::big_digit; diff --git a/bigint/src/quickcheck_impls.rs b/bigint/src/quickcheck_impls.rs deleted file mode 100644 index 208e50fb4d..0000000000 --- a/bigint/src/quickcheck_impls.rs +++ /dev/null @@ -1,82 +0,0 @@ -use bigint::{BigInt, Sign}; -use biguint::BigUint; -use quickcheck::{Arbitrary, empty_shrinker, Gen}; -use std::iter::once; -use traits::{FromPrimitive, Signed, Zero}; - -impl Arbitrary for BigInt { - fn arbitrary(g: &mut G) -> Self { - let sign = if g.gen() { - Sign::Plus - } else { - Sign::Minus - }; - Self::new(sign, Arbitrary::arbitrary(g)) - } - - fn shrink(&self) -> Box> { - /// Based on the SignedShrinker for primitive types in quickcheck - /// itself. - struct Iter(BigInt, BigInt); - impl Iterator for Iter { - type Item = BigInt; - - fn next(&mut self) -> Option { - if (self.0.clone() - &self.1).abs() < self.0.abs() { - let result = Some(self.0.clone() - &self.1); - // TODO This would benefit from in-place `/=`. - self.1 = self.1.clone() / BigInt::from_usize(2).unwrap(); - result - } else { - None - } - } - } - - if self.is_zero() { - empty_shrinker() - } else { - let two = BigInt::from_usize(2).unwrap(); - let shrinker = Iter(self.clone(), self.clone() / two); - let mut items = vec![Self::zero()]; - if shrinker.1.is_negative() { - items.push(shrinker.0.abs()); - } - Box::new(items.into_iter().chain(shrinker)) - } - } -} - -impl Arbitrary for BigUint { - fn arbitrary(g: &mut G) -> Self { - Self::new(Arbitrary::arbitrary(g)) - } - - fn shrink(&self) -> Box> { - /// Based on the UnsignedShrinker for primitive types in quickcheck - /// itself. - struct Iter(BigUint, BigUint); - impl Iterator for Iter { - type Item = BigUint; - - fn next(&mut self) -> Option { - if (self.0.clone() - &self.1) < self.0 { - let result = Some(self.0.clone() - &self.1); - // TODO This would benefit from in-place `/=`. - self.1 = self.1.clone() / BigUint::from_usize(2).unwrap(); - result - } else { - None - } - } - } - - if self.is_zero() { - empty_shrinker() - } else { - let two = BigUint::from_usize(2).unwrap(); - let shrinker = Iter(self.clone(), self.clone() / two); - Box::new(once(Self::zero()).chain(shrinker)) - } - } -} diff --git a/complex/src/lib.rs b/complex/src/lib.rs index e6423200c9..3ce73db0cc 100644 --- a/complex/src/lib.rs +++ b/complex/src/lib.rs @@ -25,9 +25,6 @@ extern crate rustc_serialize; #[cfg(feature = "serde")] extern crate serde; -#[cfg(feature = "quickcheck")] -pub mod quickcheck_impls; - use std::fmt; #[cfg(test)] use std::hash; @@ -746,6 +743,64 @@ impl fmt::Binary for Complex where } } +#[cfg(feature = "quickcheck")] +impl quickcheck::Arbitrary for Complex { + fn arbitrary(g: &mut G) -> Self { + Complex::new(T::arbitrary(g), T::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + use quickcheck::Arbitrary; + + struct Shrinker { + mode: bool, + re: T, + im: T, + re_iter: Option>>, + im_iter: Option>>, + } + + impl Shrinker { + fn new(re: T, im: T) -> Self { + Shrinker { + mode: true, + re: re.clone(), + im: im, + re_iter: Some(re.shrink()), + im_iter: None, + } + } + } + + impl Iterator for Shrinker { + type Item = Complex; + + fn next(&mut self) -> Option> { + match self.mode { + true => if let Some(re) = self.re_iter.as_mut().unwrap().next() { + Some(Complex::new(re, self.im.clone())) + } else { + self.mode = false; + self.re_iter = None; + self.im_iter = Some(self.im.clone().shrink()); + self.next() + }, + false => if let Some(im) = self.im_iter.as_mut().unwrap().next() { + Some(Complex::new(self.re.clone(), im)) + } else if let Some(re) = self.re_iter.as_mut().unwrap().next() { + self.re = re; + self.next() + } else { + None + } + } + } + } + + Box::new(Shrinker::new(self.re.clone(), self.im.clone())) + } +} + #[cfg(feature = "serde")] impl serde::Serialize for Complex where T: serde::Serialize diff --git a/complex/src/quickcheck_impls.rs b/complex/src/quickcheck_impls.rs deleted file mode 100644 index 38d742679e..0000000000 --- a/complex/src/quickcheck_impls.rs +++ /dev/null @@ -1,58 +0,0 @@ -use Complex; -use quickcheck::{Arbitrary, Gen}; -use traits::Num; - -impl Arbitrary for Complex { - fn arbitrary(g: &mut G) -> Self { - Complex::new(T::arbitrary(g), T::arbitrary(g)) - } - - fn shrink(&self) -> Box> { - Box::new(Shrinker::new(self.re.clone(), self.im.clone())) - } -} - -struct Shrinker { - mode: bool, - re: T, - im: T, - re_iter: Option>>, - im_iter: Option>>, -} - -impl Shrinker { - fn new(re: T, im: T) -> Self { - Shrinker { - mode: true, - re: re.clone(), - im: im, - re_iter: Some(re.shrink()), - im_iter: None, - } - } -} - -impl Iterator for Shrinker { - type Item = Complex; - - fn next(&mut self) -> Option> { - match self.mode { - true => if let Some(re) = self.re_iter.as_mut().unwrap().next() { - Some(Complex::new(re, self.im.clone())) - } else { - self.mode = false; - self.re_iter = None; - self.im_iter = Some(self.im.clone().shrink()); - self.next() - }, - false => if let Some(im) = self.im_iter.as_mut().unwrap().next() { - Some(Complex::new(self.re.clone(), im)) - } else if let Some(re) = self.re_iter.as_mut().unwrap().next() { - self.re = re; - self.next() - } else { - None - } - } - } -} diff --git a/rational/src/lib.rs b/rational/src/lib.rs index 9fe1353f58..7358dca119 100644 --- a/rational/src/lib.rs +++ b/rational/src/lib.rs @@ -26,9 +26,6 @@ extern crate num_bigint as bigint; extern crate num_traits as traits; extern crate num_integer as integer; -#[cfg(feature = "quickcheck")] -pub mod quickcheck_impls; - use std::cmp; use std::error::Error; use std::fmt; @@ -613,6 +610,64 @@ impl Into<(T, T)> for Ratio { } } +#[cfg(feature = "quickcheck")] +impl quickcheck::Arbitrary for Ratio { + fn arbitrary(g: &mut G) -> Self { + Ratio::new(T::arbitrary(g), T::arbitrary(g)) + } + + fn shrink(&self) -> Box> { + use quickcheck::Arbitrary; + + struct Shrinker { + mode: bool, + numer: T, + denom: T, + numer_iter: Option>>, + denom_iter: Option>>, + } + + impl Shrinker { + fn new(numer: T, denom: T) -> Self { + Shrinker { + mode: true, + numer: numer.clone(), + denom: denom, + numer_iter: Some(numer.shrink()), + denom_iter: None, + } + } + } + + impl Iterator for Shrinker { + type Item = Ratio; + + fn next(&mut self) -> Option> { + match self.mode { + true => if let Some(numer) = self.numer_iter.as_mut().unwrap().next() { + Some(Ratio::new(numer, self.denom.clone())) + } else { + self.mode = false; + self.numer_iter = None; + self.denom_iter = Some(self.denom.clone().shrink()); + self.next() + }, + false => if let Some(denom) = self.denom_iter.as_mut().unwrap().next() { + Some(Ratio::new(self.numer.clone(), denom)) + } else if let Some(numer) = self.numer_iter.as_mut().unwrap().next() { + self.numer = numer; + self.next() + } else { + None + } + } + } + } + + Box::new(Shrinker::new(self.numer.clone(), self.denom.clone())) + } +} + #[cfg(feature = "serde")] impl serde::Serialize for Ratio where T: serde::Serialize + Clone + Integer + PartialOrd diff --git a/rational/src/quickcheck_impls.rs b/rational/src/quickcheck_impls.rs deleted file mode 100644 index 6ccd06f4c2..0000000000 --- a/rational/src/quickcheck_impls.rs +++ /dev/null @@ -1,58 +0,0 @@ -use Ratio; -use integer::Integer; -use quickcheck::{Arbitrary, Gen}; - -impl Arbitrary for Ratio { - fn arbitrary(g: &mut G) -> Self { - Ratio::new(T::arbitrary(g), T::arbitrary(g)) - } - - fn shrink(&self) -> Box> { - Box::new(Shrinker::new(self.numer.clone(), self.denom.clone())) - } -} - -struct Shrinker { - mode: bool, - numer: T, - denom: T, - numer_iter: Option>>, - denom_iter: Option>>, -} - -impl Shrinker { - fn new(numer: T, denom: T) -> Self { - Shrinker { - mode: true, - numer: numer.clone(), - denom: denom, - numer_iter: Some(numer.shrink()), - denom_iter: None, - } - } -} - -impl Iterator for Shrinker { - type Item = Ratio; - - fn next(&mut self) -> Option> { - match self.mode { - true => if let Some(numer) = self.numer_iter.as_mut().unwrap().next() { - Some(Ratio::new(numer, self.denom.clone())) - } else { - self.mode = false; - self.numer_iter = None; - self.denom_iter = Some(self.denom.clone().shrink()); - self.next() - }, - false => if let Some(denom) = self.denom_iter.as_mut().unwrap().next() { - Some(Ratio::new(self.numer.clone(), denom)) - } else if let Some(numer) = self.numer_iter.as_mut().unwrap().next() { - self.numer = numer; - self.next() - } else { - None - } - } - } -}