MAINT: Remove similar branches from linalg.lstsq#9986
Conversation
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
This is a bizarre interface, and resids already contains 0 in the m <= n case, which is a more meaningful way to say "no residual" than []. But we're stuck with it, because that's how it's documented.
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
In what makes no sense at all, this branch produces the same effect as the one that follows it.
b563394 to
d813f1a
Compare
d813f1a to
a311a8d
Compare
|
|
||
| rank = results['rank'] | ||
|
|
||
| st = s[:min(n, m)].astype(result_real_t, copy=True) |
There was a problem hiding this comment.
This slice was pointless, because len(s) == min(n,m)
mhvk
left a comment
There was a problem hiding this comment.
This all looks good. My comments are mostly nitpicks.
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
I'd just remove the (0,) - now it is just confusing and the note states what happens for wrong input.
There was a problem hiding this comment.
It may be confusing, but that's because the behavior is confusing too!
And it's not even for "wrong input" - just for cases when an exact match is possible. I could move the (0,) to the last item in the list.
There was a problem hiding this comment.
Yes, maybe having it as the last item is best, since it is not the most common output.
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
Not this PR, but when I looked at this before, I wondered what would be the point of .copy(); it is not like a view gets taken and this cannot be of much speed benefit for the whole routine.
There was a problem hiding this comment.
Yeah, the copy stuff here is weird.
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
I wish we had a sensible power or so, but to avoid a needless square root, one can do
sum(r_parts.real**2 + r_parts.imag**2, axis=-2)
There was a problem hiding this comment.
r_parts * r_parts.conj() is probably a little faster, and also removes the branching. I'd rather leave this untouched though for now, since that would probably change results by a ULP.
There was a problem hiding this comment.
It's not (at least on my machine), but fine to let this be.
There was a problem hiding this comment.
It's not faster, or it's not guilty of introducing the ULP error?
Seems to me that there must be some value for which abs(x)**2 != x * x.conj(). Of course, the x * x.conj() value is closer to the true result.
There was a problem hiding this comment.
I just meant that x*x.conj() is slower than x.real**2 + x.imag**2 (which makes sense, as the former does a few useless multiplications that cancel). I do agree that there must be values of abs(x)**2 that are slightly less correct, given the sqrt and square after calculating x.real**2+x.imag**2
Anyway, fine to not worry about it here!
There was a problem hiding this comment.
I've contemplated adding a ufunc for the squared absolute value, the main problem seems to be the name.
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
Why the copy=True here; s is created in this routine, so no need to copy, it would seem.
There was a problem hiding this comment.
I agree - kept only because it was there before.
numpy/linalg/linalg.py
Outdated
There was a problem hiding this comment.
x is a view, so I guess it makes sense to copy. Maybe note that? (Also, copy=True is the default.)
There was a problem hiding this comment.
The copy=Trues confuse me, since as you note, they're the default. In fact, before #9888 there was a reasonable amount of code devoted to passing that argument.
Maybe this is trying to deal with a subclass that has a different default for copy?
Comment seems reasonable here
There was a problem hiding this comment.
Yes, that's fine. If one were to design this from scratch, one would do the coercion only if an output array was given...
There was a problem hiding this comment.
Looking back, the copy=False arguments were introduced in #5909, and the =True is deliberate and for clarity.
There was a problem hiding this comment.
If one were to design this from scratch, one would do the coercion only if an output array was given
Or maybe just work with the dtype passed in, rather than always promoting to double before handing off to the ufunc.
There was a problem hiding this comment.
That works only if one also uses different LAPACK routines (which is fine, of course), and would be less precise. But seems more logical in any case; just a different rcond.
|
Do you want me to go through and remove the needless copies in another commit, or leave that for another PR? |
|
@eric-wieser - it is a bit up to you whether you want to bother. If you think you get to it anyway with the |
86489a4 to
69d5d6c
Compare
|
Nits addressed. |
This takes numpygh-5909 a little further.
69d5d6c to
e3a50a9
Compare
|
Looks all OK. Maybe squash the commits? |
numpy/linalg/linalg.py
Outdated
| b_out = bstar.T | ||
|
|
||
| # b_out contains both the solution and the components of the residuals | ||
| x = b_out[:n,:] |
There was a problem hiding this comment.
Actually, PEP8 shows a bunch of other whitespace violations in linalg.py, so we could probably use a style PR to clean those up at some point.
|
LGTM apart from PEP8 nit. |
|
I'll fix that nit here and put this in. Thanks Eric. |
Working towards being able to fix #8720.
This doesn't change any behavior, but does add comments pointing out the existing somewhat-questionable behaviour