Skip to content

CliffordNumbers improvements - #36

Closed
AndersEdin wants to merge 20 commits into
brainandforce:mainfrom
AndersEdin:clifford-improvements
Closed

CliffordNumbers improvements#36
AndersEdin wants to merge 20 commits into
brainandforce:mainfrom
AndersEdin:clifford-improvements

Conversation

@AndersEdin

Copy link
Copy Markdown

Add math primitives, AD/GPU/SoA extensions, and performance fast paths

This branch consolidates the CliffordNumbers 0.2.0-dev work: a blade/versor structure API with general log/sqrt, parity-correct Pin-group support, three new package extensions (ChainRulesCore, StructArrays, Adapt), a benchmark suite with the performance fixes it motivated, and Julia 1.10 LTS support.

New features

  • Blade/versor structure API: isblade (Plücker relations, checked metric-free) and isversor (parity, scalar x x̃, grade preservation of the twisted conjugation); factor_blade (orthogonal 1-vector factors whose wedge reproduces the blade in any signature) and factor_versor (Cartan–Dieudonné reflection peeling, with exact resolution of null-displacement residuals); bivector_decomposition made a public function.
  • General log and sqrt on multivectors, on their principal branches: study numbers s + n with scalar (elliptic, hyperbolic, and parabolic closed forms, including odd-grade blades) and even multivectors with positive x x̃.
  • log and sqrt on rotors (EvenCliffordNumber): simple-bivector closed form plus invariant decomposition with Newton polish for dim ≥ 4; parity with Quaternions.jl on the VGA(3) rotor subalgebra.
  • Parity-correct odd-versor (Pin group) support: sandwich now uses the twisted conjugation for odd versors so a mirror acts as the proper reflection -u v u⁻¹ on every operand grade; mirror_peel gives the canonical normal form V = v · R of an odd versor; one of an odd carrier is the even identity of the same algebra.
  • det and tr of Clifford numbers.
  • metric_tuple: world-age-robust source of metric data for custom signatures.
  • ChainRulesCore extension for reverse-mode AD: rrules for the geometric product (exact Cayley-transpose pullback, correct in every signature), scalar *//, the four grade automorphisms, scalar_product, abs2, and +/-, plus a ProjectTo that projects cotangents onto the primal's grade structure.
  • StructArrays extension: structure-of-arrays layout for KVector and Z2CliffordNumber, giving each blade coefficient its own column.
  • Adapt extension and GPU enablement: scalar-type mapping across the inner NTuple, allocation-free constructor validation, GPU-safe grade automorphisms and complement/dual family — verified end-to-end on an RTX 3070.
  • Julia 1.10 LTS support: compat lower bound raised to 1.10 across the package.

New tests

  • Theorem-based test suite (test/theorems.jl) checking algebraic identities.
  • Factorization and Pin-versor suites (test/factorization.jl, test/pin_versors.jl) covering the new structure API and odd-versor semantics.
  • Custom-signature suite (test/custom_signature.jl) exercising user-defined metrics end to end.
  • Extension test suites for ChainRulesCore (pullbacks validated against central finite differences), StructArrays, Adapt, and expanded Quaternions parity checks.
  • Columnar-broadcast regression tests locking in the guarantee that broadcast preserves SoA layout and allocates only the output.
  • Determinant/trace, BitIndices, and rotor-product coverage; expanded test/operations.jl.
  • Algebra-drift regression checks built into every benchmark workload via Julia-primitive references.

Fixed defect

  • exp of a mixed-signature bivector with abs2 ∈ (-1, 0) threw; the Taylor-scaling is now clamped.
  • On Julia 1.10, dimension of a plain Signature returned Int8, sending binomial down the Float64 gamma-function fallback — nblades of a KVector in a custom-signature algebra returned a Float64 and broke construction. It now returns a full-width Int.

Performance improvements

  • left_complement/right_complement are now @generated with all coefficient positions and signs baked at compile time, replacing the runtime indexing path that made the regressive product (join) lag.
  • Validation-free inv for EvenCliffordNumber over VGA(2) (ℂ) and VGA(3) (ℍ) via a closed-form versor inverse, plus closed-form abs2 for those positive-definite even subalgebras.
  • @generated closed-form * and ^2 for the 2-component spinor.
  • Closed-form reverse(::KVector).
  • New bench/ suite (harness, complex/quaternion/multivector workloads, recorded baselines) benchmarking against Julia primitives — this drove all of the fixes above and documents the remaining PGA(3) motor-inverse hot spot.

Documentation

  • New custom-signatures tutorial (docs/src/custom_signatures.md) on defining your own metric signature.
  • New extensions page (docs/src/extensions.md) covering Zygote/ChainRulesCore usage, StructArrays, and Adapt.
  • API pages extended with the determinant, factorization, and metrics additions.
  • Documentation build fixed: reattached a detached docstring, repaired broken cross-references, and included the previously orphaned determinant docstrings in an API page.
  • Bench README and recorded results consolidated into per-group files (complex/quaternion/multivector); docs and code comments tightened to house style.

This work was done with support from Claude Code.

AndersEdin and others added 20 commits June 19, 2026 10:56
Squashed final result of branch pr-benchsuite. Adds a CN-owned bench/
suite (harness, runbenchmarks, complex/quaternion/multivector workloads,
README) with recorded baseline runs (results.md, results_enlarged.md)
that drive the perf-fix work. Each workload carries a Julia-primitive
reference doubling as an algebra-drift regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Squashed final result of branch pr-spinorfastpaths. Validation-free inv
for EvenCliffordNumber{VGA(2)} (C) and {VGA(3)} (H) delegating to a
closed-form versor_inverse; closed-form abs2 for those positive-definite
even subalgebras; and a @generated closed-form * / ^2 for the
2-component spinor. The VGA(3) closed-form product was tried and dropped
(generic kernel already SIMD-vectorizes); see bench/results_spinor.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Squashed final result of branch pr-enlargedbenchfixes. left_complement /
right_complement on AbstractCliffordNumber are now @generated (a shared
_complement_expr helper bakes every output coefficient position and sign
at compile time), replacing the runtime to_index indexing path that made
the regressive product (join) lag. Also makes the complement / dual
family GPU-safe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Squashed final result of branch pr-gpuenablement. Converts constructor
asserts to constant-String messages (drops the GPU-fatal allocation while
keeping CPU validation), adds ext/CliffordNumbersAdaptExt.jl mapping the
scalar type across the inner NTuple, makes the grade automorphisms
GPU-safe via a @generated _sign_automorphism that bakes positions/signs
at compile time, and adds closed-form reverse(::KVector). Verified
end-to-end on an RTX 3070.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Squashed final result of branch pr-rotorprimitives. Adds
Base.log(::EvenCliffordNumber) (simple-bivector closed form plus a simple
invariant decomposition with Newton polish for dim >= 4),
Base.sqrt(::EvenCliffordNumber), and clamps the exp Taylor scaling so a
mixed-signature bivector with abs2 in (-1, 0) no longer throws. Parity
with Quaternions.jl sqrt/log on the VGA(3) rotor subalgebra.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t tests

Squashed final result of branch pr-arrayvectorization. Adds
ext/CliffordNumbersStructArraysExt.jl overriding staticschema / component
/ createinstance for KVector and Z2CliffordNumber so each blade
coefficient gets its own Vector{T} column (SoA). Stages 2/3 descoped
after measurement (default broadcast already preserves SoA and allocates
only the output); delivered instead as regression tests locking in the
columnar-broadcast guarantees.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Squashed final result of branch pr-autodiff. Adds
ext/CliffordNumbersChainRulesCoreExt.jl with rrules for the geometric
product (exact Cayley-transpose pullback, correct in every signature),
scalar */ /, the four grade automorphisms, scalar_product, abs2, and
+/-, plus a ProjectTo that projects cotangents back onto the primal's
grade structure. Pullbacks validated against central finite differences;
docs/src/extensions.md documents the Zygote usage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reorganize the recorded benchmark results into one file per benchmark group
and re-record them against the consolidated clifford-improvements branch
(BENCH_SECONDS=5, all algebra-drift checks pass):

- results_complex.md   <- bench_complex group + PR-SpinorFastPaths before/after
- results_quaternion.md <- bench_quaternion group + dropped Hamilton product note
- results_multivector.md <- kvector/even/odd/general/simd groups + what the PRs
                            fixed (fast reverse, generated complements/fast join,
                            fast rotor inv) + remaining PGA(3) motor inv hot spot

Removes the previous results.md / results_enlarged.md / results_spinor.md
(their content is folded into the three group files). Updates bench/README.md
with a Recorded results section and repoints the comment in
src/math/multiply.jl to results_quaternion.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the bench result files, README, and the branch-added code comments
terser and closer to the existing prose/comment style (e.g. docs/src/
performance.md): drop the editorial register, most bold, and em-dash asides;
keep the tables and the essential "why".

- bench/results_{complex,quaternion,multivector}.md, bench/README.md: terser prose
- src/math/{duals,inverse,logarithm}.jl, ext/CliffordNumbers{StructArrays,Adapt,
  ChainRulesCore}Ext.jl, bench/harness.jl, docs/src/extensions.md: trim wordy
  comment/docstring blocks

