basic_quaternion

namespace nin {
    template <std::floating_point T>
    struct basic_quaternion;

    using quaternion = basic_quaternion<double>;
}

A Hamilton quaternion q = w + xi⃗ + yj⃗ + zk⃗ with full arithmetic support. All functions are constexpr and noexcept.

This page documents the bare mathematical quaternion type. For rotation and orientation types, see basic_rotation and basic_orientation_qty.

The type alias quaternion is provided for basic_quaternion<double>.

Data members

Member Type

w

T

x

T

y

T

z

T

Nested types

Type Definition

value_type

T

Member functions

(Constructor)

basic_quaternion()

(1)

basic_quaternion(basic_quaternion<> other)

(2)

basic_quaternion(T w, T x, T y, T z)

(3)

  • (1) Default constructor. All components are zero.

  • (2) Explicit converting constructor from a different floating-point type.

  • (3) Component constructor.

Example
import ninbot;
int main() {
    nin::quaternion q1;  // (w, x, y, z) = (0, 0, 0, 0)
}

conjugate

conjugates the quaternion in place

basic_quaternion & conjugate()

(1)

Negates the imaginary components (x, y, z).

Returns a reference to *this to allow chaining.

Example
import ninbot;
int main() {
    nin::quaternion q1c = nin::quaternion{1, 2, -3, -4}.conjugate();     // q1c = (1, -2, 3, 4)
}

normalize

normalises the quaternion in place

basic_quaternion<> & normalize()

(1)

Divides every component by norm(*this).

Returns a reference to *this to allow chaining.

Example
import ninbot;
int main() {
    nin::quaternion q1{1, 1, 1, 1};
    q1.normalize();     // q1 = (0.5, 0.5, 0.5, 0.5)
}

invert

inverts the quaternion in place

basic_quaternion<> & invert()

(1)

Conjugates and divides by the squared norm. Returns a reference to *this to allow chaining.

Example
import ninbot;
int main() {
    nin::quaternion q1 {0, 1, 0, 0};
    q1.invert();     // q1 = (0, -1, 0, 0)
}

operator+, operator- (unary)

unary plus and negation

basic_quaternion<T> operator+() const

(1)

basic_quaternion<T> operator-() const

(2)

  • (1) Returns a copy of the quaternion.

  • (2) Returns the negation of the quaternion (all components negated).

Example
import ninbot;
int main() {
    nin::quaternion q0 = {1, 2, 3, 4};
    nin::quaternion q1 = +q0;     // q1 = (1, 2, 3, 4)
    nin::quaternion q2 = -q0;     // q2 = (-1, -2, -3, -4)
}

operator+=, operator-=, operator*=, operator/=

compound assignment with another quaternion

basic_quaternion<> & operator+=(q_rhs)

(1)

basic_quaternion<> & operator-=(q_rhs)

(2)

basic_quaternion<> & operator*=(q_rhs)

(3)

basic_quaternion<> & operator/=(q_rhs)

(4)

  • (4) The result is equivalent to *this *= inv(q_rhs).

Example
import ninbot;
int main() {
    nin::quaternion q1 = {1, 2, 3,  4};
    nin::quaternion q2 = {2, 5, 8, 11};
    q1 += q2;     // q1 = (3, 7, 11, 15)
    q2 *= q2;     // q2 = (-206, 20, 32, 44)
}

operator+=, operator-=, operator*=, operator/= (scalar)

compound assignment with a scalar

basic_quaternion<> & operator+=(scalar)

(1)

basic_quaternion<> & operator-=(scalar)

(2)

basic_quaternion<> & operator*=(scalar)

(3)

basic_quaternion<> & operator/=(scalar)

(4)

  • (1) (2) Addition and subtraction for the real part only (component w).

  • (3) (4) Multiplication and division apply to every component of the quaternion.

Example
import ninbot;
int main() {
    nin::quaternion q = {1, 2, 3, 4};
    nin::quaternion q1 = q + 5;     // q1 = (6, 2, 3, 4)
    nin::quaternion q2 = q * 5;     // q2 = (5, 10, 15, 20)
}

Non-member functions

norm, norm2

norm and squared norm

T norm(q)

(1)

T norm2(q)

(2)

Example
import ninbot;
int main() {
    nin::quaternion q = {1, 1, 1, 1};
    double value1 = norm(q);      // value1 = 2
    double value2 = norm2(q);     // value2 = 4
}

conj, inv

non-member conjugate and inverse

basic_quaternion<> conj(basic_quaternion<> Q)

(1)

basic_quaternion<> inv(basic_quaternion<> Q)

(2)

Example
import ninbot;
int main() {
    nin::quaternion q = {1, 1, 0, 0};
    nin::quaternion qi = inv(q);
    nin::quaternion qc = conj(q);
}

operator+, operator-, operator*, operator/

Mixed quaternion-scalar binary arithmetic

basic_quaternion<> operator+(lhs, rhs)

(1)

basic_quaternion<> operator-(lhs, rhs)

(2)

basic_quaternion<> operator*(lhs, rhs)

(3)

basic_quaternion<> operator/(lhs, rhs)

(4)

  • (1) (2) (3) At least one of the parameters must be a quaternion. The other can be either a quaternion or a scalar.

  • (4) lhs must be a quaternion. rhs can be a quaternion, in which case the result is equivalent to lhs * inv(rhs), or a scalar.

Example
import ninbot;
int main() {
    nin::quaternion q1 = {1, 2, -1, -2};
    nin::quaternion q2 = {0, 1,  1,  1};
    nin::quaternion q3 = q1 - q2 + 10;                       // q3 = (11, 1, -2, -3)
    nin::quaternion q4 = q1 * q2 * conj(q1) / norm2(q1);     // q4 = (0, -1, -1.4, 0.2)
}

real, imag

real and imaginary projections

T & real(basic_quaternion<>& Q)

(1)

T real(basic_quaternion<> const& Q)

(2)

std::array<T,3> imag(basic_quaternion<> const& Q)

(3)

  • (1)-(2) Returns the scalar part w.

  • (3) Returns the vector part (x, y, z).

Example
import ninbot;
int main() {
    nin::quaternion q1;
    real(q1) = 1;
    auto [x, y, z] = imag(q1);
}

std::formatter<>

STL overload for the std::format and std::print families.

std::format("{:<format-spec>}", q)

(1)

Adds a specialization of std::formatter that formats the four quaternion components in the order w, x, y, z.

The <format-spec> syntax is

[<float-spec>] [ "|" <separator_w> [ "|" <separator_xyz>] ]

with the following rules:

  • <float-spec> — anything before the first | is forwarded verbatim to the STL formatter for floating points and applied to each of the four components.

  • Parentheses — when the format-spec contains no separator specifiers, the output is wrapped in parentheses.

  • Separators — the text after the first | specifies the separator placed between every component. If a second | is present, the text of the separators between w and x becomes <separator_w> and the text of the separators of the vector components becomes <separator_xyz>.

  • Escaping — inside the separator portion, \\| produces a literal | and \\\\ produces a literal backslash.

  • Defaults — when no | is given, <separator_w> defaults to "; " and <separator_xyz> to ", ".

Example
import ninbot;
#include <print>
int main() {
    nin::quaternion q = {1, 2, 3, 4};
    std::print("{}", q);               // "(1; 2, 3, 4)"
    std::print("{:.2f}", q);           // "(1.00; 2.00, 3.00, 4.00)"
    std::print("{:|, }", q);           // "1, 2, 3, 4"
    std::print("({:|\\| | })", q);     // "(1| 2 3 4)"
}