Ticket #13765: trac13765cycloembeddings.patch
File trac13765cycloembeddings.patch, 13.3 KB (added by , 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 408 408 sage: W.<a> = NumberField(x^2 + 1); W 409 409 Number Field in a with defining polynomial x^2 + 1 over its base field 410 410 411 The following has been fixed in trac ticket #8800::411 The following has been fixed in :trac:`8800`:: 412 412 413 413 sage: P.<x> = QQ[] 414 414 sage: K.<a> = NumberField(x^35,embedding=0) … … class NumberField_generic(number_field_b 3376 3376 sage: K.S_units([])[0].multiplicative_order() 3377 3377 6 3378 3378 3379 An example in a relative extension (see trac #8722)::3379 An example in a relative extension (see :trac:`8722`):: 3380 3380 3381 3381 sage: L.<a,b> = NumberField([x^2 + 1, x^2  5]) 3382 3382 sage: p = L.ideal((1/2*b  1/2)*a + 1/2*b  1/2) 3383 3383 sage: W = L.S_units([p]); [x.norm() for x in W] 3384 3384 [9, 1, 1] 3385 3385 3386 Our generators should have the correct parent ( trac #9367)::3386 Our generators should have the correct parent (:trac:`9367`):: 3387 3387 3388 3388 sage: _.<x> = QQ[] 3389 3389 sage: L.<alpha> = NumberField(x^3 + x + 1) … … class NumberField_absolute(NumberField_g 5568 5568 5569 5569 TESTS: 5570 5570 5571 The following was fixed in trac ticket #8800::5571 The following was fixed in :trac:`8800`:: 5572 5572 5573 5573 sage: P.<x> = QQ[] 5574 5574 sage: K.<a> = NumberField(x^35,embedding=0) … … class NumberField_absolute(NumberField_g 5579 5579 5580 5580 AUTHORS: 5581 5581 5582  Jeroen Demeyer (20110930): Trac ticket #118695582  Jeroen Demeyer (20110930): :trac:`11869` 5583 5583 5584 5584 """ 5585 5585 # Special case for x in QQ. This is common, so should be fast. … … class NumberField_absolute(NumberField_g 5811 5811 Defn: zeta3 > 1/2*a  1/2 5812 5812 5813 5813 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`):: 5815 5815 5816 5816 sage: K.<r4> = NumberField(x^42) 5817 5817 sage: L1.<r2_1> = NumberField(x^22, embedding = r4**2) … … class NumberField_absolute(NumberField_g 5824 5824 True 5825 5825 5826 5826 Coercion of an order (testing against a bug that was fixed in 5827 trac ticket #8800)::5827 :trac:`8800`):: 5828 5828 5829 5829 sage: K.has_coerce_map_from(L1) 5830 5830 True … … class NumberField_absolute(NumberField_g 6316 6316 6317 6317 TESTS: 6318 6318 6319 We verify that trac #2480is fixed::6319 We verify that :trac:`2480` is fixed:: 6320 6320 6321 6321 sage: K.<a> = NumberField(x^4 + 4*x^2 + 2) 6322 6322 sage: B = K.integral_basis() … … class NumberField_cyclotomic(NumberField 7733 7733 7734 7734 TESTS: 7735 7735 7736 We check that the bug reported on Trac #8938is fixed::7736 We check that the bug reported on :trac:`8938` is fixed:: 7737 7737 7738 7738 sage: C5.<z> = CyclotomicField(5) 7739 7739 sage: P.<s, t> = C5[] … … class NumberField_cyclotomic(NumberField 7755 7755 `\Q(\zeta_m)` iff `n'm`, where `n'` is the odd part of `n` if `4 \not 7756 7756  n` and `n'=n` otherwise. 7757 7757 7758 The morphism is consistant with the chosen embedding into `\CC`. In 7759 particular, if `nm` 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`. 7761 7759 7762 7760 If `K` is not a cyclotomic field, the normal coercion rules for number 7763 7761 fields are used. … … class NumberField_cyclotomic(NumberField 7813 7811 From: Cyclotomic Field of order 2 and degree 1 7814 7812 To: Cyclotomic Field of order 1 and degree 1 7815 7813 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 7816 7842 """ 7817 7843 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 7818 7849 Kn = K.__n 7819 7850 n = self.__n 7820 7851 if Kn.divides(n): … … class NumberField_cyclotomic(NumberField 7823 7854 # see #12632 7824 7855 return number_field_morphisms.NumberFieldEmbedding(K, self, self.gen()) 7825 7856 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) 7829 7859 else: 7830 7860 return None 7831 7861 else: 7832 7862 return NumberField_absolute._coerce_map_from_(self, K) 7833 7863 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 embeddingrespecting coercions. 7869 7870 If `x` is complex, the result is either an integer `e` such 7871 that the absolute value of `self.gen()^ex` 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**ex) < 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 7835 7929 def _element_constructor_(self, x): 7836 7930 """ 7837 7931 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 439 439 ## degree 2 is handled differently, because elements are 440 440 ## represented differently 441 441 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) 443 446 444 447 cdef NumberFieldElement x = <NumberFieldElement>PY_NEW_SAME_TYPE(self) 445 448 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( 386 386 sage: z3._lift_cyclotomic_element(cf6) 387 387 zeta6  1 388 388 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 389 397 AUTHOR: 390 398 391 399  Joel B. Mohler (original version) … … cdef class NumberFieldElement_quadratic( 417 425 ##  CyclotomicField(6) and CyclotomicField(6) 418 426 ##  CyclotomicField(4) and CyclotomicField(4) 419 427 ## 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 420 433 x2 = <NumberFieldElement_quadratic>(self._new()) 421 434 x2._parent = new_parent 422 435 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) 424 440 mpz_set(x2.denom, self.denom) 425 441 x2.D = self.D 426 442 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 443 443 Traceback (most recent call last): 444 444 ... 445 445 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 446 463 """ 447 464 Morphism.__init__(self, K, L) 448 465 from number_field import NumberField_cyclotomic 449 466 if not isinstance(K, NumberField_cyclotomic) or not isinstance(L, NumberField_cyclotomic): 450 467 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): 452 471 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 455 474 456 475 cpdef Element _call_(self, x): 457 476 """