Comment/docstring/markdown only; package loads and all changed files parse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Describe in docs how to create a custom signature when using CliffordNumbers package.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The check_element_count docstring was detached from its function by an
intervening comment; the metric-signature docstrings referenced the
tutorial page with quotes that break the reference; and the determinant
docstrings were never included in an API page, breaking the reference in
the custom-signature tutorial.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New predicates isblade (Plücker relations, checked metric-free in a
Euclidean reinterpretation of the coefficients) and isversor (parity,
scalar x x~, and grade preservation of the twisted conjugation).

New factorizations: factor_blade projects and orthogonalizes the basis
vectors of the dominant basis blade so the wedge of the factors
reproduces the blade in any signature, and factor_versor peels
reflections off the twisted conjugation (Cartan-Dieudonne), with the
null-displacement residual sigma(1 + N) resolved exactly through the
mirror pair of its nilpotent bivector.

The invariant decomposition of a bivector into commuting simple planes
is now a public function, bivector_decomposition. The rotor logarithm
shares its kernel, replacing the separate isoclinic branch: repeated
plane squares are split by probing an invariant plane and the general
per-plane angle recovery covers equal angles.

log and sqrt now cover general multivectors on their principal
branches: study numbers s + n with n^2 a scalar (elliptic, hyperbolic,
and parabolic planar closed forms, including odd-grade blades) and even
multivectors with a positive scalar x x~, which peel their magnitude
and reduce to the rotor forms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Raise the compat lower bound to 1.10 everywhere (1.9 support was
already nominal: package extensions are the only 1.9 feature in use).

dimension of a plain Signature now returns a full-width Int instead of
an Int8: on 1.10, binomial with a narrow integer falls back to the
Float64 gamma-function method, which made nblades of a KVector in a
custom-signature algebra return a Float64 and broke construction.

The zero-allocation test gates assert what the current stable compiler
constant-folds; the 1.10 compiler misses some of those folds, so the
gates now only assert on 1.12 and later. Correctness and inference
tests are unchanged and run on every version.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sandwich is the documented grade-preserving conjugation by a versor:
V x V~/(V V~) for even V and the twisted form with the grade involution
of the operand for odd V, so that a mirror acts as the proper
reflection -u v u^-1 and the action extends to every operand grade as
an outermorphism. The parity is read off the type where structural and
off the coefficients for dense carriers.

mirror_peel is the normal form V = v * R of an odd versor: an
invertible 1-vector times an even versor. The odd component of the Pin
group is not connected to the identity, so this normal form, not a
logarithm, is the canonical representation. The peel is deterministic:
the grade-1 part when invertible, else the heaviest-weighted non-null
basis vector in the versor's support.

one of an OddCliffordNumber type is now the even identity of the same
algebra: an odd carrier cannot store the scalar identity, and the
parity-closure law (odd*odd = even, odd*even = odd) puts the identity
in the even subalgebra. oneunit still throws, as conversion of the
identity to an odd carrier is inexact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@brainandforce

brainandforce commented Jul 3, 2026

Copy link
Copy Markdown
Owner

I greatly appreciate your interest, but I cannot merge this PR for a few reasons.

First of all, this is far too much code for me to review at once. If you can re-file this as multiple PRs corresponding to each feature or fix, then I can work on them much more effectively. I haven't worked on this codebase actively in a while, so I'd need to get up to speed with my own work again, admittedly.

Second, I will have to manually review the code here. In my experience, LLMs do not have adequate coverage of geometric algebra, and often get important details incorrect. This is in part due to the lack of standardized conventions, or conventions that deliberately break from commonly used language in the study of Clifford algebras (e.g. what is a "spinor" in this context?), and as much as possible I would like to avoid bogging down the code and documentation in the traditional approach to Clifford algebras or contradictory conventions. The code in this repo is intentionally written to facilitate study for people who are not familiar with geometric algebra or numerical approaches to it.

Third, this is an MIT licensed library, and there are GPL licensed libraries that cover Clifford algebras (among other things) written in Julia. I am concerned about code generated by an LLM reproducing code from one of these GPL libraries, which could lead to a copyright violation.

If you wish to continue this work/file this as separate PRs, my preference for order of operations is:

  • Any bug fixes that apply to the main branch's current state, including documentation issues
  • Increased test coverage
  • Performance improvements and benchmarks (though keep numerical stability in mind!)
  • New features:
    • log/sqrt implementations
    • Versor/blade tools
    • Autodiff support (ChainRulesCore extension). Don't worry about forward mode AD yet, because I'd like to try a different approach to this that exploits the fact that the dual numbers are a Clifford algebra.
    • sandwich, but if it is either more efficient or more numerically stable than a simple - a' * x * a
    • Changes to enable/improve GPU support

I hope this doesn't dissuade you from contributing - again, I do appreciate the interest. I see this is your first PR, so I figure learning some of the conventions about code contribution will come with time (it's something I'm still learning myself!)

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