Skip to content

Conversation

@stevengj
Copy link
Member

@stevengj stevengj commented Jun 30, 2025

This adds a missing checksquare to inv(::SVD), which I would argue is a bug from JuliaLang/julia#32126. If you want the pseudo-inverse, you should call pinv(::SVD) explicitly (via the method introduced in #1387) , not rely on magic undocumented behavior of inv.

Similarly for inv(::Factorization) (see below), which previously computed a left inverse for non-square ("tall") QR factorizations (see below).

(Hoisted from #1387.)

@stevengj
Copy link
Member Author

We could add a deprecation warning instead for the non-square case, but as far as I can tell it was undocumented.

@stevengj stevengj requested a review from dkarrasch June 30, 2025 15:22
@codecov
Copy link

codecov bot commented Jun 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.84%. Comparing base (db95a2a) to head (2640451).
⚠️ Report is 10 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1397   +/-   ##
=======================================
  Coverage   93.83%   93.84%           
=======================================
  Files          34       34           
  Lines       15823    15826    +3     
=======================================
+ Hits        14848    14852    +4     
+ Misses        975      974    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

Copy link
Member

@dkarrasch dkarrasch left a comment

Choose a reason for hiding this comment

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

I checked all existing inv(<:Union{AbstractMatrix,Factorization}) methods, and all of them check (sooner or later; in the LU case, it is implicit in the *Triangular constructors) for squareness. So, I agree, this is to be considered a bug, which we should backport to the LTS?

@stevengj
Copy link
Member Author

stevengj commented Jun 30, 2025

inv(qr(rand(5,3))) currently succeeds (it produces a left inverse), whereas inv(qr(rand(3,5))) gives an error.

The docstring for inv(M) says

Matrix inverse. Computes matrix N such that M * N = I

which (if anything) implies a right inverse for the non-square case. So it all seems rather inconsistent to me.

It really seems like non-square factorization inverses should require pinv. (Not that we should be encouraging people to compute explicit inverses in the first place.)

@stevengj
Copy link
Member Author

I don't think it's a good idea to backport. On the latest version, if you actually want the old behavior, you could just switch to calling pinv, but that isn't an option on previous versions.

@stevengj
Copy link
Member Author

@dkarrasch
Copy link
Member

inv(qr(rand(5,3))) currently succeeds (it produces a left inverse), whereas inv(qr(rand(3,5))) gives an error.

Ha, so I missed this...

@stevengj
Copy link
Member Author

stevengj commented Jul 2, 2025

There is a general fallback method inv(F::Factorization) = F \ I that is responsible for producing a left inverse for non-square factorizations that support it (currently QR).

This was added by @andreasnoack way back in JuliaLang/julia#5381, so maybe he can comment on this.

The behavior of inv doesn't seem clearly documented, at the very least (qr documents that QR objects support inv, but doesn't say what inv does in the non-square case, and the inv docs only talk about matrices, and only mention right inverses).

@andreasnoack
Copy link
Member

andreasnoack commented Jul 2, 2025

It has been a long time but after reading the PR text again, my best guess is that it wasn't intentional to allow non-square matrices in the fallback inv. The PR is about LU and while you can LU a non-square matrix, the use LU in this module has mostly been for square matrices.

@stevengj
Copy link
Member Author

stevengj commented Jul 2, 2025

Should we add a checksquare to the fallback inv as well?

On the one hand, non-square inv for QR has been around a long time. On the other hand, it's apparently undocumented, and it doesn't make a huge amount of sense.

@dkarrasch
Copy link
Member

I think this was just oversight, or unintended generality.

@stevengj stevengj changed the title restrict inv(::SVD) to square matrices restrict inv(::Factorization) to square matrices Jul 2, 2025
@stevengj
Copy link
Member Author

stevengj commented Jul 2, 2025

Okay, I've updated the PR to add a checksquare to inv(::Factorization) as well.

We'll see if any test failures result. Update: no failures, so apparently the non-square inv(::QR) case was untested.

@stevengj
Copy link
Member Author

stevengj commented Jul 4, 2025

Okay to squash and merge?

@andreasnoack andreasnoack merged commit 67c1103 into master Jul 4, 2025
4 checks passed
@andreasnoack andreasnoack deleted the svd_inv_square branch July 4, 2025 05:31
@ViralBShah ViralBShah added backport 1.10 Change should be backported to the 1.10 release backport 1.12 Change should be backported to release-1.12 labels Aug 13, 2025
ViralBShah added a commit that referenced this pull request Aug 19, 2025
@dkarrasch dkarrasch removed the backport 1.12 Change should be backported to release-1.12 label Aug 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport 1.10 Change should be backported to the 1.10 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants