|
59 | 59 | use Integer;
|
60 | 60 | use rand::Rng;
|
61 | 61 |
|
62 |
| -use std::{cmp, fmt}; |
| 62 | +use std::{cmp, fmt, hash}; |
63 | 63 | use std::default::Default;
|
64 | 64 | use std::from_str::FromStr;
|
65 | 65 | use std::num::CheckedDiv;
|
@@ -150,6 +150,22 @@ impl Default for BigUint {
|
150 | 150 | fn default() -> BigUint { Zero::zero() }
|
151 | 151 | }
|
152 | 152 |
|
| 153 | +impl<S: hash::Writer> hash::Hash<S> for BigUint { |
| 154 | + fn hash(&self, state: &mut S) { |
| 155 | + // hash 0 in case it's all 0's |
| 156 | + 0u32.hash(state); |
| 157 | + |
| 158 | + let mut found_first_value = false; |
| 159 | + for elem in self.data.iter().rev() { |
| 160 | + // don't hash any leading 0's, they shouldn't affect the hash |
| 161 | + if found_first_value || *elem != 0 { |
| 162 | + found_first_value = true; |
| 163 | + elem.hash(state); |
| 164 | + } |
| 165 | + } |
| 166 | + } |
| 167 | +} |
| 168 | + |
153 | 169 | impl fmt::Show for BigUint {
|
154 | 170 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
155 | 171 | write!(f, "{}", self.to_str_radix(10))
|
@@ -881,6 +897,13 @@ impl fmt::Show for BigInt {
|
881 | 897 | }
|
882 | 898 | }
|
883 | 899 |
|
| 900 | +impl<S: hash::Writer> hash::Hash<S> for BigInt { |
| 901 | + fn hash(&self, state: &mut S) { |
| 902 | + (self.sign == Plus).hash(state); |
| 903 | + self.data.hash(state); |
| 904 | + } |
| 905 | +} |
| 906 | + |
884 | 907 | impl FromStr for BigInt {
|
885 | 908 | #[inline]
|
886 | 909 | fn from_str(s: &str) -> Option<BigInt> {
|
@@ -1409,6 +1432,7 @@ mod biguint_tests {
|
1409 | 1432 | use std::num::CheckedDiv;
|
1410 | 1433 | use std::rand::task_rng;
|
1411 | 1434 | use std::u64;
|
| 1435 | + use std::hash::hash; |
1412 | 1436 |
|
1413 | 1437 | #[test]
|
1414 | 1438 | fn test_from_slice() {
|
@@ -1460,6 +1484,19 @@ mod biguint_tests {
|
1460 | 1484 | }
|
1461 | 1485 | }
|
1462 | 1486 |
|
| 1487 | + #[test] |
| 1488 | + fn test_hash() { |
| 1489 | + let a = BigUint::new(vec!()); |
| 1490 | + let b = BigUint::new(vec!(0)); |
| 1491 | + let c = BigUint::new(vec!(1)); |
| 1492 | + let d = BigUint::new(vec!(1,0,0,0,0,0)); |
| 1493 | + let e = BigUint::new(vec!(0,0,0,0,0,1)); |
| 1494 | + assert!(hash(&a) == hash(&b)); |
| 1495 | + assert!(hash(&b) != hash(&c)); |
| 1496 | + assert!(hash(&c) == hash(&d)); |
| 1497 | + assert!(hash(&d) != hash(&e)); |
| 1498 | + } |
| 1499 | + |
1463 | 1500 | #[test]
|
1464 | 1501 | fn test_bitand() {
|
1465 | 1502 | fn check(left: &[BigDigit],
|
@@ -2257,6 +2294,7 @@ mod bigint_tests {
|
2257 | 2294 | use std::num::{ToPrimitive, FromPrimitive};
|
2258 | 2295 | use std::rand::task_rng;
|
2259 | 2296 | use std::u64;
|
| 2297 | + use std::hash::hash; |
2260 | 2298 |
|
2261 | 2299 | #[test]
|
2262 | 2300 | fn test_from_biguint() {
|
@@ -2314,6 +2352,21 @@ mod bigint_tests {
|
2314 | 2352 | }
|
2315 | 2353 | }
|
2316 | 2354 |
|
| 2355 | + #[test] |
| 2356 | + fn test_hash() { |
| 2357 | + let a = BigInt::new(Zero, vec!()); |
| 2358 | + let b = BigInt::new(Zero, vec!(0)); |
| 2359 | + let c = BigInt::new(Plus, vec!(1)); |
| 2360 | + let d = BigInt::new(Plus, vec!(1,0,0,0,0,0)); |
| 2361 | + let e = BigInt::new(Plus, vec!(0,0,0,0,0,1)); |
| 2362 | + let f = BigInt::new(Minus, vec!(1)); |
| 2363 | + assert!(hash(&a) == hash(&b)); |
| 2364 | + assert!(hash(&b) != hash(&c)); |
| 2365 | + assert!(hash(&c) == hash(&d)); |
| 2366 | + assert!(hash(&d) != hash(&e)); |
| 2367 | + assert!(hash(&c) != hash(&f)); |
| 2368 | + } |
| 2369 | + |
2317 | 2370 | #[test]
|
2318 | 2371 | fn test_convert_i64() {
|
2319 | 2372 | fn check(b1: BigInt, i: i64) {
|
|
0 commit comments