First commit. The hashes and their inverses.

This commit is contained in:
Nathan Vegdahl 2023-08-01 23:27:47 +02:00
commit 62138fd9a4
3 changed files with 111 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/Cargo.lock

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "bit_mixers"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

101
src/lib.rs Normal file
View File

@ -0,0 +1,101 @@
/// 32-bit bijective bit mixer.
///
/// https://github.com/skeeto/hash-prospector
pub fn mix32(mut n: u32) -> u32 {
n ^= n >> 16;
n = n.wrapping_mul(0x21f0aaad);
n ^= n >> 15;
n = n.wrapping_mul(0xd35a2d97);
n ^= n >> 15;
n
}
/// Inverse of `mix32()`.
pub fn mix32_inv(mut n: u32) -> u32 {
n ^= (n >> 15) ^ (n >> 30);
n = n.wrapping_mul(0x37132227);
n ^= (n >> 15) ^ (n >> 30);
n = n.wrapping_mul(0x333c4925);
n ^= n >> 16;
n
}
/// 64-bit bijective bit mixer.
///
/// http://zimbry.blogspot.ch/2011/09/better-bit-mixing-improving-on.html
pub fn mix64(mut n: u64) -> u64 {
n ^= n >> 31;
n = n.wrapping_mul(0x7fb5d329728ea185);
n ^= n >> 27;
n = n.wrapping_mul(0x81dadef4bc2dd44d);
n ^= n >> 33;
n
}
/// Inverse of `mix64()`.
pub fn mix64_inv(mut n: u64) -> u64 {
n ^= n >> 33;
n = n.wrapping_mul(0x4d6dff26c61d8485);
n ^= (n >> 27) ^ (n >> 54);
n = n.wrapping_mul(0x4c5ff4596f4a2f4d);
n ^= (n >> 31) ^ (n >> 62);
n
}
#[cfg(test)]
mod tests {
use super::*;
// fn compute_multiplicative_inverse_32(a: u32) -> u32 {
// assert!(a & 1 == 1);
// let mut x = a;
// // Overkill iteration count.
// for _ in 0..100 {
// // x += x - a * x * x;
// x = x.wrapping_add(x.wrapping_sub(a.wrapping_mul(x).wrapping_mul(x)));
// }
// x
// }
// fn compute_multiplicative_inverse_64(a: u64) -> u64 {
// assert!(a & 1 == 1);
// let mut x = a;
// // Overkill iteration count.
// for _ in 0..100 {
// // x += x - a * x * x;
// x = x.wrapping_add(x.wrapping_sub(a.wrapping_mul(x).wrapping_mul(x)));
// }
// x
// }
// #[test]
// fn get_inverse() {
// // Panic, to print the result.
// panic!("0x{:x}", compute_multiplicative_inverse_32(0x21f0aaad));
// panic!("0x{:x}", compute_multiplicative_inverse_32(0xd35a2d97));
// }
#[test]
fn mix32_invertability() {
for i in 0..9999999u32 {
let n = mix32(mix32(mix32(i)));
assert_eq!(n, mix32_inv(mix32(n)));
assert_eq!(n, mix32(mix32_inv(n)));
}
}
#[test]
fn mix64_invertability() {
for i in 0..9999999u64 {
let n = mix64(mix64(mix64(i)));
assert_eq!(n, mix64_inv(mix64(n)));
assert_eq!(n, mix64(mix64_inv(n)));
}
}
}