def test_fmpq_poly(): Q = flint.fmpq_poly Z = flint.fmpz_poly assert Q() == Q([]) == Q([0]) == Q([0, 0]) assert Q() != Q([1]) assert Q([1]) == Q([1]) assert bool(Q()) == False assert bool(Q([1])) == True assert Q(Q([1, 2])) == Q([1, 2]) assert Q(Z([1, 2])) == Q([1, 2]) assert Q([1, 2]) + 3 == Q([4, 2]) assert 3 + Q([1, 2]) == Q([4, 2]) assert Q([1, 2]) - 3 == Q([-2, 2]) assert 3 - Q([1, 2]) == Q([2, -2]) assert -Q([1, 2]) == Q([-1, -2]) assert Q([flint.fmpq(1, 2), 1]) * 2 == Q([1, 2]) assert Q([1, 2]) == Z([1, 2]) assert Z([1, 2]) == Q([1, 2]) assert Q([1, 2]) != Z([3, 2]) assert Z([1, 2]) != Q([3, 2]) assert Q([1, 2, 3]) * Q([1, 2]) == Q([1, 4, 7, 6]) assert Q([1, 2, 3]) * Z([1, 2]) == Q([1, 4, 7, 6]) assert Q([1, 2, 3]) * 3 == Q([3, 6, 9]) assert 3 * Q([1, 2, 3]) == Q([3, 6, 9]) assert Q([1, 2, 3]) * flint.fmpq(2, 3) == (Q([1, 2, 3]) * 2) / 3 assert flint.fmpq(2, 3) * Q([1, 2, 3]) == (Q([1, 2, 3]) * 2) / 3 assert raises(lambda: Q([1, 2]) / Q([1, 2]), TypeError) assert Q([1, 2, 3]) / flint.fmpq(2, 3) == Q([1, 2, 3]) * flint.fmpq(3, 2) assert Q([1, 2, 3])**2 == Q([1, 2, 3]) * Q([1, 2, 3]) assert Q([1, 2, flint.fmpq(1, 2)]).coeffs() == [1, 2, flint.fmpq(1, 2)] assert Q().coeffs() == [] assert Q().degree() == -1 assert Q([1]).degree() == 0 assert Q([1, 2]).degree() == 1 assert Q().length() == 0 assert Q([1]).length() == 1 assert Q([1, 2]).length() == 2 assert (Q([1, 2, 3]) / 5).numer() == (Q([1, 2, 3]) / 5).p == Z([1, 2, 3]) assert (Q([1, 2, 3]) / 5).denom() == (Q([1, 2, 3]) / 5).q == 5 ctx.pretty = False assert repr(Q([15, 20, 10]) / 25) == "fmpq_poly([3, 4, 2], 5)" ctx.pretty = True assert str(Q([3, 4, 2], 5)) == "2/5*x^2 + 4/5*x + 3/5" a = Q([2, 2, 3], 4) assert a[2] == flint.fmpq(3, 4) a[2] = 4 assert a == Q([1, 1, 8], 2) p = Q([3, 4, 5], 7) assert p(2) == flint.fmpq(31, 7) assert p(flint.fmpq(2, 3)) == flint.fmpq(71, 63) assert p(Z([1, -1])) == Q([12, -14, 5], 7) assert p(flint.fmpq_poly([2, 3], 5)) == flint.fmpq_poly([27, 24, 9], 7 * 5)
def composed_op(P1, P2, operation): d1 = P1.degree() d2 = P2.degree() # print("compose", d1, d2) assert d1 >= 1 and d2 >= 1 cap = d1 * d2 + 1 if operation == operator.truediv: P2 = list(P2) if P2[0] == 0: raise ZeroDivisionError P2 = fmpq_poly(P2[::-1]) if operation == operator.sub: P2 = list(P2) for i in range(1, len(P2), 2): P2[i] = -P2[i] P2 = fmpq_poly(P2) orig_cap = ctx.cap try: ctx.cap = cap P1rev = list(P1)[::-1] P1drev = list(P1.derivative())[::-1] P2rev = list(P2)[::-1] P2drev = list(P2.derivative())[::-1] NP1 = fmpq_series(P1drev) / fmpq_series(P1rev) NP2 = fmpq_series(P2drev) / fmpq_series(P2rev) if operation in (operator.add, operator.sub): c = fmpq(1) a1, a2 = [NP1[0]], [NP2[0]] for j in range(1, cap): c *= j a1.append(NP1[j] / c) a2.append(NP2[j] / c) NP1E = fmpq_series(a1) NP2E = fmpq_series(a2) NP3E = NP1E * NP2E c = fmpq(-1) a3 = [fmpq(0)] for j in range(1, cap): a3.append(NP3E[j] * c) c *= j NP = fmpq_series(a3) Q = NP else: NP = fmpq_series([-NP1[j] * NP2[j] for j in range(1, cap)]) Q = NP.integral() Q = Q.exp() Q = fmpq_poly([Q[i] for i in range(cap)][::-1]) Q = Q.p return Q finally: # print("end compose") ctx.cap = orig_cap
def test_fmpq_poly(): Q = flint.fmpq_poly Z = flint.fmpz_poly assert Q() == Q([]) == Q([0]) == Q([0,0]) assert Q() != Q([1]) assert Q([1]) == Q([1]) assert bool(Q()) == False assert bool(Q([1])) == True assert Q(Q([1,2])) == Q([1,2]) assert Q(Z([1,2])) == Q([1,2]) assert Q([1,2]) + 3 == Q([4,2]) assert 3 + Q([1,2]) == Q([4,2]) assert Q([1,2]) - 3 == Q([-2,2]) assert 3 - Q([1,2]) == Q([2,-2]) assert -Q([1,2]) == Q([-1,-2]) assert Q([flint.fmpq(1,2),1]) * 2 == Q([1,2]) assert Q([1,2]) == Z([1,2]) assert Z([1,2]) == Q([1,2]) assert Q([1,2]) != Z([3,2]) assert Z([1,2]) != Q([3,2]) assert Q([1,2,3])*Q([1,2]) == Q([1,4,7,6]) assert Q([1,2,3])*Z([1,2]) == Q([1,4,7,6]) assert Q([1,2,3]) * 3 == Q([3,6,9]) assert 3 * Q([1,2,3]) == Q([3,6,9]) assert Q([1,2,3]) * flint.fmpq(2,3) == (Q([1,2,3]) * 2) / 3 assert flint.fmpq(2,3) * Q([1,2,3]) == (Q([1,2,3]) * 2) / 3 assert raises(lambda: Q([1,2]) / Q([1,2]), TypeError) assert Q([1,2,3]) / flint.fmpq(2,3) == Q([1,2,3]) * flint.fmpq(3,2) assert Q([1,2,3]) ** 2 == Q([1,2,3]) * Q([1,2,3]) assert Q([1,2,flint.fmpq(1,2)]).coeffs() == [1,2,flint.fmpq(1,2)] assert Q().coeffs() == [] assert Q().degree() == -1 assert Q([1]).degree() == 0 assert Q([1,2]).degree() == 1 assert Q().length() == 0 assert Q([1]).length() == 1 assert Q([1,2]).length() == 2 assert (Q([1,2,3]) / 5).numer() == (Q([1,2,3]) / 5).p == Z([1,2,3]) assert (Q([1,2,3]) / 5).denom() == (Q([1,2,3]) / 5).q == 5 assert repr(Q([15,20,10]) / 25) == "fmpq_poly([3, 4, 2], 5)" assert str(Q([3,4,2],5)) == "2/5*x^2 + 4/5*x + 3/5" a = Q([2,2,3],4) assert a[2] == flint.fmpq(3,4) a[2] = 4 assert a == Q([1,1,8],2) p = Q([3,4,5],7) assert p(2) == flint.fmpq(31,7) assert p(flint.fmpq(2,3)) == flint.fmpq(71,63) assert p(Z([1,-1])) == Q([12,-14,5],7) assert p(flint.fmpq_poly([2,3],5)) == flint.fmpq_poly([27,24,9],7*5)
def test_fmpz_poly(): Z = flint.fmpz_poly assert Z() == Z([]) assert Z() == Z([0]) assert Z() == Z([0, flint.fmpz(0), 0]) assert Z() == Z([0, 0, 0]) assert Z() != Z([1]) assert Z([1]) == Z([1]) assert Z([1]) == Z([flint.fmpz(1)]) assert Z(Z([1, 2])) == Z([1, 2]) for ztype in [int, long, flint.fmpz]: assert Z([1, 2, 3]) + ztype(5) == Z([6, 2, 3]) assert ztype(5) + Z([1, 2, 3]) == Z([6, 2, 3]) assert Z([1, 2, 3]) - ztype(5) == Z([-4, 2, 3]) assert ztype(5) - Z([1, 2, 3]) == Z([4, -2, -3]) assert Z([1, 2, 3]) * ztype(5) == Z([5, 10, 15]) assert ztype(5) * Z([1, 2, 3]) == Z([5, 10, 15]) assert Z([11, 6, 2]) // ztype(5) == Z([2, 1]) assert ztype(5) // Z([-2]) == Z([-3]) assert ztype(5) // Z([1, 2]) == 0 assert Z([11, 6, 2]) % ztype(5) == Z([1, 1, 2]) assert ztype(5) % Z([-2]) == Z([-1]) assert ztype(5) % Z([1, 2]) == 5 assert Z([1, 2, 3])**ztype(0) == 1 assert Z([1, 2, 3])**ztype(1) == Z([1, 2, 3]) assert Z([1, 2, 3])**ztype(2) == Z([1, 4, 10, 12, 9]) assert +Z([1, 2]) == Z([1, 2]) assert -Z([1, 2]) == Z([-1, -2]) assert raises(lambda: Z([1, 2, 3])**-1, (OverflowError, ValueError)) assert raises(lambda: Z([1, 2, 3])**Z([1, 2]), TypeError) assert raises(lambda: Z([1, 2]) // Z([]), ZeroDivisionError) assert raises(lambda: Z([]) // Z([]), ZeroDivisionError) assert raises(lambda: Z([1, 2]) % Z([]), ZeroDivisionError) assert raises(lambda: divmod(Z([1, 2]), Z([])), ZeroDivisionError) assert Z([]).degree() == -1 assert Z([]).length() == 0 p = Z([1, 2]) assert p.length() == 2 assert p.degree() == 1 assert p[0] == 1 assert p[1] == 2 assert p[2] == 0 assert p[-1] == 0 assert raises(lambda: p.__setitem__(-1, 1), ValueError) p[0] = 3 assert p[0] == 3 p[4] = 7 assert p.degree() == 4 assert p[4] == 7 assert p[3] == 0 p[4] = 0 assert p.degree() == 1 assert p.coeffs() == [3, 2] assert Z([]).coeffs() == [] assert bool(Z([])) == False assert bool(Z([1])) == True ctx.pretty = False assert repr(Z([1, 2])) == "fmpz_poly([1, 2])" ctx.pretty = True assert str(Z([1, 2])) == "2*x + 1" p = Z([3, 4, 5]) assert p(2) == 31 assert p(flint.fmpq(2, 3)) == flint.fmpq(71, 9) assert p(Z([1, -1])) == Z([12, -14, 5]) assert p(flint.fmpq_poly([2, 3], 5)) == flint.fmpq_poly([27, 24, 9], 5) assert p(flint.arb("1.1")).overlaps(flint.arb("13.45")) assert p(flint.acb("1.1", "1.2")).overlaps(flint.acb("6.25", "18.00"))
def test_fmpz_poly(): Z = flint.fmpz_poly assert Z() == Z([]) assert Z() == Z([0]) assert Z() == Z([0,flint.fmpz(0),0]) assert Z() == Z([0,0L,0]) assert Z() != Z([1]) assert Z([1]) == Z([1L]) assert Z([1]) == Z([flint.fmpz(1)]) assert Z(Z([1,2])) == Z([1,2]) for ztype in [int, long, flint.fmpz]: assert Z([1,2,3]) + ztype(5) == Z([6,2,3]) assert ztype(5) + Z([1,2,3]) == Z([6,2,3]) assert Z([1,2,3]) - ztype(5) == Z([-4,2,3]) assert ztype(5) - Z([1,2,3]) == Z([4,-2,-3]) assert Z([1,2,3]) * ztype(5) == Z([5,10,15]) assert ztype(5) * Z([1,2,3]) == Z([5,10,15]) assert Z([11,6,2]) // ztype(5) == Z([2,1]) assert ztype(5) // Z([-2]) == Z([-3]) assert ztype(5) // Z([1,2]) == 0 assert Z([11,6,2]) % ztype(5) == Z([1,1,2]) assert ztype(5) % Z([-2]) == Z([-1]) assert ztype(5) % Z([1,2]) == 5 assert Z([1,2,3]) ** ztype(0) == 1 assert Z([1,2,3]) ** ztype(1) == Z([1,2,3]) assert Z([1,2,3]) ** ztype(2) == Z([1,4,10,12,9]) assert +Z([1,2]) == Z([1,2]) assert -Z([1,2]) == Z([-1,-2]) assert raises(lambda: Z([1,2,3]) ** -1, (OverflowError, ValueError)) assert raises(lambda: Z([1,2,3]) ** Z([1,2]), TypeError) assert raises(lambda: Z([1,2]) // Z([]), ZeroDivisionError) assert raises(lambda: Z([]) // Z([]), ZeroDivisionError) assert raises(lambda: Z([1,2]) % Z([]), ZeroDivisionError) assert raises(lambda: divmod(Z([1,2]), Z([])), ZeroDivisionError) assert Z([]).degree() == -1 assert Z([]).length() == 0 p = Z([1,2]) assert p.length() == 2 assert p.degree() == 1 assert p[0] == 1 assert p[1] == 2 assert p[2] == 0 assert p[-1] == 0 assert raises(lambda: p.__setitem__(-1, 1), ValueError) p[0] = 3 assert p[0] == 3 p[4] = 7 assert p.degree() == 4 assert p[4] == 7 assert p[3] == 0 p[4] = 0 assert p.degree() == 1 assert p.coeffs() == [3,2] assert Z([]).coeffs() == [] assert bool(Z([])) == False assert bool(Z([1])) == True assert repr(Z([1,2])) == "fmpz_poly([1, 2])" assert str(Z([1,2])) == "2*x+1" p = Z([3,4,5]) assert p(2) == 31 assert p(flint.fmpq(2,3)) == flint.fmpq(71,9) assert p(Z([1,-1])) == Z([12,-14,5]) assert p(flint.fmpq_poly([2,3],5)) == flint.fmpq_poly([27,24,9],5)
def polynomial_roots(poly, canonical_order=True): """ Returns all the roots of the given *fmpz_poly* or *fmpq_poly*, or list of coefficients that can be converted to an *fmpq_poly*. (At this time, this function does not support algebraic coefficients.) The output is a list of pairs (*root*, *m*) where root is an algebraic number and *m* >= 1 is its multiplicity. With *canonical_order* set to *True*, the roots are sorted in a mathematically well-defined way, ensuring a consistent ordering of algebraic numbers. """ poly = fmpq_poly(poly).numer() # todo: flag to assume irreducible? c, factors = poly.factor() roots = [] orig = ctx.prec maxprec = 64 try: for fac, mult in factors: if fac.degree() == 1: a, b = list(fac) roots.append((alg(fmpq(-a, b)), mult)) continue ctx.prec = 64 while 1: fac_roots = fac.roots() checked_roots = [] for r, _ in fac_roots: r = alg._validate_root_enclosure(fac, r) if r is not None: checked_roots.append(r) else: break if len(checked_roots) == len(fac_roots): for i in range(len(fac_roots)): a = alg(_minpoly=fac, _enclosure=checked_roots[i]) roots.append((a, mult)) break ctx.prec *= 2 maxprec = max(maxprec, ctx.prec) if len(roots) > 1 and canonical_order: from functools import cmp_to_key real = [] nonreal = [] ctx.prec = 64 for (r, m) in roots: if r.is_real(): real.append((r, m)) else: z = r.enclosure() if z.imag > 0: nonreal.append((r, m)) else: assert z.imag < 0 def complex_algebraic_cmp(a, b): a, _ = a b, _ = b ctx.prec = 64 while 1: ac = a.enclosure() bc = b.enclosure() ac = ac.real + ac.imag * arb.pi() bc = bc.real + bc.imag * arb.pi() if ac.overlaps(bc): ctx.prec *= 2 else: if ac < bc: return -1 else: return 1 roots = sorted(real, reverse=True) nonreal = sorted(nonreal, key=cmp_to_key(complex_algebraic_cmp), reverse=True) for r, m in nonreal: roots.append((r, m)) roots.append((r.conjugate(), m)) finally: ctx.prec = orig return roots
from flint import ctx, arb, acb, fmpz, fmpq, fmpz_poly, fmpq_poly, fmpq_series, fmpz_mat, fmpq_mat import operator _fmpz_poly_x = fmpq_poly([0, 1]) # algorithm borrowed from sage def composed_op(P1, P2, operation): d1 = P1.degree() d2 = P2.degree() # print("compose", d1, d2) assert d1 >= 1 and d2 >= 1 cap = d1 * d2 + 1 if operation == operator.truediv: P2 = list(P2) if P2[0] == 0: raise ZeroDivisionError P2 = fmpq_poly(P2[::-1]) if operation == operator.sub: P2 = list(P2) for i in range(1, len(P2), 2): P2[i] = -P2[i] P2 = fmpq_poly(P2) orig_cap = ctx.cap try: ctx.cap = cap P1rev = list(P1)[::-1] P1drev = list(P1.derivative())[::-1] P2rev = list(P2)[::-1] P2drev = list(P2.derivative())[::-1] NP1 = fmpq_series(P1drev) / fmpq_series(P1rev)