dimforge / nalgebra

Linear algebra library for Rust.
https://nalgebra.org
Apache License 2.0
3.91k stars 466 forks source link

Unit Quaternion logarithm inconsistent with exp #1363

Open molni opened 6 months ago

molni commented 6 months ago

Unit<Quaternion>::ln and Quaternion::ln differ, which is unexpected. Quaternion::ln seems to be correct and it is consistent with Quaternion::exp, at least on data I encountered.

[dependencies]
nalgebra = "0.32.3"
    #[test]
    fn quaternion_2() {
        let p = UnitQuaternion::from_scaled_axis(Vector3::new(1., 2., 3.));
        let q = p.into_inner();
        assert!((q.ln().exp() - q).norm() < 1e-9); // OK - Quaternion<f64>::ln
        assert!((p.ln().exp() - q).norm() < 1e-9); // fails - Unit<Quaternion<f64>>::ln
    }
molni commented 6 months ago

After investigating more:

    #[test]
    fn quaternion_3() {
        let p = UnitQuaternion::from_scaled_axis(Vector3::new(0., 0., 1.));
        let q = p.into_inner();
        dbg!(q.ln());
        dbg!(p.ln());
        assert!((q.ln().exp() - q).norm() < 1e-9); // OK - Quaternion<f64>
        assert!((p.ln().exp() - q).norm() < 1e-9); // fails - Unit<Quaternion<f64>>
    }

outputs

[src/main.rs:559:9] q.ln() = [
    0.0,
    0.0,
    0.4999999999999999,
    0.0,
]
[src/main.rs:560:9] p.ln() = [
    0.0,
    0.0,
    1.0,
    0.0,
]

Seems like UnitQuaternion implemetation expects ln to return scaled_axis instead of returning half of it, contrary to correct statement in the doccomment of the function itself (UnitQuaternion::ln): "The vector part of the return value corresponds to the axis-angle representation (divided by 2.0) of this unit quaternion".