QUATERNION(3)
π QUATERNION(3) β bestie's guide to quaternion math
okay so first things first: this is the QUATERNION(3) page from the Library Functions Manual, and it's literally all about quaternion arithmetic. it's giving "math but make it 3D rotation" and honestly? iconic. let's get into it π¦
β¨ NAME β¨
so the whole squad here is qtom, mtoq, qadd, qsub, qneg, qmul, qdiv, qunit, qinv, qlen, slerp, qmid, and qsqrt β and collectively they're the Quaternion arithmetic department. every single one of them is in this page, no crumbs left behind π
πΈ SYNOPSIS πΈ
grab your headers first, bestie:
#include <draw.h>
#include <geometry.h>
and here's the full roster of function signatures β copy-paste ready, no cap:
Quaternion qadd(Quaternion q, Quaternion r)
Quaternion qsub(Quaternion q, Quaternion r)
Quaternion qneg(Quaternion q)
Quaternion qmul(Quaternion q, Quaternion r)
Quaternion qdiv(Quaternion q, Quaternion r)
Quaternion qinv(Quaternion q)
double qlen(Quaternion p)
Quaternion qunit(Quaternion q)
void qtom(Matrix m, Quaternion q)
Quaternion mtoq(Matrix mat)
Quaternion slerp(Quaternion q, Quaternion r, double a)
Quaternion qmid(Quaternion q, Quaternion r)
Quaternion qsqrt(Quaternion q)
like, look at all of them. the whole family showed up π
β¨ DESCRIPTION β¨
π§ the lore (aka what even IS a quaternion)
okay so. the Quaternions are a non-commutative extension field of the Real numbers, and they were designed to do for rotations in 3-space what the complex numbers do for rotations in 2-space. literally the glow-up of complex numbers, we love to see it π
a quaternion has a real component r and an imaginary vector component v=(i,j,k). they add componentwise, and they multiply according to this rule:
(r,v)(s,w)=(rs-v.w, rw+vs+vΓw)
where . and Γ are the ordinary vector dot and cross products. and the multiplicative inverse of a non-zero quaternion (r,v) is:
(r,-v)/(r2-v.v)
β οΈ note the "non-zero" bestie β that inverse only exists when it exists. don't come for me, that's just how it is π
π«Ά the struct (so you know what you're holding)
the following routines do arithmetic on quaternions, represented as:
typedef struct Quaternion Quaternion;
struct Quaternion{
double r, i, j, k;
};
four doubles. that's it. that's the whole vibe. r, i, j, k, and honestly the way these four little fields run the entire 3D rotation economy is giving main character energy β
π the routine rundown
qaddβ Add two quaternions.qsubβ Subtract two quaternions.qnegβ Negate a quaternion.qmulβ Multiply two quaternions.qdivβ Divide two quaternions.qinvβ Return the multiplicative inverse of a quaternion.qlenβ Returnsqrt(q.r*q.r+q.i*q.i+q.j*q.j+q.k*q.k), the length of a quaternion.qunitβ Return a unit quaternion (length=1) with components proportional toq's.
like, clean. simple. each one does exactly one thing and does it well. periodt π
π¦ rotations, the actual reason you're here
so a rotation by angle ΞΈ about axis A (where A is a unit vector) can be represented by the unit quaternion:
q=(cos ΞΈ/2, Asin ΞΈ/2)
and here's the iconic twist: the same rotation is represented by βq. also, a rotation by βΞΈ about βA is the same as a rotation by ΞΈ about A. double coverage, no notes π
the quaternion q transforms points by:
(0,x',y',z') = q-1(0,x,y,z)q
and quaternion multiplication composes rotations β stack 'em, chain 'em, they just work β¨
the orientation of an object in 3-space can be represented by a quaternion giving its rotation relative to some standard orientation. that's the whole concept, and honestly it ate.
π the routines that operate on rotations / orientations (as unit quaternions)
mtoqβ Convert a rotation matrix (seematrix(3)) to a unit quaternion.qtomβ Convert a unit quaternion to a rotation matrix.slerpβ Spherical lerp. Interpolate between two orientations. The rotation that carriesqtorisq-1r, soslerp(q, r, t)isq(q-1r)t.qmidβslerp(q, r, .5)qsqrtβ The square root ofq. This is just a rotation about the same axis by half the angle.
ngl slerp is the moment. spherical interpolation? the way it just smoothly carries you from one orientation to another? obsessed π
π SOURCE π
/src/libgeometry/quaternion.c
that's where she lives, if you ever wanna go visit π
π₯ SEE ALSO π₯
go read those too, bestie, they're friends of the family π«Ά
π BUGS π
okay so this is important and kind of a jump-scare: to avoid name conflicts with NetBSD, qdiv is a preprocessor macro defined as p9qdiv; see intro(3).
like β yes, the function is called qdiv, but under the hood the preprocessor is out here living a double life as p9qdiv. don't get caught lacking by that one π
β¨ that's the whole page, you're officially quaternion-literate β¨
this was the QUATERNION(3) page, from the Library Functions Manual, sourced from /src/libgeometry/quaternion.c β and yeah, no date stamped on this one, she's timeless π
see you in the next man page, bestie π
π¦ where this page comes from
- alpine 3.24: plan9port-doc 0_git20260208-r0 Β· LPL-1.02
- arch rolling: plan9port 20261021-2 Β· custom
- nixos 26.05: plan9port 0-unstable-2025-11-10
- nixos 26.05: plan9port-wayland 0-unstable-2025-11-26
- nixpkgs unstable: plan9port 0-unstable-2025-11-10
- nixpkgs unstable: plan9port-wayland 0-unstable-2025-11-26
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms