def test_fmpq_mat(): Q = flint.fmpq_mat Z = flint.fmpz_mat assert Q(1,2,[3,4]) == Z(1,2,[3,4]) assert Q(1,2,[3,4]) != Z(1,2,[5,4]) assert Q(1,2,[3,4]) != Q(1,2,[5,4]) assert Q(Q(1,2,[3,4])) == Q(1,2,[3,4]) assert Q(Z(1,2,[3,4])) == Q(1,2,[3,4]) assert Q(2,3,[1,2,3,4,5,6]) + Q(2,3,[4,5,6,7,8,9]) == Q(2,3,[5,7,9,11,13,15]) assert Q(2,3,[1,2,3,4,5,6]) - Q(2,3,[4,5,6,7,8,9]) == Q(2,3,[-3,-3,-3,-3,-3,-3]) assert Q(2,3,[1,2,3,4,5,6]) * Q(3,2,[4,5,6,7,8,9]) == Q(2,2,[40,46,94,109]) assert Q(2,3,[1,2,3,4,5,6]) * Z(3,2,[4,5,6,7,8,9]) == Q(2,2,[40,46,94,109]) assert Z(2,3,[1,2,3,4,5,6]) * Q(3,2,[4,5,6,7,8,9]) == Q(2,2,[40,46,94,109]) assert -Q(2,1,[2,5]) == Q(2,1,[-2,-5]) assert +Q(1,1,[3]) == Z(1,1,[3]) assert Q(1,2,[3,4]) * 2 == Q(1,2,[6,8]) assert Q(1,2,[3,4]) * flint.fmpq(1,3) == Q(1,2,[1,flint.fmpq(4,3)]) assert Q(1,2,[3,4]) * flint.fmpq(5,3) == Q(1,2,[5,flint.fmpq(20,3)]) assert 2 * Q(1,2,[3,4]) == Q(1,2,[6,8]) assert flint.fmpq(1,3) * Q(1,2,[3,4]) == Q(1,2,[1,flint.fmpq(4,3)]) assert Q(1,2,[3,4]) / 2 == Q(1,2,[flint.fmpq(3,2),2]) assert Q(1,2,[3,4]) / flint.fmpq(2,3) == Q(1,2,[flint.fmpq(9,2),6]) assert Q(3,2,range(6)).table() == Z(3,2,range(6)).table() assert Q(3,2,range(6)).entries() == Z(3,2,range(6)).entries() assert Q(3,2,range(6)).nrows() == 3 assert Q(3,2,range(6)).ncols() == 2 assert Q(2,2,[3,7,4,5]).det() == -13 assert (Q(2,2,[3,7,4,5]) / 5).det() == flint.fmpq(-13,25) assert raises(lambda: Q(1,2,[1,2]).det(), ValueError) assert ~~Q(2,2,[1,2,3,4]) == Q(2,2,[1,2,3,4]) assert raises(lambda: ~Q(2,2,[1,1,1,1]), ZeroDivisionError) assert raises(lambda: ~Q(2,1,[1,1]), ValueError)
def test_nmod(): G = flint.nmod assert G(0, 2) == G(2, 2) == G(-2, 2) assert G(1, 2) != G(0, 2) assert G(0, 2) != G(0, 3) assert G(3, 5) == G(8, 5) #assert G(3,5) == 8 # do we want this? #assert 8 == G(3,5) assert G(3, 5) != 7 assert 7 != G(3, 5) assert G(-3, 5) == -G(3, 5) == G(2, 5) assert G(2, 5) + G(1, 5) == G(3, 5) assert G(2, 5) + 1 == G(3, 5) assert 1 + G(2, 5) == G(3, 5) assert G(2, 5) - G(3, 5) == G(4, 5) assert G(2, 5) - 3 == G(4, 5) assert 3 - G(2, 5) == G(1, 5) assert G(2, 5) * G(3, 5) == G(1, 5) assert G(2, 5) * 3 == G(1, 5) assert 3 * G(2, 5) == G(1, 5) assert G(3, 17) / G(2, 17) == G(10, 17) assert G(3, 17) / 2 == G(10, 17) assert 3 / G(2, 17) == G(10, 17) assert G(3, 17) * flint.fmpq(11, 5) == G(10, 17) assert G(3, 17) / flint.fmpq(11, 5) == G(6, 17) assert raises(lambda: G(2, 5) / G(0, 5), ZeroDivisionError) assert raises(lambda: G(2, 5) / 0, ZeroDivisionError) assert raises(lambda: G(2, 5) + G(2, 7), ValueError) assert raises(lambda: G(2, 5) - G(2, 7), ValueError) assert raises(lambda: G(2, 5) * G(2, 7), ValueError) assert raises(lambda: G(2, 5) / G(2, 7), ValueError) assert G(3, 17).modulus() == 17
def test_nmod(): G = flint.nmod assert G(0,2) == G(2,2) == G(-2,2) assert G(1,2) != G(0,2) assert G(0,2) != G(0,3) assert G(3,5) == G(8,5) #assert G(3,5) == 8 # do we want this? #assert 8 == G(3,5) assert G(3,5) != 7 assert 7 != G(3,5) assert G(-3,5) == -G(3,5) == G(2,5) assert G(2,5) + G(1,5) == G(3,5) assert G(2,5) + 1 == G(3,5) assert 1 + G(2,5) == G(3,5) assert G(2,5) - G(3,5) == G(4,5) assert G(2,5) - 3 == G(4,5) assert 3 - G(2,5) == G(1,5) assert G(2,5) * G(3,5) == G(1,5) assert G(2,5) * 3 == G(1,5) assert 3 * G(2,5) == G(1,5) assert G(3,17) / G(2,17) == G(10,17) assert G(3,17) / 2 == G(10,17) assert 3 / G(2,17) == G(10,17) assert G(3,17) * flint.fmpq(11,5) == G(10,17) assert G(3,17) / flint.fmpq(11,5) == G(6,17) assert raises(lambda: G(2,5) / G(0,5), ZeroDivisionError) assert raises(lambda: G(2,5) / 0, ZeroDivisionError) assert raises(lambda: G(2,5) + G(2,7), ValueError) assert raises(lambda: G(2,5) - G(2,7), ValueError) assert raises(lambda: G(2,5) * G(2,7), ValueError) assert raises(lambda: G(2,5) / G(2,7), ValueError) assert G(3,17).modulus() == 17
def test_fmpq_mat(): Q = flint.fmpq_mat Z = flint.fmpz_mat assert Q(1,2,[3,4]) == Z(1,2,[3,4]) assert Q(1,2,[3,4]) != Z(1,2,[5,4]) assert Q(1,2,[3,4]) != Q(1,2,[5,4]) assert Q(Q(1,2,[3,4])) == Q(1,2,[3,4]) assert Q(Z(1,2,[3,4])) == Q(1,2,[3,4]) assert Q(2,3,[1,2,3,4,5,6]) + Q(2,3,[4,5,6,7,8,9]) == Q(2,3,[5,7,9,11,13,15]) assert Q(2,3,[1,2,3,4,5,6]) - Q(2,3,[4,5,6,7,8,9]) == Q(2,3,[-3,-3,-3,-3,-3,-3]) assert Q(2,3,[1,2,3,4,5,6]) * Q(3,2,[4,5,6,7,8,9]) == Q(2,2,[40,46,94,109]) assert Q(2,3,[1,2,3,4,5,6]) * Z(3,2,[4,5,6,7,8,9]) == Q(2,2,[40,46,94,109]) assert Z(2,3,[1,2,3,4,5,6]) * Q(3,2,[4,5,6,7,8,9]) == Q(2,2,[40,46,94,109]) assert -Q(2,1,[2,5]) == Q(2,1,[-2,-5]) assert +Q(1,1,[3]) == Z(1,1,[3]) assert Q(1,2,[3,4]) * 2 == Q(1,2,[6,8]) assert Q(1,2,[3,4]) * flint.fmpq(1,3) == Q(1,2,[1,flint.fmpq(4,3)]) assert Q(1,2,[3,4]) * flint.fmpq(5,3) == Q(1,2,[5,flint.fmpq(20,3)]) assert 2 * Q(1,2,[3,4]) == Q(1,2,[6,8]) assert flint.fmpq(1,3) * Q(1,2,[3,4]) == Q(1,2,[1,flint.fmpq(4,3)]) assert Q(1,2,[3,4]) / 2 == Q(1,2,[flint.fmpq(3,2),2]) assert Q(1,2,[3,4]) / flint.fmpq(2,3) == Q(1,2,[flint.fmpq(9,2),6]) assert Q(3,2,range(6)).table() == Z(3,2,range(6)).table() assert Q(3,2,range(6)).entries() == Z(3,2,range(6)).entries() assert Q(3,2,range(6)).nrows() == 3 assert Q(3,2,range(6)).ncols() == 2 assert Q(2,2,[3,7,4,5]).det() == -13 assert (Q(2,2,[3,7,4,5]) / 5).det() == flint.fmpq(-13,25) assert raises(lambda: Q(1,2,[1,2]).det(), ValueError) assert Q(2,2,[1,2,3,4]).inv().inv() == Q(2,2,[1,2,3,4]) assert raises(lambda: Q(2,2,[1,1,1,1]).inv(), ZeroDivisionError) assert raises(lambda: Q(2,1,[1,1]).inv(), ValueError) assert raises(lambda: Q([1]), TypeError) assert raises(lambda: Q([[1],[2,3]]), ValueError) assert Q([[1,2,3],[4,5,6]]) == Q(2,3,[1,2,3,4,5,6])
def pow(self, n): if self.is_rational(): c0 = self._minpoly[0] c1 = self._minpoly[1] if abs(n) > 2: check_bits_limit(c0.height_bits() * abs(n)) check_bits_limit(c1.height_bits() * abs(n)) if n >= 0: return alg(fmpq(c0**n) / (-c1)**n) else: return alg((-c1)**(-n) / fmpq(c0**(-n))) if n == 0: return alg(1) if n == 1: return self if n < 0: return (1 / self).pow(-n) # fast detection of perfect powers pol, d = self.minpoly().deflation() if d % n == 0: # todo: is factoring needed here? H = list(self.minpoly()) H = H[::n] H = fmpz_poly(H) c, factors = H.factor() prec = 64 orig_prec = ctx.prec try: while 1: ctx.prec = prec x = self.enclosure(pretty=True) z = acb(x)**n maybe_root = [ fac for fac, mult in factors if fac(z).contains(0) ] if len(maybe_root) == 1: fac = maybe_root[0] z2 = alg._validate_root_enclosure(fac, z) if z2 is not None: return alg(_minpoly=fac, _enclosure=z2) prec *= 2 finally: ctx.prec = orig_prec if n == 2: return self * self v = self.pow(n // 2) v = v * v if n % 2: v *= self return v
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 guessrational(q): if isinstance(q, fmpq): return q minus, fraction = cfrac(q) numer = 1 denom = 0 for j in fraction[::-1]: denom, numer = numer, denom numer += denom * j numer *= minus return fmpq(numer, denom)
def test_misc_bugs(self): x = ( (1 / (alg(3).sqrt() + alg(5).sqrt()) + 1).root(3) + 1)**2 + fmpq(1, 3) x + alg.i() u = (x + alg.i()).root(3) P = alg.polynomial_roots([ 340282366920938463463374607431768211456, 4454982093016792820459821542203090534400000000, 179577734764660553639051786303255347200000000000000, -669109415404441101038544285174988800000000000000000000, 17329972089242952969786575138568878173828125 ])[0][0].expr() assert P is not None
def test_examples(self): assert sum(1 / alg(n) for n in range(1, 101)) == fmpq.harmonic(100) sqrt = lambda n: alg(n).sqrt() x = sqrt(2 * sqrt(3) * sqrt(2 * sqrt(10) + 7) + 2 * sqrt(10) + 10) y = sqrt(2) + sqrt(3) + sqrt(5) assert x == y def R(a, n): return alg(a).root(n) assert R(2, 1) + R(2, 2) - R(2, 2) - R(2, 1) == 0 assert R(2, 1) + R(2, 2) + R(2, 3) - R(2, 2) - R(2, 1) - R(2, 3) == 0 assert R(2, 4) + R(2, 1) + R(2, 2) + R(2, 3) - R(2, 2) - R(2, 1) - R( 2, 3) - R(2, 4) == 0 assert 7 < sum(R(2, n) for n in [1, 2, 3, 4, 5]) < fmpq(702, 100)
def exp_two_pi_i(x): x = fmpq(x) check_degree_limit(10 * x.q) poly = fmpz_poly.cyclotomic(x.q) prec = ctx.prec ctx.prec = 64 try: while 1: a = arb.cos_pi_fmpq(2 * x) b = arb.sin_pi_fmpq(2 * x) z = acb(a, b) z2 = alg._validate_root_enclosure(poly, z) if z2 is not None: return alg(_minpoly=poly, _enclosure=z2) ctx.prec *= 2 finally: ctx.prec = prec
def test_fmpz_mat(): M = flint.fmpz_mat a = M(2, 3, [1, 2, 3, 4, 5, 6]) b = M(2, 3, [4, 5, 6, 7, 8, 9]) assert a == a assert a == M(a) assert a != b assert a.nrows() == 2 assert a.ncols() == 3 assert a.entries() == [1, 2, 3, 4, 5, 6] assert a.table() == [[1, 2, 3], [4, 5, 6]] assert (a + b).entries() == [5, 7, 9, 11, 13, 15] assert raises(a.det, ValueError) assert +a == a assert -a == M(2, 3, [-1, -2, -3, -4, -5, -6]) c = M(2, 2, [1, 2, 3, 4]) assert c.det() == -2 assert raises(lambda: a + c, ValueError) assert (a * 3).entries() == [3, 6, 9, 12, 15, 18] assert (3 * a).entries() == [3, 6, 9, 12, 15, 18] assert (a * long(3)).entries() == [3, 6, 9, 12, 15, 18] assert (long(3) * a).entries() == [3, 6, 9, 12, 15, 18] assert (a * flint.fmpz(3)).entries() == [3, 6, 9, 12, 15, 18] assert (flint.fmpz(3) * a).entries() == [3, 6, 9, 12, 15, 18] assert M.randrank(5, 7, 3, 10).rank() == 3 A = M.randbits(5, 3, 2) B = M.randtest(3, 7, 3) C = M.randtest(7, 2, 4) assert A * (B * C) == (A * B) * C assert bool(M(2, 2, [0, 0, 0, 0])) == False assert bool(M(2, 2, [0, 0, 0, 1])) == True ctx.pretty = False assert repr(M(2, 2, [1, 2, 3, 4])) == 'fmpz_mat(2, 2, [1, 2, 3, 4])' ctx.pretty = True assert str(M(2, 2, [1, 2, 3, 4])) == '[1, 2]\n[3, 4]' assert M(1, 2, [3, 4]) * flint.fmpq(1, 3) == flint.fmpq_mat( 1, 2, [1, flint.fmpq(4, 3)]) assert flint.fmpq(1, 3) * M(1, 2, [3, 4]) == flint.fmpq_mat( 1, 2, [1, flint.fmpq(4, 3)]) assert M(1, 2, [3, 4]) / 3 == flint.fmpq_mat(1, 2, [1, flint.fmpq(4, 3)]) assert M(2, 2, [1, 2, 3, 4 ]).inv().det() == flint.fmpq(1) / M(2, 2, [1, 2, 3, 4]).det() assert M(2, 2, [1, 2, 3, 4]).inv().inv() == M(2, 2, [1, 2, 3, 4]) assert raises(lambda: M.randrank(4, 3, 4, 1), ValueError) assert raises(lambda: M.randrank(3, 4, 4, 1), ValueError) assert M(1, 1, [3])**5 == M(1, 1, [3**5]) assert raises(lambda: M(1, 2)**3, ValueError) assert raises(lambda: M(1, 1)**M(1, 1), TypeError) assert raises(lambda: 1**M(1, 1), TypeError) assert raises(lambda: M([1]), TypeError) assert raises(lambda: M([[1], [2, 3]]), ValueError) assert M([[1, 2, 3], [4, 5, 6]]) == M(2, 3, [1, 2, 3, 4, 5, 6])
def cos_pi(x, monic=False): x = fmpq(x) check_degree_limit(10 * x.q) x2 = x / 2 poly = fmpz_poly.cos_minpoly(x2.q) prec = ctx.prec ctx.prec = 64 try: while 1: z = 2 * arb.cos_pi_fmpq(x) z2 = alg._validate_root_enclosure(poly, z) if z2 is not None: v = alg(_minpoly=poly, _enclosure=z2) if not monic: v /= 2 return v ctx.prec *= 2 finally: ctx.prec = prec
def float_to_fmpq(c): """ **Description:** Converts a float to an fmpq. **Arguments:** - `c` *(float)*: The input number. **Returns:** *(flint.fmpq)* The rational number that most reasonably approximates the input. **Example:** We convert a few floats to rational numbers. ```python {2} from cytools.utils import float_to_fmpq float_to_fmpq(0.1), float_to_fmpq(0.333333333333), float_to_fmpq(2.45) # (1/10, 1/3, 49/20) ``` """ f = Fraction(c).limit_denominator() return fmpq(f.numerator, f.denominator)
def test_fmpz_mat(): M = flint.fmpz_mat a = M(2,3,[1,2,3,4,5,6]) b = M(2,3,[4,5,6,7,8,9]) assert a == a assert a == M(a) assert a != b assert a.nrows() == 2 assert a.ncols() == 3 assert a.entries() == [1,2,3,4,5,6] assert a.table() == [[1,2,3],[4,5,6]] assert (a + b).entries() == [5,7,9,11,13,15] assert raises(a.det, ValueError) assert +a == a assert -a == M(2,3,[-1,-2,-3,-4,-5,-6]) c = M(2,2,[1,2,3,4]) assert c.det() == -2 assert raises(lambda: a + c, ValueError) assert (a * 3).entries() == [3,6,9,12,15,18] assert (3 * a).entries() == [3,6,9,12,15,18] assert (a * 3L).entries() == [3,6,9,12,15,18] assert (3L * a).entries() == [3,6,9,12,15,18] assert (a * flint.fmpz(3)).entries() == [3,6,9,12,15,18] assert (flint.fmpz(3) * a).entries() == [3,6,9,12,15,18] assert M.randrank(5,7,3,10).rank() == 3 A = M.randbits(5,3,2) B = M.randtest(3,7,3) C = M.randtest(7,2,4) assert A*(B*C) == (A*B)*C assert bool(M(2,2,[0,0,0,0])) == False assert bool(M(2,2,[0,0,0,1])) == True assert repr(M(2,2,[1,2,3,4])) == 'fmpz_mat(2, 2, [1, 2, 3, 4])' assert str(M(2,2,[1,2,3,4])) == '[1, 2]\n[3, 4]' assert M(1,2,[3,4]) * flint.fmpq(1,3) == flint.fmpq_mat(1, 2, [1, flint.fmpq(4,3)]) assert flint.fmpq(1,3) * M(1,2,[3,4]) == flint.fmpq_mat(1, 2, [1, flint.fmpq(4,3)]) assert M(1,2,[3,4]) / 3 == flint.fmpq_mat(1, 2, [1, flint.fmpq(4,3)]) assert (~M(2,2,[1,2,3,4])).det() == flint.fmpq(1) / M(2,2,[1,2,3,4]).det() assert ~~M(2,2,[1,2,3,4]) == M(2,2,[1,2,3,4]) assert raises(lambda: M.randrank(4,3,4,1), ValueError) assert raises(lambda: M.randrank(3,4,4,1), ValueError) assert M(1,1,[3]) ** 5 == M(1,1,[3**5]) assert raises(lambda: M(1,2) ** 3, ValueError) assert raises(lambda: M(1,1) ** M(1,1), TypeError) assert raises(lambda: 1 ** M(1,1), TypeError)
def reconstruct_lehmer_lower(B, m, ys): """ Reconstructs the lower bits :math:`zs` of a system of linear congurential equations in lattice form with :math:`B \\cdot xs = 0 \\mod m` for solution :math:`xs`, where :math:`xs = ys + zs`. It works by computing a smaller basis :math:`B` from the basis :math:`L` and solving equations in the smaller basis. :param B: The system of linear equation in matrix form (evaluating to 0) :param m: The modulus used for all the equations :param ys: Partial solutions for the variables (xs = ys + zs) :return: The remaining operands of the solutions zs """ ys = fmpz_mat([[y] for y in ys]) Bys = B * ys # TODO: There might be a better solution to find the individual ks # NB: B * (ys + zs) = m * ks for some ks ks = fmpz_mat([[_round_fmpq(fmpq(By) / m)] for By in Bys]) # We now solve the system of linear equations B zs = m * ks - B ys for zs Bzs = m * ks - Bys zs = B.solve(Bzs) assert all(z.denom() == 1 for z in zs) return [z.numer() % m for z in zs]
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_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 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
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 fmpq(self): if not self.is_rational(): raise ValueError("fmpq() requires a rational value") c0 = self._minpoly[0] c1 = self._minpoly[1] return fmpq(c0) / (-c1)
def as_quadratic(self, factor_limit=2**64): """ Assuming that *self* has degree 1 or 2, returns (*a*, *b*, *c*) where *a* and *b* are *fmpq* rational numbers and *c* is a *fmpz* integer, such that *self* equals `a + b \sqrt{c}`. The integer *c* will not be a perfect square, but might not be squarefree since ensuring this property requires integer factorization. If *|c|* is initially smaller than *factor_limit*, it will be completely factored into its squarefree part (with the square content moved to *b*); otherwise, only a partial factorization will be performed. >>> alg(-23).as_quadratic() (-23, 0, 0) >>> (2 + alg.i() / 3).as_quadratic() (2, 1/3, -1) >>> x = (alg(5)/2 + alg(24).sqrt())**5 >>> x.as_quadratic() (353525/32, 36341/8, 6) >>> x == alg(353525)/32 + alg(36341)/8 * alg(6).sqrt() True >>> alg(3 * 29**2 * (10**20+39)**2).sqrt().as_quadratic() (0, 2900000000000000001131, 3) >>> x = alg(3 * (10**10+1)**3 * (10**15+1)**2).sqrt() >>> a, b, c = x.as_quadratic() >>> (a, b, c) (0, 39340116598834051, 1938429316132524961593868203) >>> x == a + b*alg(c).sqrt() True >>> a, b, c = x.as_quadratic(factor_limit=10**50) >>> (a, b, c) (0, 10000000001000010000000001, 30000000003) >>> x == a + b*alg(c).sqrt() True """ poly = self._minpoly if poly.degree() == 1: return (self.fmpq(), fmpq(), fmpz()) if poly.degree() != 2: raise ValueError c, b, a = list(self.minpoly()) D = b**2 - 4 * a * c Dsqrt = alg(D).sqrt() x = (-b + Dsqrt) / (2 * a) if self == x: bsign = 1 else: x = (-b - Dsqrt) / (2 * a) bsign = -1 a, b, c = fmpq(-b) / (2 * a), fmpq(bsign, 2 * a), D if abs(c) >= 4: if abs(c) < factor_limit: fac = c.factor() else: fac = c.factor(trial_limit=1000) # todo: the partial factoring in flint is wonky; # it should at least do a perfect power test or single-word # factorisation of the last factor if 1: rem, reme = fac[-1] if rem < factor_limit: fac = fac[:-1] + [(pp, ee * reme) for (pp, ee) in rem.factor()] elif rem.is_perfect_power(): for e in range(64, 1, -1): p = rem.root(e) if p**e == rem: if p < factor_limit: fac2 = rem.factor() fac = fac[:-1] for (p, f) in fac2: fac.append((p, e * f * reme)) else: fac = fac[:-1] + [(p, e * reme)] break check = 1 for p, e in fac: check *= p**e # assert check == abs(c) square = fmpz(1) squarefree = fmpz(1) for p, e in fac: if e % 2 == 0: square *= p**(e // 2) else: square *= p**(e // 2) squarefree *= p if c < 0: squarefree = -squarefree b *= square c = squarefree # assert self == alg(a) + alg(b) * alg(c).sqrt() return a, b, c
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 w(): return alg(-1)**fmpq(2, 3)
def enclosure(self, pretty=False): if self.degree() == 1: c0 = self._minpoly[0] c1 = self._minpoly[1] return arb(c0) / (-c1) elif pretty: z = self.enclosure() re = z.real im = z.imag # detect zero real/imag part if z.real.contains(0): if self.real_sgn() == 0: re = arb(0) if z.imag.contains(0): if self.imag_sgn() == 0: im = arb(0) # detect exact (dyadic) real/imag parts # fixme: extracting real and imag parts and checking if # they are exact can be slow at high degree; this is a workaround # until that operation can be improved scale = fmpz(2)**max(10, ctx.prec - 20) if not re.is_exact() and (re * scale).unique_fmpz() is not None: n = (re * scale).unique_fmpz() b = self - fmpq(n, scale) if b.real_sgn() == 0: re = arb(fmpq(n, scale)) if not im.is_exact() and (im * scale).unique_fmpz() is not None: n = (im * scale).unique_fmpz() b = self - fmpq(n, scale) * alg.i() if b.imag_sgn() == 0: im = arb(fmpq(n, scale)) if im == 0: return arb(re) else: return acb(re, im) else: orig_prec = ctx.prec x = self._enclosure if x.rel_accuracy_bits() >= orig_prec - 2: return x # Try interval newton refinement f = self._minpoly g = self._minpoly.derivative() try: ctx.prec = max(x.rel_accuracy_bits(), 32) + 10 for step in range(40): ctx.prec *= 2 if ctx.prec > 1000000: raise ValueError("excessive precision") # print("root-refinement prec", ctx.prec) # print(x.mid().str(10), x.rad().str(10)) xmid = x.mid() y = xmid - f(xmid) / g(x) if y.rel_accuracy_bits() >= 1.1 * orig_prec: self._enclosure = y return y if y.rel_accuracy_bits() < 1.5 * x.rel_accuracy_bits() + 1: # print("refinement failed -- recomputing roots") roots = self._minpoly.roots() near = [r for (r, mult) in roots if acb(r).overlaps(x)] if len(near) == 1: y = near[0] if y.rel_accuracy_bits() >= 1.1 * orig_prec: self._enclosure = y return y x = y raise ValueError("root refinement did not converge") finally: ctx.prec = orig_prec
def sin_pi(x, monic=False): return alg.cos_pi(fmpq(1, 2) - x, monic=monic)
def exp_pi_i(x): x = fmpq(x) return alg.exp_two_pi_i(x / 2)