1 # -*- encoding: utf-8 -*-
4 # Copyright (C) 2005-2006 Michael Schindler <m-schindler@users.sourceforge.net>
5 # Copyright (C) 2006 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
9 # PyX is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # PyX is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with PyX; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 # import Numeric, LinearAlgebra
33 """sign of x, i.e. +1 or -1; returns 1 for x == 0"""
40 """Return the arc hyperbolic sine of x."""
41 return math
.log(x
+math
.sqrt(x
*x
+1))
45 """Return the arc hyperbolic cosine of x."""
46 return math
.log(x
+math
.sqrt(x
*x
-1))
49 def _realroots_quadratic(a1
, a0
):
50 """gives the real roots of x**2 + a1 * x + a0 = 0"""
55 return [0.5 * (-a1
+ SD
), 0.5 * (-a1
- SD
)]
58 def _realroots_cubic(a2
, a1
, a0
):
59 """gives the real roots of x**3 + a2 * x**2 + a1 * x + a0 = 0"""
60 # see http://mathworld.wolfram.com/CubicFormula.html for details
62 Q
= (3*a1
- a2
*a2
) / 9.0
63 R
= (9*a2
*a1
- 27*a0
- 2*a2
*a2
*a2
) / 54.0
66 if D
> 0: # one real and two complex roots
71 S
= -(-R
- SD
)**(1/3.0)
75 T
= -(SD
- R
)**(1/3.0)
76 return [S
+ T
- a2
/3.0]
78 if Q
== 0: # one real root (R==0)
80 else: # two real roots (R>0, Q<0)
82 return [2*S
- a2
/3.0, -S
- a2
/3.0]
83 else: # three real roots (Q<0)
91 theta
= math
.acos(R
/(SQ
**3))
92 return [2 * SQ
* math
.cos((theta
+ 2*2*i
*math
.pi
)/3.0) - a2
/3.0 for i
in range(3)]
95 def _realroots_quartic(a3
, a2
, a1
, a0
):
96 """gives the real roots of x**4 + a3 * x**3 + a2 * x**2 + a1 * x + a0 = 0"""
97 # see http://mathworld.wolfram.com/QuarticEquation.html for details
98 ys
= _realroots_cubic(-a2
, a1
*a3
- 4*a0
, 4*a0
*a2
- a1
*a1
- a0
*a3
*a3
)
99 ys
= [y
for y
in ys
if a3
*a3
-4*a2
+4*y
>= 0 and y
*y
-4*a0
>= 0]
104 return (_realroots_quadratic(0.5*(a3
+math
.sqrt(a3
*a3
-4*a2
+4*y1
)), 0.5*(y1
-math
.sqrt(y1
*y1
-4*a0
))) +
105 _realroots_quadratic(0.5*(a3
-math
.sqrt(a3
*a3
-4*a2
+4*y1
)), 0.5*(y1
+math
.sqrt(y1
*y1
-4*a0
))))
107 return (_realroots_quadratic(0.5*(a3
+math
.sqrt(a3
*a3
-4*a2
+4*y1
)), 0.5*(y1
+math
.sqrt(y1
*y1
-4*a0
))) +
108 _realroots_quadratic(0.5*(a3
-math
.sqrt(a3
*a3
-4*a2
+4*y1
)), 0.5*(y1
-math
.sqrt(y1
*y1
-4*a0
))))
111 def realpolyroots(*cs
):
112 """returns the roots of a polynom with given coefficients
114 polynomial with coefficients given in cs:
115 0 = \sum_i cs[i] * x^(len(cs)-i-1)
121 cs
= [f
*c
for c
in cs
[1:]]
122 except ArithmeticError:
123 return realpolyroots(*cs
[1:])
131 return _realroots_quadratic(*cs
)
133 return _realroots_cubic(*cs
)
135 return _realroots_quartic(*cs
)
137 raise RuntimeError("realpolyroots solver currently limited to polynoms up to the power of 4")
140 # def realpolyroots_eigenvalue(*cs):
141 # # as realpolyroots but using an equivalent eigenvalue problem
142 # # (this code is currently used for functional tests only)
143 # if not _has_numeric:
144 # raise RuntimeError("realpolyroots_eigenvalue depends on Numeric")
149 # cs = [f*c for c in cs[1:]]
150 # except ArithmeticError:
151 # return realpolyroots_eigenvalue(*cs[1:])
156 # a = Numeric.zeros((n, n), Numeric.Float)
157 # for i in range(n-1):
162 # for r in LinearAlgebra.eigenvalues(a):
163 # if type(r) == types.ComplexType: