Macaulay2 / Macaulay2/M2

inverse of a singular matrix over RR or CC returns the zero matrix instead of erroring

Open
#4,556 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Engine Linear Algebra
Dominant language
Macaulay2
Stars
435
Forks
297
Avg merge
4d 20h
Merged PRs (30d)
11

Description

> **Written by Claude** (Claude Opus 5, via Claude Code), not by @d-torrance, and filed under his account. He reviewed it and agrees it is a bug, but the investigation, the wording and the reading of the engine source below are the model's. Please weigh it accordingly, and treat the suggested fix as a starting point rather than a conclusion.

Over an inexact field, `inverse` on a square matrix of less than full rank returns a matrix of zeros instead of raising `matrix not invertible`.

```m2
i1 : inverse matrix {{1., 2.}, {2., 4.}}

o1 = 0

2 2
o1 : Matrix RR <-- RR
53 53

i2 : inverse matrix {{1_QQ, 2}, {2, 4}}
stdio:2:7:(3):[1]: error: matrix not invertible
```

Everything else that looks at the same matrix gets it right — only `inverse` reports success:

```m2
i3 : m = matrix{{1.,2.},{2.,4.}};

i4 : (rank m, det m)

o4 = (1, -0)

i5 : solve(m, id_(RR^2)) === null

o5 = true
```

`^-1` behaves the same, as does any rank deficit, and the wrong answer propagates rather than surfacing:

```m2
i6 : a = matrix{{1.,2.,3.},{2.,4.,6.},{1.,1.,1.}}; -- rank 2 of 3

i7 : a * inverse a

o7 = 0

3 3
o7 : Matrix RR <-- RR
53 53
```

Reproduced on 1.26.06 at `RR_53`, `CC_53` and `RR_200`, and on `CC` matrices whose singularity involves the imaginary parts. It is not a tolerance question: `matrix{{1.,2.},{2.,4.0000001}}` has determinant `1e-7` and inverts correctly, so exact rank deficiency is what trips it.

### Scope

Inexact fields only. `ZZ/5` and `ZZ/32003` raise `matrix not invertible`, through the `inverse` specializations in `dmat-lu-zzp-ffpack.hpp` and `dmat-lu-zzp-flint.hpp` that do return their invertibility result. `ZZ` and `QQ` raise it from the non-engine branch at `M2/Macaulay2/m2/matrix1.m2:629`.

### Cause

`matrix1.m2:626` sends every `InexactField` to `basicInverse` → `rawLinAlgInverse` → the generic `DMatLinAlg::inverse`, which ends:

https://github.com/Macaulay2/M2/blob/79c7ac4fc5d4de37a18aae03ac9eb8c0db1e3c7b/M2/Macaulay2/e/basic-mutable-matrices/dmat-lu.hpp#L529-L542

```cpp
solve(id, X);
return true;
```

`solve` returns `false` for an inconsistent system (`dmat-lu.hpp:379`) and that value is discarded. `rawLinAlgInverse` already checks for a null result and would raise `matrix not invertible` if it ever received one, so the fix appears to be `return solve(id, X);`.

### Relation to existing issues

This is the part of #2208 that was never fixed. That issue reported the same thing on `ZZ/5` and was closed by #2241 (a032f77d13), which changed element-level inversion in `ZZp.cpp`, `aring-zzp*.hpp`, `aring-gf-flint.hpp` and `ZZ.cpp` — the exact rings — and did not touch `dmat-lu.hpp`, so the generic path used by the inexact fields kept the hole.

Distinct from #4506, which is a non-square matrix over `ZZ` on the non-engine branch with no squareness check, and from #3738, which concerns `inverse` of a map of non-free modules.

Found while triaging `bugs/dan/1-CC-inverse` for #36, which asks that the removed `bugs/` directory be gone through. The bug file itself asks for LU via LAPACK over `RR` and `CC`, and that part works — this turned up in checking that it also fails correctly. The transcripts above are from an actual 1.26.06 session; the claim that the zeros are unintended rather than a deliberate convention for inexact fields is not verified — no commit, comment or test asserting either way was found.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the RR and CC examples from the issue, then read M2/Macaulay2/m2/matrix1.m2:626-629 and the generic inverse implementation in M2/Macaulay2/e/basic-mutable-matrices/dmat-lu.hpp:529-542, including solve near line 379. Confirm that singular inexact matrices raise “matrix not invertible” while nonsingular cases and the cited exact-field paths retain their behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.