pub fn slerp(self, mut other: Quaternion<S>, amount: S) -> Quaternion<S> {
        let mut dot = self.dot(other);
        let dot_threshold: S = cast(0.9995f64).unwrap();

        if dot < S::zero() {
            other = -other;
            dot = -dot;
        }

        // if quaternions are close together use `nlerp`
        if dot > dot_threshold {
            self.nlerp(other, amount)
        } else {
            // stay within the domain of acos()
            let robust_dot = dot.min(S::one()).max(-S::one());

            let theta = Rad::acos(robust_dot);

            let scale1 = Rad::sin(theta * (S::one() - amount));
            let scale2 = Rad::sin(theta * amount);

            (self * scale1 + other * scale2).normalize()
        }
    }
Spherical Linear Interpolation

Return the spherical linear interpolation between the quaternion and
`other`. Both quaternions should be normalized first.

This takes the shortest path, so if the quaternions have a negative
dot product, the interpolation will be between `self` and `-other`.

# Performance notes

The `acos` operation used in `slerp` is an expensive operation, so
unless your quaternions are far away from each other it's generally
more advisable to use `nlerp` when you know your rotations are going
to be small.

- [Understanding Slerp, Then Not Using It](http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
- [Arcsynthesis OpenGL tutorial](https://www.roiatalla.com/public/arcsynthesis/html/Positioning/Tut08%20Interpolation.html)
src/quaternion.rs