Skip to content

[Docs] Add user-guide page for matrix decompositions and solvers#643

Merged
hughperkins merged 26 commits intomainfrom
hp/docs-linalg-decompositions
May 7, 2026
Merged

[Docs] Add user-guide page for matrix decompositions and solvers#643
hughperkins merged 26 commits intomainfrom
hp/docs-linalg-decompositions

Conversation

@hughperkins
Copy link
Copy Markdown
Collaborator

Summary

New user-guide page docs/source/user_guide/decompositions.md documenting the per-thread small-matrix decomposition / solver entry points — qd.svd, qd.sym_eig, qd.polar_decompose, qd.eig, qd.solve.

Companion to the in-flight subgroup (#639), block (#638), atomics (#640), grid (#641), and algorithms (#642) docs; this is one of a series of tier-by-tier user-guide pages.

This page is the linear-algebra-tier counterpart to matrix_vector.md, which already covers the element-wise / arithmetic side. It clarifies the split:

  • matrix_vector.md — closed-form ops (@, inverse ≤ 4×4, determinant, transpose, dot, cross, norm, outer_product).
  • decompositions.md (new) — numerical-algorithm ops (Jacobi sweeps, Gauss elimination with pivoting).

Includes:

  • Size / signature table for all five entry points (sizes 2 and 3 for everything except qd.eig which is 2-only).
  • Per-op semantics with caveats — SVD / polar sign convention not enforced, qd.sym_eig assumes the input is exactly symmetric (no symmetrize step), qd.solve triggers an assert on singular A, qd.eig packed-complex output layout.
  • Worked examples — ARAP closest-rotation, make_spd via sym_eig, per-thread 2×2 solve, polar shape-matching.
  • Performance / portability notes — size cap is the dominant constraint, compile-time consideration, f32 vs f64, fully cross-backend.
  • Honest "What's missing" section — Jacobi for N>3, Matrix.inverse size cap, atomic_cas, 3×3 general eig.

Adds decompositions to the Core-concepts toctree, next to matrix_vector.

Test plan

  • cd docs && make html builds without warnings.
  • Cross-link to matrix_vector.md resolves.
  • Visual check rendered page on RTD preview.

Made with Cursor

Documents the per-thread small-matrix decomposition / solver entry
points (qd.svd, qd.sym_eig, qd.polar_decompose, qd.eig, qd.solve).
Companion to matrix_vector.md, which covers element-wise / arithmetic
operations; this page covers the numerical-algorithm layer
(Jacobi sweeps, Gauss elimination, etc.) sitting on top of those.

Covers per-op semantics, the supported size set (2 / 3 only —
2 only for general qd.eig), the optional dt argument, sign-convention
caveats for SVD / polar (det(R) handling), and what is missing
(N>3 symmetric EVD, larger inverse, atomic_cas, 3×3 general eig).

Worked examples include closest-rotation extraction (ARAP), 3×3
make_spd via sym_eig + clamp, per-thread linear solve, and 2×2 polar
shape-matching.

Adds decompositions.md to the Core concepts toctree (next to
matrix_vector).
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5981faaea4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


- Sizes 2 and 3.
- The implementation asserts `A.n == A.m` and `A.m == b.n`.
- Singular `A` triggers an `assert` failure (`"Matrix is singular in linear solve."`); the assert is active by default and is your only signal of singularity.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't state singular-solve asserts run by default

In the default qd.init(..., debug=False) path, kernel assert statements are only checked when debug=True (see docs/source/user_guide/debug.md line 58), and the singularity checks inside _gauss_elimination_* are kernel asserts. This sentence tells users they can rely on qd.solve raising by default for singular inputs; in normal/default runs they may instead get divide-by-zero/NaN results with no signal, so this should be qualified as debug-mode behavior or paired with an explicit-singularity-check recommendation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

@hughperkins hughperkins marked this pull request as draft May 7, 2026 08:49
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

hughperkins added 21 commits May 7, 2026 09:47
@hughperkins hughperkins marked this pull request as ready for review May 7, 2026 17:10
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d0fa3ef1d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

U, S, V = qd.svd(A, dt=qd.f64)
R = U @ V.transpose()
if R.determinant() < 0.0:
V[:, 2] *= -1.0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Choose the smallest singular vector for the ARAP flip

For 3×3 inputs where Quadrants' SVD leaves the smallest singular value in a column other than column 2 (the page notes above that 3×3 singular values are not sorted), this handedness fix can flip a larger singular direction. That still makes det(R) > 0, but it is no longer the closest proper rotation used by ARAP; the example should either sort/select the minimum diagonal entry of S before flipping or avoid calling it the closest rotation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

@alanray-tech alanray-tech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok to merge

@hughperkins hughperkins merged commit 98611d3 into main May 7, 2026
48 of 49 checks passed
@hughperkins hughperkins deleted the hp/docs-linalg-decompositions branch May 7, 2026 17:58
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants