Changeset 7427:3fef61943bd8
- Timestamp:
- 11/25/07 14:04:38 (5 years ago)
- Branch:
- default
- Location:
- sage
- Files:
-
- 7 edited
-
calculus/calculus.py (modified) (3 diffs)
-
functions/constants.py (modified) (2 diffs)
-
rings/algebraic_real.py (modified) (77 diffs)
-
rings/all.py (modified) (1 diff)
-
rings/complex_field.py (modified) (2 diffs)
-
rings/real_mpfi.pyx (modified) (2 diffs)
-
rings/real_mpfr.pyx (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sage/calculus/calculus.py
r7391 r7427 2831 2831 return ring(self) 2832 2832 2833 def _algebraic_(self, field): 2834 """ 2835 EXAMPLES: 2836 sage: a = SR(5/6) 2837 sage: AA(a) 2838 5/6 2839 sage: type(AA(a)) 2840 <class 'sage.rings.algebraic_real.AlgebraicReal'> 2841 sage: QQbar(a) 2842 5/6 2843 sage: type(QQbar(a)) 2844 <class 'sage.rings.algebraic_real.AlgebraicNumber'> 2845 sage: from sage.calculus.calculus import SymbolicConstant 2846 sage: i = SymbolicConstant(I) 2847 sage: AA(i) 2848 Traceback (most recent call last): 2849 ... 2850 TypeError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real 2851 sage: QQbar(i) 2852 1*I 2853 sage: phi = SymbolicConstant(golden_ratio) 2854 sage: AA(phi) 2855 [1.6180339887498946 .. 1.6180339887498950] 2856 sage: QQbar(phi) 2857 [1.6180339887498946 .. 1.6180339887498950] 2858 """ 2859 2860 # Out of the many kinds of things that can be in a SymbolicConstant, 2861 # we accept only rational numbers (or things that can be coerced 2862 # to rational) and a few instances of Constant. 2863 2864 if isinstance(self._obj, sage.functions.constants.Constant) \ 2865 and hasattr(self._obj, '_algebraic_'): 2866 return self._obj._algebraic_(field) 2867 return field(Rational(self._obj)) 2833 2868 2834 2869 … … 3073 3108 rops = [op._real_rqdf_(field) for op in self._operands] 3074 3109 return self._operator(*rops) 3110 3111 def _algebraic_(self, field): 3112 """ 3113 Convert a symbolic expression to an algebraic number. 3114 3115 EXAMPLES: 3116 sage: QQbar(sqrt(2) + sqrt(8)) 3117 [4.2426406871192847 .. 4.2426406871192857] 3118 sage: AA(sqrt(2) ^ 4) == 4 3119 True 3120 sage: AA(-golden_ratio) 3121 [-1.6180339887498950 .. -1.6180339887498946] 3122 sage: QQbar((2*I)^(1/2)) 3123 [1.0000000000000000 .. 1.0000000000000000] + [1.0000000000000000 .. 1.0000000000000000]*I 3124 """ 3125 3126 # We try to avoid simplifying, because maxima's simplify command 3127 # can change the value of a radical expression (by changing which 3128 # root is selected). 3129 try: 3130 if self._operator is operator.pow: 3131 base = field(self._operands[0]) 3132 expt = Rational(self._operands[1]) 3133 return field(field(base) ** expt) 3134 else: 3135 rops = [field(op) for op in self._operands] 3136 return self._operator(*rops) 3137 except TypeError: 3138 if self.is_simplified(): 3139 raise 3140 else: 3141 return self.simplify()._algebraic_(field) 3075 3142 3076 3143 def _is_atomic(self): … … 4011 4078 else: 4012 4079 return z 4080 4081 def _algebraic_(self, field): 4082 """ 4083 Coerce to an algebraic number. 4084 4085 EXAMPLES: 4086 sage: QQbar(sqrt(2)) 4087 [1.4142135623730949 .. 1.4142135623730952] 4088 sage: AA(abs(1+I)) 4089 [1.4142135623730949 .. 1.4142135623730952] 4090 """ 4091 # We try to avoid simplifying, because maxima's simplify command 4092 # can change the value of a radical expression (by changing which 4093 # root is selected). 4094 f = self._operands[0] 4095 g = self._operands[1] 4096 try: 4097 return field(f(g._algebraic_(field))) 4098 except TypeError: 4099 if self.is_simplified(): 4100 raise 4101 else: 4102 return self.simplify()._algebraic_(field) 4103 4013 4104 4014 4105 class PrimitiveFunction(SymbolicExpression): -
sage/functions/constants.py
r7348 r7427 538 538 raise TypeError 539 539 540 def _algebraic_(self, field): 541 import sage.rings.algebraic_real 542 return field(sage.rings.algebraic_real.QQbar_I) 543 540 544 def __abs__(self): 541 545 return Integer(1) … … 692 696 def _mpfr_(self,R): #is this OK for _mpfr_ ? 693 697 return (R(1)+R(5).sqrt())*R(0.5) 698 699 def _algebraic_(self, field): 700 import sage.rings.algebraic_real 701 return field(sage.rings.algebraic_real.get_AA_golden_ratio()) 694 702 695 703 golden_ratio = GoldenRatio() -
sage/rings/algebraic_real.py
r7156 r7427 1 1 """ 2 Field of Algebraic Reals2 Field of Algebraic Numbers 3 3 4 4 AUTHOR: 5 5 -- Carl Witty (2007-01-27): initial version 6 7 This is an implementation of the algebraic reals (the real numbers which 8 are the zero of a polynomial in ZZ[x]). All computations are exact. 9 10 As with many other implementations of the algebraic numbers, we avoid 11 computing a number field and working in the number field whenever possible. 6 -- Carl Witty (2007-10-29): massive rewrite to support complex 7 as well as real numbers 8 9 This is an implementation of the algebraic numbers (the complex 10 numbers which are the zero of a polynomial in ZZ[x]; in other words, 11 the algebraic closure of QQ, with an embedding into CC). All 12 computations are exact. We also include an implementation of the 13 algebraic reals (the intersection of the algebraic numbers with RR). 14 The field of algebraic numbers is available with abbreviation QQbar; 15 the field of algebraic reals has abbreviation AA. 16 17 As with many other implementations of the algebraic numbers, we try 18 hard to avoid computing a number field and working in the number 19 field; instead, we use floating-point interval arithmetic whenever 20 possible (basically whenever we need to prove disequalities), and 21 resort to symbolic computation only as needed (basically to prove 22 equalities). 12 23 13 24 Algebraic numbers exist in one of the following forms: 14 25 15 26 * a rational number 27 * the product of a rational number and an n'th root of unity 16 28 * the sum, difference, product, or quotient of algebraic numbers 29 * the negation, inverse, absolute value, norm, real part, 30 imaginary part, or complex conjugate of an algebraic number 17 31 * a particular root of a polynomial, given as a polynomial with 18 32 algebraic coefficients, an isolating interval (given as a … … 23 37 coefficients and the polynomial is given as a NumberFieldElement 24 38 25 An algebraic number can be coerced into RealIntervalField; every algebraic 26 number has a cached interval of the highest precision yet calculated. 39 The multiplicative subgroup of the algebraic numbers generated 40 by the rational numbers and the roots of unity is handled particularly 41 efficiently, as long as these roots of unity come from the QQbar.zeta() 42 method. Cyclotomic fields in general are fairly efficient, again 43 as long as they are derived from QQbar.zeta(). 44 45 An algebraic number can be coerced into ComplexIntervalField (or 46 RealIntervalField, for algebraic reals); every algebraic number has a 47 cached interval of the highest precision yet calculated. 27 48 28 49 Everything is done with intervals except for comparisons. By default, … … 45 66 sage: sqrt(AA(2)) > 0 46 67 True 47 sage: (sqrt(5 + 2*sqrt(AA(6))) - sqrt(AA(3)))**2 == 2 68 sage: (sqrt(5 + 2*sqrt(QQbar(6))) - sqrt(QQbar(3)))^2 == 2 69 True 70 sage: AA((sqrt(5 + 2*sqrt(6)) - sqrt(3))^2) == 2 48 71 True 49 72 … … 83 106 True 84 107 108 We can coerce from symbolic expressions: 109 110 sage: QQbar(sqrt(-5)) 111 [2.2360679774997893 .. 2.2360679774997899]*I 112 sage: AA(sqrt(2) + sqrt(3)) 113 [3.1462643699419721 .. 3.1462643699419726] 114 sage: AA(sqrt(2)) + sqrt(3) 115 [3.1462643699419721 .. 3.1462643699419726] 116 sage: sqrt(2) + QQbar(sqrt(3)) 117 [3.1462643699419721 .. 3.1462643699419726] 118 sage: QQbar(I) 119 1*I 120 sage: AA(I) 121 Traceback (most recent call last): 122 ... 123 TypeError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real 124 sage: QQbar(I * golden_ratio) 125 [1.6180339887498946 .. 1.6180339887498950]*I 126 sage: AA(golden_ratio)^2 - AA(golden_ratio) 127 1 128 sage: QQbar((-8)^(1/3)) 129 [0.99999999999999988 .. 1.0000000000000003] + [1.7320508075688771 .. 1.7320508075688775]*I 130 sage: AA((-8)^(1/3)) 131 -2 132 sage: QQbar((-4)^(1/4)) 133 [1.0000000000000000 .. 1.0000000000000000] + [1.0000000000000000 .. 1.0000000000000000]*I 134 sage: AA((-4)^(1/4)) 135 Traceback (most recent call last): 136 ... 137 TypeError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real 138 139 We can explicitly coerce from QQ[I]. (Technically, this is not quite 140 kosher, since QQ[I] doesn't come with an embedding; we don't know 141 whether the field generator is supposed to map to +I or -I. We assume 142 that for any quadratic field with polynomial x^2+1, the generator maps 143 to +I.) 144 145 sage: K.<im> = QQ[I] 146 sage: pythag = QQbar(3/5 + 4*im/5); pythag 147 4/5*I + 3/5 148 sage: pythag.abs() == 1 149 True 150 151 However, implicit coercion from QQ[I] is not allowed. 152 153 sage: QQbar(1) + im 154 Traceback (most recent call last): 155 ... 156 TypeError: unsupported operand parent(s) for '+': 'Algebraic Field' and 'Number Field in I with defining polynomial x^2 + 1' 157 158 We can implicitly coerce from algebraic reals to algebraic numbers: 159 160 sage: a = QQbar(1); print a, a.parent() 161 1 Algebraic Field 162 sage: b = AA(1); print b, b.parent() 163 1 Algebraic Real Field 164 sage: c = a + b; print c, c.parent() 165 2 Algebraic Field 166 85 167 Some computation with radicals: 86 168 … … 102 184 True 103 185 104 Algebraic reals which are known to be rational print as rationals; otherwise105 they print as intervals (with 53-bit precision).186 Algebraic numbers which are known to be rational print as rationals; 187 otherwise they print as intervals (with 53-bit precision). 106 188 107 189 sage: AA(2)/3 108 190 2/3 109 sage: AA(5/7)191 sage: QQbar(5/7) 110 192 5/7 111 sage: two = sqrt(AA(4)); two 193 sage: QQbar(1/3 - 1/4*I) 194 -1/4*I + 1/3 195 sage: two = QQbar(4).nth_root(4)^2; two 112 196 [1.9999999999999997 .. 2.0000000000000005] 113 197 sage: two == 2; two … … 117 201 [1.6180339887498946 .. 1.6180339887498950] 118 202 203 We can find the real and imaginary parts of an algebraic number (exactly). 204 205 sage: r = QQbar.polynomial_root(x^5 - x - 1, CIF(RIF(0.1, 0.2), RIF(1.0, 1.1))); r 206 [0.18123244446987538 .. 0.18123244446987541] + [1.0839541013177105 .. 1.0839541013177108]*I 207 sage: r.real() 208 [0.18123244446987538 .. 0.18123244446987541] 209 sage: r.imag() 210 [1.0839541013177105 .. 1.0839541013177108] 211 sage: r.minpoly() 212 x^5 - x - 1 213 sage: r.real().minpoly() 214 x^10 + 3/16*x^6 + 11/32*x^5 - 1/64*x^2 + 1/128*x - 1/1024 215 sage: r.imag().minpoly() # this takes a long time (143s on my laptop) 216 x^20 - 5/8*x^16 - 95/256*x^12 - 625/1024*x^10 - 5/512*x^8 - 1875/8192*x^6 + 25/4096*x^4 - 625/32768*x^2 + 2869/1048576 217 218 We can find the absolute value and norm of an algebraic number exactly. 219 (Note that we define the norm as the product of a number and its 220 complex conjugate; this is the algebraic definition of norm, if we 221 view QQbar as AA[I].) 222 223 sage: r = QQbar((-8)^(1/3)); r 224 [0.99999999999999988 .. 1.0000000000000003] + [1.7320508075688771 .. 1.7320508075688775]*I 225 sage: r.abs() == 2 226 True 227 sage: r.norm() == 4 228 True 229 sage: (r+I).norm().minpoly() 230 x^2 - 10*x + 13 231 sage: r = AA.polynomial_root(x^2 - x - 1, RIF(-1, 0)); r 232 [-0.61803398874989491 .. -0.61803398874989479] 233 sage: r.abs().minpoly() 234 x^2 + x - 1 235 236 We can compute the multiplicative order of an algebraic number. 237 238 sage: QQbar(-1/2 + I*sqrt(3)/2).multiplicative_order() 239 3 240 sage: QQbar(-sqrt(3)/2 + I/2).multiplicative_order() 241 12 242 sage: QQbar.zeta(12345).multiplicative_order() 243 12345 244 245 Cyclotomic fields are very fast as long as we only multiply and divide: 246 247 sage: z3_3 = QQbar.zeta(3) * 3 248 sage: z4_4 = QQbar.zeta(4) * 4 249 sage: z5_5 = QQbar.zeta(5) * 5 250 sage: z6_6 = QQbar.zeta(6) * 6 251 sage: z20_20 = QQbar.zeta(20) * 20 252 sage: z3_3 * z4_4 * z5_5 * z6_6 * z20_20 253 7200 254 255 And they're still pretty fast even if you add and subtract, and trigger 256 exact computation: 257 258 sage: (z3_3 + z4_4 + z5_5 + z6_6 + z20_20)._exact_value() 259 4*zeta60^15 + 5*zeta60^12 + 9*zeta60^10 + 20*zeta60^3 - 3 where a^16 + a^14 - a^10 - a^8 - a^6 + a^2 + 1 = 0 and a in [0.99452189536827328 .. 0.99452189536827341] + [0.10452846326765345 .. 0.10452846326765352]*I 260 119 261 The paper _ARPREC: An Arbitrary Precision Computation Package_ discusses 120 262 this result. Evidently it is difficult to find, but we can easily 121 263 verify it. 122 264 123 sage: alpha = AA.polynomial_root(x^10 + x^9 - x^7 - x^6 - x^5 - x^4 - x^3 + x + 1, RIF(1, 1.2))265 sage: alpha = QQbar.polynomial_root(x^10 + x^9 - x^7 - x^6 - x^5 - x^4 - x^3 + x + 1, RIF(1, 1.2)) 124 266 sage: lhs = alpha^630 - 1 125 267 sage: rhs_num = (alpha^315 - 1) * (alpha^210 - 1) * (alpha^126 - 1)^2 * (alpha^90 - 1) * (alpha^3 - 1)^3 * (alpha^2 - 1)^5 * (alpha - 1)^3 … … 129 271 [2.6420403358193507e44 .. 2.6420403358193520e44] 130 272 sage: rhs 131 [2.642040335819350 7e44 .. 2.6420403358193520e44]273 [2.6420403358193503e44 .. 2.6420403358193520e44] 132 274 sage: lhs - rhs 133 [- 63347712947806569000000000000. .. 65804250213263496000000000000.]275 [-79344219392947342000000000000. .. 81800756658404269000000000000.] 134 276 sage: lhs == rhs 135 277 True 136 278 sage: lhs - rhs 137 [0.00000000000000000 .. 0.00000000000000000]279 0 138 280 sage: lhs._exact_value() 139 281 -242494609856316402264822833062350847769474540*a^9 + 862295472068289472491654837785947906234680703*a^8 - 829559238431038252116584538075753012193290520*a^7 - 125882239615006638366472766103700441555126185*a^6 + 1399067970863104691667276008776398309383579345*a^5 - 1561176687069361567616835847286958553574223422*a^4 + 761706318888840943058230840550737823821027895*a^3 + 580740464974951394762758666210754821723780266*a^2 - 954587496403409756503464154898858512440951323*a + 546081123623099782018260884934770383777092602 where a^10 - 4*a^9 + 5*a^8 - a^7 - 6*a^6 + 9*a^5 - 6*a^4 - a^3 + 5*a^2 - 4*a + 1 = 0 and a in [0.44406334400909258 .. 0.44406334400909265] … … 144 286 from sage.structure.parent_gens import ParentWithGens 145 287 from sage.rings.real_mpfr import RR 146 from sage.rings.real_mpfi import RealIntervalField, RIF, RealIntervalFieldElement 147 from sage.rings.polynomial.polynomial_ring import PolynomialRing 288 from sage.rings.real_mpfi import RealIntervalField, RIF, RealIntervalFieldElement, is_RealIntervalFieldElement 289 from sage.rings.complex_field import ComplexField 290 from sage.rings.complex_interval_field import ComplexIntervalField, is_ComplexIntervalField 291 from sage.rings.complex_interval import ComplexIntervalFieldElement, is_ComplexIntervalFieldElement 292 from sage.rings.polynomial.all import PolynomialRing, is_Polynomial 148 293 from sage.rings.integer_ring import ZZ 149 294 from sage.rings.rational_field import QQ 150 from sage.rings.number_field.number_field import NumberField 295 from sage.rings.number_field.number_field import NumberField, NumberField_quadratic, QuadraticField, CyclotomicField 151 296 from sage.rings.number_field.number_field_element import is_NumberFieldElement 297 from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_quadratic 152 298 from sage.rings.arith import factor 153 299 from sage.libs.pari.gen import pari 154 300 from sage.structure.element import generic_power 301 import infinity 302 from sage.misc.functional import cyclotomic_polynomial 303 304 CC = ComplexField() 305 CIF = ComplexIntervalField() 155 306 156 307 # Singleton object implementation copied from integer_ring.py … … 163 314 return _obj 164 315 165 class AlgebraicRealField(_uniq_alg, sage.rings.ring.Field): 316 _obj_r = None 317 class _uniq_alg_r(object): 318 def __new__(cls): 319 global _obj_r 320 if _obj_r is None: 321 _obj_r = sage.rings.ring.Field.__new__(cls) 322 return _obj_r 323 324 is_SymbolicExpressionRing = None 325 326 def late_import(): 327 global is_SymbolicExpressionRing 328 if is_SymbolicExpressionRing is None: 329 import sage.calculus.calculus 330 is_SymbolicExpressionRing = sage.calculus.calculus.is_SymbolicExpressionRing 331 332 class AlgebraicField_common(sage.rings.ring.Field): 333 def default_interval_prec(self): 334 return 64 335 336 def is_finite(self): 337 return False 338 339 def characteristic(self): 340 return sage.rings.integer.Integer(0) 341 342 def order(self): 343 return infinity.infinity 344 345 def common_polynomial(self, poly): 346 """ 347 Given a polynomial with algebraic coefficients, returns a 348 wrapper that caches high-precision calculations and 349 factorizations. This wrapper can be passed to polynomial_root 350 in place of the polynomial. 351 352 Using common_polynomial makes no semantic difference, but will 353 improve efficiency if you are dealing with multiple roots 354 of a single polynomial. 355 356 EXAMPLES: 357 sage: x = polygen(ZZ) 358 sage: p = AA.common_polynomial(x^2 - x - 1) 359 sage: phi = AA.polynomial_root(p, RIF(1, 2)) 360 sage: tau = AA.polynomial_root(p, RIF(-1, 0)) 361 sage: phi + tau == 1 362 True 363 sage: phi * tau == -1 364 True 365 366 sage: x = polygen(SR) 367 sage: p = (x - sqrt(-5)) * (x - sqrt(3)); p 368 x^2 + ((1 - sqrt(3))*(1 - sqrt(5)*I) - sqrt(3)*sqrt(5)*I - 1)*x + sqrt(3)*sqrt(5)*I 369 sage: p = QQbar.common_polynomial(p) 370 sage: a = QQbar.polynomial_root(p, CIF(RIF(-0.1, 0.1), RIF(2, 3))); a 371 [-6.1814409042940318e-19 .. 6.0853195377215860e-19] + [2.2360679774997893 .. 2.2360679774997899]*I 372 sage: b = QQbar.polynomial_root(p, RIF(1, 2)); b 373 [1.7320508075688771 .. 1.7320508075688775] 374 375 These "common polynomials" can be shared between real and 376 complex roots: 377 sage: p = AA.common_polynomial(x^3 - x - 1) 378 sage: r1 = AA.polynomial_root(p, RIF(1.3, 1.4)); r1 379 [1.3247179572447458 .. 1.3247179572447461] 380 sage: r2 = QQbar.polynomial_root(p, CIF(RIF(-0.7, -0.6), RIF(0.5, 0.6))); r2 381 [-0.66235897862237303 .. -0.66235897862237291] + [0.56227951206230120 .. 0.56227951206230132]*I 382 """ 383 return AlgebraicPolynomialTracker(poly) 384 385 class AlgebraicRealField(_uniq_alg_r, AlgebraicField_common): 166 386 r""" 167 387 The field of algebraic reals. 168 169 388 """ 170 389 171 390 def __init__(self): 172 391 ParentWithGens.__init__(self, self, ('x',), normalize=False) 173 self._default_interval_field = RealIntervalField(64) 392 393 def __call__(self, x): 394 """ 395 Coerce x into the field of algebraic real numbers. 396 397 """ 398 399 if isinstance(x, AlgebraicReal): 400 return x 401 elif isinstance(x, AlgebraicNumber): 402 if x.imag().is_zero(): 403 return x.real() 404 else: 405 raise TypeError, "Cannot coerce algebraic number with non-zero imaginary part to algebraic real" 406 elif hasattr(x, '_algebraic_'): 407 return x._algebraic_(AA) 408 return AlgebraicReal(x) 174 409 175 410 def _repr_(self): 176 return "Algebraic Field"411 return "Algebraic Real Field" 177 412 178 413 # Is there a standard representation for this? 179 414 def _latex_(self): 180 415 return "\\mathbf{A}" 181 182 def __call__(self, x):183 """184 Coerce x into the field of algebraic numbers.185 186 """187 188 if isinstance(x, AlgebraicRealNumber):189 return x190 return AlgebraicRealNumber(x)191 416 192 417 def _coerce_impl(self, x): … … 194 419 sage.rings.rational.Rational)): 195 420 return self(x) 421 elif hasattr(x, '_algebraic_'): 422 return x._algebraic_(AA) 196 423 raise TypeError, 'no implicit coercion of element to the algebraic numbers' 424 425 def has_coerce_map_from_impl(self, from_par): 426 if from_par == ZZ or from_par == QQ or from_par == int or from_par == long: 427 return True 428 late_import() 429 if is_SymbolicExpressionRing(from_par): 430 return True 431 return False 197 432 198 433 def _is_valid_homomorphism_(self, codomain, im_gens): … … 202 437 return False 203 438 204 def default_interval_field(self):205 return self._default_interval_field206 207 439 def gens(self): 208 440 return (self(1), ) … … 217 449 return 1 218 450 219 def is_finite(self):220 return False221 222 451 def is_atomic_repr(self): 223 452 return True 224 225 def characteristic(self):226 return sage.rings.integer.Integer(0)227 228 def order(self):229 return infinity.infinity230 453 231 454 def zeta(self, n=2): … … 237 460 raise ValueError, "no n-th root of unity in algebraic reals" 238 461 239 def common_polynomial(self, poly):240 """241 Given a polynomial with algebraic coefficients, returns a242 wrapper that caches high-precision calculations and243 factorizations. This wrapper can be passed to polynomial_root244 in place of the polynomial.245 246 Using common_polynomial makes no semantic difference, but will247 improve efficiency if you are dealing with multiple roots248 of a single polynomial.249 250 EXAMPLES:251 sage: x = polygen(AA)252 sage: p = AA.common_polynomial(x^2 - x - 1)253 sage: phi = AA.polynomial_root(p, RIF(0, 2))254 sage: tau = AA.polynomial_root(p, RIF(-2, 0))255 sage: phi + tau == 1256 True257 sage: phi * tau == -1258 True259 """260 return AlgebraicPolynomialTracker(poly)261 262 462 def polynomial_root(self, poly, interval, multiplicity=1): 263 463 """ … … 280 480 281 481 Note that if you are constructing multiple roots of a single 282 polynomial, it is better to use AA.common_polynomial 283 to get a shared polynomial. 482 polynomial, it is better to use AA.common_polynomial (or 483 QQbar.common_polynomial; the two are equivalent) to get a 484 shared polynomial. 284 485 285 486 EXAMPLES: 286 487 sage: x = polygen(AA) 287 sage: phi = AA.polynomial_root(x^2 - x - 1, RIF( 0, 2)); phi488 sage: phi = AA.polynomial_root(x^2 - x - 1, RIF(1, 2)); phi 288 489 [1.6180339887498946 .. 1.6180339887498950] 289 490 sage: p = (x-1)^7 * (x-2) … … 297 498 [1.4142135623730949 .. 1.4142135623730952] 298 499 True 299 """ 300 return AlgebraicRealNumber(AlgebraicRealNumberRoot(poly, interval, multiplicity)) 500 501 We allow complex polynomials, as long as the particular root 502 in question is real. 503 sage: K.<im> = QQ[I] 504 sage: x = polygen(K) 505 sage: p = (im + 1) * (x^3 - 2); p 506 (I + 1)*x^3 - 2*I - 2 507 sage: r = AA.polynomial_root(p, RIF(1, 2)); r^3 508 [1.9999999999999997 .. 2.0000000000000005] 509 """ 510 if not is_RealIntervalFieldElement(interval): 511 raise ValueError, "interval argument of .polynomial_root on algebraic real field must be real" 512 513 return AlgebraicReal(ANRoot(poly, interval, multiplicity)) 301 514 302 515 def is_AlgebraicRealField(F): … … 305 518 AA = AlgebraicRealField() 306 519 307 def rif_seq(): 520 class AlgebraicField(_uniq_alg, AlgebraicField_common): 521 """ 522 The field of algebraic numbers. 523 """ 524 525 def __init__(self): 526 ParentWithGens.__init__(self, AA, ('I',), normalize=False) 527 528 def __call__(self, x): 529 """ 530 Coerce x into the field of algebraic numbers. 531 532 """ 533 534 if isinstance(x, AlgebraicNumber): 535 return x 536 elif isinstance(x, AlgebraicReal): 537 return AlgebraicNumber(x._descr) 538 elif hasattr(x, '_algebraic_'): 539 return x._algebraic_(QQbar) 540 return AlgebraicNumber(x) 541 542 def _repr_(self): 543 return "Algebraic Field" 544 545 def _coerce_impl(self, x): 546 if isinstance(x, (int, long, sage.rings.integer.Integer, 547 sage.rings.rational.Rational)): 548 return self(x) 549 elif hasattr(x, '_algebraic_'): 550 return x._algebraic_(QQbar) 551 elif isinstance(x, AlgebraicReal): 552 return AlgebraicNumber(x._descr) 553 raise TypeError, 'no implicit coercion of element to the algebraic numbers' 554 555 def has_coerce_map_from_impl(self, from_par): 556 if from_par == ZZ or from_par == QQ or from_par == int or from_par == long: 557 return True 558 if from_par == AA: 559 return True 560 late_import() 561 if is_SymbolicExpressionRing(from_par): 562 return True 563 return False 564 565 def gens(self): 566 return(QQbar_I, ) 567 568 def gen(self, n=0): 569 if n == 0: 570 return QQbar_I 571 else: 572 raise IndexError, "n must be 0" 573 574 def ngens(self): 575 return 1 576 577 def is_atomic_repr(self): 578 return False 579 580 def zeta(self, n=4): 581 """ 582 Returns a primitive n'th root of unity. (In fact, returns 583 exp(2*pi*I/n).) 584 585 EXAMPLES: 586 sage: QQbar.zeta(1) 587 1 588 sage: QQbar.zeta(2) 589 -1 590 sage: QQbar.zeta(3) 591 [-0.50000000000000012 .. -0.49999999999999994] + [0.86602540378443859 .. 0.86602540378443871]*I 592 sage: QQbar.zeta(4) 593 1*I 594 sage: QQbar.zeta() 595 1*I 596 sage: QQbar.zeta(5) 597 [0.30901699437494739 .. 0.30901699437494746] + [0.95105651629515353 .. 0.95105651629515365]*I 598 sage: QQbar.zeta(314159) 599 [0.99999999979999965 .. 0.99999999979999977] + [0.000020000016891958231 .. 0.000020000016891958236]*I 600 """ 601 return AlgebraicNumber(ANRootOfUnity(QQ_1/n, QQ_1)) 602 603 def polynomial_root(self, poly, interval, multiplicity=1): 604 """ 605 Given a polynomial with algebraic coefficients and an interval 606 enclosing exactly one root of the polynomial, constructs 607 an algebraic real representation of that root. 608 609 The polynomial need not be irreducible, or even squarefree; but 610 if the given root is a multiple root, its multiplicity must be 611 specified. (IMPORTANT NOTE: Currently, multiplicity-k roots 612 are handled by taking the (k-1)th derivative of the polynomial. 613 This means that the interval must enclose exactly one root 614 of this derivative.) 615 616 The conditions on the arguments (that the interval encloses exactly 617 one root, and that multiple roots match the given multiplicity) 618 are not checked; if they are not satisfied, an error may be 619 thrown (possibly later, when the algebraic number is used), 620 or wrong answers may result. 621 622 Note that if you are constructing multiple roots of a single 623 polynomial, it is better to use QQbar.common_polynomial 624 to get a shared polynomial. 625 626 EXAMPLES: 627 sage: x = polygen(QQbar) 628 sage: phi = QQbar.polynomial_root(x^2 - x - 1, RIF(0, 2)); phi 629 [1.6180339887498946 .. 1.6180339887498950] 630 sage: p = (x-1)^7 * (x-2) 631 sage: r = QQbar.polynomial_root(p, RIF(9/10, 11/10), multiplicity=7) 632 sage: r; r == 1 633 [1.0000000000000000 .. 1.0000000000000000] 634 True 635 sage: p = (x-phi)*(x-sqrt(QQbar(2))) 636 sage: r = QQbar.polynomial_root(p, RIF(1, 3/2)) 637 sage: r; r == sqrt(QQbar(2)) 638 [1.4142135623730949 .. 1.4142135623730952] 639 True 640 """ 641 return AlgebraicNumber(ANRoot(poly, interval, multiplicity)) 642 643 def is_AlgebraicField(F): 644 return isinstance(F, AlgebraicField) 645 646 QQbar = AlgebraicField() 647 648 def prec_seq(): 308 649 # XXX Should do some testing to see where the efficiency breaks are 309 # in MPFR. 650 # in MPFR. We could also test variants like "bits = bits + bits // 2" 651 # (I think this is what MPFR uses internally). 310 652 bits = 64 311 653 while True: 312 yield RealIntervalField(bits)654 yield bits 313 655 bits = bits * 2 314 # # XXX temporary debugging: 315 # if bits > 1024: 316 # break 656 657 _short_prec_seq = (64, 128, None) 658 def short_prec_seq(): return _short_prec_seq 659 660 def tail_prec_seq(): 661 bits = 256 662 while True: 663 yield bits 664 bits = bits * 2 665 666 def rational_exact_root(r, d): 667 """ 668 Checks whether the rational r is an exact d'th power. If so, returns 669 the d'th root of r; otherwise, returns None. 670 671 EXAMPLES: 672 sage: from sage.rings.algebraic_real import rational_exact_root 673 sage: rational_exact_root(16/81, 4) 674 2/3 675 sage: rational_exact_root(8/81, 3) is None 676 True 677 """ 678 num = r.numerator() 679 den = r.denominator() 680 681 (num_rt, num_exact) = num.nth_root(d, report_exact=True) 682 if not num_exact: return None 683 (den_rt, den_exact) = den.nth_root(d, report_exact=True) 684 if not den_exact: return None 685 return (num_rt / den_rt) 317 686 318 687 def clear_denominators(poly): … … 328 697 (Inspired by Pari's primitive_pol_to_monic().) 329 698 699 We assume that coefficient denominators are "small"; the algorithm 700 factors the denominators, to give the smallest possible scale factor. 701 330 702 EXAMPLES: 331 703 sage: from sage.rings.algebraic_real import clear_denominators … … 338 710 339 711 """ 712 713 # This algorithm factors the polynomial denominators. 714 # We should check the size of the denominators and switch to 715 # an alternate, less precise algorithm if we decide factoring 716 # would be too slow. 340 717 341 718 d = poly.denominator() … … 402 779 assert(best is not None) 403 780 parent = poly.parent() 404 return parent(best_elt), parent(best_elt.Mod(pari_poly).modreverse().lift()), parent(best) 781 rev = parent(best_elt.Mod(pari_poly).modreverse().lift()) 782 return parent(best_elt), rev, parent(best) 405 783 406 784 def isolating_interval(intv_fn, pol): 407 785 """ 408 intv_fn is a function that takes a RealIntervalFieldand returns an409 interval containing some particular root of pol. (It must return410 better approximations as the RealIntervalFieldprecision increases.)786 intv_fn is a function that takes a precision and returns an 787 interval of that precision containing some particular root of pol. 788 (It must return better approximations as the precision increases.) 411 789 pol is an irreducible polynomial with rational coefficients. 412 790 … … 417 795 418 796 sage: _.<x> = QQ['x'] 419 sage: isolating_interval(lambda rif: sqrt(rif(2)), x^2 - 2)797 sage: isolating_interval(lambda prec: sqrt(RealIntervalField(prec)(2)), x^2 - 2) 420 798 [1.41421356237309504876 .. 1.41421356237309504888] 421 799 … … 423 801 sage: delta = 10^(-70) 424 802 sage: p = (x - 1) * (x - 1 - delta) * (x - 1 + delta) 425 sage: isolating_interval(lambda rif: rif(1 + delta), p)803 sage: isolating_interval(lambda prec: RealIntervalField(prec)(1 + delta), p) 426 804 [1.00000000000000000000000000000000000000000000000000000000000000000000009999999999999999999999999999999999999999999999999999999999999999999999999999999999998 .. 1.00000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000014] 805 806 The function also works with complex intervals and complex roots: 807 sage: p = x^2 - x + 13/36 808 sage: isolating_interval(lambda prec: ComplexIntervalField(prec)(1/2, 1/3), p) 809 [0.500000000000000000000 .. 0.500000000000000000000] + [0.333333333333333333315 .. 0.333333333333333333343]*I 427 810 """ 428 for rif in rif_seq(): 429 intv = intv_fn(rif) 811 dpol = pol.derivative() 812 813 for prec in prec_seq(): 814 intv = intv_fn(prec) 815 ifld = intv.parent() 430 816 431 817 # We need to verify that pol has exactly one root in the … … 435 821 # root (that the interval is sufficiently narrow). 436 822 437 # Call the root we want alpha, and the bounding interval 438 # [bot .. top]. By Budan's theorem, if pol(x+bot) 439 # has at most one more sign change than pol(x+top), 440 # then pol has at most one root in this interval. 441 # This is true if all coefficients in pol(x+bot) 442 # except for the constant coefficient have the same 443 # sign as the corresponding coefficients in pol(x+top). 444 445 # We can check this by computing pol(x+new_intv). 446 # This gives an "interval polynomial" which represents 447 # a set of polynomials, including pol(x+bot) and 448 # pol(x+top). If all coefficients except the constant 449 # coefficient of this interval polynomial are bounded away from 450 # zero, then pol has at most one root in intv. 451 452 # This is a sufficient condition, but not a necessary one. 453 # It is not obvious that there always exists a bounding 454 # interval for alpha with this property. Fortunately, 455 # in the current case with pol irreducible, such 456 # a bounding interval does exist. 457 458 # Consider the polynomial pol(x+alpha), where 459 # pol has degree n. The coefficient of x^k in this 460 # polynomial has an exact representation as a polynomial 461 # in QQ[alpha] of degree (n-k). If this coefficient is 462 # equal to zero, then that means that alpha is a zero 463 # of this degree (n-k) polynomial. But if k>0, then this 464 # is impossible, since alpha is a root of an irreducible 465 # degree n polynomial. 466 467 # Thus, all coefficients of pol(x+alpha) are nonzero, 468 # except for the constant coefficient, which is zero. We 469 # are guaranteed that if we select a sufficiently tight bounding 470 # interval around alpha, then pol(x+[bot..top]) 471 # will have coefficients bounded away from zero, which proves 472 # that there is only one root within that bounding interval. 473 474 zero = rif(0) 475 rif_poly_ring = rif['x'] 476 477 ip = pol(rif_poly_ring.gen() + intv) 478 coeffs = ip.list() 479 assert(zero in coeffs[0]) 480 481 ok = True 482 483 for c in coeffs[1:]: 484 if zero in c: 485 ok = False 486 break 487 if ok: 823 # We do this by computing the derivative of the polynomial 824 # over the interval. If the derivative is bounded away from zero, 825 # then we know there can be at most one root. 826 827 if not dpol(intv).contains_zero(): 488 828 return intv 489 829 490 830 def find_zero_result(fn, l): 491 831 """ 492 l is a list of some sort. 493 fn is a function which maps an element of l and a RealIntervalField494 into an interval, such that for a sufficiently precise RealIntervalField,495 e xactly one element of l results in an interval containing 0.496 Returns thatone element of l.832 l is a list of some sort. fn is a function which maps an element 833 of l and a precision into an interval (either real or complex) of 834 that precision, such that for sufficient precision, exactly one 835 element of l results in an interval containing 0. Returns that 836 one element of l. 497 837 498 838 EXAMPLES: … … 503 843 sage: p2 = x - 1 - delta 504 844 sage: p3 = x - 1 + delta 505 sage: p2 == find_zero_result(lambda p, rif: p(rif(1 + delta)), [p1, p2, p3])845 sage: p2 == find_zero_result(lambda p, prec: p(RealIntervalField(prec)(1 + delta)), [p1, p2, p3]) 506 846 True 507 847 """ 508 for rif in rif_seq():848 for prec in prec_seq(): 509 849 result = None 510 850 ambig = False 511 851 for v in l: 512 intv = fn(v, rif)513 if 0 in intv:852 intv = fn(v, prec) 853 if intv.contains_zero(): 514 854 if result is not None: 515 855 ambig = True … … 521 861 raise ValueError, 'find_zero_result could not find any zeroes' 522 862 return result 863 864 def conjugate_expand(v): 865 """ 866 If the interval v (which may be real or complex) includes some 867 purely real numbers, return v' containing v such that 868 v' == v'.conjugate(). Otherwise return v unchanged. (Note that if 869 v' == v'.conjugate(), and v' includes one non-real root of a real 870 polynomial, then v' also includes the conjugate of that root. 871 Also note that the diameter of the return value is at most twice 872 the diameter of the input.) 873 874 EXAMPLES: 875 sage: from sage.rings.algebraic_real import conjugate_expand 876 sage: conjugate_expand(CIF(RIF(0, 1), RIF(1, 2))) 877 [0.00000000000000000 .. 1.0000000000000000] + [1.0000000000000000 .. 2.0000000000000000]*I 878 sage: conjugate_expand(CIF(RIF(0, 1), RIF(0, 1))) 879 [0.00000000000000000 .. 1.0000000000000000] + [-1.0000000000000000 .. 1.0000000000000000]*I 880 sage: conjugate_expand(CIF(RIF(0, 1), RIF(-2, 1))) 881 [0.00000000000000000 .. 1.0000000000000000] + [-2.0000000000000000 .. 2.0000000000000000]*I 882 sage: conjugate_expand(RIF(1, 2)) 883 [1.0000000000000000 .. 2.0000000000000000] 884 """ 885 if is_RealIntervalFieldElement(v): 886 return v 887 im = v.imag() 888 if not im.contains_zero(): 889 return v 890 re = v.real() 891 fld = ComplexIntervalField(v.prec()) 892 return fld(re, im.union(-im)) 893 894 def conjugate_shrink(v): 895 """ 896 If the interval v includes some purely real numbers, return 897 a real interval containing only those real numbers. Otherwise 898 return v unchanged. 899 900 If v includes exactly one root of a real polynomial, and v was 901 returned by conjugate_expand(), then conjugate_shrink(v) still 902 includes that root, and is a RealIntervalFieldElement iff the root 903 in question is real. 904 905 EXAMPLES: 906 sage: from sage.rings.algebraic_real import conjugate_shrink 907 sage: conjugate_shrink(RIF(3, 4)) 908 [3.0000000000000000 .. 4.0000000000000000] 909 sage: conjugate_shrink(CIF(RIF(1, 2), RIF(1, 2))) 910 [1.0000000000000000 .. 2.0000000000000000] + [1.0000000000000000 .. 2.0000000000000000]*I 911 sage: conjugate_shrink(CIF(RIF(1, 2), RIF(0, 1))) 912 [1.0000000000000000 .. 2.0000000000000000] 913 sage: conjugate_shrink(CIF(RIF(1, 2), RIF(-1, 2))) 914 [1.0000000000000000 .. 2.0000000000000000] 915 """ 916 if is_RealIntervalFieldElement(v): 917 return v 918 im = v.imag() 919 if im.contains_zero(): 920 return v.real() 921 return v 523 922 524 923 # Cache some commonly-used polynomial rings … … 547 946 class AlgebraicGenerator(SageObject): 548 947 """ 549 An AlgebraicGenerator represents both an algebraic realalpha and948 An AlgebraicGenerator represents both an algebraic number alpha and 550 949 the number field QQ[alpha]. There is a single AlgebraicGenerator 551 representing QQ (with alpha== 1).950 representing QQ (with alpha==0). 552 951 553 952 The AlgebraicGenerator class is private, and should not be used … … 559 958 Construct an AlgebraicGenerator object. 560 959 561 sage: from sage.rings.algebraic_real import A lgebraicRealNumberRoot, AlgebraicGenerator, unit_generator960 sage: from sage.rings.algebraic_real import ANRoot, AlgebraicGenerator, qq_generator 562 961 sage: _.<y> = QQ['y'] 563 sage: x = polygen( AA)962 sage: x = polygen(QQbar) 564 963 sage: nf = NumberField(y^2 - y - 1, name='a', check=False) 565 sage: root = A lgebraicRealNumberRoot(x^2 - x - 1, RIF(1, 2))566 sage: x= AlgebraicGenerator(nf, root)567 sage: x964 sage: root = ANRoot(x^2 - x - 1, RIF(1, 2)) 965 sage: gen = AlgebraicGenerator(nf, root) 966 sage: gen 568 967 Number Field in a with defining polynomial y^2 - y - 1 with a in [1.6180339887498946 .. 1.6180339887498950] 569 sage: x.field()968 sage: gen.field() 570 969 Number Field in a with defining polynomial y^2 - y - 1 571 sage: x.is_unit()970 sage: gen.is_trivial() 572 971 False 573 sage: x.union(unit_generator) is x972 sage: gen.union(qq_generator) is gen 574 973 True 575 sage: unit_generator.union(x) is x974 sage: qq_generator.union(gen) is gen 576 975 True 976 sage: nf = NumberField(y^2 + 1, name='a', check=False) 977 sage: root = ANRoot(x^2 + 1, CIF(0, 1)) 978 sage: x = AlgebraicGenerator(nf, root); x 979 Number Field in a with defining polynomial y^2 + 1 with a in [1.0000000000000000 .. 1.0000000000000000]*I 577 980 """ 578 981 self._field = field 579 self._unit = (field is None) 982 self._pari_field = None 983 self._trivial = (field is None) 580 984 self._root = root 581 985 self._unions = {} 986 self._cyclotomic = False 582 987 global algebraic_generator_counter 583 988 self._index = algebraic_generator_counter … … 590 995 return cmp(self._index, other._index) 591 996 997 def set_cyclotomic(self, n): 998 self._cyclotomic = True 999 self._cyclotomic_order = ZZ(n) 1000 1001 def is_complex(self): 1002 return self._root.is_complex() 1003 592 1004 def _repr_(self): 593 if self._ unit:594 return ' Unitgenerator'1005 if self._trivial: 1006 return 'Trivial generator' 595 1007 else: 596 return '%s with a in %s'%(self._field, self._root.interval_fast(RIF)) 597 598 def is_unit(self): 599 """ 600 Returns true iff this is the unit generator (alpha == 1), which 1008 if isinstance(self._root, ANRootOfUnity): 1009 return str(self._root) 1010 else: 1011 return '%s with a in %s'%(self._field, self._root._interval_fast(53)) 1012 1013 def is_trivial(self): 1014 """ 1015 Returns true iff this is the trivial generator (alpha == 0), which 601 1016 does not actually extend the rationals. 602 1017 603 1018 EXAMPLES: 604 sage: from sage.rings.algebraic_real import unit_generator605 sage: unit_generator.is_unit()1019 sage: from sage.rings.algebraic_real import qq_generator 1020 sage: qq_generator.is_trivial() 606 1021 True 607 1022 """ 608 return self._ unit1023 return self._trivial 609 1024 610 1025 def field(self): 611 1026 return self._field 612 1027 613 def interval_fast(self, field): 1028 def pari_field(self): 1029 if self._pari_field is None: 1030 pari_pol = self._field.pari_polynomial().subst('x','y') 1031 self._pari_field = pari_pol.nfinit(1) 1032 return self._pari_field 1033 1034 def conjugate(self): 1035 """ 1036 If this generator is for the algebraic number alpha, return a 1037 generator for the complex conjugate of alpha. 1038 """ 1039 try: 1040 return self._conjugate 1041 except AttributeError: 1042 if not self.is_complex(): 1043 self._conjugate = self 1044 else: 1045 conj = AlgebraicGenerator(self._field, self._root.conjugate(None)) 1046 self._conjugate = conj 1047 conj._conjugate = self 1048 if self._cyclotomic: 1049 conj_rel = QQx_x ** (self._cyclotomic_order - 1) 1050 rel = AlgebraicGeneratorRelation(self, conj_rel, conj, conj_rel, self) 1051 self._unions[conj] = rel 1052 conj._unions[self] = rel 1053 return self._conjugate 1054 1055 def _interval_fast(self, prec): 614 1056 """ 615 1057 Returns an interval containing this generator, to the specified 616 1058 precision. 617 1059 """ 618 return self._root. interval_fast(field)1060 return self._root._interval_fast(prec) 619 1061 620 1062 def union(self, other): … … 624 1066 625 1067 EXAMPLES: 626 sage: from sage.rings.algebraic_real import A lgebraicRealNumberRoot, AlgebraicGenerator, unit_generator1068 sage: from sage.rings.algebraic_real import ANRoot, AlgebraicGenerator, qq_generator 627 1069 sage: _.<y> = QQ['y'] 628 sage: x = polygen( AA)1070 sage: x = polygen(QQbar) 629 1071 sage: nf2 = NumberField(y^2 - 2, name='a', check=False) 630 sage: root2 = A lgebraicRealNumberRoot(x^2 - 2, RIF(1, 2))1072 sage: root2 = ANRoot(x^2 - 2, RIF(1, 2)) 631 1073 sage: gen2 = AlgebraicGenerator(nf2, root2) 632 1074 sage: gen2 633 1075 Number Field in a with defining polynomial y^2 - 2 with a in [1.4142135623730949 .. 1.4142135623730952] 634 1076 sage: nf3 = NumberField(y^2 - 3, name='a', check=False) 635 sage: root3 = A lgebraicRealNumberRoot(x^2 - 3, RIF(1, 2))1077 sage: root3 = ANRoot(x^2 - 3, RIF(1, 2)) 636 1078 sage: gen3 = AlgebraicGenerator(nf3, root3) 637 1079 sage: gen3 638 1080 Number Field in a with defining polynomial y^2 - 3 with a in [1.7320508075688771 .. 1.7320508075688775] 639 sage: gen2.union( unit_generator) is gen21081 sage: gen2.union(qq_generator) is gen2 640 1082 True 641 sage: unit_generator.union(gen3) is gen31083 sage: qq_generator.union(gen3) is gen3 642 1084 True 643 1085 sage: gen2.union(gen3) 644 1086 Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a in [0.51763809020504147 .. 0.51763809020504159] 645 1087 """ 646 if self._ unit:1088 if self._trivial: 647 1089 return other 648 if other._ unit:1090 if other._trivial: 649 1091 return self 650 1092 if self is other: … … 654 1096 if self._field.polynomial().degree() < other._field.polynomial().degree(): 655 1097 self, other = other, self 1098 elif other._cyclotomic: 1099 self, other = other, self 1100 1101 if self._cyclotomic and other._cyclotomic: 1102 parent_order = self._cyclotomic_order.lcm(other._cyclotomic_order) 1103 new_gen = cyclotomic_generator(parent_order) 1104 rel = AlgebraicGeneratorRelation(self, QQx_x ** (parent_order // self._cyclotomic_order), 1105 other, QQx_x ** (parent_order // other._cyclotomic_order), 1106 new_gen) 1107 self._unions[other] = rel 1108 other._unions[self] = rel 1109 return new_gen 1110 656 1111 sp = self._field.polynomial() 657 1112 op = other._field.polynomial() … … 662 1117 # print self._field.polynomial().degree() 663 1118 # pari_nf = self._field.pari_nf() 664 pari_nf = pari_nf_hack(self._field)1119 pari_nf = self.pari_field() 665 1120 # print pari_nf[0] 666 1121 factors = list(pari_nf.nffactor(op).lift())[0] 667 1122 # print factors 668 1123 x, y = QQxy.gens() 669 # XXX Go through strings because multivariate polynomial coercion from 670 # Pari is not implemented 671 factors_sage = [QQxy(str(p)) for p in factors] 1124 factors_sage = [QQxy(p) for p in factors] 672 1125 # print factors_sage 673 def find_fn(p, rif): 674 rif_poly = rif['x', 'y'] 675 ip = rif_poly(p) 676 return ip(other._root.interval_fast(rif), self._root.interval_fast(rif)) 1126 def find_fn(p, prec): 1127 ifield = RealIntervalField(prec) 1128 if_poly = ifield['x', 'y'] 1129 ip = if_poly(p) 1130 return ip(other._root._interval_fast(prec), self._root._interval_fast(prec)) 677 1131 my_factor = find_zero_result(find_fn, factors_sage) 678 1132 … … 707 1161 new_nf_a = new_nf.gen() 708 1162 709 def intv_fn( rif):710 return red_elt(self._root.interval_fast(rif) * k + other._root.interval_fast(rif))711 new_intv = isolating_interval(intv_fn, red_pol)712 713 new_gen = AlgebraicGenerator(new_nf, A lgebraicRealNumberRoot(QQx(red_pol), new_intv))1163 def intv_fn(prec): 1164 return conjugate_expand(red_elt(self._root._interval_fast(prec) * k + other._root._interval_fast(prec))) 1165 new_intv = conjugate_shrink(isolating_interval(intv_fn, red_pol)) 1166 1167 new_gen = AlgebraicGenerator(new_nf, ANRoot(QQx(red_pol), new_intv)) 714 1168 rel = AlgebraicGeneratorRelation(self, self_pol_sage(red_back_x), 715 1169 other, (QQx_x - k*self_pol_sage)(red_back_x), … … 717 1171 self._unions[other] = rel 718 1172 other._unions[self] = rel 719 return rel.parent1173 return new_gen 720 1174 721 1175 def super_poly(self, super, checked=None): … … 725 1179 leaves is gen, gen.super_poly(super) returns a polynomial 726 1180 expressing the value of gen in terms of the value of super. 727 (Except that if gen is unit_generator, super_poly() always1181 (Except that if gen is qq_generator, super_poly() always 728 1182 returns None.) 729 1183 730 1184 EXAMPLES: 731 sage: from sage.rings.algebraic_real import AlgebraicGenerator, A lgebraicRealNumberRoot, unit_generator1185 sage: from sage.rings.algebraic_real import AlgebraicGenerator, ANRoot, qq_generator 732 1186 sage: _.<y> = QQ['y'] 733 sage: x = polygen( AA)1187 sage: x = polygen(QQbar) 734 1188 sage: nf2 = NumberField(y^2 - 2, name='a', check=False) 735 sage: root2 = A lgebraicRealNumberRoot(x^2 - 2, RIF(1, 2))1189 sage: root2 = ANRoot(x^2 - 2, RIF(1, 2)) 736 1190 sage: gen2 = AlgebraicGenerator(nf2, root2) 737 1191 sage: gen2 738 1192 Number Field in a with defining polynomial y^2 - 2 with a in [1.4142135623730949 .. 1.4142135623730952] 739 1193 sage: nf3 = NumberField(y^2 - 3, name='a', check=False) 740 sage: root3 = A lgebraicRealNumberRoot(x^2 - 3, RIF(1, 2))1194 sage: root3 = ANRoot(x^2 - 3, RIF(1, 2)) 741 1195 sage: gen3 = AlgebraicGenerator(nf3, root3) 742 1196 sage: gen3 … … 745 1199 sage: gen2_3 746 1200 Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a in [0.51763809020504147 .. 0.51763809020504159] 747 sage: unit_generator.super_poly(gen2) is None1201 sage: qq_generator.super_poly(gen2) is None 748 1202 True 749 1203 sage: gen2.super_poly(gen2_3) … … 775 1229 def __call__(self, elt): 776 1230 """ 777 Takes an AlgebraicRealNumber which is represented as either a rational1231 Takes an algebraic number which is represented as either a rational 778 1232 or a number field element, and which is in a subfield of the 779 1233 field generated by this generator. Lifts the number into the 780 1234 field of this generator, and returns either a Rational or a 781 NumberFieldElement depending on whether this is the unitgenerator.782 783 EXAMPLES: 784 sage: from sage.rings.algebraic_real import A lgebraicRealNumberRoot, AlgebraicGenerator, AlgebraicRealNumberExtensionElement, AlgebraicRealNumberRational1235 NumberFieldElement depending on whether this is the trivial generator. 1236 1237 EXAMPLES: 1238 sage: from sage.rings.algebraic_real import ANRoot, AlgebraicGenerator, ANExtensionElement, ANRational 785 1239 sage: _.<y> = QQ['y'] 786 sage: x = polygen( AA)1240 sage: x = polygen(QQbar) 787 1241 sage: nf2 = NumberField(y^2 - 2, name='a', check=False) 788 sage: root2 = A lgebraicRealNumberRoot(x^2 - 2, RIF(1, 2))1242 sage: root2 = ANRoot(x^2 - 2, RIF(1, 2)) 789 1243 sage: gen2 = AlgebraicGenerator(nf2, root2) 790 1244 sage: gen2 791 1245 Number Field in a with defining polynomial y^2 - 2 with a in [1.4142135623730949 .. 1.4142135623730952] 792 sage: sqrt2 = A lgebraicRealNumberExtensionElement(gen2, nf2.gen())1246 sage: sqrt2 = ANExtensionElement(gen2, nf2.gen()) 793 1247 sage: nf3 = NumberField(y^2 - 3, name='a', check=False) 794 sage: root3 = A lgebraicRealNumberRoot(x^2 - 3, RIF(1, 2))1248 sage: root3 = ANRoot(x^2 - 3, RIF(1, 2)) 795 1249 sage: gen3 = AlgebraicGenerator(nf3, root3) 796 1250 sage: gen3 797 1251 Number Field in a with defining polynomial y^2 - 3 with a in [1.7320508075688771 .. 1.7320508075688775] 798 sage: sqrt3 = A lgebraicRealNumberExtensionElement(gen3, nf3.gen())1252 sage: sqrt3 = ANExtensionElement(gen3, nf3.gen()) 799 1253 sage: gen2_3 = gen2.union(gen3) 800 1254 sage: gen2_3 … … 802 1256 sage: gen2_3(sqrt2) 803 1257 -a^3 + 3*a 804 sage: gen2_3(A lgebraicRealNumberRational(1/7))1258 sage: gen2_3(ANRational(1/7)) 805 1259 1/7 806 1260 sage: gen2_3(sqrt3) 807 1261 -a^2 + 2 808 1262 """ 809 if self._ unit:1263 if self._trivial: 810 1264 return elt.rational_value() 811 1265 if elt.is_rational(): … … 822 1276 return self._field(elt.field_element_value().polynomial()(sp)) 823 1277 824 class AlgebraicRealNumberDescr(SageObject): 1278 # These are the functions used to add, subtract, multiply, and divide 1279 # algebraic numbers. Basically, we try to compute exactly if the 1280 # result would be a Gaussian rational, or a rational times a root 1281 # of unity; or if both arguments are already known to be in the same 1282 # number field. Otherwise we fall back to floating-point computation, 1283 # to be backed up by exact symbolic computation only as required. 1284 1285 # These choices are motivated partly by efficiency considerations 1286 # (not backed up by benchmarks, so other possibilities might be more 1287 # efficient), and partly by concerns for the prettiness of output: 1288 # we want algebraic numbers to print as Gaussian rationals, rather 1289 # than as intervals, as often as possible. 1290 1291 def an_addsub_rational(a, b, sub): 1292 va = a._descr._value 1293 vb = b._descr._value 1294 if sub: 1295 v = va - vb 1296 else: 1297 v = va + vb 1298 return ANRational(v) 1299 1300 def an_muldiv_rational(a, b, div): 1301 va = a._descr._value 1302 vb = b._descr._value 1303 if div: 1304 v = va / vb 1305 else: 1306 v = va * vb 1307 return ANRational(v) 1308 1309 def an_addsub_zero(a, b, sub): 1310 if b._descr.is_rational() and b._descr.rational_value().is_zero(): 1311 return a._descr 1312 # we know a is 0 1313 if sub: 1314 return b._descr.neg(b) 1315 else: 1316 return b._descr 1317 1318 def an_muldiv_zero(a, b, div): 1319 if b._descr.is_rational() and b._descr.rational_value().is_zero(): 1320 if div: 1321 raise ValueError, "algebraic number division by zero" 1322 else: 1323 return ANRational(0) 1324 # we know a is 0 1325 return ANRational(0) 1326 1327 def an_addsub_gaussian(a, b, sub): 1328 va = a._descr.gaussian_value() 1329 vb = b._descr.gaussian_value() 1330 if sub: 1331 v = va - vb 1332 else: 1333 v = va + vb 1334 return ANExtensionElement(QQbar_I_generator, v) 1335 1336 def an_muldiv_gaussian(a, b, div): 1337 va = a._descr.gaussian_value() 1338 vb = b._descr.gaussian_value() 1339 if div: 1340 v = va / vb 1341 else: 1342 v = va * vb 1343 return ANExtensionElement(QQbar_I_generator, v) 1344 1345 def an_addsub_expr(a, b, sub): 1346 return ANBinaryExpr(a, b, ('-' if sub else '+')) 1347 1348 def an_muldiv_expr(a, b, div): 1349 return ANBinaryExpr(a, b, ('/' if div else '*')) 1350 1351 def an_muldiv_rootunity(a, b, div): 1352 ad = a._descr 1353 bd = b._descr 1354 if div: 1355 return ANRootOfUnity(ad.angle() - bd.angle(), ad.scale() / bd.scale()) 1356 else: 1357 return ANRootOfUnity(ad.angle() + bd.angle(), ad.scale() * bd.scale()) 1358 1359 def an_addsub_rootunity(a, b, sub): 1360 ad = a._descr 1361 bd = b._descr 1362 if ad._angle == bd._angle: 1363 if sub: 1364 return ANRootOfUnity(ad.angle(), ad.scale() - bd.scale()) 1365 else: 1366 return ANRootOfUnity(ad.angle(), ad.scale() + bd.scale()) 1367 else: 1368 return an_addsub_expr(a, b, sub) 1369 1370 def an_muldiv_element(a, b, div): 1371 ad = a._descr 1372 bd = b._descr 1373 adg = ad.generator() 1374 bdg = bd.generator() 1375 if adg == qq_generator or adg == bdg: 1376 if div: 1377 return ANExtensionElement(bdg, ad._value / bd._value) 1378 else: 1379 return ANExtensionElement(bdg, ad._value * bd._value) 1380 if bdg == qq_generator: 1381 if div: 1382 return ANExtensionElement(adg, ad._value / bd._value) 1383 else: 1384 return ANExtensionElement(adg, ad._value * bd._value) 1385 return ANBinaryExpr(a, b, ('/' if div else '*')) 1386 1387 def an_addsub_element(a, b, sub): 1388 ad = a._descr 1389 bd = b._descr 1390 adg = ad.generator() 1391 bdg = bd.generator() 1392 if adg == qq_generator or adg == bdg: 1393 if sub: 1394 return ANExtensionElement(bdg, ad._value - bd._value) 1395 else: 1396 return ANExtensionElement(bdg, ad._value + bd._value) 1397 if bdg == qq_generator: 1398 if sub: 1399 return ANExtensionElement(adg, ad._value - bd._value) 1400 else: 1401 return ANExtensionElement(adg, ad._value + bd._value) 1402 return ANBinaryExpr(a, b, ('-' if sub else '+')) 1403 1404 # Here we hand-craft a simple multimethod dispatch. 1405 _mul_algo = {} 1406 _add_algo = {} 1407 _descriptors = ('zero', 'rational', 'imaginary', 'gaussian', 'rootunity', 'element', 'other') 1408 for a in _descriptors: 1409 for b in _descriptors: 1410 key = (a, b) 1411 if a == 'zero' or b == 'zero': 1412 _mul_algo[key] = an_muldiv_zero 1413 _add_algo[key] = an_addsub_zero 1414 continue 1415 if a == 'rational' and b == 'rational': 1416 _mul_algo[key] = an_muldiv_rational 1417 _add_algo[key] = an_addsub_rational 1418 continue 1419 if b == 'rational': 1420 a1, b1 = b, a 1421 else: 1422 a1, b1 = a, b 1423 if a1 == 'rational': 1424 if b1 == 'imaginary': 1425 _mul_algo[key] = an_muldiv_rootunity 1426 _add_algo[key] = an_addsub_gaussian 1427 continue 1428 if b1 == 'gaussian': 1429 _mul_algo[key] = an_muldiv_gaussian 1430 _add_algo[key] = an_addsub_gaussian 1431 continue 1432 if b1 == 'rootunity': 1433 _mul_algo[key] = an_muldiv_rootunity 1434 _add_algo[key] = an_addsub_expr 1435 continue 1436 if b1 == 'element': 1437 _mul_algo[key] = an_muldiv_element 1438 _add_algo[key] = an_addsub_element 1439 continue 1440 if b1 == 'imaginary': 1441 a1, b1 = b1, a1 1442 if a1 == 'imaginary': 1443 if b1 == 'imaginary' or b1 == 'rootunity': 1444 _mul_algo[key] = an_muldiv_rootunity 1445 _add_algo[key] = an_addsub_rootunity 1446 continue 1447 if b1 == 'gaussian': 1448 _mul_algo[key] = an_muldiv_gaussian 1449 _add_algo[key] = an_addsub_gaussian 1450 continue 1451 if a1 == 'gaussian' and b1 == 'gaussian': 1452 _mul_algo[key] = an_muldiv_gaussian 1453 _add_algo[key] = an_addsub_gaussian 1454 continue 1455 if a1 == 'rootunity' and b1 == 'rootunity': 1456 _mul_algo[key] = an_muldiv_rootunity 1457 _add_algo[key] = an_addsub_rootunity 1458 continue 1459 if a1 == 'element' and b1 == 'element': 1460 _mul_algo[key] = an_muldiv_element 1461 _add_algo[key] = an_addsub_element 1462 continue 1463 _mul_algo[key] = an_muldiv_expr 1464 _add_algo[key] = an_addsub_expr 1465 1466 class ANDescr(SageObject): 825 1467 """ 826 An Algebraic RealNumber is a wrapper around an AlgebraicRealNumberDescr object.827 A lgebraicRealNumberDescr is an abstract base class, which should never1468 An AlgebraicNumber or AlgebraicReal is a wrapper around an ANDescr object. 1469 ANDescr is an abstract base class, which should never 828 1470 be directly instantiated; its concrete subclasses are 829 A lgebraicRealNumberRational, AlgebraicRealNumberExpression,830 A lgebraicRealNumberRoot, and AlgebraicRealNumberExtensionElement.831 A lgebraicRealNumberDescr and all of its subclasses are private, and1471 ANRational, ANBinaryExpr, ANUnaryExpr, ANRootOfUnity, 1472 ANRoot, and ANExtensionElement. 1473 ANDescr and all of its subclasses are private, and 832 1474 should not be used directly. 833 1475 """ 834 1476 def is_exact(self): 835 1477 """ 836 Returns True if self is an A lgebraicRealNumberRational or an837 A lgebraicRealNumberExtensionElement.838 839 EXAMPLES: 840 sage: from sage.rings.algebraic_real import A lgebraicRealNumberRational841 sage: A lgebraicRealNumberRational(1/2).is_exact()1478 Returns True if self is an ANRational, ANRootOfUnity, or 1479 ANExtensionElement. 1480 1481 EXAMPLES: 1482 sage: from sage.rings.algebraic_real import ANRational 1483 sage: ANRational(1/2).is_exact() 842 1484 True 1485 sage: QQbar(3+I)._descr.is_exact() 1486 True 1487 sage: QQbar.zeta(17)._descr.is_exact() 1488 True 843 1489 """ 844 1490 return False … … 846 1492 def is_rational(self): 847 1493 """ 848 Returns True if self is an AlgebraicRealNumberRational or 849 an AlgebraicRealNumberExtensionElement which is actually rational. 850 851 EXAMPLES: 852 sage: from sage.rings.algebraic_real import AlgebraicRealNumberRational 853 sage: AlgebraicRealNumberRational(3/7).is_rational() 1494 Returns True if self is an ANRational object. (Note that 1495 the constructors for ANExtensionElement and ANRootOfUnity 1496 will actually return ANRational objects for rational numbers.) 1497 1498 EXAMPLES: 1499 sage: from sage.rings.algebraic_real import ANRational 1500 sage: ANRational(3/7).is_rational() 854 1501 True 855 1502 """ … … 858 1505 def is_field_element(self): 859 1506 """ 860 Returns True if self is an A lgebraicRealNumberExtensionElement.861 862 sage: from sage.rings.algebraic_real import A lgebraicRealNumberExtensionElement, AlgebraicRealNumberRoot, AlgebraicGenerator1507 Returns True if self is an ANExtensionElement. 1508 1509 sage: from sage.rings.algebraic_real import ANExtensionElement, ANRoot, AlgebraicGenerator 863 1510 sage: _.<y> = QQ['y'] 864 sage: x = polygen( AA)1511 sage: x = polygen(QQbar) 865 1512 sage: nf2 = NumberField(y^2 - 2, name='a', check=False) 866 sage: root2 = A lgebraicRealNumberRoot(x^2 - 2, RIF(1, 2))1513 sage: root2 = ANRoot(x^2 - 2, RIF(1, 2)) 867 1514 sage: gen2 = AlgebraicGenerator(nf2, root2) 868 sage: sqrt2 = A lgebraicRealNumberExtensionElement(gen2, nf2.gen())1515 sage: sqrt2 = ANExtensionElement(gen2, nf2.gen()) 869 1516 sage: sqrt2.is_field_element() 870 1517 True … … 872 1519 return False 873 1520 874 class AlgebraicRealNumberRational(AlgebraicRealNumberDescr): 1521 def neg(self, n): 1522 return ANUnaryExpr(n, '-') 1523 1524 def invert(self, n): 1525 return ANUnaryExpr(n, '~') 1526 1527 def abs(self, n): 1528 return ANUnaryExpr(n, 'abs') 1529 1530 def real(self, n): 1531 if self.is_complex(): 1532 return ANUnaryExpr(n, 'real') 1533 else: 1534 return self 1535 1536 def imag(self, n): 1537 if self.is_complex(): 1538 return ANUnaryExpr(n, 'imag') 1539 else: 1540 return ANRational(0) 1541 1542 def conjugate(self, n): 1543 if self.is_complex(): 1544 return ANUnaryExpr(n, 'conjugate') 1545 else: 1546 return self 1547 1548 def norm(self, n): 1549 if self.is_complex(): 1550 return ANUnaryExpr(n, 'norm') 1551 else: 1552 return (n*n)._descr 1553 1554 class AlgebraicNumber_base(sage.structure.element.FieldElement): 875 1555 """ 876 The subclass of AlgebraicRealNumberDescr that represents an arbitrary 877 rational. This class is private, and should not be used directly. 878 """ 879 880 def __init__(self, x): 881 """ 882 TESTS: 883 sage: polygen(AA) / int(3) 884 1/3*x 885 sage: AA(int(7)) / AA(long(2)) 886 7/2 887 """ 888 if isinstance(x, (sage.rings.integer.Integer, 889 sage.rings.rational.Rational)): 890 self._value = x 891 elif isinstance(x, (int, long)): 892 self._value = ZZ(x) 893 else: 894 raise TypeError, "Illegal initializer for algebraic number rational" 895 896 def _repr_(self): 897 return repr(self._value) 898 899 def interval_fast(self, rif): 900 return rif(self._value) 901 902 def is_rational(self): 903 return True 904 905 def rational_value(self): 906 return self._value 907 908 def exactify(self): 909 return self 910 911 def is_exact(self): 912 return True 913 914 def minpoly(self): 915 return QQx_x - self._value 916 917 class AlgebraicRealNumberExpression(AlgebraicRealNumberDescr): 918 """ 919 The subclass of AlgebraicRealNumberDescr that represents the sum, 920 difference, product, or quotient of two algebraic numbers. 921 This class is private, and should not be used directly. 922 """ 923 924 def __init__(self, left, right, op): 925 """ 926 op can be '+', '-', '*', or '/'. 927 left and right are algebraic numbers. 928 If op is '-', then left can be None (in which case it is taken to 929 mean 0). 930 if op is '/', then left can be None (in which case it is taken to 931 mean 1). 932 933 EXAMPLES: 934 sage: from sage.rings.algebraic_real import AlgebraicRealNumberExpression 935 sage: AlgebraicRealNumberExpression(AA(1/3), AA(1/2), '+') 936 [0.83333333333333325 .. 0.83333333333333338] (1/3 + 1/2) 937 sage: AlgebraicRealNumberExpression(AA(1/3), AA(1/2), '-') 938 [-0.16666666666666669 .. -0.16666666666666662] (1/3 - 1/2) 939 sage: AlgebraicRealNumberExpression(AA(1/3), AA(1/2), '*') 940 [0.16666666666666665 .. 0.16666666666666669] (1/3 * 1/2) 941 sage: AlgebraicRealNumberExpression(AA(1/3), AA(1/2), '/') 942 [0.66666666666666662 .. 0.66666666666666675] (1/3 / 1/2) 943 sage: AlgebraicRealNumberExpression(None, AA(1/2), '-') 944 [-0.50000000000000000 .. -0.50000000000000000] (None - 1/2) 945 sage: AlgebraicRealNumberExpression(None, AA(1/2), '/') 946 [2.0000000000000000 .. 2.0000000000000000] (None / 1/2) 947 """ 948 self._left = left 949 self._right = right 950 self._op = op 951 952 def _repr_(self): 953 return '%s (%s %s %s)'%(self.interval_fast(RIF), self._left, self._op, self._right) 954 955 def interval_fast(self, field): 956 """ 957 Returns an interval containing self with precision given by the 958 field argument (which must be a RealIntervalField). Note that 959 the result may not be a minimal-width interval. 960 961 EXAMPLES: 962 sage: from sage.rings.algebraic_real import AlgebraicRealNumberExpression 963 sage: five_sixths = AlgebraicRealNumberExpression(AA(1/2), AA(1/3), '+') 964 sage: five_sixths.interval_fast(RealIntervalField(4)) 965 [0.812 .. 0.875] 966 sage: five_sixths.interval_fast(RealIntervalField(70)) 967 [0.83333333333333333333305 .. 0.83333333333333333333390] 968 """ 969 op = self._op 970 if op == '+': 971 return self._left.interval_fast(field) + self._right.interval_fast(field) 972 if op == '-': 973 if self._left is None: 974 return -self._right.interval_fast(field) 975 else: 976 return self._left.interval_fast(field) - self._right.interval_fast(field) 977 if op == '*': 978 return self._left.interval_fast(field) * self._right.interval_fast(field) 979 if op == '/': 980 # Note: this may trigger exact computation 981 if self._right.sign() == 0: 982 raise ZeroDivisionError, 'Division by zero in algebraic number field' 983 if self._left is None: 984 return ~self._right.interval_fast(field) 985 else: 986 return self._left.interval_fast(field) / self._right.interval_fast(field) 987 raise ValueError, 'Illegal operation for AlgebraicRealNumberExpression' 988 989 def exactify(self): 990 """ 991 Return a new exact AlgebraicRealNumberDescr with the same value as self. 992 993 EXAMPLES: 994 sage: from sage.rings.algebraic_real import AlgebraicRealNumberExpression 995 sage: five_sixths = AlgebraicRealNumberExpression(AA(1/2), AA(1/3), '+') 996 sage: five_sixths.exactify() 997 5/6 998 """ 999 op = self._op 1000 left = self._left 1001 if left is None: 1002 if op == '-': 1003 left = AA(0) 1004 else: 1005 left = AA(1) 1006 left.exactify() 1007 1008 right = self._right 1009 right.exactify() 1010 1011 gen = left._exact_field().union(right._exact_field()) 1012 1013 # print gen 1014 # print left 1015 # print right 1016 1017 left_value = gen(left._exact_value()) 1018 right_value = gen(right._exact_value()) 1019 1020 if op == '+': 1021 value = left_value + right_value 1022 if op == '-': 1023 value = left_value - right_value 1024 if op == '*': 1025 value = left_value * right_value 1026 if op == '/': 1027 value = left_value / right_value 1028 1029 # print gen 1030 # print left, left_value 1031 # print right, right_value 1032 1033 if gen.is_unit(): 1034 return AlgebraicRealNumberRational(value) 1035 else: 1036 return AlgebraicRealNumberExtensionElement(gen, value) 1037 1038 1039 class AlgebraicRealNumber(sage.structure.element.FieldElement): 1040 """ 1041 An algebraic real (a real number which is the zero of a polynomial 1042 in ZZ[x]). 1043 1044 AlgebraicRealNumber objects can be created using AA (== AlgebraicRealNumberField()); 1045 either by coercing a rational, or by using the AA.polynomial_root() 1046 method to construct a particular root of a polynomial with algebraic 1047 coefficients. Also, AlgebraicRealNumber is closed under addition, 1048 subtraction, multiplication, division (except by 0), and rational 1049 powers (including roots), except for negative numbers and powers 1050 with an even denominator. 1051 1052 AlgebraicRealNumber objects can be approximated to any desired precision. 1053 They can be compared exactly; if the two numbers are very close, 1054 this may require exact computation, which can be extremely slow. 1556 This is the common base class for algebraic numbers (complex 1557 numbers which are the zero of a polynomial in ZZ[x]) and algebraic 1558 reals (algebraic numbers which happen to be real). 1559 1560 AlgebraicNumber objects can be created using QQbar (== 1561 AlgebraicNumberField()), and AlgebraicReal objects can be created 1562 using AA (== AlgebraicRealField()). They can be created either by 1563 coercing a rational or a symbolic expression, or by using the 1564 QQbar.polynomial_root() or AA.polynomial_root() method to 1565 construct a particular root of a polynomial with algebraic 1566 coefficients. Also, AlgebraicNumber and AlgebraicReal are closed 1567 under addition, subtraction, multiplication, division (except by 1568 0), and rational powers (including roots), except that for a 1569 negative AlgebraicReal, taking a power with an even denominator returns 1570 an AlgebraicNumber instead of an AlgebraicReal. 1571 1572 AlgebraicNumber and AlgebraicReal objects can be approximated to 1573 any desired precision. They can be compared exactly; if the two 1574 numbers are very close, or are equal, this may require exact 1575 computation, which can be extremely slow. 1055 1576 1056 1577 As long as exact computation is not triggered, computation with 1057 algebraic reals should not be too much slower than computation with1578 algebraic numbers should not be too much slower than computation with 1058 1579 intervals. As mentioned above, exact computation is triggered 1059 when comparing two algebraic reals which are very close together.1580 when comparing two algebraic numbers which are very close together. 1060 1581 This can be an explicit comparison in user code, but the following 1061 1582 list of actions (not necessarily complete) can also trigger exact 1062 1583 computation: 1063 Dividing by an algebraic realwhich is very close to 0.1064 Using an algebraic real which is very close to 0 as the leading coefficient1065 in a polynomial.1066 Taking a root of an alebraic realwhich is very close to 0.1584 Dividing by an algebraic number which is very close to 0. 1585 Using an algebraic number which is very close to 0 as the leading 1586 coefficient in a polynomial. 1587 Taking a root of an alebraic number which is very close to 0. 1067 1588 1068 1589 The exact definition of "very close" is subject to change; currently, 1069 1590 we compute our best approximation of the two numbers using 128-bit 1070 1591 arithmetic, and see if that's sufficient to decide the comparison. 1071 Note that comparing two algebraic reals which are actually equal will1072 always trigger exact computation .1592 Note that comparing two algebraic numbers which are actually equal will 1593 always trigger exact computation, unless they are actually the same object. 1073 1594 1074 1595 EXAMPLES: 1075 sage: sqrt( AA(2))1596 sage: sqrt(QQbar(2)) 1076 1597 [1.4142135623730949 .. 1.4142135623730952] 1077 sage: sqrt( AA(2))^2 == 21598 sage: sqrt(QQbar(2))^2 == 2 1078 1599 True 1079 sage: x = polygen( AA)1080 sage: phi = AA.polynomial_root(x^2 - x - 1, RIF(0, 2))1600 sage: x = polygen(QQbar) 1601 sage: phi = QQbar.polynomial_root(x^2 - x - 1, RIF(1, 2)) 1081 1602 sage: phi 1082 1603 [1.6180339887498946 .. 1.6180339887498950] 1083 1604 sage: phi^2 == phi+1 1084 1605 True 1606 sage: AA(sqrt(65537)) 1607 [256.00195311754941 .. 256.00195311754948] 1085 1608 """ 1086 1609 1087 def __init__(self, x):1610 def __init__(self, parent, x): 1088 1611 """ 1089 1612 Initialize an algebraic number. The argument must be either 1090 a rational number or a subclass of AlgebraicRealNumberDescr.1091 1092 sage: from sage.rings.algebraic_real import A lgebraicRealNumberExpression1093 sage: AlgebraicReal Number(22/7)1613 a rational number, a Gaussian rational, or a subclass of ANDescr. 1614 1615 sage: from sage.rings.algebraic_real import ANRootOfUnity 1616 sage: AlgebraicReal(22/7) 1094 1617 22/7 1095 sage: Algebraic RealNumber(AlgebraicRealNumberExpression(AA(1/2), AA(1/5), '+'))1096 [ 0.69999999999999995 .. 0.70000000000000007]1097 """ 1098 sage.structure.element.FieldElement.__init__(self, AA)1618 sage: AlgebraicNumber(ANRootOfUnity(2/5, 1)) 1619 [-0.80901699437494746 .. -0.80901699437494734] + [0.58778525229247302 .. 0.58778525229247314]*I 1620 """ 1621 sage.structure.element.FieldElement.__init__(self, parent) 1099 1622 if isinstance(x, (int, long, sage.rings.integer.Integer, 1100 1623 sage.rings.rational.Rational)): 1101 self._descr = A lgebraicRealNumberRational(x)1102 elif isinstance(x, (A lgebraicRealNumberDescr)):1624 self._descr = ANRational(x) 1625 elif isinstance(x, (ANDescr)): 1103 1626 self._descr = x 1627 elif parent is QQbar and \ 1628 isinstance(x, NumberFieldElement_quadratic) and \ 1629 list(x.parent().polynomial()) == [1, 0, 1]: 1630 self._descr = ANExtensionElement(QQbar_I_generator, QQbar_I_nf(x)) 1104 1631 else: 1105 1632 raise TypeError, "Illegal initializer for algebraic number" 1106 1633 1107 self._value = self._descr. interval_fast(AA.default_interval_field())1634 self._value = self._descr._interval_fast(64) 1108 1635 1109 1636 def _repr_(self): 1637 """ 1638 Returns the print representation of this number. 1639 1640 EXAMPLES: 1641 sage: AA(22/7) 1642 22/7 1643 sage: QQbar(1/3 + 2/7*I) 1644 2/7*I + 1/3 1645 sage: QQbar.zeta(4) + 5 1646 I + 5 1647 sage: QQbar.zeta(17) 1648 [0.93247222940435570 .. 0.93247222940435582] + [0.36124166618715292 .. 0.36124166618715298]*I 1649 sage: AA(19).sqrt() 1650 [4.3588989435406730 .. 4.3588989435406740] 1651 """ 1110 1652 if self._descr.is_rational(): 1111 1653 return repr(self._descr) 1112 return repr(RIF(self._value)) 1654 if isinstance(self._descr, ANRootOfUnity) and self._descr._angle == QQ_1_4: 1655 return '%s*I'%self._descr._scale 1656 if isinstance(self._descr, ANExtensionElement) and self._descr._generator is QQbar_I_generator: 1657 return repr(self._descr._value) 1658 if self.parent() is QQbar: 1659 return repr(CIF(self._value)) 1660 else: 1661 return repr(RIF(self._value)) 1113 1662 1114 1663 def _mul_(self, other): 1664 """ 1665 TESTS: 1666 sage: AA(sqrt(2)) * AA(sqrt(8)) 1667 [3.9999999999999995 .. 4.0000000000000009] 1668 """ 1115 1669 sd = self._descr 1116 1670 od = other._descr 1117 if sd.is_rational() and od.is_rational(): 1118 value = sd.rational_value() * od.rational_value() 1119 return AlgebraicRealNumber(AlgebraicRealNumberRational(value)) 1120 elif sd.is_field_element() and \ 1121 od.is_field_element() and \ 1122 sd.field_parent() == od.field_parent(): 1123 value = sd.field_element_value() * od.field_element_value() 1124 return AlgebraicRealNumber(AlgebraicRealNumberExtensionElement(sd.field_parent(), value)) 1125 else: 1126 value = AlgebraicRealNumberExpression(self, other, '*') 1127 return AlgebraicRealNumber(value) 1671 sdk = sd.kind() 1672 odk = od.kind() 1673 return type(self)(_mul_algo[sdk, odk](self, other, False)) 1128 1674 1129 1675 def _div_(self, other): 1676 """ 1677 TESTS: 1678 sage: AA(sqrt(2)) / AA(sqrt(8)) 1679 [0.49999999999999994 .. 0.50000000000000012] 1680 """ 1130 1681 sd = self._descr 1131 1682 od = other._descr 1132 if sd.is_rational() and od.is_rational(): 1133 value = sd.rational_value() / od.rational_value() 1134 return AlgebraicRealNumber(AlgebraicRealNumberRational(value)) 1135 elif sd.is_field_element() and \ 1136 od.is_field_element() and \ 1137 sd.field_parent() == od.field_parent(): 1138 value = sd.field_element_value() / od.field_element_value() 1139 return AlgebraicRealNumber(AlgebraicRealNumberExtensionElement(sd.field_parent(), value)) 1140 else: 1141 value = AlgebraicRealNumberExpression(self, other, '/') 1142 return AlgebraicRealNumber(value) 1683 sdk = sd.kind() 1684 odk = od.kind() 1685 return type(self)(_mul_algo[sdk, odk](self, other, True)) 1143 1686 1144 1687 def __invert__(self): 1688 """ 1689 TESTS: 1690 sage: ~AA(sqrt(~2)) 1691 [1.4142135623730949 .. 1.4142135623730952] 1692 """ 1145 1693 sd = self._descr 1146 if sd.is_rational: 1147 value = ~sd.rational_value() 1148 return AlgebraicRealNumber(AlgebraicRealNumberRational(value)) 1149 elif sd.is_field_element(): 1150 value = ~sd.field_element_value() 1151 return AlgebraicRealNumber(AlgebraicRealNumberExtensionElement(sd.field_parent(), value)) 1152 else: 1153 value = AlgebraicRealNumberExpression(None, self, '/') 1154 return AlgebraicRealNumber(value) 1694 return type(self)(self._descr.invert(self)) 1155 1695 1156 1696 def _add_(self, other): 1697 """ 1698 TESTS: 1699 sage: x = polygen(ZZ) 1700 sage: rt1, rt2 = (x^2 - x - 1).roots(ring=AA, multiplicities=False) 1701 sage: rt1 + rt2 1702 [0.99999999999999988 .. 1.0000000000000003] 1703 """ 1157 1704 sd = self._descr 1158 1705 od = other._descr 1159 if sd.is_rational() and od.is_rational(): 1160 value = sd.rational_value() + od.rational_value() 1161 return AlgebraicRealNumber(AlgebraicRealNumberRational(value)) 1162 elif sd.is_field_element() and \ 1163 od.is_field_element() and \ 1164 sd.field_parent() == od.field_parent(): 1165 value = sd.field_element_value() + od.field_element_value() 1166 return AlgebraicRealNumber(AlgebraicRealNumberExtensionElement(sd.field_parent(), value)) 1167 else: 1168 value = AlgebraicRealNumberExpression(self, other, '+') 1169 return AlgebraicRealNumber(value) 1706 sdk = sd.kind() 1707 odk = od.kind() 1708 return type(self)(_add_algo[sdk, odk](self, other, False)) 1170 1709 1171 1710 def _sub_(self, other): 1711 """ 1712 TESTS: 1713 sage: AA(golden_ratio) * 2 - AA(5).sqrt() 1714 [0.99999999999999988 .. 1.0000000000000003] 1715 """ 1172 1716 sd = self._descr 1173 1717 od = other._descr 1174 if sd.is_rational() and od.is_rational(): 1175 value = sd.rational_value() - od.rational_value() 1176 return AlgebraicRealNumber(AlgebraicRealNumberRational(value)) 1177 elif sd.is_field_element() and \ 1178 od.is_field_element() and \ 1179 sd.field_parent() == od.field_parent(): 1180 value = sd.field_element_value() - od.field_element_value() 1181 return AlgebraicRealNumber(AlgebraicRealNumberExtensionElement(sd.field_parent(), value)) 1718 sdk = sd.kind() 1719 odk = od.kind() 1720 return type(self)(_add_algo[sdk, odk](self, other, True)) 1721 1722 def _neg_(self): 1723 """ 1724 TESTS: 1725 sage: -QQbar(I) 1726 -1*I 1727 """ 1728 return type(self)(self._descr.neg(self)) 1729 1730 def __abs__(self): 1731 """ 1732 TESTS: 1733 sage: abs(AA(sqrt(2) - sqrt(3))) 1734 [0.31783724519578221 .. 0.31783724519578227] 1735 sage: abs(QQbar(3+4*I)) 1736 5 1737 """ 1738 return AlgebraicReal(self._descr.abs(self)) 1739 1740 def __hash__(self): 1741 """ 1742 Compute a hash code for this number (equal algebraic numbers will 1743 have the same hash code, different algebraic numbers are likely 1744 to have different hash codes). 1745 1746 This may trigger exact computation, but that is very unlikely. 1747 1748 TESTS: 1749 The hash code is stable, even when the representation changes. 1750 sage: two = QQbar(4).nth_root(4)^2 1751 sage: two 1752 [1.9999999999999997 .. 2.0000000000000005] 1753 sage: h1 = hash(two) 1754 sage: two == 2 1755 True 1756 sage: two 1757 2 1758 sage: h2 = hash(two) 1759 sage: h1 == h2 1760 True 1761 1762 sage: h1 = hash(QQbar.zeta(6)) 1763 sage: h2 = hash(QQbar(1/2 + I*sqrt(3)/2)) 1764 sage: h1 == h2 1765 True 1766 1767 Unfortunately, the hash code for algebraic numbers which are close 1768 enough to each other are the same. (This is inevitable, if 1769 equal algebraic reals give the same hash code and hashing does 1770 not always trigger exact computation.) 1771 sage: h1 = hash(QQbar(0)) 1772 sage: h2 = hash(QQbar(1/2^100)) 1773 sage: hash(h1) == hash(h2) 1774 True 1775 1776 """ 1777 1778 # The only way I can think of to hash algebraic numbers without 1779 # always triggering exact computation is to use interval_exact(). 1780 # However, interval_exact() always triggers exact computation 1781 # if the number is exactly representable in floating point, which 1782 # is presumably not too unlikely (algebraic reals like 0, 1/2, 1783 # 1, or 2 are presumably not uncommon). 1784 1785 # So I modify the algebraic real by adding 1/123456789 to it before 1786 # calling interval_exact(). Then, exact computation will be triggered 1787 # by algebraic reals which are sufficiently close to 1788 # (some floating point number minus 1/123456789). Hopefully, 1789 # -1/123456789 comes up in algebraic real computations far less 1790 # often than 0 does. Algebraic numbers have a similar offset added, 1791 # with an additional complex component of 1/987654321*I. 1792 1793 # All of this effort to avoid exact computation is probably wasted, 1794 # anyway... in almost all uses of hash codes, if the hash codes 1795 # match, the next step is to compare for equality; and comparing 1796 # for equality often requires exact computation. (If a==b, 1797 # then checking a==b requires exact computation unless (a is b).) 1798 1799 if self.parent() is AA: 1800 return hash((self + AA_hash_offset).interval_exact(RIF)) 1182 1801 else: 1183 value = AlgebraicRealNumberExpression(self, other, '-') 1184 return AlgebraicRealNumber(value) 1185 1186 def _neg_(self): 1802 return hash((self + QQbar_hash_offset).interval_exact(CIF)) 1803 1804 def sqrt(self): 1805 """ 1806 Return the square root of this number. 1807 1808 EXAMPLES: 1809 sage: AA(2).sqrt() 1810 [1.4142135623730949 .. 1.4142135623730952] 1811 sage: QQbar(I).sqrt() 1812 [0.70710678118654746 .. 0.70710678118654758] + [0.70710678118654746 .. 0.70710678118654758]*I 1813 """ 1814 return self.__pow__(~ZZ(2)) 1815 1816 def nth_root(self, n): 1817 """ 1818 Return the nth root of this number. 1819 1820 Note that for odd n and negative real numbers, AlgebraicReal 1821 and AlgebraicNumber values give different answers: AlgebraicReal 1822 values prefer real results, and AlgebraicNumber values 1823 return the principle root. 1824 1825 EXAMPLES: 1826 sage: AA(-8).nth_root(3) 1827 -2 1828 sage: QQbar(-8).nth_root(3) 1829 [0.99999999999999988 .. 1.0000000000000003] + [1.7320508075688771 .. 1.7320508075688775]*I 1830 sage: QQbar.zeta(12).nth_root(15) 1831 [0.99939082701909565 .. 0.99939082701909577] + [0.034899496702500969 .. 0.034899496702500977]*I 1832 """ 1833 return self.__pow__(~ZZ(n)) 1834 1835 def exactify(self): 1836 """ 1837 Compute an exact representation for this number. 1838 1839 EXAMPLES: 1840 sage: two = QQbar(4).nth_root(4)^2 1841 sage: two 1842 [1.9999999999999997 .. 2.0000000000000005] 1843 sage: two.exactify() 1844 sage: two 1845 2 1846 """ 1847 od = self._descr 1848 if od.is_exact(): return 1849 self._descr = self._descr.exactify() 1850 new_val = self._descr._interval_fast(self.parent().default_interval_prec()) 1851 if is_RealIntervalFieldElement(new_val) and is_ComplexIntervalFieldElement(self._value): 1852 self._value = self._value.real().intersection(new_val) 1853 elif is_RealIntervalFieldElement(self._value) and is_ComplexIntervalFieldElement(new_val): 1854 self._value = self._value.intersection(new_val.real()) 1855 else: 1856 self._value = self._value.intersection(new_val) 1857 1858 def _exact_field(self): 1859 """ 1860 Returns a generator for a number field that includes this number 1861 (not necessarily the smallest such number field). 1862 1863 EXAMPLES: 1864 sage: QQbar(2)._exact_field() 1865 Trivial generator 1866 sage: (sqrt(QQbar(2)) + sqrt(QQbar(19)))._exact_field() 1867 Number Field in a with defining polynomial y^4 - 20*y^2 + 81 with a in [3.7893137826710354 .. 3.7893137826710360] 1868 sage: (QQbar(7)^(3/5))._exact_field() 1869 Number Field in a with defining polynomial y^5 - 7 with a in [1.4757731615945519 .. 1.4757731615945522] 1870 """ 1871 1187 1872 sd = self._descr 1188 if sd.is_rational(): 1189 value = -sd.rational_value() 1190 return AlgebraicRealNumber(AlgebraicRealNumberRational(value)) 1191 elif sd.is_field_element(): 1192 value = -sd.field_element_value() 1193 return AlgebraicRealNumber(AlgebraicRealNumberExtensionElement(sd.field_parent(), value)) 1873 if sd.is_exact(): 1874 return sd.generator() 1875 self.exactify() 1876 return self._exact_field() 1877 1878 def _exact_value(self): 1879 """ 1880 Returns an ANRational, an ANRootOfUnity, or an 1881 ANExtensionElement representing this value. 1882 1883 EXAMPLES: 1884 sage: QQbar(2)._exact_value() 1885 2 1886 sage: (sqrt(QQbar(2)) + sqrt(QQbar(19)))._exact_value() 1887 1/9*a^3 + a^2 - 11/9*a - 10 where a^4 - 20*a^2 + 81 = 0 and a in [3.7893137826710354 .. 3.7893137826710360] 1888 sage: (QQbar(7)^(3/5))._exact_value() 1889 a^3 where a^5 - 7 = 0 and a in [1.4757731615945519 .. 1.4757731615945522] 1890 """ 1891 sd = self._descr 1892 if sd.is_exact(): 1893 return sd 1894 self.exactify() 1895 return self._descr 1896 1897 def _more_precision(self): 1898 """ 1899 Recompute the interval bounding this number with higher-precision 1900 interval arithmetic. 1901 1902 EXAMPLES: 1903 sage: rt2 = sqrt(QQbar(2)) 1904 sage: rt2._value 1905 [1.41421356237309504876 .. 1.41421356237309504888] 1906 sage: rt2._more_precision() 1907 sage: rt2._value 1908 [1.414213562373095048801688724209698078568 .. 1.414213562373095048801688724209698078575] 1909 sage: rt2._more_precision() 1910 sage: rt2._value 1911 [1.414213562373095048801688724209698078569671875376948073176679737990732478462101 .. 1.414213562373095048801688724209698078569671875376948073176679737990732478462120] 1912 """ 1913 prec = self._value.prec() 1914 self._value = self._descr._interval_fast(prec*2) 1915 1916 def minpoly(self): 1917 """ 1918 Compute the minimal polynomial of this algebraic number. 1919 The minimal polynomial is the monic polynomial of least degree 1920 having this number as a root; it is unique. 1921 1922 EXAMPLES: 1923 sage: QQbar(4).sqrt().minpoly() 1924 x - 2 1925 sage: ((QQbar(2).nth_root(4))^2).minpoly() 1926 x^2 - 2 1927 sage: v = sqrt(QQbar(2)) + sqrt(QQbar(3)); v 1928 [3.1462643699419721 .. 3.1462643699419726] 1929 sage: p = v.minpoly(); p 1930 x^4 - 10*x^2 + 1 1931 sage: p(RR(v.real())) 1932 0.0000000000000131006316905768 1933 """ 1934 try: 1935 return self._minimal_polynomial 1936 except AttributeError: 1937 self.exactify() 1938 self._minimal_polynomial = self._descr.minpoly() 1939 return self._minimal_polynomial 1940 1941 def degree(self): 1942 """ 1943 Return the degree of this algebraic number (the degree of its 1944 minimal polynomial, or equivalently, the degree of the smallest 1945 algebraic extension of the rationals containing this number). 1946 1947 EXAMPLES: 1948 sage: QQbar(5/3).degree() 1949 1 1950 sage: sqrt(QQbar(2)).degree() 1951 2 1952 sage: QQbar(17).nth_root(5).degree() 1953 5 1954 sage: sqrt(3+sqrt(QQbar(8))).degree() 1955 2 1956 """ 1957 return self.minpoly().degree() 1958 1959 def interval_fast(self, field): 1960 """ 1961 Given a RealIntervalField, compute the value of this number 1962 using interval arithmetic of at least the precision of the field, 1963 and return the value in that field. (More precision may be used 1964 in the computation.) The returned interval may be arbitrarily 1965 imprecise, if this number is the result of a sufficiently long 1966 computation chain. 1967 1968 EXAMPLES: 1969 sage: x = AA(2).sqrt() 1970 sage: x.interval_fast(RIF) 1971 [1.4142135623730949 .. 1.4142135623730952] 1972 sage: x.interval_fast(RealIntervalField(200)) 1973 [1.4142135623730950488016887242096980785696718753769480731766796 .. 1.4142135623730950488016887242096980785696718753769480731766809] 1974 sage: x = QQbar(I).sqrt() 1975 sage: x.interval_fast(CIF) 1976 [0.70710678118654746 .. 0.70710678118654758] + [0.70710678118654746 .. 0.70710678118654758]*I 1977 sage: x.interval_fast(RIF) 1978 Traceback (most recent call last): 1979 ... 1980 TypeError: Unable to convert number to real interval. 1981 """ 1982 if field.prec() == self._value.prec(): 1983 return field(self._value) 1984 elif field.prec() > self._value.prec(): 1985 self._more_precision() 1986 return self.interval_fast(field) 1194 1987 else: 1195 value = AlgebraicRealNumberExpression(None, self, '-') 1196 return AlgebraicRealNumber(value) 1988 return field(self._value) 1989 1990 def interval_diameter(self, diam): 1991 """ 1992 Compute an interval representation of self with diameter() at 1993 most diam. The precision of the returned value is unpredictable. 1994 1995 EXAMPLES: 1996 sage: AA(2).sqrt().interval_diameter(1e-10) 1997 [1.41421356237309504876 .. 1.41421356237309504888] 1998 sage: AA(2).sqrt().interval_diameter(1e-30) 1999 [1.414213562373095048801688724209698078568 .. 1.414213562373095048801688724209698078575] 2000 sage: QQbar(2).sqrt().interval_diameter(1e-10) 2001 [1.41421356237309504876 .. 1.41421356237309504888] 2002 sage: QQbar(2).sqrt().interval_diameter(1e-30) 2003 [1.414213562373095048801688724209698078568 .. 1.414213562373095048801688724209698078575] 2004 """ 2005 if diam <= 0: 2006 raise ValueError, 'diameter must be positive in interval_diameter' 2007 2008 while self._value.diameter() > diam: 2009 self._more_precision() 2010 2011 return self._value 2012 2013 def interval(self, field): 2014 """ 2015 Given an interval field (real or complex, as appropriate) of 2016 precision p, compute an interval representation of self with 2017 diameter() at most 2^-p; then round that representation into 2018 the given field. Here diameter() is relative diameter for 2019 intervals not containing 0, and absolute diameter for 2020 intervals that do contain 0; thus, if the returned interval 2021 does not contain 0, it has at least p-1 good bits. 2022 2023 EXAMPLES: 2024 sage: RIF64 = RealIntervalField(64) 2025 sage: x = AA(2).sqrt() 2026 sage: y = x*x 2027 sage: y = 1000 * y - 999 * y 2028 sage: y.interval_fast(RIF64) 2029 [1.99999999999999966693 .. 2.00000000000000033307] 2030 sage: y.interval(RIF64) 2031 [1.99999999999999999989 .. 2.00000000000000000022] 2032 sage: CIF64 = ComplexIntervalField(64) 2033 sage: x = QQbar.zeta(11) 2034 sage: x.interval_fast(CIF64) 2035 [0.841253532831181168808 .. 0.841253532831181168918] + [0.540640817455597581992 .. 0.540640817455597582210]*I 2036 sage: x.interval(CIF64) 2037 [0.841253532831181168808 .. 0.841253532831181168864] + [0.540640817455597582101 .. 0.540640817455597582156]*I 2038 """ 2039 target = RR(1.0) >> field.prec() 2040 val = self.interval_diameter(target) 2041 return field(val) 2042 2043 class AlgebraicNumber(AlgebraicNumber_base): 2044 """ 2045 The class for algebraic numbers (complex numbers which are the roots 2046 of a polynomial with integer coefficients). Much of its functionality 2047 is inherited from AlgebraicNumber_base. 2048 """ 2049 def __init__(self, x): 2050 AlgebraicNumber_base.__init__(self, QQbar, x) 1197 2051 1198 2052 def __cmp__(self, other): 2053 """ 2054 Compare two algebraic numbers, lexicographically. (That is, 2055 first compare the real components; if the real componetns are 2056 equal, compare the imaginary components.) 2057 2058 EXAMPLES: 2059 sage: x = QQbar.zeta(3); x 2060 [-0.50000000000000012 .. -0.49999999999999994] + [0.86602540378443859 .. 0.86602540378443871]*I 2061 sage: cmp(QQbar(-1), x) 2062 -1 2063 sage: cmp(QQbar(-1/2), x) 2064 -1 2065 sage: cmp(QQbar(0), x) 2066 1 2067 """ 2068 if self is other: return 0 2069 rcmp = cmp(self.real(), other.real()) 2070 if rcmp != 0: 2071 return rcmp 2072 return cmp(self.imag(), other.imag()) 2073 2074 def __eq__(self, other): 2075 """ 2076 Test two algebraic numbers for equality. 2077 2078 EXAMPLES: 2079 sage: QQbar.zeta(6) == QQbar(1/2 + I*sqrt(3)/2) 2080 True 2081 sage: QQbar(I) == QQbar(I * (2^100+1)/(2^100)) 2082 False 2083 """ 2084 if not isinstance(other, AlgebraicNumber): 2085 other = self.parent()(other) 2086 if self is other: return True 2087 if other._descr.is_rational() and other._descr.rational_value() == 0: 2088 return not self.__nonzero__() 2089 if self._descr.is_rational() and self._descr.rational_value() == 0: 2090 return not other.__nonzero__() 2091 return not self._sub_(other).__nonzero__() 2092 2093 def __ne__(self, other): 2094 return not self.__eq__(other) 2095 2096 def __nonzero__(self): 2097 """ 2098 Check whether self is equal is nonzero. This is fast if 2099 interval arithmetic proves that self is nonzero, but may be 2100 slow if the number actually is very close to zero. 2101 2102 EXAMPLES: 2103 sage: (QQbar.zeta(2) + 1).__nonzero__() 2104 False 2105 sage: (QQbar.zeta(7) / (2^500)).__nonzero__() 2106 True 2107 """ 2108 val = self._value 2109 if not val.contains_zero(): 2110 return True 2111 if self._descr.is_field_element(): 2112 # The ANExtensionElement constructor returns an ANRational 2113 # instead, if the number is zero. 2114 return True 2115 if self._descr.is_rational(): 2116 return self._descr.rational_value().__nonzero__() 2117 if self._value.prec() < 128: 2118 self._more_precision() 2119 return self.__nonzero__() 2120 2121 # Sigh... 2122 self.exactify() 2123 return self.__nonzero__() 2124 2125 def __pow__(self, e): 2126 """ 2127 self^p returns the p'th power of self (where p can be an arbitrary 2128 rational). If p is (a/b), takes the principle b'th root of self, 2129 then takes that to the a'th power. (Note that this differs 2130 from __pow__ on algebraic reals, where real roots are preferred 2131 over principle roots if they exist.) 2132 2133 EXAMPLES: 2134 sage: QQbar(2)^(1/2) 2135 [1.4142135623730949 .. 1.4142135623730952] 2136 sage: QQbar(8)^(2/3) 2137 4 2138 sage: QQbar(8)^(2/3) == 4 2139 True 2140 sage: x = polygen(QQbar) 2141 sage: phi = QQbar.polynomial_root(x^2 - x - 1, RIF(1, 2)) 2142 sage: tau = QQbar.polynomial_root(x^2 - x - 1, RIF(-1, 0)) 2143 sage: rt5 = QQbar(5)^(1/2) 2144 sage: phi^10 / rt5 2145 [55.003636123247410 .. 55.003636123247418] 2146 sage: tau^10 / rt5 2147 [0.0036361232474132654 .. 0.0036361232474132659] 2148 sage: (phi^10 - tau^10) / rt5 2149 [54.999999999999992 .. 55.000000000000008] 2150 sage: (phi^10 - tau^10) / rt5 == fibonacci(10) 2151 True 2152 sage: (phi^50 - tau^50) / rt5 == fibonacci(50) 2153 True 2154 sage: QQbar(-8)^(1/3) 2155 [0.99999999999999988 .. 1.0000000000000003] + [1.7320508075688771 .. 1.7320508075688775]*I 2156 sage: (QQbar(-8)^(1/3))^3 2157 -8 2158 sage: QQbar(32)^(1/5) 2159 2 2160 sage: a = QQbar.zeta(7)^(1/3); a 2161 [0.95557280578614067 .. 0.95557280578614079] + [0.29475517441090420 .. 0.29475517441090427]*I 2162 sage: a == QQbar.zeta(21) 2163 True 2164 sage: QQbar.zeta(7)^6 2165 [0.62348980185873348 .. 0.62348980185873360] - [0.78183148246802980 .. 0.78183148246802992]*I 2166 sage: (QQbar.zeta(7)^6)^(1/3) * QQbar.zeta(21) 2167 1 2168 """ 2169 e = QQ._coerce_(e) 2170 n = e.numerator() 2171 d = e.denominator() 2172 if d == 1: 2173 return generic_power(self, n) 2174 2175 # First, check for exact roots. 2176 if isinstance(self._descr, ANRational): 2177 rt = rational_exact_root(abs(self._descr._value), d) 2178 if rt is not None: 2179 if self._descr._value < 0: 2180 return AlgebraicNumber(ANRootOfUnity(~(2*d), rt))**n 2181 else: 2182 return AlgebraicNumber(ANRational(rt))**n 2183 elif isinstance(self._descr, ANRootOfUnity): 2184 rt = rational_exact_root(abs(self._descr._scale), d) 2185 if rt is not None: 2186 if self._descr._scale < 0: 2187 return AlgebraicNumber(ANRootOfUnity((self._descr._angle - QQ_1_2)/d, rt))**n 2188 else: 2189 return AlgebraicNumber(ANRootOfUnity(self._descr._angle/d, rt))**n 2190 2191 # Without this special case, we don't know the multiplicity 2192 # of the desired root 2193 if self.is_zero(): 2194 return AlgebriacNumber(0) 2195 argument_is_pi = False 2196 for prec in short_prec_seq(): 2197 if prec is None: 2198 # We know that self.real() < 0, since self._value 2199 # crosses the negative real line and self._value 2200 # is known to be non-zero. 2201 isgn = self.imag().sign() 2202 val = self._value 2203 argument = val.argument() 2204 if isgn == 0: 2205 argument = argument.parent().pi() 2206 argument_is_pi = True 2207 elif isgn > 0: 2208 if argument < 0: 2209 argument = argument + 2 * argument.parent().pi() 2210 else: 2211 if argument > 0: 2212 argument = argument - 2 * argument.parent().pi() 2213 else: 2214 val = self._interval_fast(prec) 2215 if not val.crosses_log_branch_cut(): 2216 argument = val.argument() 2217 if val.imag().is_zero() and val.real() < 0: 2218 argument_is_pi = True 2219 break 2220 2221 target_abs = abs(val) ** e 2222 target_arg = argument * e 2223 2224 for prec in tail_prec_seq(): 2225 if target_abs.relative_diameter() < RR_1_10 and (target_arg * d).absolute_diameter() < RR_1_10: 2226 break 2227 2228 val = self._interval_fast(prec) 2229 2230 target_abs = abs(val) ** e 2231 argument = val.argument() 2232 if argument_is_pi: 2233 argument = argument.parent().pi() 2234 target_arg = argument * e 2235 2236 pow_n = self**n 2237 poly = QQbarPoly.gen()**d - pow_n 2238 2239 prec = target_abs.prec() 2240 if argument_is_pi and d == 2: 2241 target_real = 0 2242 else: 2243 target_real = target_arg.cos() * target_abs 2244 target = ComplexIntervalField(prec)(target_real, 2245 target_arg.sin() * target_abs) 2246 2247 return AlgebraicNumber(ANRoot(poly, target)) 2248 2249 def _interval_fast(self, prec): 2250 return self.interval_fast(ComplexIntervalField(prec)) 2251 2252 def real(self): 2253 return AlgebraicReal(self._descr.real(self)) 2254 2255 def imag(self): 2256 return AlgebraicReal(self._descr.imag(self)) 2257 2258 def conjugate(self): 2259 """ 2260 Returns the complex conjugate of self. 2261 2262 EXAMPLES: 2263 sage: QQbar(3 + 4*I).conjugate() 2264 [3.0000000000000000 .. 3.0000000000000000] - [4.0000000000000000 .. 4.0000000000000000]*I 2265 sage: QQbar.zeta(7).conjugate() 2266 [0.62348980185873348 .. 0.62348980185873360] - [0.78183148246802980 .. 0.78183148246802992]*I 2267 sage: QQbar.zeta(7) + QQbar.zeta(7).conjugate() 2268 [1.2469796037174669 .. 1.2469796037174672] + [-3.2526065174565134e-19 .. 3.7947076036992656e-19]*I 2269 """ 2270 return AlgebraicNumber(self._descr.conjugate(self)) 2271 2272 def norm(self): 2273 """ 2274 Returns self * self.conjugate(). This is the algebraic 2275 definition of norm, if we view QQbar as AA[I]. 2276 2277 EXAMPLES: 2278 sage: QQbar(3 + 4*I).norm() 2279 25 2280 sage: type(QQbar(I).norm()) 2281 <class 'sage.rings.algebraic_real.AlgebraicReal'> 2282 sage: QQbar.zeta(1007).norm() 2283 1 2284 """ 2285 return AlgebraicReal(self._descr.norm(self)) 2286 2287 def interval_exact(self, field): 2288 """ 2289 Given a ComplexIntervalField, compute the best possible 2290 approximation of this number in that field. Note that if 2291 either the real or imaginary parts of this number are 2292 sufficiently close to some floating-point number (and, in 2293 particular, if either is exactly representable in floating-point), 2294 then this will trigger exact computation, which may be very slow. 2295 2296 EXAMPLES: 2297 sage: a = QQbar(I).sqrt(); a 2298 [0.70710678118654746 .. 0.70710678118654758] + [0.70710678118654746 .. 0.70710678118654758]*I 2299 sage: a.interval_exact(CIF) 2300 [0.70710678118654746 .. 0.70710678118654758] + [0.70710678118654746 .. 0.70710678118654758]*I 2301 sage: b = QQbar((1+I)*sqrt(2)/2) 2302 sage: (a - b).interval(CIF) 2303 [-5.4210108624275222e-20 .. 5.4210108624275222e-20] + [-1.0842021724855045e-19 .. 5.4210108624275222e-20]*I 2304 sage: (a - b).interval_exact(CIF) 2305 0 2306 """ 2307 if not is_ComplexIntervalField(field): 2308 raise ValueError, "AlgebraicNumber interval_exact requires a ComplexIntervalField" 2309 rfld = field._real_field() 2310 re = self.real().interval_exact(rfld) 2311 im = self.imag().interval_exact(rfld) 2312 return field(re, im) 2313 2314 def _complex_mpfr_field_(self, field): 2315 if is_ComplexIntervalField(field): 2316 return self.interval(field) 2317 else: 2318 return self.complex_number(field) 2319 2320 2321 def complex_number(self, field): 2322 """ 2323 Given a ComplexField, compute a good approximation to self in that 2324 field. The approximation will be off by at most two ulp's in 2325 each component, except for components which are very close to 2326 zero, which will have an abolute error at most 2^(-(field.prec()-1)). 2327 2328 EXAMPLES: 2329 sage: a = QQbar.zeta(5) 2330 sage: a.complex_number(CIF) 2331 0.309016994374947 + 0.951056516295154*I 2332 sage: (a + a.conjugate()).complex_number(CIF) 2333 0.618033988749895 - 5.42101086242752e-20*I 2334 """ 2335 v = self.interval(ComplexIntervalField(field.prec())) 2336 return v.center() 2337 2338 def complex_exact(self, field): 2339 """ 2340 Given a ComplexField, return the best possible approximation of 2341 this number in that field. Note that if either component is 2342 sufficiently close to the halfway point between two floating-point 2343 numbers in the corresponding RealField, then this will trigger 2344 exact computation, which may be very slow. 2345 2346 EXAMPLES: 2347 sage: a = QQbar.zeta(9) + I + QQbar.zeta(9).conjugate(); a 2348 [1.5320888862379560 .. 1.5320888862379563] + [0.99999999999999988 .. 1.0000000000000003]*I 2349 sage: a.complex_exact(CIF) 2350 [1.5320888862379560 .. 1.5320888862379563] + [1.0000000000000000 .. 1.0000000000000000]*I 2351 """ 2352 rfld = field._real_field() 2353 re = self.real().real_exact(rfld) 2354 im = self.imag().real_exact(rfld) 2355 return field(re, im) 2356 2357 def multiplicative_order(self): 2358 """ 2359 Compute the multiplicative order of this algebraic real 2360 number. That is, find the smallest positive integer n such 2361 that x^n == 1. If there is no such n, returns +Infinity. 2362 2363 We first check that abs(x) is very close to 1. If so, we compute 2364 x exactly and examine its argument. 2365 2366 EXAMPLES: 2367 sage: QQbar(-sqrt(3)/2 - I/2).multiplicative_order() 2368 12 2369 sage: QQbar(1).multiplicative_order() 2370 1 2371 sage: QQbar(-I).multiplicative_order() 2372 4 2373 sage: QQbar(707/1000 + 707/1000*I).multiplicative_order() 2374 +Infinity 2375 sage: QQbar(3/5 + 4/5*I).multiplicative_order() 2376 +Infinity 2377 """ 2378 if not (1 in CIF(self).norm()): 2379 return infinity.infinity 2380 if self.norm() != 1: 2381 return infinity.infinity 2382 ra = self.rational_argument() 2383 if ra is None: 2384 return infinity.infinity 2385 return ra.denominator() 2386 2387 def rational_argument(self): 2388 """ 2389 Returns the argument of self, divided by 2*pi, as long as this 2390 result is rational. Otherwise returns None. Always triggers 2391 exact computation. 2392 2393 EXAMPLES: 2394 sage: QQbar((1+I)*(sqrt(2)+sqrt(5))).rational_argument() 2395 1/8 2396 sage: QQbar(-1 + I*sqrt(3)).rational_argument() 2397 1/3 2398 sage: QQbar(-1 - I*sqrt(3)).rational_argument() 2399 -1/3 2400 sage: QQbar(3+4*I).rational_argument() is None 2401 True 2402 sage: (QQbar.zeta(7654321)^65536).rational_argument() 2403 65536/7654321 2404 sage: (QQbar.zeta(3)^65536).rational_argument() 2405 1/3 2406 """ 2407 # This always triggers exact computation. An alternate method 2408 # could almost always avoid exact computation when the result 2409 # is None: if we can compute an upper bound on the degree of 2410 # this algebraic number without exact computation, we can use 2411 # the method of ANExtensionElement.rational_argument(). 2412 2413 # Even a very loose upper bound would suffice; for instance, 2414 # an upper bound of 2^100, when the true degree was 8, would 2415 # still be efficient. 2416 2417 self.exactify() 2418 return self._descr.rational_argument(self) 2419 2420 class AlgebraicReal(AlgebraicNumber_base): 2421 def __init__(self, x): 2422 AlgebraicNumber_base.__init__(self, AA, x) 2423 2424 def __cmp__(self, other): 2425 """ 2426 Compare two algebraic reals. 2427 2428 EXAMPLES: 2429 sage: cmp(AA(golden_ratio), AA(sqrt(5))) 2430 -1 2431 sage: cmp(AA(golden_ratio), AA((sqrt(5)+1)/2)) 2432 0 2433 sage: cmp(AA(7), AA(50/7)) 2434 -1 2435 """ 2436 if self is other: return 0 1199 2437 if other._descr.is_rational() and other._descr.rational_value() == 0: 1200 2438 return self.sign() … … 1206 2444 def __pow__(self, e): 1207 2445 """ 1208 self^p returns the p'th power of self (where p can be an arbitrary 1209 rational). 2446 self^p returns the p'th power of self (where p can be an 2447 arbitrary rational). If p is (a/b), takes the b'th root of 2448 self, then takes that to the a'th power. If self is negative 2449 and b is odd, it takes the real b'th root; if self is odd and 2450 b is even, this takes a complex root. Note that the behavior 2451 when self is negative and b is odd differs from the complex 2452 case; algebraic numbers select the principle complex b'th 2453 root, but algebraic reals select the real root. 1210 2454 1211 2455 EXAMPLES: … … 1213 2457 [1.4142135623730949 .. 1.4142135623730952] 1214 2458 sage: AA(8)^(2/3) 1215 [3.9999999999999995 .. 4.0000000000000009]2459 4 1216 2460 sage: AA(8)^(2/3) == 4 1217 2461 True … … 1230 2474 sage: (phi^50 - tau^50) / rt5 == fibonacci(50) 1231 2475 True 2476 2477 TESTS: 2478 sage: AA(-8)^(1/3) 2479 -2 2480 sage: AA(-8)^(2/3) 2481 4 2482 sage: AA(32)^(3/5) 2483 8 2484 sage: AA(-16)^(1/2) 2485 4*I 2486 sage: AA(-16)^(1/4) 2487 [1.4142135623730949 .. 1.4142135623730952] + [1.4142135623730949 .. 1.4142135623730952]*I 2488 sage: AA(-16)^(1/4)/QQbar.zeta(8) 2489 2 1232 2490 """ 1233 2491 e = QQ._coerce_(e) … … 1236 2494 if d == 1: 1237 2495 return generic_power(self, n) 2496 2497 # First, check for exact roots. 2498 if isinstance(self._descr, ANRational): 2499 rt = rational_exact_root(abs(self._descr._value), d) 2500 if rt is not None: 2501 if self._descr._value < 0: 2502 if d % 2 == 0: 2503 return AlgebraicNumber(ANRootOfUnity(~(2*d), rt))**n 2504 else: 2505 return AlgebraicReal(ANRational(-rt))**n 2506 else: 2507 return AlgebraicReal(ANRational(rt))**n 2508 1238 2509 # Without this special case, we don't know the multiplicity 1239 2510 # of the desired root … … 1242 2513 if d % 2 == 0: 1243 2514 if self.sign() < 0: 1244 r aise ValueError, 'complex algebraics not implemented'2515 return QQbar(self).__pow__(e) 1245 2516 pow_n = self**n 1246 2517 poly = AAPoly.gen()**d - pow_n … … 1251 2522 result_min = min(range.lower(), -1) 1252 2523 result_max = max(range.upper(), 1) 1253 return AlgebraicRealNumber(AlgebraicRealNumberRoot(poly, RIF(result_min, result_max))) 1254 1255 def __hash__(self): 1256 """ 1257 Compute a hash code for this number (equal algebraic reals will 1258 have the same hash code, different algebraic reals are likely 1259 to have different hash codes). 1260 1261 This may trigger exact computation, but that is very unlikely. 1262 1263 TESTS: 1264 The hash code is stable, even when the representation changes. 1265 sage: two = sqrt(AA(4)) 1266 sage: two 1267 [1.9999999999999997 .. 2.0000000000000005] 1268 sage: h1 = hash(two) 1269 sage: two == 2 1270 True 1271 sage: two 1272 2 1273 sage: h2 = hash(two) 1274 sage: h1 == h2 1275 True 1276 1277 Unfortunately, the hash code for algebraic reals which are close 1278 enough to each other are the same. (This is inevitable, if 1279 equal algebraic reals give the same hash code and hashing does 1280 not trigger exact computation.) 1281 sage: h1 = hash(AA(0)) 1282 sage: h2 = hash(AA(1/2^100)) 1283 sage: hash(h1) == hash(h2) 1284 True 1285 """ 1286 1287 # The only way I can think of to hash algebraic reals without 1288 # always triggering exact computation is to use interval_exact(). 1289 # However, interval_exact() always triggers exact computation 1290 # if the number is exactly representable in floating point, which 1291 # is presumably not too unlikely (algebraic reals like 0, 1/2, 1292 # 1, or 2 are presumably not uncommon). 1293 1294 # So I modify the algebraic real by adding 1/123456789 to it before 1295 # calling interval_exact(). Then, exact computation will be triggered 1296 # by algebraic reals which are sufficiently close to 1297 # (some floating point number minus 1/123456789). Hopefully, 1298 # -1/123456789 comes up in algebraic real computations far less 1299 # often than 0 does. 1300 1301 # All of this effort to avoid exact computation is probably wasted, 1302 # anyway... in almost all uses of hash codes, if the hash codes 1303 # match, the next step is to compare for equality; and comparing 1304 # for equality always triggers exact computation. 1305 1306 return hash((self + AA_1_123456789).interval_exact(RIF)) 1307 1308 def sqrt(self): 1309 return self.__pow__(~ZZ(2)) 1310 1311 def nth_root(self, n): 1312 return self.__pow__(~ZZ(n)) 1313 1314 def exactify(self): 1315 """ 1316 Compute an exact representation for this number. 1317 1318 EXAMPLES: 1319 sage: two = sqrt(AA(4)) 1320 sage: two 1321 [1.9999999999999997 .. 2.0000000000000005] 1322 sage: two.exactify() 1323 sage: two 1324 2 1325 """ 1326 od = self._descr 1327 if od.is_exact(): return 1328 self._descr = self._descr.exactify() 1329 new_val = self._descr.interval_fast(self.parent().default_interval_field()) 1330 self._value = self._value.intersection(new_val) 1331 # if self._value != self._descr.interval_fast(RIF): 1332 # v1 = self._value 1333 # v2 = self._descr.interval_fast(RIF) 1334 # # print (v1 != v2) 1335 # # print v1 - v2 1336 # # print v1, v2 1337 # # print 'try1', self._descr.interval_fast(RIF), 'done' 1338 # global od2 1339 # od2 = od 1340 # # print 'a', od.interval_fast(RIF), self._value 1341 # # print 'b', self._descr.interval_fast(RIF), v2 1342 # # print 'try2', self._descr.interval_fast(RIF), 'done' 1343 # raise ValueError 1344 1345 def _exact_field(self): 1346 """ 1347 Returns a generator for a number field that includes this number 1348 (not necessarily the smallest such number field). 1349 1350 EXAMPLES: 1351 sage: AA(2)._exact_field() 1352 Unit generator 1353 sage: (sqrt(AA(2)) + sqrt(AA(19)))._exact_field() 1354 Number Field in a with defining polynomial y^4 - 20*y^2 + 81 with a in [3.7893137826710354 .. 3.7893137826710360] 1355 sage: (AA(7)^(3/5))._exact_field() 1356 Number Field in a with defining polynomial y^5 - 7 with a in [1.4757731615945519 .. 1.4757731615945522] 1357 """ 1358 1359 sd = self._descr 1360 if sd.is_rational(): 1361 return unit_generator 1362 if sd.is_field_element(): 1363 return sd.field_parent() 1364 self.exactify() 1365 return self._exact_field() 1366 1367 def _exact_value(self): 1368 """ 1369 Returns either an AlgebraicRealNumberRational or an 1370 AlgebraicRealNumberExtensionElement representing this value. 1371 1372 EXAMPLES: 1373 sage: AA(2)._exact_value() 1374 2 1375 sage: (sqrt(AA(2)) + sqrt(AA(19)))._exact_value() 1376 1/9*a^3 + a^2 - 11/9*a - 10 where a^4 - 20*a^2 + 81 = 0 and a in [3.7893137826710354 .. 3.7893137826710360] 1377 sage: (AA(7)^(3/5))._exact_value() 1378 a^3 where a^5 - 7 = 0 and a in [1.4757731615945519 .. 1.4757731615945522] 1379 """ 1380 sd = self._descr 1381 if sd.is_exact(): 1382 return sd 1383 self.exactify() 1384 return self._exact_value() 1385 1386 def _more_precision(self): 1387 """ 1388 Recompute the interval bounding this number with higher-precision 1389 interval arithmetic. 1390 1391 EXAMPLES: 1392 sage: rt2 = sqrt(AA(2)) 1393 sage: rt2._value 1394 [1.41421356237309504876 .. 1.41421356237309504888] 1395 sage: rt2._more_precision() 1396 sage: rt2._value 1397 [1.414213562373095048801688724209698078568 .. 1.414213562373095048801688724209698078575] 1398 sage: rt2._more_precision() 1399 sage: rt2._value 1400 [1.414213562373095048801688724209698078569671875376948073176679737990732478462101 .. 1.414213562373095048801688724209698078569671875376948073176679737990732478462120] 1401 """ 1402 prec = self._value.prec() 1403 field = RealIntervalField(prec * 2) 1404 self._value = self._descr.interval_fast(field) 1405 1406 def minpoly(self): 1407 """ 1408 Compute the minimal polynomial of this algebraic number. 1409 The minimal polynomial is the monic polynomial of least degree 1410 having this number as a root; it is unique. 1411 1412 EXAMPLES: 1413 sage: AA(4).sqrt().minpoly() 1414 x - 2 1415 sage: ((AA(2).nth_root(4))^2).minpoly() 1416 x^2 - 2 1417 sage: v = sqrt(AA(2)) + sqrt(AA(3)); v 1418 [3.1462643699419721 .. 3.1462643699419726] 1419 sage: p = v.minpoly(); p 1420 x^4 - 10*x^2 + 1 1421 sage: p(RR(v)) 1422 0.0000000000000131006316905768 1423 """ 1424 try: 1425 return self._minimal_polynomial 1426 except AttributeError: 1427 self.exactify() 1428 self._minimal_polynomial = self._descr.minpoly() 1429 return self._minimal_polynomial 1430 1431 def degree(self): 1432 """ 1433 Return the degree of this algebraic number (the degree of its 1434 minimal polynomial, or equivalently, the degree of the smallest 1435 algebraic extension of the rationals containing this number). 1436 1437 EXAMPLES: 1438 sage: AA(5/3).degree() 1439 1 1440 sage: sqrt(AA(2)).degree() 1441 2 1442 sage: AA(17).nth_root(5).degree() 1443 5 1444 sage: sqrt(3+sqrt(AA(8))).degree() 1445 2 1446 """ 1447 return self.minpoly().degree() 2524 return AlgebraicReal(ANRoot(poly, RIF(result_min, result_max))) 1448 2525 1449 2526 def sign(self): … … 1475 2552 return 0 1476 2553 elif self._descr.is_field_element(): 1477 if not self._descr.is_irrational():1478 self._descr = AlgebraicRealNumberRational(self._descr.rational_value())1479 return self.sign()2554 # All field elements are irrational by construction 2555 # (the ANExtensionElement constructor will return an ANRational 2556 # instead, if the number is actually rational). 1480 2557 # An irrational number must eventually be different from 0 1481 2558 self._more_precision() … … 1491 2568 return self.sign() 1492 2569 1493 def interval_fast(self, field): 1494 """ 1495 Given a RealIntervalField, compute the value of this number 1496 using interval arithmetic of at least the precision of the field, 1497 and return the value in that field. (More precision may be used 1498 in the computation.) The returned interval may be arbitrarily 1499 imprecise, if this number is the result of a sufficiently long 1500 computation chain. 1501 1502 EXAMPLES: 1503 sage: x = AA(2).sqrt() 1504 sage: x.interval_fast(RIF) 1505 [1.4142135623730949 .. 1.4142135623730952] 1506 sage: x.interval_fast(RealIntervalField(200)) 1507 [1.4142135623730950488016887242096980785696718753769480731766796 .. 1.4142135623730950488016887242096980785696718753769480731766809] 1508 sage: x = AA(4).sqrt() 1509 sage: (x-2).interval_fast(RIF) 1510 [-1.0842021724855045e-19 .. 2.1684043449710089e-19] 1511 """ 1512 if field.prec() == self._value.prec(): 1513 return self._value 1514 elif field.prec() > self._value.prec(): 1515 self._more_precision() 1516 return self.interval_fast(field) 1517 else: 1518 return field(self._value) 1519 1520 def interval_diameter(self, diam): 1521 """ 1522 Compute an interval representation of self with diameter() at 1523 most diam. The precision of the returned value is unpredictable. 1524 1525 EXAMPLES: 1526 sage: AA(2).sqrt().interval_diameter(1e-10) 1527 [1.41421356237309504876 .. 1.41421356237309504888] 1528 sage: AA(2).sqrt().interval_diameter(1e-30) 1529 [1.414213562373095048801688724209698078568 .. 1.414213562373095048801688724209698078575] 1530 """ 1531 if diam <= 0: 1532 raise ValueError, 'diameter must be positive in interval_diameter' 1533 1534 while self._value.diameter() > diam: 1535 self._more_precision() 1536 1537 return self._value 1538 1539 def interval(self, field): 1540 """ 1541 Given a RealIntervalField of precision p, compute an interval 1542 representation of self with diameter() at most 2^-p; then round 1543 that representation into the given field. Here diameter() is 1544 relative diameter for intervals not containing 0, and absolute 1545 diameter for intervals that do contain 0; thus, if the returned 1546 interval does not contain 0, it has at least p-1 good bits. 1547 1548 EXAMPLES: 1549 sage: RIF64 = RealIntervalField(64) 1550 sage: x = AA(2).sqrt() 1551 sage: y = x*x 1552 sage: y = 1000 * y - 999 * y 1553 sage: y.interval_fast(RIF64) 1554 [1.99999999999999966693 .. 2.00000000000000033307] 1555 sage: y.interval(RIF64) 1556 [1.99999999999999999989 .. 2.00000000000000000022] 1557 """ 1558 target = RR(1.0) >> field.prec() 1559 val = self.interval_diameter(target) 1560 return field(val) 2570 def _interval_fast(self, prec): 2571 return self.interval_fast(RealIntervalField(prec)) 1561 2572 1562 2573 def interval_exact(self, field): … … 1620 2631 self._more_precision() 1621 2632 1622 def real (self, field):2633 def real_number(self, field): 1623 2634 """ 1624 2635 Given a RealField, compute a good approximation to self in that field. … … 1630 2641 EXAMPLES: 1631 2642 sage: x = AA(2).sqrt()^2 1632 sage: x.real (RR)2643 sage: x.real_number(RR) 1633 2644 2.00000000000000 1634 sage: x.real (RealField(53, rnd='RNDD'))2645 sage: x.real_number(RealField(53, rnd='RNDD')) 1635 2646 1.99999999999999 1636 sage: x.real (RealField(53, rnd='RNDU'))2647 sage: x.real_number(RealField(53, rnd='RNDU')) 1637 2648 2.00000000000001 1638 sage: x.real (RealField(53, rnd='RNDZ'))2649 sage: x.real_number(RealField(53, rnd='RNDZ')) 1639 2650 1.99999999999999 1640 sage: (-x).real (RR)2651 sage: (-x).real_number(RR) 1641 2652 -2.00000000000000 1642 sage: (-x).real (RealField(53, rnd='RNDD'))2653 sage: (-x).real_number(RealField(53, rnd='RNDD')) 1643 2654 -2.00000000000001 1644 sage: (-x).real (RealField(53, rnd='RNDU'))2655 sage: (-x).real_number(RealField(53, rnd='RNDU')) 1645 2656 -1.99999999999999 1646 sage: (-x).real (RealField(53, rnd='RNDZ'))2657 sage: (-x).real_number(RealField(53, rnd='RNDZ')) 1647 2658 -1.99999999999999 1648 sage: (x-2).real (RR)2659 sage: (x-2).real_number(RR) 1649 2660 5.42101086242752e-20 1650 sage: (x-2).real (RealField(53, rnd='RNDD'))2661 sage: (x-2).real_number(RealField(53, rnd='RNDD')) 1651 2662 -1.08420217248551e-19 1652 sage: (x-2).real (RealField(53, rnd='RNDU'))2663 sage: (x-2).real_number(RealField(53, rnd='RNDU')) 1653 2664 2.16840434497101e-19 1654 sage: (x-2).real (RealField(53, rnd='RNDZ'))2665 sage: (x-2).real_number(RealField(53, rnd='RNDZ')) 1655 2666 0.000000000000000 1656 2667 sage: y = AA(2).sqrt() 1657 sage: y.real (RR)2668 sage: y.real_number(RR) 1658 2669 1.41421356237309 1659 sage: y.real (RealField(53, rnd='RNDD'))2670 sage: y.real_number(RealField(53, rnd='RNDD')) 1660 2671 1.41421356237309 1661 sage: y.real (RealField(53, rnd='RNDU'))2672 sage: y.real_number(RealField(53, rnd='RNDU')) 1662 2673 1.41421356237310 1663 sage: y.real (RealField(53, rnd='RNDZ'))2674 sage: y.real_number(RealField(53, rnd='RNDZ')) 1664 2675 1.41421356237309 1665 2676 """ … … 1681 2692 return field(0) 1682 2693 2694 _mpfr_ = real_number 2695 2696 def _complex_mpfr_field_(self, field): 2697 if is_ComplexIntervalField(field): 2698 return field(self.interval(field._real_field())) 2699 else: 2700 return field(self.real_number(field._real_field())) 2701 1683 2702 def real_exact(self, field): 1684 2703 """ 1685 2704 Given a RealField, compute the best possible approximation of 1686 this number in that field. Note that if this number is sufficiently 1687 close to some floating-point number in the field (and, in particular, 1688 if this number is exactly representable in the field), then 1689 this will trigger exact computation, which may be very slow. 2705 this number in that field. Note that if this number is 2706 sufficiently close to the halfway point between two 2707 floating-point numbers in the field (for the default 2708 round-to-nearest mode) or if the number is sufficiently close 2709 to a floating-point number in the field (for directed rounding 2710 modes), then this will trigger exact computation, which may be 2711 very slow. 1690 2712 1691 2713 The rounding mode of the field is respected. … … 1760 2782 return field(mid) 1761 2783 1762 def is_AlgebraicRealNumber(x): 1763 return isinstance(x, AlgebraicRealNumber) 1764 2784 class ANRational(ANDescr): 2785 """ 2786 The subclass of ANDescr that represents an arbitrary 2787 rational. This class is private, and should not be used directly. 2788 """ 2789 2790 def __init__(self, x): 2791 """ 2792 TESTS: 2793 sage: polygen(QQbar) / int(3) 2794 1/3*x 2795 sage: QQbar(int(7)) / QQbar(long(2)) 2796 7/2 2797 """ 2798 if isinstance(x, (sage.rings.integer.Integer, 2799 sage.rings.rational.Rational)): 2800 self._value = x 2801 elif isinstance(x, (int, long)): 2802 self._value = ZZ(x) 2803 else: 2804 raise TypeError, "Illegal initializer for algebraic number rational" 2805 2806 def _repr_(self): 2807 return repr(self._value) 2808 2809 def kind(self): 2810 if self._value.is_zero(): 2811 return 'zero' 2812 else: 2813 return 'rational' 2814 2815 def _interval_fast(self, prec): 2816 return RealIntervalField(prec)(self._value) 2817 2818 def generator(self): 2819 return qq_generator 2820 2821 def is_complex(self): 2822 return False 2823 2824 def is_rational(self): 2825 return True 2826 2827 def rational_value(self): 2828 return self._value 2829 2830 def exactify(self): 2831 return self 2832 2833 def is_exact(self): 2834 return True 2835 2836 def minpoly(self): 2837 return QQx_x - self._value 2838 2839 def neg(self, n): 2840 return ANRational(-self._value) 2841 2842 def invert(self, n): 2843 return ANRational(~self._value) 2844 2845 def abs(self, n): 2846 return ANRational(abs(self._value)) 2847 2848 def rational_argument(self, n): 2849 if self._value > 0: 2850 return QQ(0) 2851 if self._value < 0: 2852 return QQ(1)/2 2853 return None 2854 2855 def gaussian_value(self): 2856 return QQbar_I_nf(self._value) 2857 2858 def angle(self): 2859 return QQ_0 2860 2861 def scale(self): 2862 return self._value 2863 2864 class ANRootOfUnity(ANDescr): 2865 """ 2866 The subclass of ANDescr that represents a rational multiplied 2867 by a root of unity. This class is private, and should not be 2868 used directly. 2869 2870 Such numbers are represented by a "rational angle" and a rational 2871 scale. The "rational angle" is the argument of the number, divided by 2872 2*pi; so given angle and scale, the number is: 2873 scale*(cos(2*pi*angle) + sin(2*pi*angle)*I); or equivalently 2874 scale*(e^(2*pi*angle*I)). 2875 2876 We normalize so that 0<angle<1/2; this requires allowing both positive 2877 and negative scales. (Attempts to create an ANRootOfUnity with an 2878 angle which is a multiple of 1/2 end up creating an ANRational instead.) 2879 """ 2880 2881 def __new__(self, angle, scale): 2882 """ 2883 Construct an ANRootOfUnity from a rational angle and a rational 2884 scale. If the number is actually a real rational, returns an 2885 ANRational instead. 2886 """ 2887 if scale.is_zero(): 2888 return ANRational(0) 2889 try: 2890 int_angle = ZZ(angle*2) 2891 except TypeError: 2892 return ANDescr.__new__(self) 2893 2894 if int_angle & 1: 2895 # int_angle is odd 2896 return ANRational(-scale) 2897 else: 2898 # int_angle is even 2899 return ANRational(scale) 2900 2901 def __init__(self, angle, scale): 2902 """ 2903 Construct an ANRootOfUnity from a rational angle and a rational 2904 scale. 2905 """ 2906 2907 angle2 = angle * 2 2908 fl2 = angle2.floor() 2909 angle2 = angle2 - fl2 2910 angle = angle2 / 2 2911 if fl2 & 1: 2912 scale = -scale 2913 self._angle = angle 2914 self._scale = scale 2915 2916 def _repr_(self): 2917 return "%s*e^(2*pi*I*%s)"%(self._scale, self._angle) 2918 2919 def kind(self): 2920 if self._angle == QQ_1_4: 2921 return 'imaginary' 2922 else: 2923 return 'rootunity' 2924 2925 def _interval_fast(self, prec): 2926 argument = self._angle * RealIntervalField(prec).pi() * 2 2927 if self._angle == QQ_1_4: 2928 return ComplexIntervalField(prec)(0, self._scale) 2929 else: 2930 return ComplexIntervalField(prec)(argument.cos(), argument.sin()) * self._scale 2931 2932 def generator(self): 2933 return cyclotomic_generator(self._angle.denominator()) 2934 2935 def field_element_value(self): 2936 gen = self.generator() 2937 f = gen._field 2938 a = f.gen() 2939 return self._scale * a ** self._angle.numerator() 2940 2941 def is_complex(self): 2942 return True 2943 2944 def exactify(self): 2945 return self 2946 2947 def is_exact(self): 2948 return True 2949 2950 def minpoly(self): 2951 """ 2952 EXAMPLES: 2953 sage: a = QQbar.zeta(7) * 2; a 2954 [1.2469796037174669 .. 1.2469796037174672] + [1.5636629649360596 .. 1.5636629649360599]*I 2955 sage: a.minpoly() 2956 x^6 + 2*x^5 + 4*x^4 + 8*x^3 + 16*x^2 + 32*x + 64 2957 sage: a.minpoly()(a) 2958 [-0.00000000000000031918911957973251 .. 0.00000000000000034694469519536142] + [-0.00000000000000033133218391157016 .. 0.00000000000000032786273695961655]*I 2959 sage: a.minpoly()(a) == 0 2960 True 2961 """ 2962 # This could be more efficient... 2963 p = cyclotomic_polynomial(self._angle.denominator()) 2964 p = p(p.parent().gen() / self._scale) 2965 p = p / p.leading_coefficient() 2966 return p 2967 2968 def neg(self, n): 2969 return ANRootOfUnity(self._angle, -self._scale) 2970 2971 def invert(self, n): 2972 # We want ANRootOfUnity(-self._angle, ~self._scale); 2973 # but that's not normalized, so we pre-normalize it to: 2974 return ANRootOfUnity(QQ_1_2 - self._angle, -~self._scale) 2975 2976 def conjugate(self, n): 2977 # We want ANRootOfUnity(-self._angle, self._scale); 2978 # but that's not normalized, so we pre-normalize it to: 2979 return ANRootOfUnity(QQ_1_2 - self._angle, -self._scale) 2980 2981 def abs(self, n): 2982 return ANRational(abs(self._scale)) 2983 2984 def norm(self, n): 2985 return ANRational(self._scale * self._scale) 2986 2987 def rational_argument(self, n): 2988 if self._scale > 0: 2989 return self._angle 2990 else: 2991 return self._angle - QQ_1_2 2992 2993 def gaussian_value(self): 2994 assert(self._angle == QQ_1_4) 2995 return QQbar_I_nf(self._scale * QQbar_I_nf.gen()) 2996 2997 def angle(self): 2998 return self._angle 2999 3000 def scale(self): 3001 return self._scale 3002 3003 def is_AlgebraicReal(x): 3004 return isinstance(x, AlgebraicReal) 3005 3006 def is_AlgebraicNumber(x): 3007 return isinstance(x, AlgebraicNumber) 3008 3009 QQbarPoly = PolynomialRing(QQbar, 'x') 1765 3010 AAPoly = PolynomialRing(AA, 'x') 1766 3011 … … 1772 3017 polynomial, this allows the polynomial and information about 1773 3018 the polynomial to be shared. This reduces work if the polynomial 1774 must be recomputed at higher precision, or if it must be made 1775 exact. 3019 must be recomputed at higher precision, or if it must be factored. 1776 3020 1777 3021 This class is private, and should only be constructed by 1778 AlgebraicRealField.common_polynomial(), and should only be used as 1779 an argument to AlgebraicRealField.polynomial_root(). 3022 AA.common_polynomial() or QQbar.common_polynomial(), and should 3023 only be used as an argument to AA.polynomial_root() or 3024 QQbar.polynomial_root(). (It doesn't matter whether you create 3025 the common polynomial with AA.common_polynomial() or 3026 QQbar.common_polynomial().) 1780 3027 1781 3028 EXAMPLES: 1782 sage: x = polygen( AA)1783 sage: P = AA.common_polynomial(x^2 - x - 1)3029 sage: x = polygen(QQbar) 3030 sage: P = QQbar.common_polynomial(x^2 - x - 1) 1784 3031 sage: P 1785 x^2 -x - 11786 sage: AA.polynomial_root(P, RIF(0, 2))3032 x^2 + (-1)*x - 1 3033 sage: QQbar.polynomial_root(P, RIF(1, 2)) 1787 3034 [1.6180339887498946 .. 1.6180339887498950] 1788 3035 """ 1789 3036 1790 3037 def __init__(self, poly): 1791 poly = AAPoly._coerce_(poly) 3038 if not is_Polynomial(poly): 3039 raise ValueError, "Trying to create AlgebraicPolynomialTracker on non-Polynomial" 3040 if isinstance(poly.base_ring(), AlgebraicField_common): 3041 complex = is_AlgebraicField(poly.base_ring()) 3042 else: 3043 try: 3044 poly = poly.change_ring(AA) 3045 complex = False 3046 except TypeError: 3047 poly = poly.change_ring(QQbar) 3048 complex = True 1792 3049 self._poly = poly 3050 self._complex = complex 1793 3051 self._exact = False 3052 self._roots_cache = {} 1794 3053 1795 3054 def _repr_(self): … … 1798 3057 def poly(self): 1799 3058 return self._poly 3059 3060 def is_complex(self): 3061 return self._complex 3062 3063 def complex_roots(self, prec, multiplicity): 3064 """ 3065 EXAMPLES: 3066 sage: x = polygen(ZZ) 3067 sage: cp = AA.common_polynomial(x^4 - 1) 3068 sage: cp.complex_roots(30, 1) 3069 [[1.0000000000000000 .. 1.0000000000000000], [-1.0000000000000000 .. -1.0000000000000000], [1.0000000000000000 .. 1.0000000000000000]*I, [-1.0000000000000000 .. -1.0000000000000000]*I] 3070 """ 3071 if self._roots_cache.has_key(multiplicity): 3072 roots = self._roots_cache[multiplicity] 3073 if roots[0] >= prec: 3074 return roots[1] 3075 3076 p = self._poly 3077 for i in range(multiplicity - 1): 3078 p = p.derivative() 3079 3080 from sage.rings.polynomial.complex_roots import complex_roots 3081 roots_mult = complex_roots(p, min_prec=prec) 3082 roots = [rt for (rt, mult) in roots_mult if mult == 1] 3083 self._roots_cache[multiplicity] = (prec, roots) 3084 return roots 1800 3085 1801 3086 def exactify(self): … … 1810 3095 self._exact = True 1811 3096 1812 gen = unit_generator3097 gen = qq_generator 1813 3098 1814 3099 for c in self._poly.list(): … … 1820 3105 coeffs = [gen(c._exact_value()) for c in self._poly.list()] 1821 3106 1822 if gen.is_ unit():3107 if gen.is_trivial(): 1823 3108 qp = QQy(coeffs) 1824 3109 self._factors = [fac_exp[0] for fac_exp in qp.factor()] … … 1839 3124 return self._gen 1840 3125 1841 class A lgebraicRealNumberRoot(AlgebraicRealNumberDescr):3126 class ANRoot(ANDescr): 1842 3127 """ 1843 The subclass of A lgebraicRealNumberDescr that represents a particular3128 The subclass of ANDescr that represents a particular 1844 3129 root of a polynomial with algebraic coefficients. 1845 3130 This class is private, and should not be used directly. … … 1849 3134 poly = AlgebraicPolynomialTracker(poly) 1850 3135 self._poly = poly 1851 # Rethink precision control...integer bitcounts vs.1852 # RealIntervalField values1853 3136 self._multiplicity = multiplicity 3137 self._complex = is_ComplexIntervalFieldElement(interval) 3138 self._complex_poly = poly.is_complex() 1854 3139 self._interval = self.refine_interval(interval, 64) 1855 3140 … … 1857 3142 return 'Root %s of %s'%(self._interval, self._poly) 1858 3143 1859 def refine_interval(self, interval, precision): 3144 def kind(self): 3145 return 'other' 3146 3147 def is_complex(self): 3148 return self._complex 3149 3150 def conjugate(self, n): 3151 if not self._complex: 3152 return self 3153 if not self._complex_poly: 3154 return ANRoot(self._poly, self._interval.conjugate(), self._multiplicity) 3155 3156 raise NotImplementedError 3157 3158 def refine_interval(self, interval, prec): 3159 if self._complex or self._complex_poly: 3160 v = self._complex_refine_interval(interval, prec) 3161 if self._complex: 3162 return v 3163 else: 3164 return v.real() 3165 else: 3166 return self._real_refine_interval(interval, prec) 3167 3168 def _real_refine_interval(self, interval, prec): 1860 3169 """ 1861 3170 Takes an interval which is assumed to enclose exactly one root … … 1872 3181 1873 3182 EXAMPLES: 1874 sage: from sage.rings.algebraic_real import A lgebraicRealNumberRoot3183 sage: from sage.rings.algebraic_real import ANRoot 1875 3184 sage: x = polygen(AA) 1876 sage: rt2 = A lgebraicRealNumberRoot(x^2 - 2, RIF(0, 2))3185 sage: rt2 = ANRoot(x^2 - 2, RIF(0, 2)) 1877 3186 sage: rt2.refine_interval(RIF(0, 2), 75) 1878 3187 [1.41421356237309504880163 .. 1.41421356237309504880175] 1879 3188 """ 3189 # Don't throw away bits in the original interval; doing so might 3190 # invalidate it (include an extra root) 3191 3192 field = RealIntervalField(max(prec, interval.prec())) 3193 interval = field(interval) 3194 if interval.is_exact(): 3195 return interval 3196 1880 3197 p = self._poly.poly() 1881 3198 dp = p.derivative() … … 1884 3201 dp = p.derivative() 1885 3202 1886 # Don't throw away bits in the original interval; doing so might1887 # invalidate it (include an extra root)1888 field = RealIntervalField(max(precision, interval.prec()))1889 3203 zero = field(0) 1890 interval = field(interval) 3204 1891 3205 poly_ring = field['x'] 1892 3206 1893 # XXX Once this is properly integrated into SAGE,1894 # then the following should be replaced with:1895 3207 # interval_p = poly_ring(p) 1896 # (and similarly for interval_dp) 1897 coeffs = [c.interval_fast(field) for c in p.list()] 3208 coeffs = [c._interval_fast(prec) for c in p.list()] 1898 3209 interval_p = poly_ring(coeffs) 1899 3210 … … 1903 3214 # this case here means we don't have to worry about iterating too 1904 3215 # many times later 1905 if coeffs[0].is_zero() and zero in interval:3216 if coeffs[0].is_zero() and interval.contains_zero(): 1906 3217 return zero 1907 3218 3219 # interval_dp = poly_ring(dp) 1908 3220 dcoeffs = [c.interval_fast(field) for c in dp.list()] 1909 3221 interval_dp = poly_ring(dcoeffs) … … 1911 3223 linfo = {} 1912 3224 uinfo = {} 1913 1914 # print coeffs1915 # print p1916 3225 1917 3226 def update_info(info, x): … … 1941 3250 return interval 1942 3251 1943 # print interval1944 1945 3252 if linfo['sign'] == uinfo['sign']: 1946 3253 # Oops... 1947 print self._poly.poly()1948 print interval_p1949 print linfo['endpoint'], linfo['value'], linfo['sign']1950 print uinfo['endpoint'], uinfo['value'], uinfo['sign']3254 # print self._poly.poly() 3255 # print interval_p 3256 # print linfo['endpoint'], linfo['value'], linfo['sign'] 3257 # print uinfo['endpoint'], uinfo['value'], uinfo['sign'] 1951 3258 raise ValueError, "Refining interval that does not bound unique root!" 1952 3259 … … 2035 3342 return interval 2036 3343 3344 def _complex_refine_interval(self, interval, prec): 3345 """ 3346 Takes an interval which is assumed to enclose exactly one root 3347 of the polynomial (or, with multiplicity=k, exactly one root 3348 of the k-1'th derivative); and a precision, in bits. 3349 3350 Tries to find a narrow interval enclosing the root using 3351 interval arithmetic of the given precision. (No particular 3352 number of resulting bits of precision is guaranteed.) 3353 3354 Uses Newton's method (adapted for interval arithmetic). The 3355 algorithm will converge very quickly if started with a 3356 sufficiently narrow interval. If Newton's method fails, then 3357 we falls back on computing all the roots of the polynomial 3358 numerically, and select the appropriate root. 3359 3360 EXAMPLES: 3361 sage: from sage.rings.algebraic_real import ANRoot 3362 sage: x = polygen(QQbar) 3363 sage: intv = CIF(RIF(0, 1), RIF(0.1, 1)) 3364 sage: rt = ANRoot(x^5 - 1, intv) 3365 sage: new_intv = rt.refine_interval(intv, 53); new_intv 3366 [0.309016994374947424022 .. 0.309016994374947424185] + [0.951056516295153572002 .. 0.951056516295153572219]*I 3367 sage: rt.refine_interval(new_intv, 70) 3368 [0.30901699437494742410148 .. 0.30901699437494742410319] + [0.95105651629515357211565 .. 0.95105651629515357211735]*I 3369 """ 3370 # Don't throw away bits in the original interval; doing so might 3371 # invalidate it (include an extra root) 3372 3373 field = ComplexIntervalField(max(prec, interval.prec())) 3374 interval = field(interval) 3375 if interval.is_exact(): 3376 return interval 3377 3378 p = self._poly.poly() 3379 dp = p.derivative() 3380 for i in xrange(0, self._multiplicity - 1): 3381 p = dp 3382 dp = p.derivative() 3383 3384 zero = field(0) 3385 3386 poly_ring = field['x'] 3387 3388 # interval_p = poly_ring(p) 3389 coeffs = [c.interval_fast(field) for c in p.list()] 3390 interval_p = poly_ring(coeffs) 3391 3392 # This special case is important: this is the only way we could 3393 # refine "infinitely deep" (we could get an interval of diameter 3394 # about 2^{-2^31}, and then hit floating-point underflow); avoiding 3395 # this case here means we don't have to worry about iterating too 3396 # many times later 3397 if coeffs[0].is_zero() and zero in interval: 3398 return zero 3399 3400 # interval_dp = poly_ring(dp) 3401 dcoeffs = [c.interval_fast(field) for c in dp.list()] 3402 interval_dp = poly_ring(dcoeffs) 3403 3404 while True: 3405 center = field(interval.center()) 3406 val = interval_p(center) 3407 3408 slope = interval_dp(interval) 3409 3410 diam = interval.diameter() 3411 3412 if zero in slope: 3413 # Give up and fall back on root isolation. 3414 return self._complex_isolate_interval(interval, prec) 3415 3416 if not (zero in slope): 3417 new_range = center - val / slope 3418 interval = interval.intersection(new_range) 3419 3420 new_diam = interval.diameter() 3421 3422 if new_diam == 0: 3423 # Wow; we nailed it exactly. (This may happen 3424 # whenever the root is exactly equal to some 3425 # floating-point number, and cannot happen 3426 # if the root is not equal to a floating-point 3427 # number.) We just return the perfect answer. 3428 return interval 3429 3430 if new_diam == diam: 3431 # We're not getting any better. There are two 3432 # possible reasons for this. Either we have 3433 # refined as much as possible given the imprecision 3434 # of our interval polynomial, and we have the best 3435 # answer we're going to get at this precision; 3436 # or we started with a poor approximation to the 3437 # root, resulting in a broad range of possible 3438 # slopes in this interval, and Newton-Raphson refining 3439 # is not going to help. 3440 3441 # I don't have a formal proof, but I believe the 3442 # following test differentiates between these two 3443 # behaviors. (If I'm wrong, we might get bad behavior 3444 # like infinite loops, but we still won't actually 3445 # return a wrong answer.) 3446 3447 if val.contains_zero(): 3448 # OK, center must be a good approximation 3449 # to the root (in the current precision, anyway). 3450 # And the expression "center - val / slope" 3451 # above means that we have a pretty good interval, 3452 # even if slope is a poor estimate. 3453 return interval 3454 3455 # The center of the current interval is known 3456 # not to be a root. This should let us divide 3457 # the interval in half, and improve on our previous 3458 # estimates. I can only think of two reasons why 3459 # it might not: 3460 # 1) the "center" of the interval is actually 3461 # on one of the edges of the interval (because the 3462 # interval is only one ulp wide), or 3463 # 2) the slope estimate is so bad that 3464 # "center - val / slope" doesn't give us information. 3465 3466 # With complex intervals implemented as 3467 # rectangular regions of the complex plane, it's 3468 # possible that "val / slope" includes zero even 3469 # if both "val" and "slope" are bounded away from 3470 # zero, if the diameter of the (interval) argument 3471 # of val or slope is large enough. 3472 3473 # So we test the diameter of the argument of 3474 # slope; if it's small, we decide that we must 3475 # have a good interval, but if it's big, we decide 3476 # that we probably can't make progress with 3477 # Newton-Raphson. 3478 3479 # I think the relevant measure of "small" is 3480 # whether the diameter is less than pi/2; in that 3481 # case, no matter the value of "val" (as long as 3482 # "val" is fairly precise), "val / slope" should 3483 # be bounded away from zero. But we compare 3484 # against 1 instead, in the hopes that this might 3485 # be slightly faster. 3486 3487 if slope.argument().absolute_diameter() < 1: 3488 return interval 3489 3490 # And now it's time to give up. 3491 return self._complex_isolate_interval(interval, prec) 3492 3493 def _complex_isolate_interval(self, interval, prec): 3494 """ 3495 Find a precise approximation to the unique root in interval, 3496 by finding a precise approximation to all roots of the 3497 polynomial, and checking which one is in interval. Slow but sure. 3498 3499 EXAMPLES: 3500 sage: from sage.rings.algebraic_real import ANRoot 3501 sage: x = polygen(QQbar) 3502 sage: intv = CIF(RIF(0, 1), RIF(0.1, 1)) 3503 sage: rt = ANRoot(x^5 - 1, intv) 3504 sage: rt._complex_isolate_interval(intv, 53) 3505 [0.309016994374947424022 .. 0.309016994374947424185] + [0.951056516295153572002 .. 0.951056516295153572219]*I 3506 """ 3507 rts = self._poly.complex_roots(prec, self._multiplicity) 3508 3509 # Find all the roots that overlap interval. 3510 our_root = [rt for rt in rts if rt.overlaps(interval)] 3511 3512 if len(our_root) == 1: 3513 return our_root[0] 3514 3515 if len(our_root) == 0: 3516 raise ValueError, "Complex root interval does not include any roots" 3517 3518 # We have more than one root that overlap the current interval. 3519 # Technically, this might not be an error; perhaps the actual 3520 # root is just outside our interval, even though the (presumably 3521 # tight) interval containing that root touches our interval. 3522 3523 # But it seems far more likely that the provided interval is 3524 # just too big. 3525 3526 raise ValueError, "Complex root interval probably includes multiple roots" 2037 3527 2038 3528 def exactify(self): 2039 3529 """ 2040 Returns either an A lgebraicRealNumberRational or an2041 A lgebraicRealNumberExtensionElement with the same value as this number.2042 2043 EXAMPLES: 2044 sage: from sage.rings.algebraic_real import A lgebraicRealNumberRoot2045 sage: x = polygen( AA)2046 sage: two = A lgebraicRealNumberRoot((x-2)*(x-sqrt(AA(2))), RIF(1.5, 3))3530 Returns either an ANRational or an 3531 ANExtensionElement with the same value as this number. 3532 3533 EXAMPLES: 3534 sage: from sage.rings.algebraic_real import ANRoot 3535 sage: x = polygen(QQbar) 3536 sage: two = ANRoot((x-2)*(x-sqrt(QQbar(2))), RIF(1.9, 2.1)) 2047 3537 sage: two.exactify() 2048 2 where a^2 - 2 = 0 and a in [1.4142135623730949 .. 1.4142135623730952]3538 2 2049 3539 sage: two.exactify().rational_value() 2050 3540 2 2051 sage: strange = A lgebraicRealNumberRoot(x^2 + sqrt(AA(3))*x - sqrt(AA(2)), RIF(-1, 3))3541 sage: strange = ANRoot(x^2 + sqrt(QQbar(3))*x - sqrt(QQbar(2)), RIF(-0, 1)) 2052 3542 sage: strange.exactify() 2053 3543 a where a^8 - 6*a^6 + 5*a^4 - 12*a^2 + 4 = 0 and a in [0.60510122651395104 .. 0.60510122651395116] … … 2055 3545 gen = self._poly.generator() 2056 3546 2057 if gen.is_ unit():3547 if gen.is_trivial(): 2058 3548 qpf = self._poly.factors() 2059 def find_fn(factor, rif):2060 return factor(self. interval_fast(rif))3549 def find_fn(factor, prec): 3550 return factor(self._interval_fast(prec)) 2061 3551 my_factor = find_zero_result(find_fn, qpf) 2062 3552 … … 2065 3555 2066 3556 if my_factor.degree() == 1: 2067 return A lgebraicRealNumberRational(-my_factor[0])3557 return ANRational(-my_factor[0]) 2068 3558 2069 3559 den, my_factor = clear_denominators(my_factor) … … 2074 3564 2075 3565 def intv_fn(rif): 2076 return red_elt(self.interval_fast(rif) * den)2077 new_intv = isolating_interval(intv_fn, red_pol)2078 root = A lgebraicRealNumberRoot(AAPoly(red_pol), new_intv)3566 return conjugate_expand(red_elt(self._interval_fast(rif) * den)) 3567 new_intv = conjugate_shrink(isolating_interval(intv_fn, red_pol)) 3568 root = ANRoot(QQx(red_pol), new_intv) 2079 3569 new_gen = AlgebraicGenerator(field, root) 2080 3570 2081 return A lgebraicRealNumberExtensionElement(new_gen, red_back(field.gen())/den)3571 return ANExtensionElement(new_gen, red_back(field.gen())/den) 2082 3572 else: 2083 3573 fld = gen.field() … … 2085 3575 fpf = self._poly.factors() 2086 3576 # print fpf 2087 def find_fn(factor, rif): 2088 rif_poly = rif['x'] 2089 gen_val = gen.interval_fast(rif) 2090 self_val = self.interval_fast(rif) 2091 ip = rif_poly([c.polynomial()(gen_val) for c in factor]) 3577 def find_fn(factor, prec): 3578 # XXX 3579 ifield = (ComplexIntervalField if self.is_complex() else RealIntervalField)(prec) 3580 if_poly = ifield['x'] 3581 gen_val = gen._interval_fast(prec) 3582 self_val = self._interval_fast(prec) 3583 ip = if_poly([c.polynomial()(gen_val) for c in factor]) 2092 3584 return ip(self_val) 2093 3585 my_factor = find_zero_result(find_fn, fpf) … … 2097 3589 2098 3590 if my_factor.degree() == 1: 2099 return A lgebraicRealNumberExtensionElement(gen, -my_factor[0])3591 return ANExtensionElement(gen, -my_factor[0]) 2100 3592 2101 3593 # rnfequation needs a monic polynomial with integral coefficients. … … 2105 3597 2106 3598 2107 pari_nf = pari_nf_hack(gen.field())3599 pari_nf = gen.pari_field() 2108 3600 2109 3601 # print pari_nf[0] … … 2132 3624 new_nf_a = new_nf.gen() 2133 3625 2134 def intv_fn( rif):2135 return red_elt(gen.interval_fast(rif) * k + self.interval_fast(rif) * den)2136 new_intv = isolating_interval(intv_fn, red_pol)2137 2138 root = A lgebraicRealNumberRoot(QQx(red_pol), new_intv)3626 def intv_fn(prec): 3627 return conjugate_expand(red_elt(gen._interval_fast(prec) * k + self._interval_fast(prec) * den)) 3628 new_intv = conjugate_shrink(isolating_interval(intv_fn, red_pol)) 3629 3630 root = ANRoot(QQx(red_pol), new_intv) 2139 3631 new_gen = AlgebraicGenerator(new_nf, root) 2140 3632 red_back_a = red_back(new_nf.gen()) 2141 3633 new_poly = ((QQx_x - k * self_pol_sage)(red_back_a)/den) 2142 return A lgebraicRealNumberExtensionElement(new_gen, new_poly)3634 return ANExtensionElement(new_gen, new_poly) 2143 3635 2144 3636 def _more_precision(self): … … 2150 3642 self._interval = self.refine_interval(self._interval, prec*2) 2151 3643 2152 def interval_fast(self, field):3644 def _interval_fast(self, prec): 2153 3645 """ 2154 3646 Given a RealIntervalField, compute the value of this number … … 2157 3649 in the computation.) 2158 3650 """ 2159 if field.prec()== self._interval.prec():3651 if prec == self._interval.prec(): 2160 3652 return self._interval 2161 if field.prec()< self._interval.prec():2162 return field(self._interval)3653 if prec < self._interval.prec(): 3654 return type(self._interval.parent())(prec)(self._interval) 2163 3655 self._more_precision() 2164 return self.interval_fast(field) 2165 2166 unit_generator = AlgebraicGenerator(None, AlgebraicRealNumberRoot(AAPoly.gen() - 1, RIF(1))) 2167 2168 class AlgebraicRealNumberExtensionElement(AlgebraicRealNumberDescr): 3656 return self._interval_fast(prec) 3657 3658 qq_generator = AlgebraicGenerator(None, ANRoot(AAPoly.gen(), RIF(0))) 3659 3660 _cyclotomic_gen_cache = {} 3661 def cyclotomic_generator(n): 3662 try: 3663 return _cyclotomic_gen_cache[n] 3664 except KeyError: 3665 assert(n > 2 and n != 4) 3666 n = ZZ(n) 3667 f = CyclotomicField(n) 3668 v = ANRootOfUnity(~n, QQ_1) 3669 g = AlgebraicGenerator(f, v) 3670 g.set_cyclotomic(n) 3671 _cyclotomic_gen_cache[n] = g 3672 return g 3673 3674 class ANExtensionElement(ANDescr): 2169 3675 """ 2170 The subclass of A lgebraicRealNumberDescr that represents a number field3676 The subclass of ANDescr that represents a number field 2171 3677 element in terms of a specific generator. Consists of a polynomial 2172 3678 with rational coefficients in terms of the generator, and the … … 2174 3680 """ 2175 3681 2176 # XXX Should override __new__, and return an AlgebraicRealNumberRational 2177 # if the value is rational. 3682 def __new__(self, generator, value): 3683 try: 3684 return ANRational(value._rational_()) 3685 except TypeError: 3686 if generator is QQbar_I_generator and value[0].is_zero(): 3687 return ANRootOfUnity(QQ_1_4, value[1]) 3688 return ANDescr.__new__(self) 2178 3689 2179 3690 def __init__(self, generator, value): 2180 3691 self._generator = generator 2181 3692 self._value = value 3693 self._exactly_real = not generator.is_complex() 2182 3694 2183 3695 def _repr_(self): 2184 3696 return '%s where %s = 0 and a in %s'%(self._value, 2185 3697 self._generator.field().polynomial()._repr(name='a'), 2186 self._generator.interval_fast(RIF)) 3698 self._generator._interval_fast(53)) 3699 3700 def kind(self): 3701 if self._generator is QQbar_I_generator: 3702 return 'gaussian' 3703 else: 3704 return 'element' 3705 3706 def is_complex(self): 3707 return not self._exactly_real 3708 3709 def is_exact(self): 3710 return True 3711 3712 def is_field_element(self): 3713 return True 2187 3714 2188 3715 def generator(self): 2189 3716 return self._generator 2190 3717 2191 def is_exact(self):2192 return True2193 2194 def is_field_element(self):2195 return True2196 2197 def field_parent(self):2198 return self._generator2199 2200 3718 def exactify(self): 2201 3719 return self 2202 3720 2203 def rational_value(self):2204 poly = self._value.polynomial()2205 assert(poly.is_constant())2206 return poly[0]2207 2208 def is_irrational(self):2209 return self._value.polynomial().degree() >= 12210 2211 3721 def field_element_value(self): 2212 3722 return self._value … … 2215 3725 return self._value.minpoly() 2216 3726 2217 def interval_fast(self, field): 2218 gen_val = self._generator.interval_fast(field) 2219 # XXX Coercion to field() below is necessary in case this is 2220 # a constant polynomial (that is, this is a rational number). 2221 # If we maintain the invariant that AlgebraicRealNumberExtensionElement 2222 # values are never rational, then the coercion is redundant. 2223 return field(self._value.polynomial()(gen_val)) 2224 2225 ax = AAPoly.gen() 3727 def _interval_fast(self, prec): 3728 gen_val = self._generator._interval_fast(prec) 3729 v = self._value.polynomial()(gen_val) 3730 if self._exactly_real and is_ComplexIntervalFieldElement(v): 3731 return v.real() 3732 return v 3733 3734 def neg(self, n): 3735 return ANExtensionElement(self._generator, -self._value) 3736 3737 def invert(self, n): 3738 return ANExtensionElement(self._generator, ~self._value) 3739 3740 def conjugate(self, n): 3741 if self._exactly_real: 3742 return self 3743 else: 3744 return ANExtensionElement(self._generator.conjugate(), self._value) 3745 3746 def norm(self, n): 3747 if self._exactly_real: 3748 return (n*n)._descr 3749 elif self._generator is QQbar_I_generator: 3750 return ANRational(self._value.norm()) 3751 else: 3752 return ANUnaryExpr(n, 'norm') 3753 3754 def abs(self, n): 3755 return AlgebraicReal(self.norm(self)).sqrt()._descr 3756 3757 def rational_argument(self, n): 3758 """ 3759 If the argument of self is 2*pi times some rational number, 3760 return that rational; otherwise, return None. 3761 """ 3762 3763 # If the argument of self is 2*pi times some rational number a/b, 3764 # then self/abs(self) is a root of the b'th cyclotomic polynomial. 3765 # This implies that the algebraic degree of self is at least 3766 # phi(b). Working backward, we know that the algebraic degree 3767 # of self is at most the degree of the generator, so that gives 3768 # an upper bound on phi(b). According to 3769 # http://mathworld.wolfram.com/TotientFunction.html, 3770 # phi(b) >= sqrt(b) for b > 6; this gives us an upper bound on b. 3771 # We then check to see if this is possible; if so, we test 3772 # to see if it actually holds. 3773 3774 if self._exactly_real: 3775 if n > 0: 3776 return 0 3777 else: 3778 return QQ(1)/2 3779 3780 gen_degree = self._generator._field.degree() 3781 if gen_degree <= 2: 3782 max_b = 6 3783 else: 3784 max_b = gen_degree*gen_degree 3785 rat_arg_fl = ComplexIntervalField(100)(n).argument() / RealIntervalField(100).pi() / 2 3786 rat_arg = rat_arg_fl.simplest_rational() 3787 if rat_arg.denominator() > max_b: 3788 return None 3789 n_exp = n ** rat_arg.denominator() 3790 if n_exp.real() > 0 and n_exp.imag() == 0: 3791 return rat_arg 3792 # Strictly speaking, we need to look for the second-simplest 3793 # rational in rat_arg_fl and make sure its denominator is > max_b. 3794 # For now, we just punt. 3795 raise NotImplementedError 3796 3797 def gaussian_value(self): 3798 assert(self._generator is QQbar_I_generator) 3799 return self._value 3800 3801 class ANUnaryExpr(ANDescr): 3802 def __init__(self, arg, op): 3803 self._arg = arg 3804 self._op = op 3805 3806 def kind(self): 3807 return 'other' 3808 3809 def _interval_fast(self, prec): 3810 op = self._op 3811 3812 if op == '-': 3813 return -self._arg._interval_fast(prec) 3814 3815 if op == '~': 3816 return ~self._arg._interval_fast(prec) 3817 3818 if op == 'real': 3819 v = self._arg._interval_fast(prec) 3820 if is_ComplexIntervalFieldElement(v): 3821 return v.real() 3822 else: 3823 return v 3824 3825 if op == 'imag': 3826 v = self._arg._interval_fast(prec) 3827 if is_ComplexIntervalFieldElement(v): 3828 return v.imag() 3829 else: 3830 return RealIntervalField(prec)(0) 3831 3832 if op == 'abs': 3833 return abs(self._arg._interval_fast(prec)) 3834 3835 if op == 'norm': 3836 v = self._arg._interval_fast(prec) 3837 if is_ComplexIntervalFieldElement(v): 3838 return v.norm() 3839 else: 3840 return v.square() 3841 3842 if op == 'conjugate': 3843 v = self._arg._interval_fast(prec) 3844 if is_ComplexIntervalFieldElement(v): 3845 return v.conjugate() 3846 else: 3847 return v 3848 3849 raise NotImplementedError 3850 3851 def exactify(self): 3852 op = self._op 3853 arg = self._arg 3854 3855 if op == '-': 3856 arg.exactify() 3857 return arg._descr.neg(None) 3858 3859 if op == '~': 3860 arg.exactify() 3861 return arg._descr.invert(None) 3862 3863 if op == 'real': 3864 arg.exactify() 3865 rv = (arg + arg.conjugate()) / 2 3866 rv.exactify() 3867 rvd = rv._descr 3868 rvd._exactly_real = True 3869 return rvd 3870 3871 if op == 'imag': 3872 arg.exactify() 3873 iv = QQbar_I * (arg.conjugate() - arg) / 2 3874 iv.exactify() 3875 ivd = iv._descr 3876 ivd._exactly_real = True 3877 return ivd 3878 3879 if op == 'abs': 3880 arg.exactify() 3881 if arg.parent() is AA: 3882 if arg.sign() > 0: 3883 return arg._descr 3884 else: 3885 return arg._descr.neg(None) 3886 3887 v = (arg * arg.conjugate()).sqrt() 3888 v.exactify() 3889 vd = v._descr 3890 vd._exactly_real = True 3891 return vd 3892 3893 if op == 'norm': 3894 arg.exactify() 3895 v = arg * arg.conjugate() 3896 v.exactify() 3897 vd = v._descr 3898 vd._exactly_real = True 3899 return vd 3900 3901 if op == 'conjugate': 3902 arg.exactify() 3903 return arg._descr.conjugate(None) 3904 3905 class ANBinaryExpr(ANDescr): 3906 def __init__(self, left, right, op): 3907 self._left = left 3908 self._right = right 3909 self._op = op 3910 self._complex = True 3911 3912 def kind(self): 3913 return 'other' 3914 3915 def is_complex(self): 3916 return self._complex 3917 3918 def _interval_fast(self, prec): 3919 op = self._op 3920 3921 lv = self._left._interval_fast(prec) 3922 rv = self._right._interval_fast(prec) 3923 3924 if not (is_ComplexIntervalFieldElement(lv) or is_ComplexIntervalFieldElement(rv)): 3925 self._complex = False 3926 3927 if op == '-': 3928 return lv - rv 3929 3930 if op == '+': 3931 return lv + rv 3932 3933 if op == '/': 3934 return lv / rv 3935 3936 if op == '*': 3937 return lv * rv 3938 3939 raise NotImplementedError 3940 3941 def exactify(self): 3942 left = self._left 3943 right = self._right 3944 left.exactify() 3945 right.exactify() 3946 gen = left._exact_field().union(right._exact_field()) 3947 left_value = gen(left._exact_value()) 3948 right_value = gen(right._exact_value()) 3949 3950 op = self._op 3951 3952 if op == '+': 3953 value = left_value + right_value 3954 if op == '-': 3955 value = left_value - right_value 3956 if op == '*': 3957 value = left_value * right_value 3958 if op == '/': 3959 value = left_value / right_value 3960 3961 if gen.is_trivial(): 3962 return ANRational(value) 3963 else: 3964 return ANExtensionElement(gen, value) 3965 3966 ax = QQbarPoly.gen() 2226 3967 # def heptadecagon(): 2227 3968 # # Compute the exact (x,y) coordinates of the vertices of a 34-gon. … … 2274 4015 2275 4016 2276 def pari_nf_hack(k): 2277 f = k.pari_polynomial().subst('x','y') 2278 return f.nfinit(1) 2279 2280 AA_1_123456789 = AA(~ZZ(123456789)) 2281 4017 RR_1_10 = RR(ZZ(1)/10) 4018 QQ_0 = QQ(0) 4019 QQ_1 = QQ(1) 4020 QQ_1_2 = QQ(1)/2 4021 QQ_1_4 = QQ(1)/4 4022 4023 QQbar_I_nf = QuadraticField(-1, 'I') 4024 # XXX change ANRoot to ANRootOfUnity below 4025 QQbar_I_generator = AlgebraicGenerator(QQbar_I_nf, ANRoot(AAPoly.gen()**2 + 1, CIF(0, 1))) 4026 QQbar_I = AlgebraicNumber(ANExtensionElement(QQbar_I_generator, QQbar_I_nf.gen())) 4027 _cyclotomic_gen_cache[4] = QQbar_I_generator 4028 QQbar_I_generator.set_cyclotomic(4) 4029 4030 AA_hash_offset = AA(~ZZ(123456789)) 4031 4032 QQbar_hash_offset = AlgebraicNumber(ANExtensionElement(QQbar_I_generator, ~ZZ(123456789) + QQbar_I_nf.gen()/ZZ(987654321))) 4033 4034 ZZX_x = ZZ['x'].gen() 4035 4036 # This is used in the _algebraic_ method of the golden_ratio constant, 4037 # in sage/functions/constants.py 4038 AA_golden_ratio = None 4039 4040 def get_AA_golden_ratio(): 4041 global AA_golden_ratio 4042 if AA_golden_ratio is None: 4043 AA_golden_ratio_nf = NumberField(ZZX_x**2 - ZZX_x - 1, 'phi') 4044 AA_golden_ratio_generator = AlgebraicGenerator(AA_golden_ratio_nf, ANRoot(AAPoly.gen()**2 - AAPoly.gen() - 1, RIF(1.618, 1.6181))) 4045 AA_golden_ratio = AlgebraicReal(ANExtensionElement(AA_golden_ratio_generator, AA_golden_ratio_nf.gen())) 4046 return AA_golden_ratio -
sage/rings/all.py
r7425 r7427 92 92 # with the reals) 93 93 from algebraic_real import (AlgebraicRealField, is_AlgebraicRealField, AA, 94 AlgebraicRealNumber, is_AlgebraicRealNumber) 94 AlgebraicReal, is_AlgebraicReal, 95 AlgebraicField, is_AlgebraicField, QQbar, 96 AlgebraicNumber, is_AlgebraicNumber) 95 97 96 98 # Intervals -
sage/rings/complex_field.py
r7425 r7427 27 27 28 28 NumberFieldElement_quadratic = None 29 AlgebraicNumber_base = None 30 AlgebraicNumber = None 31 AlgebraicReal = None 29 32 def late_import(): 30 33 global NumberFieldElement_quadratic 34 global AlgebraicNumber_base 35 global AlgebraicNumber 36 global AlgebraicReal 31 37 if NumberFieldElement_quadratic is None: 32 38 import sage.rings.number_field.number_field_element_quadratic as nfeq 33 39 NumberFieldElement_quadratic = nfeq.NumberFieldElement_quadratic 40 import sage.rings.algebraic_real 41 AlgebraicNumber_base = sage.rings.algebraic_real.AlgebraicNumber_base 42 AlgebraicNumber = sage.rings.algebraic_real.AlgebraicNumber 43 AlgebraicReal = sage.rings.algebraic_real.AlgebraicReal 34 44 35 45 def is_ComplexField(x): … … 210 220 except AttributeError: 211 221 pass 222 late_import() 223 if isinstance(x, AlgebraicNumber_base): 224 return self(x) 212 225 return self._coerce_try(x, self._real_field()) 213 226 -
sage/rings/real_mpfi.pyx
r7425 r7427 405 405 be adjacent floating-point numbers that surround the given value. 406 406 """ 407 import sage.rings.algebraic_real408 409 407 if isinstance(x, real_mpfr.RealNumber): 410 408 P = x.parent() … … 747 745 mpfi_interv_fr(self.value, <mpfr_t> rn.value, <mpfr_t> rn1.value) 748 746 749 elif isinstance(x, sage.rings.algebraic_real.AlgebraicReal Number):747 elif isinstance(x, sage.rings.algebraic_real.AlgebraicReal): 750 748 d = x.interval(self._parent) 751 749 mpfi_set(self.value, d.value) -
sage/rings/real_mpfr.pyx
r7385 r7427 256 256 * the field of algebraic reals 257 257 """ 258 import sage.rings.algebraic_real259 260 258 if isinstance(x, RealNumber): 261 259 P = x.parent() … … 264 262 else: 265 263 raise TypeError, "Canonical coercion from lower to higher precision not defined" 266 elif isinstance(x, (Integer, Rational , sage.rings.algebraic_real.AlgebraicRealNumber)):264 elif isinstance(x, (Integer, Rational)): 267 265 return self(x) 268 266 elif isinstance(x,QuadDoubleElement) and self.__prec <=212: 269 267 return self(x) 270 268 elif is_RealDoubleElement(x) and self.__prec <= 53: 269 return self(x) 270 import sage.rings.algebraic_real 271 if isinstance(x, sage.rings.algebraic_real.AlgebraicReal): 271 272 return self(x) 272 273 raise TypeError … … 622 623 623 624 cdef _set(self, x, int base): 624 import sage.rings.algebraic_real625 626 625 # This should not be called except when the number is being created. 627 626 # Real Numbers are supposed to be immutable. … … 653 652 qd = x 654 653 self._set_from_qd(qd) 655 elif isinstance(x, sage.rings.algebraic_real.AlgebraicRealNumber):656 d = x.real(parent)657 mpfr_set(self.value, d.value, parent.rnd)658 654 elif hasattr(x, '_mpfr_'): 659 655 return x._mpfr_(self)
Note: See TracChangeset
for help on using the changeset viewer.
