To improve the performance of np.roots
according to the cubic equation, I am trying to implement the Cardan (o) method :
def cardan(a,b,c,d):
Works well when the roots are real:
In [2]: P=poly1d([1,2,3],True) In [3]: roots(P) Out[3]: array([ 3., 2., 1.]) In [4]: cardan(*P) Out[4]: ((3+0j), (1+0j), (2+1.110e-16j))
But a crash in a difficult case:
In [8]: P=poly1d([1,-1j,1j],True) In [9]: P Out[9]: poly1d([ 1., -1., 1., -1.]) In [10]: roots(P) Out[10]: array([ 1.0000e+00+0.j, 7.771e-16+1.j, 7.771e-16-1.j]) In [11]: cardan(*P) Out[11]: ((1.366+0.211j),(5.551e-17+0.577j),(-0.366-0.788j))
I assume that the problem is estimating u
and v
roots of the cube. The theory says uv=-p/3
, but here uv=pJ/3
: (u,v)
not a good pair of roots.
What is the best way to get the right pair in all cases?
EDIT
After posting @Sally, I can pinpoint the problem. A good couple is not always (u,v)
, it can be (u,vJ)
or (uJ,v)
. So the question may be as follows:
- Is there an easy way to catch a good pair?
And final: at the moment, compiling this code with Numba
, it is 20 times faster than np.roots
.
- Is there a better algorithm for calculating the three roots of a cubic equation?