#quaternions #operator-overloading #vector #math-expressions

no-std quaternion-wrapper

Operator overloading allows implementation similar to mathematical expressions

4 releases (2 breaking)

0.3.0 Sep 18, 2023
0.2.0 Jun 20, 2022
0.1.1 Jun 19, 2022
0.1.0 May 7, 2022

#598 in Math

27 downloads per month

MIT/Apache

43KB
466 lines

quaternion-wrapper

Latest version Documentation Minimum rustc License

This is a wrapper for the quaternion-core crate.

Provides quaternion operations and interconversion with several attitude representations.

Operator overloading allows implementation similar to mathematical expressions.

Usage

Add this to your Cargo.toml:

[dependencies]
quaternion-wrapper = "0.3"

For use in a no_std environment:

[dependencies.quaternion-wrapper]
version = "0.3"
default-features = false
features = ["libm"]

Operator Overloading

Operator overloading allows operations between QuaternionWrapper, Vector3Wrapper, and ScalarWrapper.

The supported operations are listed in the table below:

Left↓ / Right→ QuaternionWrapper Vector3Wrapper ScalarWrapper
QuaternionWrapper +, -, *, +=, -=, *= +, -, * +, -, *, /
Vector3Wrapper +, -, * +, -, *, +=, -= +, -, *, /
ScalarWrapper +, -, * +, -, * +, -, *, /, +=, -=, *=, /=

To prevent implementation errors by users, the operation with T (f32 or f64) is intentionally not implemented. That is, ScalarWrapper<f64> * QuaternionWrapper<f64> can be calculated, but f64 * QuaternionWrapper<f64> cannot.

Features

fma

When this feature is enabled, the mul_add method will be used internally as much as possible. That is, (s * a) + b will be expanded as s.mul_add(a, b) at compile time.

This crate uses the mul_add method mainly to improve calculation speed, but if the CPU does not support the FMA (Fused Multiply-Add) instruction or if the libm feature is enabled, then the calculation is performed by the software implementation. In this case, it may be rather slower than if the fma feature is not enabled.

libm

If you set default-features=false (do not import std), you must enable this feature.

In this case, mathematical functions (e.g. sin, cos, sqrt ...) are provided by libm crate.

norm-sqrt

By default, the a.norm() method is implemented in such a way that overflow and underflow are less likely to occur than with dot(a, a).sqrt(). However, if extremely large values are not input and underflow is not that much of a concern, dot(a, a).sqrt() is sufficient (and dot(a, a).sqrt() is faster than the default implementation in most cases).

Example

src/main.rs:

use quaternion_wrapper::{QuaternionWrapper, Vector3Wrapper};

const PI: f64 = std::f64::consts::PI;
const EPSILON: f64 = 1e-12;

fn main() {
    // Generates a quaternion representing the
    // rotation of π/2[rad] around the y-axis.
    let q = QuaternionWrapper::from_axis_angle([0.0, 1.0, 0.0], PI/2.0);

    // Point
    let v = Vector3Wrapper([2.0, 2.0, 0.0]);

    let result = (q * v * q.conj()).get_vector_part();
    //let result = q.point_rotation(v);  // <--- It could be written like this

    // Check if the calculation is correct.
    let true_val = Vector3Wrapper([0.0, 2.0, -2.0]);
    let diff: [f64; 3] = (true_val - result).unwrap();
    for val in diff {
        assert!(val.abs() < EPSILON);
    }
}

License

Licensed under either of Apache License, Version 2.0 or MIT License at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~180–300KB