hcomplex 0.2.0

Lightweight complex and hypercomplex algebra library
Documentation
use rand::{prelude::*};
use rand_xorshift::XorShiftRng;
use approx::*;
use crate::{prelude::*, transform::*, Complex, Quaternion, random::Unit};


const SAMPLE_ATTEMPTS: usize = 256;


#[test]
fn chaining() {
    let mut rng = XorShiftRng::seed_from_u64(0xBEEF0);
    for _ in 0..SAMPLE_ATTEMPTS {
        let a: Moebius<Complex<f64>> = rng.sample(&Normalized);
        let b: Moebius<Complex<f64>> = rng.sample(&Normalized);
        let c: Quaternion<f64> = rng.sample(&StandardNormal);
        assert_abs_diff_eq!(
            a.chain(b).apply(c),
            a.apply(b.apply(c)),
            epsilon=1e-12,
        );
    }
}

#[test]
fn complex_derivation() {
    let mut rng = XorShiftRng::seed_from_u64(0xBEEF1);
    const EPS: f64 = 1e-8;

    for _ in 0..SAMPLE_ATTEMPTS {
        let a: Moebius<Complex<f64>> = rng.sample(&Normalized);
        let p: Complex<f64> = rng.sample(&StandardNormal);
        let v: Complex<f64> = rng.sample(&Unit);

        let deriv = a.deriv(p);
        let dabs = deriv.abs();
        assert_abs_diff_eq!(
            (a.apply(p + EPS * v) - a.apply(p)) / (EPS * v),
            deriv,
            epsilon=1e-4*dabs
        );
    }
}

#[test]
fn quaternion_directional_derivation() {
    let mut rng = XorShiftRng::seed_from_u64(0xBEEF2);
    const EPS: f64 = 1e-8;

    for _ in 0..SAMPLE_ATTEMPTS {
        let a: Moebius<Complex<f64>> = rng.sample(&Normalized);
        let p: Quaternion<f64> = rng.sample(&StandardNormal);
        let v: Quaternion<f64> = rng.sample(&Unit);

        let deriv = a.deriv_dir(p, v);
        let dabs = deriv.abs();
        assert_abs_diff_eq!(
            (a.apply(p + EPS * v) - a.apply(p)) / EPS,
            deriv,
            epsilon=1e-4*dabs
        );
    }
}