Ticket #9541: trac_9541-part7-generic_elts.patch
File trac_9541-part7-generic_elts.patch, 40.3 KB (added by , 12 years ago) |
---|
-
sage/rings/number_field/implementation.pyx
# HG changeset patch # User William Stein <wstein@gmail.com> # Date 1279753987 -7200 # Node ID 53c4551ed34f4ee655eb78c0b9c87fb3c45a9d51 # Parent f09d5a19ec34645612cc112d30fa735cc7b77aa0 [mq]: trac_9541-part7-generic_elts.patch diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/implementation.pyx
a b 80 80 """ 81 81 return cmp(self.name(), right.name()) 82 82 83 def use_absolute_polynomials(self): 84 """ 85 Returns True if in this implementation elements of a relative 86 extension are represented using an absolute polynomial. 87 88 EXAMPLES:: 89 90 sage: sage.rings.number_field.implementation.ArithmeticImplementation('test').use_absolute_polynomials() 91 False 92 """ 93 return False 94 83 95 cdef class ArithmeticImplementation_generic(ArithmeticImplementation): 84 96 def __init__(self, modulus): 85 97 """ … … 101 113 """ 102 114 return self.__class__, (self.modulus, ) 103 115 116 def use_absolute_polynomials(self): 117 """ 118 Returns True if in this implementation elements of a relative 119 extension are represented using an absolute polynomial. 120 121 EXAMPLES:: 122 123 sage: A = sage.rings.number_field.implementation.ArithmeticImplementation_generic(x^2 + 3) 124 sage: A.use_absolute_polynomials() 125 False 126 """ 127 return False 128 104 129 cdef class ArithmeticImplementation_ntl(ArithmeticImplementation): 105 130 def __init__(self): 106 131 """ … … 111 136 """ 112 137 ArithmeticImplementation.__init__(self, 'ntl') 113 138 139 def use_absolute_polynomials(self): 140 """ 141 Returns True if in this implementation elements of a relative 142 extension are represented using an absolute polynomial. 143 144 EXAMPLES:: 145 146 sage: sage.rings.number_field.implementation.ArithmeticImplementation_ntl().use_absolute_polynomials() 147 True 148 """ 149 return True 150 114 151 cdef class ArithmeticImplementation_flint(ArithmeticImplementation): 115 152 def __init__(self, modulus): 116 153 """ … … 128 165 def __dealloc__(self): 129 166 fmpq_poly_clear(self.modulus) 130 167 168 def use_absolute_polynomials(self): 169 """ 170 Returns True if in this implementation elements of a relative 171 extension are represented using an absolute polynomial. 172 173 EXAMPLES:: 174 175 sage: R.<x> = QQ[] 176 sage: sage.rings.number_field.implementation.ArithmeticImplementation_flint(x-1).use_absolute_polynomials() 177 True 178 """ 179 return True 131 180 132 181 cdef class ArithmeticImplementation_singular(ArithmeticImplementation): 133 182 def __init__(self): -
sage/rings/number_field/maps.py
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/maps.py
a b 262 262 263 263 def _call_(self, v): 264 264 """ 265 INPUT:: 266 267 - `v` -- element 265 INPUT: 266 - `v` -- element 268 267 269 268 EXAMPLES:: 270 269 271 sage: K.<a,b> = NumberField([x^3+2,x^2-2]); phi = K.relative_vector_space()[1] 270 sage: K.<a,b> = NumberField([x^3 + 7, x^3 + 2], implementation='generic') 271 sage: V,f,t = K.relative_vector_space() 272 sage: [f(z) for z in V.basis()] 273 [1, a, a^2] 274 275 sage: K.<a,b> = NumberField([x^3+2, x^2-2]); phi = K.relative_vector_space()[1] 272 276 sage: V = phi.domain(); phi(V.0 + 3*V.1) 273 277 3*a + 1 274 278 """ 275 # Given a relative vector space element, we have to276 # compute the corresponding number field element, in terms279 # Given a relative vector space element, this function 280 # computes the corresponding number field element, in terms 277 281 # of an absolute generator. 278 282 w = self.__V(v).list() 283 284 if self.__K.implementation().use_absolute_polynomials(): 279 285 280 # First, construct from w a PARI polynomial in x with coefficients 281 # that are polynomials in y: 282 B = self.__B 283 _, to_B = B.structure() 284 # Apply to_B, so now each coefficient is in an absolute field, 285 # and is expressed in terms of a polynomial in y, then make 286 # the PARI poly in x. 287 w = [pari(to_B(a).polynomial('y')) for a in w] 288 h = pari(w).Polrev() 286 # First, construct from w a PARI polynomial in x with coefficients 287 # that are polynomials in y: 288 B = self.__B 289 _, to_B = B.structure() 289 290 290 # Next we write the poly in x over a poly in y in terms 291 # of an absolute polynomial for the rnf. 292 g = self.__R(self.__rnf.rnfeltreltoabs(h)) 293 return self.__K._element_class(self.__K, g) 291 # Apply to_B, so now each coefficient is in an absolute field, 292 # and is expressed in terms of a polynomial in y, then make 293 # the PARI poly in x. 294 w = [pari(to_B(a).polynomial('y')) for a in w] 295 h = pari(w).Polrev() 296 297 # Next we write the poly in x over a poly in y in terms 298 # of an absolute polynomial for the rnf. 299 g = self.__R(self.__rnf.rnfeltreltoabs(h)) 300 return self.__K._element_class(self.__K, g) 301 302 else: 303 304 # much easier case 305 return self.__K._element_class(self.__K, w) 294 306 295 307 class MapRelativeNumberFieldToRelativeVectorSpace(NumberFieldIsomorphism): 296 308 def __init__(self, K, V): … … 318 330 """ 319 331 TESTS:: 320 332 321 sage: K.<a> = NumberField(x^5+2) 333 sage: K.<a,b> = NumberField([x^3 + 7, x^3 + 2], implementation='generic') 334 sage: V,f,t = K.relative_vector_space() 335 sage: t(a) 336 (0, 1, 0) 337 sage: t(b) 338 (b, 0, 0) 339 sage: t(a^2*b + a - 3/4) 340 (-3/4, 1, b) 341 342 The ntl implementation tests the code in the case when 343 everything is represented using an absolute polynomial:: 344 345 sage: K.<a> = NumberField(x^5+2, implementation='ntl') 322 346 sage: R.<y> = K[] 323 347 sage: D.<x0> = K.extension(y + a + 1) 324 348 sage: D(a) … … 344 368 (a) 345 369 """ 346 370 # An element of a relative number field is represented 347 # internally by an absolute polynomial over QQ. 371 # internally by either a relative or absolute polynomial over QQ. 372 348 373 alpha = self.__K(alpha) 374 375 if not self.__K.implementation().use_absolute_polynomials(): 376 377 return self.__V(alpha.relative_polynomial().padded_list(self.__K.relative_degree())) 349 378 350 # Pari doesn't return a valid relative polynomial from an 351 # absolute one in the case of relative degree one, so we work 352 # around it. (Bug submitted to Pari, fixed in svn unstable as 353 # of 1/22/08 according to Karim Belabas. Trac #1891 is a 354 # reminder to remove this workaround once we update Pari in 355 # Sage.) 356 if self.__K.relative_degree() == 1: 357 # Let K/F be our relative extension, let z be the absolute 358 # polynomial for K (which *need not* be the absolute 359 # polynomial for F!), and let pol be the relative 360 # polynomial for K/F. Then self.__rnf[10] returns a triple 361 # z, a, k, where z is as above, a is a polynomial 362 # representing the absolute generator gamma of F as a 363 # polynomial in a root of z, and k is an integer 364 # satisfying 365 # theta = beta + k*gamma 366 # where theta is a root of z, and beta is a root of pol. 379 else: 380 # The case of an absolute polynomial... 367 381 # 368 # Now f is a polynomial representing our element alpha as 369 # a polynomial in theta. However, we need a polynomial g 370 # representing alpha in terms of gamma, so we simply use 371 # the relation above to write theta as a polynomial in 372 # gamma, and then we can simply evaluate f at that 373 # polynomial, and this is our g. The code below does 374 # exactly this -- all the business with subst and 375 # self.__x, self.__y is there to deal with Pari's 376 # frustrating representation of relative number fields and 377 # "variable priority." 378 # 379 f = alpha._pari_().lift() 380 z, a, k = self.__rnf[10] 381 beta = -self.__rnf[0][0] / self.__rnf[0][1] 382 theta = beta + k*self.__y 383 f_in_base = f.subst(self.__x, theta).lift().subst(self.__y, self.__x) 384 return self.__V([self.__K.base_field()(f_in_base)]) 382 # Pari doesn't return a valid relative polynomial from an 383 # absolute one in the case of relative degree one, so we work 384 # around it. (Bug submitted to Pari, fixed in svn unstable as 385 # of 1/22/08 according to Karim Belabas. Trac #1891 is a 386 # reminder to remove this workaround once we update Pari in 387 # Sage.) 388 if self.__K.relative_degree() == 1: 389 # Let K/F be our relative extension, let z be the absolute 390 # polynomial for K (which *need not* be the absolute 391 # polynomial for F!), and let pol be the relative 392 # polynomial for K/F. Then self.__rnf[10] returns a triple 393 # z, a, k, where z is as above, a is a polynomial 394 # representing the absolute generator gamma of F as a 395 # polynomial in a root of z, and k is an integer 396 # satisfying 397 # theta = beta + k*gamma 398 # where theta is a root of z, and beta is a root of pol. 399 # 400 # Now f is a polynomial representing our element alpha as 401 # a polynomial in theta. However, we need a polynomial g 402 # representing alpha in terms of gamma, so we simply use 403 # the relation above to write theta as a polynomial in 404 # gamma, and then we can simply evaluate f at that 405 # polynomial, and this is our g. The code below does 406 # exactly this -- all the business with subst and 407 # self.__x, self.__y is there to deal with Pari's 408 # frustrating representation of relative number fields and 409 # "variable priority." 410 # 411 f = alpha._pari_().lift() 412 z, a, k = self.__rnf[10] 413 beta = -self.__rnf[0][0] / self.__rnf[0][1] 414 theta = beta + k*self.__y 415 f_in_base = f.subst(self.__x, theta).lift().subst(self.__y, self.__x) 416 return self.__V([self.__K.base_field()(f_in_base)]) 385 417 386 # f is the absolute polynomial that defines this number field 387 # element 388 f = alpha.polynomial('x') 389 g = self.__rnf.rnfeltabstorel(pari(f)) 390 # Now g is a relative polynomial that defines this element. 391 # This g is a polynomial in a pari variable x with 392 # coefficients polynomials in a variable y. These 393 # coefficients define the coordinates of the vector we are 394 # constructing. 395 396 # The list v below has the coefficients that are the 397 # components of the vector we are constructing, but each is 398 # converted into polynomials in a variable x, which we will 399 # use to define elements of the base field. 400 (x, y) = (self.__x, self.__y) 401 v = [g.polcoeff(i).subst(x,y) for i in range(self.__n)] 402 B,from_B, _ = self.__B 403 w = [from_B(B(z)) for z in v] 418 # f is the absolute polynomial that defines this number field 419 # element 420 f = alpha.polynomial('x') 421 g = self.__rnf.rnfeltabstorel(pari(f)) 422 # Now g is a relative polynomial that defines this element. 423 # This g is a polynomial in a pari variable x with 424 # coefficients polynomials in a variable y. These 425 # coefficients define the coordinates of the vector we are 426 # constructing. 404 427 405 # Now w gives the coefficients. 406 return self.__V(w) 428 # The list v below has the coefficients that are the 429 # components of the vector we are constructing, but each is 430 # converted into polynomials in a variable x, which we will 431 # use to define elements of the base field. 432 (x, y) = (self.__x, self.__y) 433 v = [g.polcoeff(i).subst(x,y) for i in range(self.__n)] 434 B,from_B, _ = self.__B 435 w = [from_B(B(z)) for z in v] 436 437 # Now w gives the coefficients. 438 return self.__V(w) 407 439 408 440 409 441 class IdentityMap(NumberFieldIsomorphism): … … 492 524 EXAMPLES:: 493 525 494 526 sage: K.<a> = NumberField(x^6 + 4*x^2 + 200) 495 sage: L = K.relativize(K.subfields(3)[0][1], 'b'); L 496 Number Field in b0 with defining polynomial x^2 + a0 over its base field 527 sage: L = K.relativize(K.subfields(3)[0][1], 'b') 497 528 sage: fr, to = L.structure() 498 529 sage: fr 499 530 Relative number field morphism: … … 553 584 """ 554 585 EXAMPLES:: 555 586 556 sage: K.<a,b> = NumberField([x^2+1, x^2+3]); L.<c> = K.absolute_field(); phi = L.structure()[1]587 sage: K.<a,b> = NumberField([x^2+1, x^2+3]); L.<c> = K.absolute_field(); phi = L.structure()[1] 557 588 sage: phi(a+b) 558 589 -1/2*c^3 - 4*c 559 590 sage: L.structure()[0](phi(a+b)) … … 562 593 2/3 563 594 sage: phi(2/3).parent() 564 595 Number Field in c with defining polynomial x^4 + 8*x^2 + 4 596 597 sage: K.<a,b> = NumberField([x^3+2,x^3+3]) 598 sage: L.<c> = K.absolute_field() 599 sage: phi = L.structure()[1] 600 sage: phi(a) 601 -2/45*c^7 + 7/45*c^4 - 311/45*c 602 sage: phi(b) 603 -2/45*c^7 + 7/45*c^4 - 356/45*c 604 sage: phi(a).minpoly() 605 x^3 + 2 606 sage: phi(b).minpoly() 607 x^3 + 3 565 608 """ 566 f = self.__R(x). polynomial()609 f = self.__R(x).absolute_polynomial('x') 567 610 return self.__A._element_class(self.__A, f) 568 611 569 612 class MapAbsoluteToRelativeNumberField(NumberFieldIsomorphism): -
sage/rings/number_field/number_field.py
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field.py
a b 249 249 from sage.rings.real_lazy import RLF, CLF 250 250 251 251 252 # Use this dictionary to set the default implementation for relative 253 # and absolute number fields. Choices include: 254 # - 'ntl' 255 # - 'flint' 256 # - 'generic' 257 # - 'singular' 258 #DEFAULT_IMPLEMENTATION = {'relative':'generic', 'absolute':'generic'} 259 DEFAULT_IMPLEMENTATION = {'relative':'ntl', 'absolute':'ntl'} 260 252 261 _nf_cache = {} 253 262 def NumberField(polynomial, name=None, check=True, names=None, cache=True, 254 263 embedding=None, latex_name=None, … … 477 486 if polynomial.degree() == 2 and polynomial.base_ring() == QQ: 478 487 implementation = 'quadratic' 479 488 else: 480 implementation = 'ntl'489 implementation = DEFAULT_IMPLEMENTATION['absolute'] 481 490 482 491 if cache: 483 492 key = (polynomial, polynomial.base_ring(), name, latex_name, … … 4827 4836 self._order_element_class = number_field_element_generic.OrderElement_generic 4828 4837 self._set_implementation(arithmetic_implementation.ArithmeticImplementation_generic(polynomial)) 4829 4838 else: 4830 raise ValueError, " unknownimplementation '%s'"%implementation4839 raise ValueError, "invalid number field implementation '%s'"%implementation 4831 4840 4832 4841 assert self.implementation() is not None 4833 4842 … … 5313 5322 a = self(elts[i]) 5314 5323 if self.coerce_embedding() is not None: 5315 5324 embedding = self.coerce_embedding()(a) 5316 K = NumberField(f, names=name + str(i), embedding=embedding )5325 K = NumberField(f, names=name + str(i), embedding=embedding, implementation=self.implementation().name()) 5317 5326 5318 5327 from_K = K.hom([a]) # check=False here ?? would be safe unless there are bugs. 5319 5328 … … 7346 7355 7347 7356 sage: K.<a> = NumberField(x^2 + 17); type(a) 7348 7357 <type 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic'> 7349 sage: K.<a> = NumberField(x^2 + 17, implementation='generic'); type(a) 7350 <type 'sage.rings.number_field.number_field_element_generic.NumberFieldElement_generic'> 7351 sage: K.<a> = NumberField(x^2 + 17, implementation='flint'); type(a) 7352 <type 'sage.rings.number_field.number_field_element_flint.NumberFieldElement_flint'> 7353 sage: K.<a> = NumberField(x^2 + 17, implementation='ntl'); type(a) 7354 <type 'sage.rings.number_field.number_field_element_ntl.NumberFieldElement_ntl_absolute'> 7355 """ 7358 """ 7359 # Only 'quadratic' is supported for this field -- get segfaults otherwise, which 7360 # I don't yet have time to fully debug. 7361 implementation = 'quadratic' 7356 7362 NumberField_absolute.__init__(self, polynomial, name=name, check=check, embedding=embedding, 7357 7363 latex_name=latex_name, implementation=implementation) 7358 7364 -
sage/rings/number_field/number_field_element.pyx
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_element.pyx
a b 296 296 # Compute representation of self in terms of relative vector space. 297 297 return self.relative_polynomial()._repr(K.variable_name()) 298 298 299 def absolute_polynomial(self, var=None): 300 """ 301 Return polynomial that represents self in terms of the 302 isomorphic absolute extension. 303 304 EXAMPLES:: 305 306 sage: K.<a> = NumberField(x^6 + 4*x^2 + 200); a.absolute_polynomial() 307 x 308 sage: L.<b,b2> = K.relativize(K.subfields(3)[0][1]) 309 sage: b.absolute_polynomial() 310 x 311 """ 312 if self.is_absolute(): 313 return self.polynomial(var) 314 else: 315 if self._parent.implementation().use_absolute_polynomials(): 316 return self.polynomial(var) 317 else: 318 return self._parent.absolute_field('z').structure()[1](self).polynomial(var) 319 299 320 def relative_polynomial(self, var=None): 300 321 """ 301 322 Return the polynomial in var (default: 'x') over the base … … 404 425 405 426 :: 406 427 407 sage: y = QQ['y'].gen()428 sage: R.<y> = QQ[] 408 429 sage: k.<j> = NumberField(y^3 - 2) 409 430 sage: pari(j) 410 431 Mod(x, x^3 - 2) … … 442 463 443 464 :: 444 465 445 sage: y = QQ['y'].gen()466 sage: R.<y> = QQ[] 446 467 sage: k.<j> = NumberField([y^2 - 7, y^3 - 2]) 447 468 sage: pari(j) 448 469 Mod(42/5515*x^5 - 9/11030*x^4 - 196/1103*x^3 + 273/5515*x^2 + 10281/5515*x + 4459/11030, x^6 - 21*x^4 + 4*x^3 + 147*x^2 + 84*x - 339) … … 498 519 if var is None: 499 520 var = self.number_field().variable_name() 500 521 if self.is_absolute(): 501 f = self.polynomial( )._pari_().subst('x', var)522 f = self.polynomial('x')._pari_().subst('x', var) 502 523 g = self.number_field().pari_polynomial().subst('x', var) 503 524 h = f.Mod(g) 504 525 self.__pari[var] = h 505 526 return h 506 527 else: 507 528 g = self.parent().pari_polynomial(var) 508 f = self. polynomial()._pari_()529 f = self.absolute_polynomial('x')._pari_() 509 530 f = f.subst('x', var) 510 531 h = f.Mod(g) 511 532 self.__pari[var] = h 512 533 return h 513 534 514 515 516 535 def _pari_init_(self, var='x'): 517 536 """ 518 537 Return GP/PARI string representation of self. This is used for -
sage/rings/number_field/number_field_element_generic.pyx
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_element_generic.pyx
a b 60 60 <type 'sage.rings.number_field.number_field_element_generic.NumberFieldElement_generic'> 61 61 sage: a.is_absolute() 62 62 True 63 64 sage: K.<a> = NumberField(x^6 + 4*x^2 + 200) 65 sage: L.<b,b2> = K.relativize(K.subfields(3)[0][1]) 66 sage: b.is_absolute() 67 False 63 68 """ 64 69 return self._parent.is_absolute() 65 70 … … 81 86 self._f = (<NumberFieldElement_generic>f)._f 82 87 else: 83 88 self._f = parent.polynomial_ring()(f) 89 g = self.modulus() 90 if self._f.degree() >= g.degree(): 91 self._f = self._f % g 92 93 def __copy__(self): 94 """ 95 EXAMPLES:: 96 97 sage: K.<a> = NumberField(x^5 + 5); L.<c> = K.absolute_field() 98 sage: c.__copy__() 99 c 100 sage: t = L.maximal_order().1; t 101 c 102 sage: t.__copy__() 103 c 104 sage: type(t.__copy__()) 105 <type 'sage.rings.number_field.number_field_element_generic.OrderElement_generic'> 106 sage: type(c.__copy__()) 107 <type 'sage.rings.number_field.number_field_element_generic.NumberFieldElement_generic'> 108 sage: t.__copy__().parent() 109 Maximal Order in Number Field in c with defining polynomial x^5 + 5 110 sage: c.__copy__().parent() 111 Number Field in c with defining polynomial x^5 + 5 112 """ 113 return self._new(self._f) 84 114 85 115 cdef _new(self, f): 86 116 cdef NumberFieldElement_generic x = PY_NEW(NumberFieldElement_generic) … … 89 119 return x 90 120 91 121 cdef void _randomize(self, num_bound, den_bound, distribution): 92 raise NotImplementedError 122 K = self._parent.base_field() 123 v = [K.random_element(num_bound, den_bound, distribution) for i in self._parent.degree()] 124 f = self._parent.polynomial_ring()(v) 125 self._f = f 126 127 def relative_polynomial(self, var=None): 128 """ 129 Return the relative polynomial that defines self. 130 131 For elements with the generic representation, this is the same as self.polynomial(). 132 133 EXAMPLES:: 134 135 sage: K.<a,b> = NumberField([x^3+7, x^3 + 2], implementation='generic') 136 sage: a.relative_polynomial() 137 x 138 sage: (a+3).relative_polynomial('T') 139 T + 3 140 sage: (2/3*a^2+3).relative_polynomial('T') 141 2/3*T^2 + 3 142 sage: (a^2 + 2*b + 3/4).relative_polynomial() 143 x^2 + 2*b + 3/4 144 """ 145 return self.polynomial(var=var) 93 146 94 147 def polynomial(self, var=None): 95 148 """ 96 149 Return polynomial representative for this number field element, in the variable x. 150 151 For elements with the generic representation, this is the same as self.relative_polynomial(). 97 152 98 153 EXAMPLES:: 99 154 -
sage/rings/number_field/number_field_element_quadratic.pyx
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_element_quadratic.pyx
a b 5 5 computations in quadratic extensions of `\QQ`. 6 6 7 7 AUTHORS: 8 9 - Robert Bradshaw (2007-09): Initial version 10 - David Harvey (2007-10): fix up a few bugs, polish around the edges 11 - David Loeffler (2009-05): add more documentation and tests 8 - Robert Bradshaw (2007-09): Initial version 9 - David Harvey (2007-10): fix up a few bugs, polish around the edges 10 - David Loeffler (2009-05): add more documentation and tests 12 11 13 12 TODO: 14 13 -
sage/rings/number_field/number_field_rel.py
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/number_field_rel.py
a b 3 3 4 4 AUTHORS: 5 5 6 - William Stein (2004, 2005): initial version7 - Steven Sivek (2006-05-12): added support for relative extensions8 - William Stein (2007-09-04): major rewrite and documentation9 - Robert Bradshaw (2008-10): specified embeddings into ambient fields10 - Nick Alexander (2009-01): modernize coercion implementation6 - William Stein (2004, 2005): initial version 7 - Steven Sivek (2006-05-12): added support for relative extensions 8 - William Stein (2007-09-04): major rewrite and documentation 9 - Robert Bradshaw (2008-10): specified embeddings into ambient fields 10 - Nick Alexander (2009-01): modernize coercion implementation 11 11 12 12 This example follows one in the Magma reference manual:: 13 13 … … 150 150 from sage.rings.complex_double import CDF 151 151 from sage.rings.real_lazy import RLF, CLF 152 152 153 # from sage.rings.number_field.number_field import is_AbsoluteNumberField 154 # from sage.rings.number_field.number_field import is_QuadraticField 155 # from sage.rings.number_field.number_field import is_CyclotomicField 153 import number_field 154 156 155 157 156 def is_RelativeNumberField(x): 158 157 r""" … … 258 257 ... 259 258 ValueError: defining polynomial (x^2 + 2) must be irreducible 260 259 """ 260 ######################################### 261 # Check preconditions 262 ######################################### 261 263 if embedding is not None: 262 264 raise NotImplementedError, "Embeddings not implemented for relative number fields" 263 265 if not names is None: name = names … … 272 274 raise ValueError, "Base field and extension cannot have the same name" 273 275 if polynomial.parent().base_ring() != base: 274 276 polynomial = polynomial.change_ring(base) 275 #raise ValueError, "The polynomial must be defined over the base field"276 277 277 # Generate the nf and bnf corresponding to the base field 278 # defined as polynomials in y, e.g. for rnfisfree 279 280 # Convert the polynomial defining the base field into a 281 # polynomial in y to satisfy PARI's ordering requirements. 282 283 if base.is_relative(): 284 abs_base = base.absolute_field(name+'0') 285 from_abs_base, to_abs_base = abs_base.structure() 286 else: 287 abs_base = base 288 from_abs_base = maps.IdentityMap(base) 289 to_abs_base = maps.IdentityMap(base) 290 291 self.__absolute_base_field = abs_base, from_abs_base, to_abs_base 292 self.__base_field = base 293 self.__relative_polynomial = polynomial 294 278 ######################################### 279 # Set the implementation object 280 ######################################### 295 281 if implementation == 'default': 296 implementation = 'ntl'297 282 implementation = number_field.DEFAULT_IMPLEMENTATION['relative'] 283 298 284 if implementation == 'ntl': 299 285 import number_field_element_ntl 300 286 self._element_class = number_field_element_ntl.NumberFieldElement_ntl_relative … … 309 295 import number_field_element_singular 310 296 self._element_class = number_field_element_singular.NumberFieldElement_singular 311 297 self._order_element_class = number_field_element_singular.OrderElement_singular 312 self._set_implementation(arithmetic_implementation.ArithmeticImplementation_singular()) 298 self._set_implementation(arithmetic_implementation.ArithmeticImplementation_singular()) 313 299 else: 314 raise ValueError, "unknown implementation '%s'"%implementation 315 300 raise ValueError, "invalid relative number field implementation '%s'"%implementation 316 301 assert self.implementation() is not None 317 302 303 ################################################################################## 304 # Compute the absolute field isomorphic to the base field, which we must do since 305 # PARI can *only* deal with 2-step towers of number fields. 306 ################################################################################## 307 308 # Generate the nf and bnf corresponding to the base field 309 # defined as polynomials in y, e.g. for rnfisfree. 310 # We also convert the polynomial defining the base field into a 311 # polynomial in y to satisfy PARI's ordering requirements. 312 if base.is_relative(): 313 abs_base = base.absolute_field(name+'0') 314 from_abs_base, to_abs_base = abs_base.structure() 315 else: 316 abs_base = base 317 from_abs_base = maps.IdentityMap(base) 318 to_abs_base = maps.IdentityMap(base) 319 self.__absolute_base_field = abs_base, from_abs_base, to_abs_base 320 self.__base_field = base 321 self.__relative_polynomial = polynomial 322 323 # Check that defining polynomial for this field is irreducible. 318 324 if check: 319 325 if not self.pari_relative_polynomial().polisirreducible(): 320 326 # this is *much* faster than 321 # polynomial.is_irreducible() at some point in the327 # polynomial.is_irreducible(); at some point in the 322 328 # future, is_irreducible should be made faster for 323 329 # polynomials over number fields -- see ticket #4724 324 330 raise ValueError, "defining polynomial (%s) must be irreducible"%polynomial 325 331 332 ######################################### 333 # Compute the generators of this field, 334 # going down the tower and coercing in 335 # each generator. 336 ######################################### 326 337 self.__gens = [None] 327 328 338 v = [None] 329 339 K = base 330 340 names = [name] … … 333 343 v.append(K.gen()) 334 344 K = K.base_field() 335 345 346 ######################################### 347 # Generic initialization 348 ######################################### 336 349 self._assign_names(tuple(names), normalize=False) 337 338 350 NumberField_generic.__init__(self, self.absolute_polynomial(), name=None, 339 351 latex_name=latex_name, check=False, 340 352 embedding=embedding) 341 353 354 ######################################### 355 # Now we can finish our gens initialization 356 ######################################### 342 357 v[0] = self._gen_relative() 343 358 v = [self(x) for x in v] 344 359 self.__gens = tuple(v) … … 785 800 """ 786 801 if x.parent() is self.base_ring() or x.parent() == self.base_ring(): 787 802 return self.__base_inclusion(x) 788 789 803 f = x.polynomial() 790 804 if f.degree() <= 0: 791 805 return self._element_class(self, f[0]) … … 1145 1159 sage: K._coerce_(K.base_field().0)^2 1146 1160 -3 1147 1161 """ 1148 abs_base, from_abs_base, to_abs_base = self.absolute_base_field()1149 # Write element in terms of the absolute base field1150 element = self.base_field().coerce(element)1151 element = to_abs_base(element)1152 # Find an expression in terms of the absolute generator for self of element.1153 expr_x = self._rnfeltreltoabs(element)1154 # Convert to a Sage polynomial, then to one in gen(), and return it1155 1162 R = self.polynomial_ring() 1156 # We do NOT call self(...) because this code is called by 1157 # __init__ before we initialize self.gens(), and self(...) 1158 # uses self.gens() 1159 return self._element_class(self, R(expr_x)) 1163 if self.implementation().use_absolute_polynomials(): 1164 abs_base, from_abs_base, to_abs_base = self.absolute_base_field() 1165 # Write element in terms of the absolute base field 1166 element = self.base_field().coerce(element) 1167 element = to_abs_base(element) 1168 # Find an expression in terms of the absolute generator for self of element. 1169 expr_x = self._rnfeltreltoabs(element) 1170 # Convert to a Sage polynomial, then to one in gen(), and return it 1171 # We do NOT call self(...) because this code is called by 1172 # __init__ before we initialize self.gens(), and self(...) 1173 # uses self.gens() 1174 return self._element_class(self, R(expr_x)) 1175 else: 1176 return self._element_class(self, R(element)) 1160 1177 1161 1178 def _fractional_ideal_class_(self): 1162 1179 """ … … 1426 1443 sage: c^2 + 3 1427 1444 0 1428 1445 """ 1446 if self.implementation().use_absolute_polynomials(): 1447 f = self._absolute_pari_polynomial() 1448 else: 1449 f = self.polynomial_ring().gen() 1450 return self._element_class(self, f) 1451 1452 @cached_method 1453 def _absolute_pari_polynomial(self): 1454 """ 1455 Return polynomial that the generator of self satisfies, in 1456 terms of some choice of defining polynomial for the absolute 1457 extension. 1458 1459 1460 EXAMPLES:: 1461 1462 sage: K.<a,b> = NumberField([x^3+7, x^3 + 2], implementation='generic') 1463 sage: f = K._absolute_pari_polynomial(); f 1464 2/405*x^7 + 7/81*x^4 + 1196/405*x 1465 sage: type(f) 1466 <type 'sage.libs.pari.gen.gen'> 1467 sage: pari('polcompositum(x^3+7, x^3 + 2)') 1468 [x^9 - 15*x^6 + 453*x^3 - 125] 1469 sage: pari('Mod(2/405*x^7 + 7/81*x^4 + 1196/405*x, x^9 + 15*x^6 + 453*x^3 + 125)^3') 1470 Mod(-7, x^9 + 15*x^6 + 453*x^3 + 125) 1471 """ 1429 1472 rnfeqn = self._pari_rnfequation() 1430 f = (pari('x') - rnfeqn[2]*rnfeqn[1]).lift() 1431 g = self._element_class(self, f) 1432 return g 1473 return (pari('x') - rnfeqn[2]*rnfeqn[1]).lift() 1433 1474 1434 1475 def pari_polynomial(self, name='x'): 1435 1476 """ -
sage/rings/number_field/order.py
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/order.py
a b 42 42 from sage.structure.element import is_Element 43 43 44 44 #TODO: fix this 45 from number_field_element_ntl import OrderElement_ntl_ absolute, OrderElement_ntl_relative45 from number_field_element_ntl import OrderElement_ntl_relative 46 46 47 47 from number_field_element_quadratic import OrderElement_quadratic 48 48 … … 1378 1378 abs_order = self._absolute_order 1379 1379 to_abs = abs_order._K.structure()[1] 1380 1380 x = abs_order(to_abs(x)) # will test membership 1381 return OrderElement_ntl_relative(self, x)1381 return self.number_field()._order_element_class(self, x) 1382 1382 1383 1383 def _repr_(self): 1384 1384 """ … … 1485 1485 O = self._absolute_order 1486 1486 K = O.number_field() 1487 1487 from_K, _ = K.structure() 1488 self.__basis = [OrderElement_ntl_relative(self, from_K(a)) for a in O.basis()] 1488 self.__basis = [self.number_field()._order_element_class(self, from_K(a)) for 1489 a in O.basis()] 1489 1490 return self.__basis 1490 1491 1491 1492 def __add__(left, right): -
sage/rings/number_field/todo.txt
diff -r f09d5a19ec34 -r 53c4551ed34f sage/rings/number_field/todo.txt
a b 31 31 32 32 [x] flint elements 33 33 [x] implement OrderElement_flint 34 35 [ ] rewrite order elements to use implementation, e.g., this line in order.py: 34 [x] rewrite order elements to use implementation, e.g., this line in order.py: 36 35 #TODO: fix this 37 36 from number_field_element_ntl import OrderElement_absolute, OrderElement_relative 37 [x] stabilize ntl-based code 38 [x] make sure the _cmp_c_impl's are compatible across number field element implementations. 39 [x] make default implementation computation be centralized somehow?? 38 40 41 [ ] libsingular elements 39 42 [ ] implement OrderElement_singular 40 43 41 [ ] generic: get to work in the *relative case* 44 [ ] write general implementation of algorithm for computing absolute_field 45 [ ] find random element 46 [ ] compute charpoly 47 [ ] if irred and squarefree, it gens 48 [ ] do linear algebra to write everything in terms of that elements 49 [ ] setup maps: 50 this class MapRelativeToAbsoluteNumberField in maps.py maybe has to change 42 51 43 [ ] libsingular elements 52 [ ] rewrite base class "def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):" 53 [ ] fix unpickling of old nf elts 44 54 45 55 [ ] get implementation = 'generic' to fully work as another default type 46 47 [ ] move data out of elements into implementation objects for ntl and quadratic types48 49 [ ] fix all INPUT block list formatting50 51 [ ] rewrite base class "def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):"52 53 [ ] make default implementation computation be centralized somehow??54 55 [ ] fix unpickling of old nf elts56 57 [ ] change number_field_element_quadratic to derive from58 number_field_element code (i.e., the abstract base), instead of59 deriving from number_field_element_ntl.60 61 [ ] write generic ver def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):62 of this in number_field_element.pyx63 64 [ ] make sure the _cmp_c_impl's are compatible across number field element implementations.65 66 [ ] format all documentation perfectly67 68 56 [ ] make the implementation part of elements into a cython class hierarchy with 69 57 [ ] implementation object needs to get pickled with number field -- test 70 58 [ ] flint implementation object 71 59 [ ] libsingular implementation object 60 [ ] benchmark for comparison with magma 61 [ ] get doctest coverage to 100% for the number_field directory 72 62 73 [ ] benchmark *every single operation* with each type of elements... for sanity 74 [ ] benchmark for comparison with magma 75 76 [ ] get doctest coverage to 100% for the number_field directory 63 [ ] optimization -- make computing an absolute field lazy, and only 64 do it when we really need it for some computation, e.g., 65 mazimal order. 66 67 [ ] this warning: "WARNING: Doing arithmetic in towers of relative 68 fields that depends on canonical coercions is currently VERY SLOW. It 69 is much better to explicitly coerce all elements into a common field, 70 then do arithmetic with them there (which is quite fast)." 77 71 78 72 [ ] arithmetic/automatic coercions between isomorphic fields, where 79 73 the only difference is the underlying implementation of … … 86 80 [ ] quaternion algebra elements -- deal with that they only work for ntl number field elements 87 81 [ ] matrix_cyclo_dense.pyx 88 82 89 [ ] write a function that can be included in doctests that90 guarantees at least a certain amount of speed. add this to91 library so that nobody can frack my shizzle up.92 93 83 [ ] add proper headers 94 84 [ ] add overview docs to each file 95 85 [ ] overview of everything … … 101 91 [ ] suspicious bound: 102 92 " D = (Dpoly.numer() * Dpoly.denom()).squarefree_part(bound=10000) " 103 93 104 OTHER:94 For LATER: 105 95 106 [ ] optimize -- creation of the order generated by elements, especially in relative case (use singular?) 107 [ ] plug in sebastian's code for QQ['x']? 108 [ ] Organize a similar refactoring for function fields. 109 [ ] to look into: non-maximal orders and GB's over ZZ??? 96 [ ] write a function that can be included in doctests that 97 guarantees at least a certain amount of speed. add this to 98 library so that nobody can frack my shizzle up. 99 100 [ ] benchmark *every single operation* with each type of elements... for sanity 101 [ ] change number_field_element_quadratic to derive from 102 number_field_element code (i.e., the abstract base), instead of 103 deriving from number_field_element_ntl. 104 [ ] fix all INPUT block list formatting 105 [ ] move data out of elements into implementation objects for ntl and quadratic types 106 [ ] optimize -- creation of the order generated by elements, especially in relative case (use singular?) 107 [ ] plug in sebastian's code for QQ['x']? 108 [ ] Organize a similar refactoring for function fields. 109 [ ] to look into: non-maximal orders and GB's over ZZ??? 110 110