Make BigUint and BigInt Hash, fixes #16551

This commit is contained in:
Alexis Beingessner 2014-08-17 11:15:07 -04:00
parent 02f9fd87ec
commit af82adce75
2 changed files with 55 additions and 1 deletions

View File

@ -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() {
@ -1460,6 +1484,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],
@ -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() {
@ -2314,6 +2352,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) {

View File

@ -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]