quat
Quaternion Algebra for NumPy
quat brings first-class quaternion support to NumPy. Scalar quaternions, vector/matrix/tensor collections, SVD, SLERP interpolation, QFFT signal processing, serialization — with a three-tier-einsum Hamilton kernel that picks the fastest strategy at every data size. All in pure Python, zero C extensions.
pip install quat-numpy
Why quat?
Most quaternion libraries stop at rotating 3D vectors. quat gives you the full toolbox:
| What | How |
|---|---|
| Scalar quaternions | Full algebra — +, *, /, exp, log, pow, Hamilton product |
| Collections | QuatVector (1D), QuatMatrix (2D), QuatTensor (3D) — broadcast-aware |
| Linear algebra | SVD, rank, condition number, pseudo-inverse, determinant — on quaternion matrices |
| Interpolation | SLERP (shortest arc on S³), squad cubic spline, batch SLERP |
| Signal processing | 1D/2D QFFT, quaternion convolution, FIR filter design |
| Random generation | Reproducible generators for all four types |
| Serialization | JSON + compact binary roundtrip for all types; SciPy Rotation interop |
| Performance | Three-tier Hamilton kernel (component-wise → einsum), ~20x faster SVD fast-path |
Quickstart
import numpy as np
from quat import Quaternion, QuatVector, QuatMatrix
from quat import slerp, squad, random_unit_quat
# ---- Construction -------------------------------------------------
q = Quaternion(1, 2, 3, 4) # a + bi + cj + dk
r = Quaternion(5.0) # pure real
u = Quaternion.from_axis_angle((0,0,1), np.pi/2) # 90 deg around z
e = Quaternion.from_euler((0.1, 0.2, 0.3)) # intrinsic ZYX
# ---- Hamilton product ---------------------------------------------
i, j, k = Quaternion(0,1,0,0), Quaternion(0,0,1,0), Quaternion(0,0,0,1)
print(i * j) # Quaternion(0, 0, 0, 1) — i*j = k
print(i * j * k) # Quaternion(-1, 0, 0, 0) — i² = j² = k² = ijk = -1
# ---- Algebra ------------------------------------------------------
q.conjugate() # Quaternion(1, -2, -3, -4)
q.norm() # Euclidean norm
q.inverse() * q # ≈ identity
q.exp() # quaternion exponential
q.log() # quaternion logarithm
# ---- 3D rotation --------------------------------------------------
u = Quaternion.from_axis_angle((0, 0, 1), np.pi / 2)
u.rotate_vector((1, 0, 0)) # ≈ (0, 1, 0) — 90° rotation
axis, angle = u.to_axis_angle() # roundtrip (axis, angle)
# ---- Smooth interpolation -----------------------------------------
a = Quaternion(1, 0, 0, 0)
b = Quaternion(0, 1, 0, 0)
mid = slerp(a, b, 0.5) # shortest arc on the 3-sphere
q0, q1, q2, q3 = [random_unit_quat() for _ in range(4)]
curve = squad(q0, q1, q2, q3, 0.75) # cubic spline (Shoemake 1987)
# ---- Collections --------------------------------------------------
v = QuatVector([
Quaternion(1,0,0,0), Quaternion(0,1,0,0), Quaternion(0,0,1,0)
])
v.real # array([1., 0., 0.])
v.data.shape # (3, 4)
A = QuatMatrix.eye(3)
B = QuatMatrix(np.random.randn(3, 4, 4))
C = A @ B # quaternion matrix multiply (A * B also works)
C.shape # (3, 4)
# ---- Linear algebra -----------------------------------------------
from quat.linalg import svd, pseudo_inverse, solve
U, s, Vh = svd(C)
A_pinv = pseudo_inverse(C)
x = solve(A_pinv, QuatVector(np.ones((3, 4))))
# ---- Signal processing --------------------------------------------
from quat.signal import qfft, qconv, lowpass
X = qfft(np.random.randn(256, 4)) # 1D quaternion FFT
k = lowpass(16, cutoff=0.2) # FIR lowpass filter
y = qconv(np.random.randn(128, 4), k._data) # quaternion convolution
# ---- Serialization ------------------------------------------------
s = q.to_json() # → '{"type":"Quaternion","data":[...]}'
b = q.to_bytes() # → compact binary
q2 = Quaternion.from_json(s)
q3 = Quaternion.from_bytes(b)
# ---- Basis constants ----------------------------------------------
from quat import _I, _J, _K, _R, _ZERO
print(_I * _J * _K) # -1 (Hamilton's fundamental identity)
API Reference
Quaternion — scalar quaternion
| category | methods |
|---|---|
| constructors | zero(), one_q(), from_axis_angle(), from_euler(), from_complex_matrix(), from_real_matrix_left() |
| components | .r, .i, .j, .k, .real, .imag, .components, .data |
| arithmetic | +, -, *, /, -q, @ |
| algebra | .conjugate(), .norm(), .normalize(), .inverse(), .exp(), .log(), .pow(t), .re_inner(q), .commutator(q) |
| rotation | .rotate_vector(v), .to_axis_angle(), .to_euler(seq='zyx') |
| validation | .isnan(), .isinf(), .isfinite(), .isclose(q) |
| serialization | .to_json(), .from_json(s), .to_bytes(), .from_bytes(b) |
| matrices | .to_complex_matrix(), .to_real_matrix_left(), .to_real_matrix_right() |
| conversion | float(q), int(q), complex(q), abs(q), np.asarray(q) |
QuatVector / QuatMatrix / QuatTensor
| QuatVector | QuatMatrix | QuatTensor | |
|---|---|---|---|
| ndim | 1D | 2D | 3D |
| shape | (n,) |
(m, n) |
(p, q, r) |
| create | zeros, ones |
zeros, eye |
zeros |
| access | .data, .real/.i/.j/.k |
.data, .real/.i/.j/.k, .row(i), .col(j) |
.data, .real/.i/.j/.k |
| ops | .inner(v), .norm() |
.norm(), .T, .H, .conjugate() |
.inner(T), .unfold(mode), .mode_n_product(A) |
Module overview
| module | exports |
|---|---|
quat.random |
random_quat, random_unit_quat, random_quat_vector, random_quat_matrix, random_quat_tensor |
quat.interpolate |
slerp, slerp_vector, squad |
quat.linalg |
svd, rank, condition_number, pseudo_inverse, trace, det, norm, solve |
quat.serialization |
to_json, from_json, to_bytes, from_bytes, to_scipy_rotation, from_scipy_rotation |
quat.signal |
qfft, iqfft, qfft2, iqfft2, qconv, qconv2, lowpass, highpass, bandpass, bandstop |
quat.optimized |
hamilton_einsum, quat_matmul, conjugate_batch, norm_squared_batch, normalize_batch |
Performance
The Hamilton product kernel uses a three-tier dispatch that selects the fastest strategy based on data size:
| size | kernel | strategy |
|---|---|---|
| ≤ 500 elements | _hamilton_component |
direct float arithmetic |
| 500 – 5000 | _hamilton_einsum_noopt |
einsum without contraction-path optimisation |
| > 5000 | _hamilton_einsum |
einsum with full optimisation |
SVD fast-path: rank(), condition_number(), and norm(A, 2) compute
only singular values via the complex (2×2) representation — ~20× faster
than the full 4m×4n real SVD.
Zero-copy interop: q.to_numpy(copy=False) returns the internal buffer
without copying. .to_complex_matrix() and .to_real_matrix_left() use
np.empty to skip zero-initialisation.
Install
pip install quat-numpy
Requires Python ≥ 3.9, NumPy ≥ 1.21. Optional scipy for
to_scipy_rotation / from_scipy_rotation.
For development:
git clone https://github.com/gealachlee/quat.git
cd quat
pip install -e .
pytest tests/
Metadata
Release files for quat-numpy 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| quat_numpy-0.2.0.tar.gz | 42.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| quat_numpy-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.3 kB
Release files / quat_numpy-0.2.0.tar.gz
| Download URL | quat_numpy-0.2.0.tar.gz |
|---|---|
| Size | 42.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6b4953581c052a93f96172dd59843e815706e9607fc0b69f3b28d110f70f1d23
|
|
BLAKE2b-256 checksum How to use checksums |
b76bec58885463c45bb5d5e7677576909feb732941a165f15325a5dfdc1bfb74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 29, 2026.
Transparency logRelease files / quat_numpy-0.2.0-py3-none-any.whl
| Download URL | quat_numpy-0.2.0-py3-none-any.whl |
|---|---|
| Size | 35.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4746f81a294a791c3a45ce351eec87de0a753f414dc1c1c3068b921fdd6cec32
|
|
BLAKE2b-256 checksum How to use checksums |
3f5af84e1db0d40f0756897c3a57e39cc0bb30be2ad950cf323a1fbd61b146b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 29, 2026.
Transparency log