API Reference — tdm/Computations
mat<N, N, T> adjoint(const mat<N, N, T>& m)
Compute the adjugate (classical adjoint) of a square matrix — the transpose of its cofactor matrix.
When to use this
Use as a building block for matrix inversion via adj(M) / det(M). This function is in namespace tdm::impl and is an internal helper; use inverse directly for the full inversion operation.
Example
tdm::mat<2, 2, float> m = {{4, 3}, {3, 2}};
tdm::mat<2, 2, float> adj = tdm::impl::adjoint(m);
// adj == {{2, -3}, {-3, 4}}
Parameters
| Name | Type | Description |
|---|---|---|
m |
const mat<N, N, T>& |
required — square matrix |
Returns
mat<N, N, T> — the adjugate matrix. For a 1x1 matrix, returns mat<N,N,T>{1}.
quat<T> conjugate(const quat<T>& q)
Return the conjugate of a quaternion by negating its x, y, z components while keeping w unchanged.
When to use this
Use as a building block when computing the quaternion inverse for unit quaternions — for unit quaternions, the conjugate is equal to the inverse and is cheaper to compute. Use inverse instead when the quaternion may not be unit-length.
Example
tdm::quat<float> q = {0.0f, 0.707f, 0.0f, 0.707f}; // 90-degree rotation around Y
tdm::quat<float> qc = tdm::conjugate(q);
// qc == {0.0f, -0.707f, 0.0f, 0.707f}
// qc represents the inverse rotation (for unit quaternions)
Parameters
| Name | Type | Description |
|---|---|---|
q |
const quat<T>& |
required — quaternion to conjugate |
Returns
quat<T> — a new quaternion with {-q.x, -q.y, -q.z, q.w}.
vec3<T> cross(const vec3<T>& lhs, const vec3<T>& rhs)
Compute the cross product of two 3D vectors, returning a vector orthogonal to both.
When to use this
Use when you need a vector perpendicular to a plane defined by two direction vectors — for example, computing a surface normal from two edge vectors. Only valid for vec3; for dot products or higher-dimensional vectors, see dot.
Example
tdm::vec3<float> edge1 = {1.0f, 0.0f, 0.0f};
tdm::vec3<float> edge2 = {0.0f, 1.0f, 0.0f};
tdm::vec3<float> normal = tdm::cross(edge1, edge2);
// normal == {0.0f, 0.0f, 1.0f}
Parameters
| Name | Type | Description |
|---|---|---|
lhs |
const vec3<T>& |
required — left-hand 3D vector |
rhs |
const vec3<T>& |
required — right-hand 3D vector |
Returns
vec3<T> — a vector perpendicular to both lhs and rhs, with magnitude equal to |lhs| * |rhs| * sin(theta).
bool decompose(mat<N, N, T>& a, vec<N, dim_t>& permute)
Perform LU decomposition with partial pivoting on a square matrix in-place, returning false if the matrix is singular.
When to use this
Use as the first step before calling substitute to solve a linear system Ax = b. The LU form is cheaper to compute once and reuse for multiple right-hand sides than calling inverse repeatedly. This function is in namespace tdm::lu.
Watch out for
- Modifies
ain-place. The original matrix is destroyed and replaced by its LU factors. Pass a copy if you need to preserve the original. - Returns
falsewhen any row is all-zero (encountered during pivoting). Check the return value before callingsubstitute.
Example
tdm::mat<3, 3, float> a = {{2, 1, -1}, {-3, -1, 2}, {-2, 1, 2}};
tdm::vec<3, tdm::dim_t> permute;
if (tdm::lu::decompose(a, permute)) {
tdm::vec<3, float> b = {8.0f, -11.0f, -3.0f};
tdm::lu::substitute(a, permute, b);
// b now contains the solution x
}
Parameters
| Name | Type | Description |
|---|---|---|
a |
mat<N, N, T>& |
required — square matrix; overwritten in-place with LU factors |
permute |
vec<N, dim_t>& |
required — output permutation vector recording row swaps |
Returns
bool — true if decomposition succeeded; false if the matrix is singular (a zero row was encountered).
T determinant(const mat<N, N, T>& m)
Compute the scalar determinant of a square matrix to check invertibility or measure transformation scale.
When to use this
Use to test whether a matrix is invertible before calling inverse — a zero determinant means no inverse exists. Also useful for checking whether a transform preserves handedness (positive determinant) or reflects it (negative).
Example
tdm::mat<3, 3, float> m = {{2, 0, 0}, {0, 3, 0}, {0, 0, 4}};
float det = tdm::determinant(m);
// det == 24.0f (non-zero: matrix is invertible)
tdm::mat<3, 3, float> singular = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
float det2 = tdm::determinant(singular);
// det2 == 0.0f (matrix is singular)
Parameters
| Name | Type | Description |
|---|---|---|
m |
const mat<N, N, T>& |
required — square matrix of dimension N x N |
Returns
T — the scalar determinant. Zero indicates a singular (non-invertible) matrix.
T dot(const vec<L, T>& lhs, const vec<L, T>& rhs) / T dot(const quat<T>& q1, const quat<T>& q2)
Compute the dot product of two vectors or two quaternions.
When to use this
Use the vector overload to measure projection or check orthogonality between two vectors of the same dimension. Use the quaternion overload when computing the cosine of the angle between two orientations — for example, as a prerequisite inside slerp to determine interpolation direction.
Example
tdm::vec3<float> a = {1.0f, 0.0f, 0.0f};
tdm::vec3<float> b = {0.0f, 1.0f, 0.0f};
float result = tdm::dot(a, b);
// result == 0.0f (orthogonal vectors)
tdm::quat<float> q1 = {0.0f, 0.0f, 0.0f, 1.0f};
tdm::quat<float> q2 = {0.0f, 0.0f, 0.0f, 1.0f};
float cosAngle = tdm::dot(q1, q2);
// cosAngle == 1.0f (same orientation)
Parameters
| Name | Type | Description |
|---|---|---|
lhs / q1 |
const vec<L, T>& or const quat<T>& |
required — first operand |
rhs / q2 |
const vec<L, T>& or const quat<T>& |
required — second operand; must be same type and dimension as first |
Returns
T — scalar dot product. For unit vectors, equals the cosine of the angle between them.
quat<T> inverse(const quat<T>& q) / mat<N, N, T> inverse(const mat<N, N, T>& m)
Compute the inverse of a quaternion or a square matrix, returning a zero-initialized result for singular matrices.
When to use this
Use the quaternion overload to reverse an applied rotation — for example, to transform a vector from world space back to local space. Use the matrix overload when you need the exact matrix inverse; for unit quaternions, prefer conjugate which is equivalent but cheaper.
Watch out for
- The matrix overload checks whether the determinant is zero and returns a default-constructed (zero) matrix in that case. Always verify the result is non-zero before using it in a transform chain.
- The quaternion overload divides by
length2(). Passing a zero quaternion causes division by zero.
Example
// Quaternion inverse
tdm::quat<float> rotation = {0.0f, 0.707f, 0.0f, 0.707f};
tdm::quat<float> inv_rotation = tdm::inverse(rotation);
// Applying rotation then inv_rotation yields identity
// Matrix inverse
tdm::mat<3, 3, float> m = { /* non-singular 3x3 matrix */ };
tdm::mat<3, 3, float> m_inv = tdm::inverse(m);
if (m_inv != tdm::mat<3, 3, float>{}) {
// use m_inv
}
Parameters
| Name | Type | Description |
|---|---|---|
q |
const quat<T>& |
required — quaternion to invert |
m |
const mat<N, N, T>& |
required — square matrix to invert; must be non-singular |
Returns
quat<T> or mat<N, N, T> — the inverse. For the matrix overload, returns a zero-initialized matrix if the determinant is zero.
T length(const vec<L, T>& v) / T length(const quat<T>& q)
Compute the Euclidean length (magnitude) of a vector or quaternion.
When to use this
Use to measure the magnitude of a direction or displacement vector, or to verify that a quaternion is unit-length before using it as a rotation. Only available for floating-point element types; the SFINAE guard prevents instantiation with integer types.
Example
tdm::vec3<float> v = {3.0f, 4.0f, 0.0f};
float len = tdm::length(v);
// len == 5.0f
tdm::quat<double> q = {0.0, 0.0, 0.0, 1.0};
double qlen = tdm::length(q);
// qlen == 1.0 (unit quaternion)
Parameters
| Name | Type | Description |
|---|---|---|
v |
const vec<L, T>& |
required — vector; T must be a floating-point type |
q |
const quat<T>& |
required — quaternion; T must be a floating-point type |
Returns
T — the Euclidean norm: sqrt(sum of squared components).
Constraints
Tmust satisfystd::is_floating_point<T>. Instantiation with integer element types will not compile.
quat<T> lerp(const quat<T>& q1, const quat<T>& q2, T t)
Linearly interpolate between two quaternions using a weighted component blend.
When to use this
Use when speed and simplicity matter more than constant angular velocity — for example, blending nearby poses where arc distortion is negligible. Use slerp instead when you need smooth constant-speed rotation interpolation along the shortest arc.
Watch out for
- The result is not normalized. Call
normalizeon the output before using it as a rotation if unit length is required. - Does not take the shortest path automatically. If
dot(q1, q2) < 0, negate one quaternion before calling to avoid rotating the long way around.
Example
tdm::quat<float> start = {0.0f, 0.0f, 0.0f, 1.0f}; // identity
tdm::quat<float> end = {0.0f, 0.707f, 0.0f, 0.707f}; // 90 degrees around Y
tdm::quat<float> mid = tdm::normalize(tdm::lerp(start, end, 0.5f));
// mid is approximately halfway between the two orientations
Parameters
| Name | Type | Description |
|---|---|---|
q1 |
const quat<T>& |
required — start quaternion |
q2 |
const quat<T>& |
required — end quaternion |
t |
T |
required — interpolation factor; 0.0 returns q1, 1.0 returns q2 |
Returns
quat<T> — component-wise blended quaternion. Not guaranteed to be unit-length.
void minor(const mat<N, N, T>& input, dim_t dimensions, dim_t i, dim_t j, mat<N, N, T>& output)
Extract the submatrix formed by deleting row i and column j from a square matrix.
When to use this
Use as a building block for cofactor expansion when computing determinants or the adjugate matrix. This function is in namespace tdm::impl and is an internal helper; prefer determinant and adjoint for direct use.
Example
tdm::mat<3, 3, float> m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
tdm::mat<3, 3, float> sub;
tdm::impl::minor(m, 3, 0, 0, sub);
// sub contains the 2x2 submatrix with row 0 and col 0 deleted
Parameters
| Name | Type | Description |
|---|---|---|
input |
const mat<N, N, T>& |
required — source square matrix |
dimensions |
dim_t |
required — active size of the matrix (may be less than N for recursive calls) |
i |
dim_t |
required — row index to exclude |
j |
dim_t |
required — column index to exclude |
output |
mat<N, N, T>& |
required — output matrix; active region [0, dimensions-1) is overwritten |
Returns
Void — result is written to output.
negate(vec<L, T>) / negate(mat<R, C, T>) / negate(quat<T>)
Flip the sign of every component of a vector, matrix, or quaternion.
When to use this
Use when you need to reverse the direction of a vector or negate a quaternion (e.g., to represent the same rotation reached via the antipodal path). Note that negate(q) and q represent the same 3D rotation — choose based on which hemisphere you need for interpolation continuity.
Example
tdm::vec3<float> v = {1.0f, -2.0f, 3.0f};
tdm::vec3<float> neg_v = tdm::negate(v);
// neg_v == {-1.0f, 2.0f, -3.0f}
tdm::quat<float> q = {0.0f, 0.707f, 0.0f, 0.707f};
tdm::quat<float> neg_q = tdm::negate(q);
// neg_q represents the same rotation as q
Parameters
| Name | Type | Description |
|---|---|---|
v |
vec<L, T> |
required — vector to negate (passed by value) |
m |
mat<R, C, T> |
required — matrix to negate (passed by value) |
q |
quat<T> |
required — quaternion to negate (passed by value) |
Returns
The same type as the input — a new object with all components sign-flipped.
vec<L, T> normalize(vec<L, T> v) / quat<T> normalize(quat<T> q)
Scale a vector or quaternion to unit length.
When to use this
Use before passing a direction vector to operations that assume unit-length input — such as computing lighting normals or feeding orientations to slerp. Only available for floating-point element types.
Watch out for
- Normalizing a zero vector produces undefined behavior (division by zero). Check that the vector is non-zero before calling.
Example
tdm::vec3<float> dir = {3.0f, 0.0f, 4.0f};
tdm::vec3<float> unit = tdm::normalize(dir);
// unit == {0.6f, 0.0f, 0.8f} (length == 1.0f)
Parameters
| Name | Type | Description |
|---|---|---|
v |
vec<L, T> |
required — vector to normalize; T must be floating-point |
q |
quat<T> |
required — quaternion to normalize; T must be floating-point |
Returns
The same type as the input — a new object scaled to length 1.
Constraints
Tmust satisfystd::is_floating_point<T>. Integer element types will not compile.
quat<T> slerp(const quat<T>& q1, const quat<T>& q2, T t)
Smoothly interpolate between two quaternion orientations at constant angular velocity.
When to use this
Use for animation blending or camera interpolation where you need the rotation to proceed at constant speed without distortion through the midpoint. Use lerp instead when blending very close orientations where the difference is too small to matter — slerp automatically falls back to linear blending when cos(theta) is near 1, so there is no discontinuity at the boundary.
Watch out for
- Automatically negates
q2whendot(q1, q2) < 0to ensure the shortest-path arc is taken. This means the output quaternion may differ in sign fromq2even att = 1.0. - Falls back to linear interpolation when the quaternions are nearly parallel (
cos(theta) > 1 - epsilon). This prevents division by near-zero sine values.
Example
tdm::quat<float> start = {0.0f, 0.0f, 0.0f, 1.0f}; // identity rotation
tdm::quat<float> end = {0.0f, 1.0f, 0.0f, 0.0f}; // 180 degrees around Y
tdm::quat<float> mid = tdm::slerp(start, end, 0.5f);
// mid is exactly 90 degrees around Y, traveled at constant angular speed
Parameters
| Name | Type | Description |
|---|---|---|
q1 |
const quat<T>& |
required — start orientation |
q2 |
const quat<T>& |
required — end orientation |
t |
T |
required — interpolation factor in [0, 1]; 0.0 returns q1, 1.0 returns q2 |
Returns
quat<T> — unit quaternion interpolated along the great-circle arc from q1 to q2.
void substitute(const mat<N, N, T>& a, const vec<N, dim_t>& permute, vec<N, T>& b)
Solve a linear system Ax = b using forward and backward substitution on an LU-decomposed matrix.
When to use this
Call this after tdm::lu::decompose to solve for x in Ax = b. You can reuse the same decomposed matrix a and permute for multiple different right-hand sides b without re-decomposing. This function is in namespace tdm::lu.
Watch out for
- Modifies
bin-place. On return,bcontains the solution vectorx, not the original right-hand side. - Only safe to call after a successful
decomposecall (return valuetrue). Calling on a singular decomposition produces undefined results.
Example
tdm::mat<3, 3, float> a = {{2, 1, -1}, {-3, -1, 2}, {-2, 1, 2}};
tdm::vec<3, tdm::dim_t> permute;
if (tdm::lu::decompose(a, permute)) {
tdm::vec<3, float> b = {8.0f, -11.0f, -3.0f};
tdm::lu::substitute(a, permute, b);
// b now holds the solution: {2.0f, 3.0f, -1.0f}
}
Parameters
| Name | Type | Description |
|---|---|---|
a |
const mat<N, N, T>& |
required — LU-decomposed matrix from decompose |
permute |
const vec<N, dim_t>& |
required — permutation vector from decompose |
b |
vec<N, T>& |
required — right-hand side on input; solution vector on output |
Returns
Void — the solution is written back into b.
T trace(const mat<N, N, T>& m)
Sum the diagonal elements of a square matrix.
When to use this
Use to extract the sum of eigenvalues of a matrix, or as part of algorithms that derive rotation angle from a rotation matrix (the trace of a 3x3 rotation matrix equals 1 + 2*cos(theta)).
Example
tdm::mat<3, 3, float> m = {{1, 0, 0}, {0, 2, 0}, {0, 0, 3}};
float tr = tdm::trace(m);
// tr == 6.0f
Parameters
| Name | Type | Description |
|---|---|---|
m |
const mat<N, N, T>& |
required — square N x N matrix |
Returns
T — sum of m(0,0) + m(1,1) + ... + m(N-1,N-1).
mat<C, R, T> transpose(const mat<R, C, T>& m)
Produce the transpose of a matrix by swapping rows and columns.
When to use this
Use when converting between row-major and column-major conventions, or when you need the adjoint direction matrix for a normal transform (the inverse-transpose of the model matrix). For square orthogonal matrices, the transpose equals the inverse — prefer this over inverse in that case.
Example
tdm::mat<2, 3, float> m = {{1, 2, 3}, {4, 5, 6}};
tdm::mat<3, 2, float> t = tdm::transpose(m);
// t == {{1, 4}, {2, 5}, {3, 6}}
Parameters
| Name | Type | Description |
|---|---|---|
m |
const mat<R, C, T>& |
required — input matrix with R rows and C columns |
Returns
mat<C, R, T> — new matrix with dimensions swapped; element at [i][j] in the input appears at [j][i] in the output.