quadrs 1.0.0

Experimental quad remeshing library and tools based on Instant Meshes
Documentation
//! Immutable deterministic RNG utilities plus compile-time string tags for domain separation.

use std::fmt;
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Rng(u64);

impl Rng {
    pub fn new(seed: u64) -> Self {
        Self(seed)
    }

    pub fn from_time() -> Self {
        Self(
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_nanos() as u64,
        )
    }

    pub fn mix(self, value: u64) -> Self {
        Self(hash64(self.0 ^ value.wrapping_mul(0x9e3779b97f4a7c15)))
    }

    pub fn next(self) -> f64 {
        (hash64(self.0) >> 11) as f64 / ((1u64 << 53) as f64)
    }

    pub(crate) fn value(self) -> u64 {
        self.0
    }
}

pub const fn tag(name: &str) -> u64 {
    let bytes = name.as_bytes();
    let mut hash = 0xcbf29ce484222325u64;
    let mut i = 0;
    while i < bytes.len() {
        hash ^= bytes[i] as u64;
        hash = hash.wrapping_mul(0x100000001b3);
        i += 1;
    }
    hash
}

impl fmt::Display for Rng {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

fn hash64(mut x: u64) -> u64 {
    x ^= x >> 33;
    x = x.wrapping_mul(0xff51afd7ed558ccd);
    x ^= x >> 33;
    x = x.wrapping_mul(0xc4ceb9fe1a85ec53);
    x ^ (x >> 33)
}