-
-
Notifications
You must be signed in to change notification settings - Fork 11.3k
BUG: change poly() real output checking to test if all imaginary parts are zero #4073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
oh wait now it doesn't work for |
It might be better to have a |
That would be equivalent to Regardless, if the output is exactly real, or input are exact conjugates, it should automatically not use a complex type for output. |
Ok I changed it back to the conjugate then sort method, and added a bunch of tests. Does this look good? Is there a reason it's |
…ry parts Fixed in numpy/numpy#4073, but we can't depend on a specific numpy version, so copying it here, too.
if (len(pos_roots) == len(neg_roots) and | ||
NX.alltrue(neg_roots == pos_roots)): | ||
a = a.real.copy() | ||
pos_roots = NX.compress(roots.imag > 0, roots) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could just check np.all(roots.sort() == roots.conjugate().sort())
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, .sort()
is in-place sorting and doesn't return anything, so anything.sort() == anythingelse.sort()
is always true.
np.all(np.sort(roots) == np.sort(roots.conjugate()))
?
np.sort_complex()
just calls np.sort()
internally but always outputs a complex type? Not sure if it's necessary, but just kept what was in the original code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right about the sort method.
Both the polynomial and sort_complex code date back to 2002 with later refactoring, so I expect not using sort directly is just historical accident.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And since only complex types are checked, the return will be complex anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume checking the size first is to speed up rejections for huge arrays?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though I guess polynomials are always going to be short 1d arrays?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd guess that going much over 20 is going to be a problem in general. I've gone up to 60 equally spaced roots in the polynomial package, which does better than this, but the results can be sensitive to root placement.
You need to rebase on master, some changes were made to the type handling a while back. On a separate note regarding the actual object of this PR, wouldn't it make sense to detect the conjugate roots before multiplying? That way you could collapse every two conjugate roots into a strictly real second degree binomial and avoid roundoff errors creeping into the imaginary part of the result. |
@jaimefrio Yes, and for power series that is pretty easy to do, although the convolution here would need modification. For other polynomial basis it gets a bit more involved. |
Change to a deterministic test instead of using rand
Ok, I rebased it and fixed an import error. Should I definitely change to |
@endolith I think it would be cleaner. I don't think speed is of much importance here, but it might even be faster. |
Ok I changed it. |
@charris this seems about ready to merge. ignore the test failure, that's unrelated (couldn't download Cython) |
Actually instead of that long string of numbers in the test, it could just set the numpy random seed for determinism and go back to
|
also fixed some PEP8 issues
Was there anything else that needed to be done on this? |
Is there anything wrong with this change? |
No, LGTM ;) Thanks @endolith . |
Removed code defending against old Numpy: [1] was included in Numpy 1.12.0, and minimum Numpy now is 1.23.5. See [2] for context. [1] numpy/numpy#4073 [2] scipy#3085 (comment)
Removed code defending against old Numpy: [1] was included in Numpy 1.12.0, and minimum Numpy now is 1.23.5. See [2] for context. [1] numpy/numpy#4073 [2] scipy#3085 (comment)
…test for complex k, real p, z (#22213) Removed code defending against old Numpy: [1] was included in Numpy 1.12.0, and minimum Numpy now is 1.23.5. See [2] for context. [1] numpy/numpy#4073 [2] #3085 (comment)
Some arrays should produce real output but don't:
I think the check was meant to be
sort_complex(conjugate(...
rather thanconjugate(sort_complex(...
, which would work, but checking that the imaginary parts are exactly zero is equivalent and simpler anyway.