Skip to content

Take the inverse as the adjugate over the determinant - #2353

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
an-inverse-is-the-adjugate-over-the-determinant
Nov 3, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
an-inverse-is-the-adjugate-over-the-determinant

Conversation

@Rafael-SOWNet

@Rafael-SOWNet Rafael-SOWNet commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Closes #2346.

2.6.0 and master now
[[a, b], [c, d]].Inverse.Simplify() each entry … provided not a = 0 [[d / (a * d - b * c), -b / (a * d - b * c)], [-c / (a * d - b * c), a / (a * d - b * c)]]
[[cos(t), -sin(t)], [sin(t), cos(t)]].Inverse.Simplify() [[cos(t), sin(t) provided not cos(t) = 0], [-sin(t) provided not cos(t) = 0, cos(t)]] [[cos(t), sin(t)], [-sin(t), cos(t)]]
the rotation's inverse at t = π/2, evaluated NaN [[0, 1], [-1, 0]]

The inverse was GenericTensor's InvertMatrix. That takes the determinant by elimination, which divides by the first pivot and multiplies it back, so the determinant came to a * (d * a + -c * b) / a, and simplifying its a / a wrote the pivot's condition on every entry. As the issue suggests, the inverse is now the matrix's own Adjugate over its own Determinant, entry by entry. The determinant is a polynomial in the entries (Bareiss' fraction-free elimination, or Laplace), and the adjugate's entries are cofactors. Only the division by the determinant is left, and its condition is the inverse's own.

A matrix of numbers has the inverse it had: the existing inverse tests pass unchanged, and matrixcheck's A A^-1 = I and A adj(A) = det(A) I are clean on 1200 random matrices (seeds 14–16). The cost is the same, since GenericTensor's inversion also went through the adjugate. GenTensorGuard.InvertMatrix had no caller left and is removed.

Tests: AnInverseIsTheAdjugateOverTheDeterminantTest, 7 cases. 4 fail on master; the numeric, singular and adjugate-value cases pass on both. The full suite, AOT and the nine harnesses pass. There is a BREAKING-CHANGES entry, measured on 2.6.0.

🤖 Generated with Claude Code

The inverse was GenericTensor's, which takes the determinant by
elimination: it divides by the first pivot and multiplies it back, so the
determinant of [[a, b], [c, d]] came to a * (d * a + -c * b) / a, and
simplifying its a / a wrote "provided not a = 0" on every entry of the
inverse. The rotation's carried cos t != 0. Each inverse exists wherever
the determinant is not 0, a = 0 and t = pi/2 included, and at pi/2 the
rotation's is [[0, 1], [-1, 0]]. 2.6.0 does the same.

The inverse is the matrix's own Adjugate over its own Determinant, entry
by entry: the determinant is a polynomial in the entries, Bareiss' or
Laplace's, and the adjugate's entries are cofactors, so nothing divides
but the one division by the determinant, whose condition is the inverse's
own. A matrix of numbers has the inverse it had, and matrixcheck's
A A^-1 = I is clean on 1200 random matrices. GenTensorGuard's InvertMatrix
had no caller left and is removed.

Closes #2346

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rafael-SOWNet Rafael-SOWNet added this to the 2.7.0 milestone Nov 3, 2026
@Rafael-SOWNet Rafael-SOWNet moved this from Todo to In review in AngouriMath Nov 3, 2026
@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 86.78%. Comparing base (40dd98f) to head (1736e19).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...rces/AngouriMath/Core/Entity/Omni/Entity.Matrix.cs 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2353      +/-   ##
==========================================
- Coverage   86.79%   86.78%   -0.01%     
==========================================
  Files         312      312              
  Lines       68709    68727      +18     
  Branches    20006    20014       +8     
==========================================
+ Hits        59637    59647      +10     
- Misses       4904     4907       +3     
- Partials     4168     4173       +5     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.33% <75.00%> (-0.01%) ⬇️
fsharp 32.97% <ø> (ø)
interactive 40.72% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
Sources/AngouriMath/Functions/GenTensorGuard.cs 100.00% <ø> (ø)
...rces/AngouriMath/Core/Entity/Omni/Entity.Matrix.cs 84.89% <75.00%> (-0.17%) ⬇️

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Rafael-SOWNet
Rafael-SOWNet merged commit 5a665c6 into master Nov 3, 2026
47 of 53 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in AngouriMath Nov 3, 2026
@Rafael-SOWNet
Rafael-SOWNet deleted the an-inverse-is-the-adjugate-over-the-determinant branch November 3, 2026 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

The inverse of a symbolic matrix carries a condition from its elimination: [[a, b], [c, d]] needs a ≠ 0

1 participant