Skip to content

Quat.cpp / Quat.hpp optimizaiton #7

Description

@yingyue2030699

Some optimizable aspects of Quat.hpp and Quat.cpp are:

  • Make read-only operations const.
    Functions such as multiplication, norm calculation, conjugation, inversion, normalization, scaling, and rotation should not modify the source quaternion.

    Quat operator*(const Quat& rhs) const;
    double normSquared() const;
    Quat inverse() const;
  • Mark non-throwing operations noexcept.
    Pure arithmetic operations such as multiplication, scaling, conjugation, and squared-norm calculation can generally be noexcept. Do not mark inverse() or normalization noexcept if they throw for a zero quaternion.

  • Use [[nodiscard]] for returned mathematical results.
    This helps detect accidentally discarded results, such as:

    rotQuat.normalized(); // warning if result is ignored
    q1 * q2;              // warning if product is ignored
  • Separate copy-returning and in-place operations.
    Provide both forms where useful:

    [[nodiscard]] Quat scaled(double scalar) const noexcept;
    Quat& operator*=(double scalar) noexcept;
    
    [[nodiscard]] Quat normalized() const;
    Quat& normalize();

    This also prevents bugs such as calling unit() and discarding its returned quaternion.

  • Prefer conventional compound operators.
    Use operator*= rather than names such as scaled_overwrite():

    Quat& operator*=(double scalar) noexcept;
    Quat& operator*=(const Quat& rhs) noexcept;
  • Add output-parameter overloads only for proven hot paths.
    An API such as:

    void multiply(const Quat& rhs, Quat& output) const noexcept;

    may be useful when writing directly into preallocated storage, but it must correctly support or explicitly reject aliasing.

  • Avoid recomputing the inverse for batch rotations.
    The largest quaternion-specific optimization is to calculate the inverse once when one quaternion rotates many vectors:

    const Quat inverse = rotation.inverse();
    
    for (Vector& vec : vectors) {
        rotation.rotate(vec, inverse);
    }
  • Introduce a prepared rotation abstraction.
    Store a quaternion together with its precomputed inverse:

    const auto prepared = rotation.prepareRotation();
    
    for (Vector& vec : vectors) {
        prepared.rotate(vec);
    }

    This is safer than allowing callers to accidentally pass an inverse belonging to another quaternion.

  • Retain the existing one-off rotation interface.
    Keep a convenient overload that calculates the inverse internally:

    void rotate(Vector& vec) const;

    Add a faster overload for repeated applications:

    void rotate(Vector& vec, const Quat& inverse) const noexcept;
  • Handle zero quaternions explicitly.
    inverse() and normalization currently divide by zero when the norm is zero. Either throw an exception, assert, return an error indicator, or document NaN/infinity behavior.

  • Use std::sqrt and floating-point literals explicitly.

    return std::sqrt(normSquared());
    return conjugate().scaled(1.0 / squaredNorm);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions