diff options
| author | bors <bors@rust-lang.org> | 2014-08-17 19:31:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-08-17 19:31:10 +0000 |
| commit | 3f57c8988dfd2eba8fb751fe72dde503a6ebf2c6 (patch) | |
| tree | 261ce44cb820c1be32687734eaaf5ca3ac2b37c1 /src/libnum | |
| parent | fb018a3d4b1d45d75cb6118940ca33e7ab7735ce (diff) | |
| parent | af82adce751ec8bc983478ad201d148502bb4a69 (diff) | |
| download | rust-3f57c8988dfd2eba8fb751fe72dde503a6ebf2c6.tar.gz rust-3f57c8988dfd2eba8fb751fe72dde503a6ebf2c6.zip | |
auto merge of #16558 : Gankro/rust/hashbig, r=pcwalton
Pretty self-explanatory. Only annoying thing is that it *seems* that I had to add `#![feature(default_type_params)]` to libnum because of Hasher. Don't know if there's a way around that. Fix #16551
Diffstat (limited to 'src/libnum')
| -rw-r--r-- | src/libnum/bigint.rs | 55 | ||||
| -rw-r--r-- | src/libnum/lib.rs | 1 |
2 files changed, 55 insertions, 1 deletions
diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 3a5f7649201..48fc9fb4a38 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -59,7 +59,7 @@ use Integer; use rand::Rng; -use std::{cmp, fmt}; +use std::{cmp, fmt, hash}; use std::default::Default; use std::from_str::FromStr; use std::num::CheckedDiv; @@ -150,6 +150,22 @@ impl Default for BigUint { fn default() -> BigUint { Zero::zero() } } +impl<S: hash::Writer> hash::Hash<S> for BigUint { + fn hash(&self, state: &mut S) { + // hash 0 in case it's all 0's + 0u32.hash(state); + + let mut found_first_value = false; + for elem in self.data.iter().rev() { + // don't hash any leading 0's, they shouldn't affect the hash + if found_first_value || *elem != 0 { + found_first_value = true; + elem.hash(state); + } + } + } +} + impl fmt::Show for BigUint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_str_radix(10)) @@ -881,6 +897,13 @@ impl fmt::Show for BigInt { } } +impl<S: hash::Writer> hash::Hash<S> for BigInt { + fn hash(&self, state: &mut S) { + (self.sign == Plus).hash(state); + self.data.hash(state); + } +} + impl FromStr for BigInt { #[inline] fn from_str(s: &str) -> Option<BigInt> { @@ -1409,6 +1432,7 @@ mod biguint_tests { use std::num::CheckedDiv; use std::rand::task_rng; use std::u64; + use std::hash::hash; #[test] fn test_from_slice() { @@ -1461,6 +1485,19 @@ mod biguint_tests { } #[test] + fn test_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)); + } + + #[test] fn test_bitand() { fn check(left: &[BigDigit], right: &[BigDigit], @@ -2257,6 +2294,7 @@ mod bigint_tests { use std::num::{ToPrimitive, FromPrimitive}; use std::rand::task_rng; use std::u64; + use std::hash::hash; #[test] fn test_from_biguint() { @@ -2315,6 +2353,21 @@ mod bigint_tests { } #[test] + fn test_hash() { + let a = BigInt::new(Zero, vec!()); + let b = BigInt::new(Zero, 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(); diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index 5cc2eee7da7..f12279b20e8 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -43,6 +43,7 @@ //! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method #![feature(macro_rules)] +#![feature(default_type_params)] #![crate_name = "num"] #![experimental] |
