Ticket #1183: trac-1183-through_step_3.patch

File trac-1183-through_step_3.patch, 4.2 KB (added by was, 15 years ago)
  • sage/rings/residue_field.pyx

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1196591888 28800
    # Node ID 6a7a05ed7b705b22c1e1589fe8263cfc03bb28b1
    # Parent  54cdaf20dc6ff93f16ba63be50a62efe38ea2476
    Work in progress on trac #1183.
    
    diff -r 54cdaf20dc6f -r 6a7a05ed7b70 sage/rings/residue_field.pyx
    a b from sage.rings.finite_field_ext_pari im 
    4949from sage.rings.finite_field_ext_pari import FiniteField_ext_pari
    5050from sage.structure.parent_base import ParentWithBase
    5151
     52from sage.rings.polynomial.polynomial_ring import PolynomialRing
     53
    5254residue_field_cache = {}
    5355
    5456def ResidueField(p, names = None, check = True):
    def ResidueField(p, names = None, check  
    7678        Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
    7779        sage: k.order()
    7880        841
     81
     82    An example where the generator of the number field doesn't
     83    generate the residue class field.
     84        sage: K.<a> = NumberField(x^3-875)
     85        sage: P = K.ideal(5).factor()[0][0]; k = K.residue_field(P); k
     86        Residue field in abar of Fractional ideal (5, -2/25*a^2 - 1/5*a + 2)
     87        sage: k.polynomial()
     88        abar^2 + 3*abar + 4
     89        sage: k.0^3 - 875
     90        2
    7991    """
    8092    if isinstance(names, tuple):
    8193        if len(names) > 0:
    def ResidueField(p, names = None, check  
    100112            raise ValueError, "p must be prime"
    101113        # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
    102114        characteristic = p.smallest_integer()
     115
    103116        K = p.number_field()
    104117        OK = K.maximal_order() # should change to p.order once this works.
    105         f = OK.number_field().polynomial().change_ring(Integers(characteristic)) #polynomial() should change to absolute_polynomial()
    106         L = f.factor()
    107         for i in range(len(L)):
    108             g = L[i][0]
    109             a = K(g.change_ring(QQ))
    110             if a in p:
    111                 break
     118       
     119        U, to_vs, to_order = p._p_quotient(characteristic)
     120        k = U.base_ring()
     121        R = PolynomialRing(k, names)
     122        n = p.residue_class_degree()
     123        gen_ok = False
     124        from sage.matrix.constructor import matrix
     125        try:
     126            x = K.gen()
     127            M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)]).transpose()
     128            M.echelonize()
     129            if M.rank() == n:
     130                gen_ok = True
     131                f = R((-M.column(n)).list() + [1])
     132        except TypeError:
     133            pass
     134        if not gen_ok:
     135            bad = True
     136            for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
     137                if u:
     138                    x = to_order(u)
     139                    M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)]).transpose()
     140                    M.echelonize()
     141                    if M.rank() == n:
     142                        f = R((-M.column(n)).list() + [1])
     143                        bad = False
     144                        break
     145            assert not bad, "error -- didn't find a generator."
     146        if n == 1:
     147            k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer())
    112148        else:
    113             raise RuntimeError, "should have found a prime"
    114         if g.degree() == 1:
    115             k = ResidueFiniteField_prime_modn(p, names, im_gen = -g[0], intp = p.smallest_integer())
    116         else:
    117             q = characteristic**(g.degree())
     149            q = characteristic**(f.degree())
    118150            if q < Integer(2)**Integer(16):
    119                 k = ResidueFiniteField_givaro(p, q, names, g, characteristic)
     151                k = ResidueFiniteField_givaro(p, q, names, f, characteristic)           
    120152            else:
    121                 k = ResidueFiniteField_ext_pari(p, q, names, g, characteristic)
     153                k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic)
     154            k.structure = (U, to_vs, to_order)
    122155    else: # Add support for primes in other rings later.
    123156        raise TypeError, "p must be a prime in the integers or a number field"
    124157    residue_field_cache[key] = weakref.ref(k)