2 equation -- methods to solve algebraic equations. 4 If you would like to solve an equation in the complex field and need 5 more precision, then you can import and use plugins.SETPRECISION. 8 from nzmath.plugins import SETPRECISION 11 Then, the following computations will be done in such precision, if 12 plugins.PRECISION_CHANGEABLE is true. 15 from __future__
import division
25 from nzmath.plugins import MATHMODULE
as math, CMATHMODULE
as cmath, \
26 FLOATTYPE
as Float, COMPLEXTYPE
as Complex
28 _log = logging.getLogger(
'nzmath.equation')
29 _log.setLevel(logging.DEBUG)
38 raise ZeroDivisionError(
"No Solution")
44 Return the solution of x[0] + x[1]*t = 0 (mod n). 45 x[0], x[1] and n must be positive integers. 48 return (-x[0] * arith1.inverse(x[1], n)) % n
49 except ZeroDivisionError:
50 raise ValueError(
"No Solution")
54 0 = x[0] + x[1]*t + x[2]*t**2 62 return ((-b + sqrtd)/(2*a), (-b - sqrtd)/(2*a))
67 f = x[0] + x[1]*t + x[2]*t**2 69 c, b, a = [_x % p
for _x
in x]
76 if (x[0] + x[1] + x[2]) & 1 == 0:
78 if len(solutions) == 1:
82 if arith1.legendre(d, p) == -1:
84 sqrtd = arith1.modsqrt(d, p)
85 a = arith1.inverse(2*a, p)
86 return [((-b+sqrtd)*a)%p, ((-b-sqrtd)*a)%p]
90 0 = x[0] + x[1]*t + x[2]*t**2 + x[3]*t**3 97 q = 2*(a**3)/27 - a*b/3 + c
98 w = (-1 + cmath.sqrt(-3)) / 2
99 W = (1, w, w.conjugate())
100 k = -q/2 + cmath.sqrt((q**2)/4 + (p**3)/27)
101 l = -q/2 - cmath.sqrt((q**2)/4 + (p**3)/27)
106 checker = [abs(3*m*n*z + p)
for z
in W]
107 n = n * W[checker.index(min(checker))]
111 sol.append(W[i]*m + W[-i]*n - a/3)
117 0 = x[0] + x[1]*t + x[2]*t**2 + x[3]*t**3 123 coeff.append((c * lc_inv).n)
125 for i
in bigrange.range(p):
126 if (i**3 + coeff[0]*i**2 + coeff[1]*i + coeff[2]) % p == 0:
131 X =
e2_Fp([coeff[1] + (coeff[0] + sol[0])*sol[0], coeff[0] + sol[0], 1], p)
138 Compute x s.t. 0 = f[0] + f[1] * x + ... + f[n] * x ** n 142 for i
in range(1, length):
145 for k
in range(repeat):
148 for i
in range(1, length):
149 coeff = coeff * l + f[-i]
150 dfcoeff += dfcoeff * l + df[-i]
151 coeff = coeff * l + f[0]
155 raise ValueError(
"There is not solution or Choose different initial")
157 l = l - coeff / dfcoeff
163 Return zeros of a polynomial given as a list. 165 if NewtonInitial != 1:
169 return _SimMethod(f, newtoninitial=ni, repeat=repeat)
172 def _SimMethod(g, initials=None, newtoninitial=None, repeat=250):
174 Return zeros of a polynomial given as a list. 176 - g is the list of the polynomial coefficient in ascending order. 177 - initial (optional) is a list of initial approximations of zeros. 178 - newtoninitial (optional) is an initial value for Newton method to 179 obtain an initial approximations of zeros if 'initial' is not given. 180 - repeat (optional) is the number of iteration. The default is 250. 190 f = uniutil.polynomial(enumerate(g), imaginary.theComplexField)
192 df = f.differentiate()
194 value_list = [f(z[i])
for i
in range(deg)]
195 for loop
in range(repeat):
196 sigma_list = [0] * deg
198 if not value_list[i]:
202 sigma += 1 / (z[i] - z[j])
203 for j
in range(i+1, deg):
204 sigma += 1 / (z[i] - z[j])
205 sigma_list[i] = sigma
208 if not value_list[i]:
210 ratio = value_list[i] / df(z[i])
211 z[i] -= ratio / (1 - ratio*sigma_list[i])
212 value_list[i] = f(z[i])
218 create initial values of equation given as a list g. 220 g = [float(c)
for c
in g[:]]
221 q = [-abs(c)
for c
in g[:-1]]
223 if newtoninitial
is None:
226 r =
Newton(q, newtoninitial)
229 center = -g[-2]/(deg*g[-1])
231 angular_step = cmath.exp(Complex(0, 1) * about_two_pi / deg)
235 z.append(center + angular_move)
236 angular_move *= angular_step
242 Return an upper bound of roots. 244 weight = len(filter(
None, g))
246 return max([pow(weight*abs(c/g[-1]), 1/len(g))
for c
in g])
250 Return a root over F_p of nonzero polynomial g. 252 If flag = False, return a root randomly 254 if isinstance(g, list):
255 if not isinstance(g[0], tuple):
256 g = zip(
range(len(g)), g)
258 g = uniutil.FinitePrimeFieldPolynomial(g, Fp)
259 h = uniutil.FinitePrimeFieldPolynomial({1:-1, p:1}, Fp)
264 g = g.shift_degree_to(deg_g)
269 return (-g[0]/g[1]).toInteger()
271 d = g[1]*g[1] - 4*g[0]
272 e = arith1.modsqrt(d.toInteger(), p)
273 return ((-g[1]-e)/(2*g[2])).toInteger()
275 x = uniutil.FinitePrimeFieldPolynomial({0:-1, (p-1)>>1:1}, Fp)
278 while deg_h == 0
or deg_h == deg_g:
279 b = uniutil.FinitePrimeFieldPolynomial({0:-a, 1:1}, Fp)
284 b = uniutil.FinitePrimeFieldPolynomial({0:a-1, 1:1}, Fp)
286 while deg_h == 0
or deg_h == deg_g:
287 a = bigrandom.randrange(p)
288 b = uniutil.FinitePrimeFieldPolynomial({0:-a, 1:1}, Fp)
292 b = uniutil.FinitePrimeFieldPolynomial({0:a, 1:1}, Fp)
298 Return roots over F_p of nonzero polynomial g. 301 if isinstance(g, list):
302 if not isinstance(g[0], tuple):
303 g = zip(
range(len(g)), g)
305 g = uniutil.FinitePrimeFieldPolynomial(g, Fp)
306 h = uniutil.FinitePrimeFieldPolynomial({1:-1, p:1}, Fp)
313 g = g.shift_degree_to(deg_g)
320 return [(-g[0]/g[1]).toInteger()]
323 e = arith1.modsqrt(d.toInteger(), p)
326 return [((g1 - e) / g2).toInteger(), ((g1 + e) / g2).toInteger()]
328 x = uniutil.FinitePrimeFieldPolynomial({0:-1, (p-1)>>1:1}, Fp)
330 while deg_h == 0
or deg_h == deg_g:
331 b = uniutil.FinitePrimeFieldPolynomial({0:-a, 1:1}, Fp)
336 b = uniutil.FinitePrimeFieldPolynomial({0:a-1, 1:1}, Fp)
339 t = g.exact_division(s)