mod consts;
pub mod raw;
use cfg_if::cfg_if;
use raw::fingerprint_scalar;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Fingerprint {
pub fingerprint: [u32; 24],
}
impl Fingerprint {
pub const MAX_SIMILARITY_SCORE: u32 = 24;
pub fn similarity_score(self, other: Self) -> u32 {
let mut score = 0;
for (a, b) in self.fingerprint.iter().zip(other.fingerprint.iter()) {
if a == b {
score += 1;
}
}
score
}
pub fn similarity_score_ratio(self, other: Self) -> f32 {
let score = self.similarity_score(other);
score as f32 / Self::MAX_SIMILARITY_SCORE as f32
}
}
pub fn fingerprint(data: &[u8]) -> Fingerprint {
cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
use crate::raw::x86::*;
if std::is_x86_feature_detected!("avx") && std::is_x86_feature_detected!("avx2") {
unsafe {fingerprint_avx2(data)}
} else if std::is_x86_feature_detected!("sse2") && std::is_x86_feature_detected!("sse4.1") {
unsafe {fingerprint_sse41(data)}
} else {
fingerprint_scalar(data)
}
} else {
fingeprint_scalar(data)
}
}
}
#[cfg(test)]
mod test_utils {
use rand::prelude::*;
use rand_chacha::*;
pub fn make_data(seed: u64) -> Vec<u8> {
let mut rand = ChaChaRng::seed_from_u64(seed);
let size = rand.gen_range(0, 32000);
let mut data = vec![0_u8; size];
rand.fill(&mut data[..]);
data
}
}