Ticket #13765: trac-13765-cyclo-embeddings.patch

File trac-13765-cyclo-embeddings.patch, 13.3 KB (added by chapoton, 7 years ago)
  • sage/rings/number_field/number_field.py

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1354217296 28800
    # Node ID a07456988c32612b2fe911ab455a438d0e48962c
    # Parent  4c4ddacd34872800655e7283277f8c5aef00b4d4
    trac #13765 : Cyclotomic embeddings should respect coercions.
    
    diff --git a/sage/rings/number_field/number_field.py b/sage/rings/number_field/number_field.py
    a b def NumberField(polynomial, name=None, c 
    408408        sage: W.<a> = NumberField(x^2 + 1); W
    409409        Number Field in a with defining polynomial x^2 + 1 over its base field
    410410
    411     The following has been fixed in trac ticket #8800::
     411    The following has been fixed in :trac:`8800`::
    412412
    413413        sage: P.<x> = QQ[]
    414414        sage: K.<a> = NumberField(x^3-5,embedding=0)
    class NumberField_generic(number_field_b 
    33763376            sage: K.S_units([])[0].multiplicative_order()
    33773377            6
    33783378
    3379         An example in a relative extension (see trac #8722)::
     3379        An example in a relative extension (see :trac:`8722`)::
    33803380       
    33813381            sage: L.<a,b> = NumberField([x^2 + 1, x^2 - 5])
    33823382            sage: p = L.ideal((-1/2*b - 1/2)*a + 1/2*b - 1/2)
    33833383            sage: W = L.S_units([p]); [x.norm() for x in W]
    33843384            [9, 1, 1]
    33853385
    3386         Our generators should have the correct parent (trac #9367)::
     3386        Our generators should have the correct parent (:trac:`9367`)::
    33873387
    33883388            sage: _.<x> = QQ[]
    33893389            sage: L.<alpha> = NumberField(x^3 + x + 1)
    class NumberField_absolute(NumberField_g 
    55685568
    55695569        TESTS:
    55705570
    5571         The following was fixed in trac ticket #8800::
     5571        The following was fixed in :trac:`8800`::
    55725572
    55735573            sage: P.<x> = QQ[]
    55745574            sage: K.<a> = NumberField(x^3-5,embedding=0)
    class NumberField_absolute(NumberField_g 
    55795579
    55805580        AUTHORS:
    55815581
    5582         - Jeroen Demeyer (2011-09-30): Trac ticket #11869
     5582        - Jeroen Demeyer (2011-09-30): :trac:`11869`
    55835583
    55845584        """
    55855585        # Special case for x in QQ.  This is common, so should be fast.
    class NumberField_absolute(NumberField_g 
    58115811              Defn: zeta3 -> 1/2*a - 1/2
    58125812
    58135813        Two embedded number fields with mutual coercions (testing against a
    5814         bug that was fixed in trac ticket #8800)::
     5814        bug that was fixed in :trac:`8800`)::
    58155815
    58165816            sage: K.<r4> = NumberField(x^4-2)
    58175817            sage: L1.<r2_1> = NumberField(x^2-2, embedding = r4**2)
    class NumberField_absolute(NumberField_g 
    58245824            True
    58255825
    58265826        Coercion of an order (testing against a bug that was fixed in
    5827         trac ticket #8800)::
     5827        :trac:`8800`)::
    58285828
    58295829            sage: K.has_coerce_map_from(L1)
    58305830            True
    class NumberField_absolute(NumberField_g 
    63166316
    63176317        TESTS:
    63186318
    6319         We verify that trac #2480 is fixed::
     6319        We verify that :trac:`2480` is fixed::
    63206320
    63216321            sage: K.<a> = NumberField(x^4 + 4*x^2 + 2)
    63226322            sage: B = K.integral_basis()
    class NumberField_cyclotomic(NumberField 
    77337733           
    77347734        TESTS:
    77357735       
    7736         We check that the bug reported on Trac #8938 is fixed::
     7736        We check that the bug reported on :trac:`8938` is fixed::
    77377737       
    77387738            sage: C5.<z> = CyclotomicField(5)
    77397739            sage: P.<s, t> = C5[]
    class NumberField_cyclotomic(NumberField 
    77557755        `\Q(\zeta_m)` iff `n'|m`, where `n'` is the odd part of `n` if `4 \not
    77567756        | n` and `n'=n` otherwise.
    77577757       
    7758         The morphism is consistant with the chosen embedding into `\CC`. In
    7759         particular, if `n|m` then the resulting morphism is defined by `\zeta_n
    7760         \mapsto \zeta_m^(m/n)`.
     7758        The morphism is consistant with the chosen embedding into `\CC`.
    77617759       
    77627760        If `K` is not a cyclotomic field, the normal coercion rules for number
    77637761        fields are used.
    class NumberField_cyclotomic(NumberField 
    78137811              From: Cyclotomic Field of order 2 and degree 1
    78147812              To:   Cyclotomic Field of order 1 and degree 1
    78157813              Defn: zeta2 -> -1
     7814
     7815        Check that custom embeddings are respected (:trac:`13765`)::
     7816
     7817            sage: z105 = CDF(exp(2*pi*I/105))
     7818            sage: Ka.<a> = CyclotomicField(105, embedding=z105^11)
     7819            sage: Kb.<b> = CyclotomicField(35, embedding=z105^6)
     7820            sage: Ka.coerce_map_from(Kb)
     7821            Generic morphism:
     7822              From: Cyclotomic Field of order 35 and degree 24
     7823              To:   Cyclotomic Field of order 105 and degree 48
     7824              Defn: b -> -a^44 - a^42 + a^39 + a^37 + a^35 - a^29 - a^27 - a^25 + a^24 - a^23 + a^22 - a^21 + a^20 + a^18 + a^16 - a^12 - a^10 - a^8 - a^6 + a^5 + a^3 + a
     7825            sage: CC(b)
     7826            0.936234870639737 + 0.351374824081343*I
     7827            sage: CC(-a^44 - a^42 + a^39 + a^37 + a^35 - a^29 - a^27 - a^25 + a^24 - a^23 + a^22 - a^21 + a^20 + a^18 + a^16 - a^12 - a^10 - a^8 - a^6 + a^5 + a^3 + a)
     7828            0.936234870639731 + 0.351374824081341*I
     7829
     7830            sage: z15 = CDF(exp(2*pi*I/15))
     7831            sage: CyclotomicField(15).coerce_map_from(CyclotomicField(6, embedding=-z15^5))
     7832            Generic morphism:
     7833              From: Cyclotomic Field of order 6 and degree 2
     7834              To:   Cyclotomic Field of order 15 and degree 8
     7835              Defn: zeta6 -> -zeta15^5
     7836
     7837            sage: CyclotomicField(15, embedding=z15^4).coerce_map_from(CyclotomicField(6, embedding=-z15^5))
     7838            Generic morphism:
     7839              From: Cyclotomic Field of order 6 and degree 2
     7840              To:   Cyclotomic Field of order 15 and degree 8
     7841              Defn: zeta6 -> -zeta15^5
    78167842        """
    78177843        if isinstance(K, NumberField_cyclotomic):
     7844            if (self.coerce_embedding() is None or K.coerce_embedding() is None):
     7845                return None
     7846            ambient_field = self.coerce_embedding().codomain()
     7847            if not ambient_field.has_coerce_map_from(K.coerce_embedding().codomain()):
     7848                return None
    78187849            Kn = K.__n
    78197850            n = self.__n
    78207851            if Kn.divides(n):
    class NumberField_cyclotomic(NumberField 
    78237854                # see #12632
    78247855                return number_field_morphisms.NumberFieldEmbedding(K, self, -self.gen())
    78257856            if Kn % 4 == 2 and (Kn//2).divides(n):
    7826                 e1 = (~mod(2, Kn//2)).lift()
    7827                 e2 = 2*n // Kn
    7828                 return number_field_morphisms.NumberFieldEmbedding(K, self, -self.gen() ** (e1*e2))
     7857                e = self._log_gen(ambient_field(-K.gen()))
     7858                return number_field_morphisms.NumberFieldEmbedding(K, self, -self.gen() ** e)
    78297859            else:
    78307860                return None
    78317861        else:
    78327862            return NumberField_absolute._coerce_map_from_(self, K)
    78337863
    7834                
     7864    def _log_gen(self, x):
     7865        """
     7866        Returns an integer `e` such that `self.gen()^e == x`, or `None`
     7867        if no such integer exists. This is primarily used to construct
     7868        embedding-respecting coercions.
     7869
     7870        If `x` is complex, the result is either an integer `e` such
     7871        that the absolute value of `self.gen()^e-x` is small or
     7872        `None` if no such `e` is found.
     7873
     7874        EXAMPLES::
     7875
     7876            sage: K.<a> = CyclotomicField(5)
     7877            sage: K._log_gen(CDF(a))
     7878            1
     7879            sage: K._log_gen(CDF(a^4))
     7880            4
     7881
     7882            sage: zeta105 = CC(exp(2*pi*i/105))
     7883            sage: K.<a> = CyclotomicField(105, embedding=zeta105^13)
     7884            sage: zeta105^13, CC(a)
     7885            (0.712376096951345 + 0.701797902883992*I, 0.712376096951345 + 0.701797902883991*I)
     7886            sage: K._log_gen(zeta105^26)
     7887            2
     7888            sage: K._log_gen(zeta105)
     7889            97
     7890            sage: zeta105, CC(a^97)
     7891            (0.998210129767735 + 0.0598041539450342*I, 0.998210129767736 + 0.0598041539450313*I)
     7892            sage: K._log_gen(zeta105^3)
     7893            81
     7894            sage: zeta105^3, CC(a)^81
     7895            (0.983929588598630 + 0.178556894798637*I, 0.983929588598631 + 0.178556894798635*I)
     7896
     7897            sage: K.<a> = CyclotomicField(5, embedding=None)
     7898            sage: K._log_gen(CDF(.5, -.8)) is None
     7899            True
     7900
     7901            sage: zeta5 = cyclotomic_polynomial(5).change_ring(Qp(11)).roots()[0][0]
     7902            sage: zeta5 ^ 5
     7903            1 + O(11^20)
     7904            sage: K.<a> = CyclotomicField(5, embedding=zeta5^2)
     7905            sage: K._log_gen(zeta5)
     7906            3
     7907        """
     7908        if not x.parent().has_coerce_map_from(self):
     7909            return None
     7910        if CDF.has_coerce_map_from(x.parent()):
     7911            x = CDF(x)
     7912        gen = x.parent().coerce(self.gen())
     7913        n = self._n()
     7914        two_pi = 2*RDF.pi()
     7915        if x.parent() is CDF:
     7916            # Let zeta = e^(2*pi*i/n)
     7917            a = (n * x.arg() / two_pi).round()         # x = zeta^a
     7918            b = (n * gen.arg() / two_pi).round()      # gen = zeta^b
     7919            e = mod(a/b, n).lift()          # e is the expected result
     7920            if abs(gen**e-x) < 1/n:        # a sanity check
     7921                return e
     7922        else:
     7923            gen_pow_e = 1
     7924            for e in range(n):
     7925                if gen_pow_e == x:
     7926                    return e
     7927                gen_pow_e *= gen
     7928
    78357929    def _element_constructor_(self, x):
    78367930        """
    78377931        Create an element of this cyclotomic field from `x`.
  • sage/rings/number_field/number_field_element.pyx

    diff --git a/sage/rings/number_field/number_field_element.pyx b/sage/rings/number_field/number_field_element.pyx
    a b cdef class NumberFieldElement(FieldEleme 
    439439        ## degree 2 is handled differently, because elements are
    440440        ## represented differently
    441441        if new_parent.degree() == 2:
    442             return new_parent._element_class(new_parent, self)
     442            if rel == 1:
     443                return new_parent._element_class(new_parent, self)
     444            else:
     445                return self.polynomial()(new_parent.gen()**rel)
    443446
    444447        cdef NumberFieldElement x = <NumberFieldElement>PY_NEW_SAME_TYPE(self)
    445448        x._parent = <ParentWithBase>new_parent
  • sage/rings/number_field/number_field_element_quadratic.pyx

    diff --git a/sage/rings/number_field/number_field_element_quadratic.pyx b/sage/rings/number_field/number_field_element_quadratic.pyx
    a b cdef class NumberFieldElement_quadratic( 
    386386            sage: z3._lift_cyclotomic_element(cf6)
    387387            zeta6 - 1
    388388
     389        Verify embeddings are respected::
     390
     391            sage: cf6c = CyclotomicField(6, embedding=CDF(exp(-pi*I/3))) ; z6c = cf6c.0
     392            sage: cf3(z6c)
     393            -zeta3
     394            sage: cf6c(z3)
     395            -zeta6
     396
    389397        AUTHOR:
    390398
    391399        - Joel B. Mohler (original version)
    cdef class NumberFieldElement_quadratic( 
    417425            ## - CyclotomicField(6) and CyclotomicField(6)
    418426            ## - CyclotomicField(4) and CyclotomicField(4)
    419427            ## In all cases, conversion of elements is trivial!
     428            if n == <int>new_parent._n():
     429                conjugate = rel != 1
     430            else:
     431                # n = 3, new_n = 6
     432                conjugate = rel == 4
    420433            x2 = <NumberFieldElement_quadratic>(self._new())
    421434            x2._parent = new_parent
    422435            mpz_set(x2.a, self.a)
    423             mpz_set(x2.b, self.b)
     436            if conjugate:
     437                mpz_neg(x2.b, self.b)
     438            else:
     439                mpz_set(x2.b, self.b)
    424440            mpz_set(x2.denom, self.denom)
    425441            x2.D = self.D
    426442            return x2
  • sage/rings/number_field/number_field_morphisms.pyx

    diff --git a/sage/rings/number_field/number_field_morphisms.pyx b/sage/rings/number_field/number_field_morphisms.pyx
    a b cdef class CyclotomicFieldEmbedding(Numb 
    443443            Traceback (most recent call last):
    444444            ...
    445445            TypeError: The zeta_order of the new field must be a multiple of the zeta_order of the original.
     446
     447        Check that :trac:`13765` is fixed::
     448
     449            sage: z3=(CC(-1)^(1/3))^2
     450            sage: Ka.<a>=CyclotomicField(3,embedding=z3)
     451            sage: Kb.<b>=CyclotomicField(3,embedding=z3^2)
     452            sage: CyclotomicFieldEmbedding(Ka, Kb)
     453            Generic morphism:
     454              From: Cyclotomic Field of order 3 and degree 2
     455              To:   Cyclotomic Field of order 3 and degree 2
     456              Defn: a -> -b - 1
     457            sage: Ka(b)
     458            -a - 1
     459            sage: a + b
     460            -1
     461            sage: b + a
     462            -1
    446463        """
    447464        Morphism.__init__(self, K, L)
    448465        from number_field import NumberField_cyclotomic
    449466        if not isinstance(K, NumberField_cyclotomic) or not isinstance(L, NumberField_cyclotomic):
    450467            raise TypeError, "CyclotomicFieldEmbedding only valid for cyclotomic fields."
    451         if not K._n().divides(L._n()):
     468        Kn = K._n()
     469        Ln = L._n()
     470        if not Kn.divides(Ln):
    452471            raise TypeError, "The zeta_order of the new field must be a multiple of the zeta_order of the original."
    453         self.ratio = int(L._n() // K._n())
    454         self._gen_image = self(K.gen())
     472        self.ratio = L._log_gen(K.coerce_embedding()(K.gen()))
     473        self._gen_image = L.gen() ** self.ratio
    455474   
    456475    cpdef Element _call_(self, x):
    457476        """