dualquat 0.1.3

Quaternion and Dual Quaternion math library for high-precision physics simulation
Documentation
use crate::{DualQuaternion, Quaternion, Vec3};

pub const FORWARD: Vec3 = Vec3::new(1.0, 0.0, 0.0);
pub const UP: Vec3 = Vec3::new(0.0, 0.0, 1.0);

use nanorand::{Rng, WyRand};

pub(crate) fn gen_rand(generator: Option<&mut WyRand>) -> f64 {
    let rng: &mut WyRand;
    let mut _holder: Option<WyRand> = None;
    match generator {
        Some(gen) => {
            rng = gen;
        }
        None => {
            _holder = Some(WyRand::new());
            rng = _holder.as_mut().unwrap();
        }
    }
    let sign = match rng.generate_range(1_u64..=2) {
        1 => -1.0,
        _ => 1.0,
    };
    let dividend: f64 = rng.generate_range(1_u64..=2) as f64;
    let divisor: f64 = rng.generate_range(1_u64..=2) as f64;
    return sign * (dividend / divisor);
}

pub(crate) fn gen_rand_mat() -> [f64; 16] {
    let mut rng = WyRand::new();
    let mut ret: [f64; 16] = [0.0; 16];
    for i in 0..16 {
        ret[i] = gen_rand(Some(&mut rng));
    }
    return ret;
}

pub(crate) fn gen_rand_vec() -> Vec3 {
    let mut rng = WyRand::new();
    Vec3::new(
        gen_rand(Some(&mut rng)),
        gen_rand(Some(&mut rng)),
        gen_rand(Some(&mut rng)),
    )
}

pub(crate) fn trans_mat(mat: &[f64; 16]) -> [f64; 16] {
    let mut ret: [f64; 16] = [0.0; 16];
    let mut k = 0;
    for i in 0..4 {
        for j in 0..4 {
            ret[k] = mat[j * 4 + i];
            k += 1
        }
    }
    return ret;
}

pub(crate) fn gen_rand_q() -> Quaternion {
    fn gen_rand(rng: &mut WyRand) -> f64 {
        let sign = match rng.generate_range(1_u64..=2) {
            1 => -1.0,
            _ => 1.0,
        };
        let dividend: f64 = rng.generate_range(1_u64..=2) as f64;
        let divisor: f64 = rng.generate_range(1_u64..=2) as f64;
        return sign * dividend / divisor;
    }
    let mut rng = WyRand::new();
    let ret = Quaternion {
        scalar: gen_rand(&mut rng),
        vector: Vec3::new(gen_rand(&mut rng), gen_rand(&mut rng), gen_rand(&mut rng)),
    };

    #[cfg(unused)]
    match class {
        Some(Class::Vector) => {
            ret.scalar = 0.0;
        }
        Some(Class::Unit) => ret = ret.normalized(),
        _ => (),
    };
    return ret;
}

pub(crate) enum Class {
    Unit,
}

pub(crate) fn gen_rand_dq(class: Option<Class>) -> DualQuaternion {
    fn gen_rand(rng: &mut WyRand) -> f64 {
        let sign = match rng.generate_range(1_u64..=2) {
            1 => -1.0,
            _ => 1.0,
        };
        let dividend: f64 = rng.generate_range(1_u64..=2) as f64;
        let divisor: f64 = rng.generate_range(1_u64..=2) as f64;
        return sign * dividend / divisor;
    }
    let mut rng = WyRand::new();
    let ret = DualQuaternion {
        real: Quaternion {
            scalar: gen_rand(&mut rng),
            vector: Vec3::new(gen_rand(&mut rng), gen_rand(&mut rng), gen_rand(&mut rng)),
        },
        dual: Quaternion {
            scalar: gen_rand(&mut rng),
            vector: Vec3::new(gen_rand(&mut rng), gen_rand(&mut rng), gen_rand(&mut rng)),
        },
    };
    match class {
        #[cfg(unused)]
        Some(Class::Vector) => {
            ret.real.scalar = 0.0;
            ret.dual.scalar = 0.0;
        }
        Some(Class::Unit) => ret.normalized(),
        _ => ret,
    }
}

pub(crate) fn eps_equal(
    first: impl Iterator<Item = f64>,
    second: impl Iterator<Item = f64>,
    eps: f64,
) -> bool {
    first
        .zip(second)
        .filter(|(val1, val2)| (val1 - val2).abs() > eps)
        .count()
        == 0
}