Ticket #12555: 12555_CA.patch
| File 12555_CA.patch, 88.6 KB (added by roed, 15 months ago) |
|---|
-
new file sage/rings/padics/CA_template.pxi
# HG changeset patch # User David Roe <roed@math.harvard.edu> # Date 1330837831 28800 # Node ID 7499e540d8aab77ef8248e6078c7fc898405e54f # Parent 1bcc70085997c9c22eb530a00ce71617c988d495 #12555: capped absolute templates diff --git a/sage/rings/padics/CA_template.pxi b/sage/rings/padics/CA_template.pxi new file mode 100644
- + 1 """ 2 Capped absolute template for complete discrete valuation rings. 3 4 In order to use this template you need to write a linkage file and gluing file. 5 For an example see mpz_linkage.pxi (linkage file) and padic_capped_absolute_element.pyx (gluing file). 6 7 The linkage file implements a common API that is then used in the class CAElement defined here. 8 See the documentation of mpz_linkage.pxi for the functions needed. 9 10 The gluing file does the following: 11 12 - includes "../../ext/cdefs.pxi" 13 - ctypedef's celement to be the appropriate type (e.g. mpz_t) 14 - includes the linkage file 15 - includes this template 16 - defines a concrete class inheriting from CRElement, and implements any desired extra methods 17 18 AUTHORS: 19 20 - David Roe (2012-3-1) -- initial version 21 """ 22 23 #***************************************************************************** 24 # Copyright (C) 2012 David Roe <roed.math@gmail.com> 25 # William Stein <wstein@gmail.com> 26 # 27 # Distributed under the terms of the GNU General Public License (GPL) 28 # 29 # http://www.gnu.org/licenses/ 30 #***************************************************************************** 31 32 # This file implements common functionality among template elements 33 include "padic_template_element.pxi" 34 35 from sage.structure.element cimport Element 36 from sage.rings.padics.common_conversion cimport comb_prec, _process_args_and_kwds 37 from sage.rings.integer_ring import ZZ 38 from sage.rings.rational_field import QQ 39 from sage.categories.sets_cat import Sets 40 from sage.categories.sets_with_partial_maps import SetsWithPartialMaps 41 from sage.categories.homset import Hom 42 43 cdef class CAElement(pAdicTemplateElement): 44 cdef int _set(self, x, long val, long xprec, absprec, relprec) except -1: 45 """ 46 TESTS:: 47 48 sage: R = ZpCA(5) 49 sage: a = R(17,5); a #indirect doctest 50 2 + 3*5 + O(5^5) 51 sage: a = R(75, absprec = 5, relprec = 4); a #indirect doctest 52 3*5^2 + O(5^5) 53 sage: a = R(25/9, absprec = 5); a #indirect doctest 54 4*5^2 + 2*5^3 + O(5^5) 55 sage: a = R(25/9, absprec = 5, relprec = 4); a #indirect doctest 56 4*5^2 + 2*5^3 + O(5^5) 57 """ 58 cconstruct(self.value, self.prime_pow) 59 cdef long rprec = comb_prec(relprec, self.prime_pow.prec_cap) 60 cdef long aprec = comb_prec(absprec, min(self.prime_pow.prec_cap, xprec)) 61 if aprec <= val: 62 csetzero(self.value, self.prime_pow) 63 self.absprec = aprec 64 else: 65 self.absprec = min(aprec, val + rprec) 66 cconv(self.value, x, self.absprec, 0, self.prime_pow) 67 68 cdef CAElement _new_c(self): 69 """ 70 Creates a new element with the same basic info. 71 72 TESTS:: 73 74 sage: R = ZpCA(5); R(6,5) * R(7,8) #indirect doctest 75 2 + 3*5 + 5^2 + O(5^5) 76 """ 77 cdef CAElement ans = PY_NEW(self.__class__) 78 ans._parent = self._parent 79 ans.prime_pow = self.prime_pow 80 cconstruct(ans.value, ans.prime_pow) 81 return ans 82 83 cdef int check_preccap(self) except -1: 84 """ 85 Checks that this element doesn't have precision higher than allowed by the precision cap. 86 87 TESTS:: 88 89 sage: ZpCA(5)(1).lift_to_precision(30) 90 Traceback (most recent call last): 91 ... 92 PrecisionError: Precision higher than allowed by the precision cap. 93 """ 94 if self.absprec > self.prime_pow.prec_cap: 95 raise PrecisionError("Precision higher than allowed by the precision cap.") 96 97 def __copy__(self): 98 """ 99 Returns a copy of ``self``. 100 101 EXAMPLES:: 102 103 sage: a = ZpCA(5,6)(17); b = copy(a) 104 sage: a == b 105 True 106 sage: a is b 107 False 108 """ 109 cdef CAElement ans = self._new_c() 110 ans.absprec = self.absprec 111 ccopy(ans.value, self.value, ans.prime_pow) 112 return ans 113 114 def __dealloc__(self): 115 """ 116 Deallocation. 117 118 TESTS:: 119 120 sage: R = ZpCA(5) 121 sage: a = R(17) 122 sage: del(a) 123 """ 124 cdestruct(self.value, self.prime_pow) 125 126 def __reduce__(self): 127 """ 128 Pickling. 129 130 TESTS:: 131 132 sage: a = ZpCA(5)(-3) 133 sage: type(a) 134 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCappedAbsoluteElement'> 135 sage: loads(dumps(a)) == a 136 True 137 """ 138 return unpickle_cae_v2, (self.__class__, self.parent(), cpickle(self.value, self.prime_pow), self.absprec) 139 140 def __richcmp__(self, right, int op): 141 """ 142 Comparison. 143 144 TESTS:: 145 146 sage: R = ZpCA(5) 147 sage: a = R(17) 148 sage: b = R(21) 149 sage: a == b 150 False 151 sage: a < b 152 True 153 """ 154 return (<Element>self)._richcmp(right, op) 155 156 cpdef ModuleElement _neg_(self): 157 """ 158 Returns the negation of self. 159 160 EXAMPLES:: 161 162 sage: R = Zp(5, prec=10, type='capped-abs') 163 sage: a = R(1) 164 sage: -a #indirect doctest 165 4 + 4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + 4*5^6 + 4*5^7 + 4*5^8 + 4*5^9 + O(5^10) 166 """ 167 cdef CAElement ans = self._new_c() 168 ans.absprec = self.absprec 169 cneg(ans.value, self.value, ans.absprec, ans.prime_pow) 170 creduce_small(ans.value, ans.value, ans.absprec, ans.prime_pow) 171 return ans 172 173 cpdef ModuleElement _add_(self, ModuleElement _right): 174 """ 175 Addition. 176 177 EXAMPLES:: 178 179 sage: R = ZpCA(13, 4) 180 sage: R(2) + R(3) #indirect doctest 181 5 + O(13^4) 182 sage: R(12) + R(1) 183 13 + O(13^4) 184 """ 185 cdef CAElement right = <CAElement>_right 186 cdef CAElement ans = self._new_c() 187 ans.absprec = min(self.absprec, right.absprec) 188 cadd(ans.value, self.value, right.value, ans.absprec, ans.prime_pow) 189 creduce_small(ans.value, ans.value, ans.absprec, ans.prime_pow) 190 return ans 191 192 cpdef ModuleElement _sub_(self, ModuleElement _right): 193 """ 194 Subtraction. 195 196 EXAMPLES:: 197 198 sage: R = ZpCA(13, 4) 199 sage: R(10) - R(10) #indirect doctest 200 O(13^4) 201 sage: R(10) - R(11) 202 12 + 12*13 + 12*13^2 + 12*13^3 + O(13^4) 203 """ 204 cdef CAElement right = <CAElement>_right 205 cdef CAElement ans = self._new_c() 206 ans.absprec = min(self.absprec, right.absprec) 207 csub(ans.value, self.value, right.value, ans.absprec, ans.prime_pow) 208 creduce_small(ans.value, ans.value, ans.absprec, ans.prime_pow) 209 return ans 210 211 def __invert__(self): 212 """ 213 Returns the multiplicative inverse of ``self``. 214 215 EXAMPLES:: 216 217 sage: R = ZpCA(17) 218 sage: ~R(-1) == R(-1) 219 True 220 sage: ~R(5) * 5 221 1 + O(17^20) 222 sage: ~R(5) 223 7 + 3*17 + 10*17^2 + 13*17^3 + 6*17^4 + 3*17^5 + 10*17^6 + 13*17^7 + 6*17^8 + 3*17^9 + 10*17^10 + 13*17^11 + 6*17^12 + 3*17^13 + 10*17^14 + 13*17^15 + 6*17^16 + 3*17^17 + 10*17^18 + 13*17^19 + O(17^20) 224 sage: ~R(-1) == R(-1) #indirect doctest 225 True 226 """ 227 return self.parent().fraction_field()(self).__invert__() 228 229 cpdef RingElement _mul_(self, RingElement _right): 230 """ 231 Multiplication. 232 233 EXAMPLES:: 234 235 sage: R = ZpCA(5) 236 sage: a = R(20,5); b = R(75, 4); a * b #indirect doctest 237 2*5^3 + 2*5^4 + O(5^5) 238 """ 239 cdef CAElement right = <CAElement>_right 240 cdef CAElement ans = self._new_c() 241 cdef long vals, valr 242 if self.absprec == self.prime_pow.prec_cap and right.absprec == self.prime_pow.prec_cap: 243 ans.absprec = self.absprec 244 else: 245 vals = self.valuation_c() 246 valr = right.valuation_c() 247 ans.absprec = min(vals + valr + min(self.absprec - vals, right.absprec - valr), self.prime_pow.prec_cap) 248 cmul(ans.value, self.value, right.value, ans.absprec, ans.prime_pow) 249 creduce(ans.value, ans.value, ans.absprec, ans.prime_pow) 250 return ans 251 252 cpdef RingElement _div_(self, RingElement right): 253 """ 254 Division. 255 256 EXAMPLES:: 257 258 sage: R = ZpCA(13, 4) 259 sage: R(2) / R(3) # indirect doctest 260 5 + 4*13 + 4*13^2 + 4*13^3 + O(13^4) 261 sage: a = R(169 * 2) / R(13); a 262 2*13 + O(13^3) 263 sage: R(13) / R(169 * 2) 264 7*13^-1 + 6 + O(13) 265 sage: ~a 266 7*13^-1 + 6 + O(13) 267 sage: 1 / a 268 7*13^-1 + 6 + O(13) 269 """ 270 K = self.parent().fraction_field() 271 return K(self) / K(right) 272 273 def __pow__(CAElement self, _right, dummy): 274 """ 275 Exponentiation. 276 277 EXAMPLES:: 278 279 sage: R = ZpCA(11, 5) 280 sage: R(1/2)^5 281 10 + 7*11 + 11^2 + 5*11^3 + 4*11^4 + O(11^5) 282 sage: R(1/32) 283 10 + 7*11 + 11^2 + 5*11^3 + 4*11^4 + O(11^5) 284 sage: R(1/2)^5 == R(1/32) 285 True 286 sage: R(3)^1000 287 1 + 4*11^2 + 3*11^3 + 7*11^4 + O(11^5) 288 """ 289 cdef long base_level, exp_prec, relprec, val 290 cdef mpz_t tmp 291 cdef Integer right 292 cdef CAElement base, ans = self._new_c() 293 if isinstance(_right, (int, long, Integer)) and _right == 0: 294 # return 1 to maximum precision 295 ans.absprec = self.prime_pow.prec_cap 296 csetone(ans.value, ans.prime_pow) 297 elif ciszero(self.value, self.prime_pow): 298 # If a positive integer exponent, return an inexact zero of valuation right * self.ordp. Otherwise raise an error. 299 if isinstance(_right, (int, long)): 300 _right = Integer(_right) 301 if PY_TYPE_CHECK(_right, Integer): 302 if _right < 0: 303 raise ValueError, "Need more precision" 304 if self.absprec == self.prime_pow.prec_cap or mpz_cmp_si((<Integer>_right).value, self.prime_pow.prec_cap / self.absprec + 1) > 0: 305 ans.absprec = self.prime_pow.prec_cap 306 else: 307 ans.absprec = min(self.prime_pow.prec_cap, self.absprec * mpz_get_si((<Integer>_right).value)) 308 csetzero(ans.value, ans.prime_pow) 309 elif PY_TYPE_CHECK(_right, Rational) or (PY_TYPE_CHECK(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime)): 310 raise ValueError("Need more precision") 311 else: 312 raise TypeError, "exponent must be an integer, rational or base p-adic with the same prime" 313 else: 314 val = self.valuation_c() 315 relprec = self.absprec - self.valuation_c() 316 # pow_helper is defined in padic_template_element.pxi 317 right = pow_helper(&relprec, &exp_prec, val, self.absprec - val, _right, self.prime_pow.prime) 318 if exp_prec == 0: 319 # a p-adic exponent with no relative precision 320 ans.absprec = 0 321 csetzero(ans.value, ans.prime_pow) 322 return ans 323 mpz_init_set_si(tmp, val) 324 mpz_mul(tmp, right.value, tmp) 325 if mpz_cmp_si(tmp, self.prime_pow.prec_cap) >= 0: 326 ans.absprec = self.prime_pow.prec_cap 327 csetzero(ans.value, ans.prime_pow) 328 else: 329 ans.absprec = min(mpz_get_si(tmp) + relprec, self.prime_pow.prec_cap) 330 if right < 0: 331 base = ~self 332 right = -right 333 else: 334 base = self 335 cpow(ans.value, base.value, right.value, ans.absprec, ans.prime_pow) 336 mpz_clear(tmp) 337 return ans 338 339 cdef pAdicTemplateElement _lshift_c(self, long shift): 340 """ 341 Multiplies by ``p^shift``. 342 343 TESTS:: 344 345 sage: R = ZpCA(5); a = R(17); a << 2 346 2*5^2 + 3*5^3 + O(5^20) 347 """ 348 if shift < 0: 349 return self._rshift_c(-shift) 350 elif shift == 0: 351 return self 352 cdef CAElement ans = self._new_c() 353 if shift >= self.prime_pow.prec_cap: 354 csetzero(ans.value, ans.prime_pow) 355 ans.absprec = self.prime_pow.prec_cap 356 else: 357 ans.absprec = min(self.absprec + shift, self.prime_pow.prec_cap) 358 cshift(ans.value, self.value, shift, ans.absprec, ans.prime_pow, False) 359 return ans 360 361 cdef pAdicTemplateElement _rshift_c(self, long shift): 362 """ 363 Divides by ``p^shift`` and truncates. 364 365 TESTS:: 366 367 sage: R = ZpCA(5); a = R(77); a >> 1 368 3*5 + O(5^19) 369 """ 370 if shift < 0: 371 return self._lshift_c(-shift) 372 elif shift == 0: 373 return self 374 cdef CAElement ans = self._new_c() 375 if shift >= self.absprec: 376 csetzero(ans.value, ans.prime_pow) 377 ans.absprec = 0 378 else: 379 ans.absprec = self.absprec - shift 380 cshift(ans.value, self.value, -shift, ans.absprec, ans.prime_pow, False) 381 return ans 382 383 def add_bigoh(self, absprec): 384 """ 385 Returns a new element with absolute precision decreased to 386 ``prec``. The precision never increases. 387 388 INPUT: 389 390 - ``self`` -- a `p`-adic element 391 392 - ``prec`` -- an integer 393 394 OUTPUT: 395 396 - ``element`` -- ``self`` with precision set to the minimum of ``self's`` precision and ``prec`` 397 398 EXAMPLES:: 399 400 sage: R = Zp(7,4,'capped-abs','series'); a = R(8); a.add_bigoh(1) 401 1 + O(7) 402 403 sage: k = ZpCA(3,5) 404 sage: a = k(41); a 405 2 + 3 + 3^2 + 3^3 + O(3^5) 406 sage: a.add_bigoh(7) 407 2 + 3 + 3^2 + 3^3 + O(3^5) 408 sage: a.add_bigoh(3) 409 2 + 3 + 3^2 + O(3^3) 410 """ 411 cdef long aprec, newprec 412 if PY_TYPE_CHECK(absprec, int): 413 aprec = absprec 414 else: 415 if not PY_TYPE_CHECK(absprec, Integer): 416 absprec = Integer(absprec) 417 aprec = mpz_get_si((<Integer>absprec).value) 418 if aprec >= self.absprec: 419 return self 420 cdef CAElement ans = self._new_c() 421 ans.absprec = aprec 422 creduce(ans.value, self.value, ans.absprec, ans.prime_pow) 423 return ans 424 425 cpdef bint _is_exact_zero(self) except -1: 426 return False 427 428 cpdef bint _is_inexact_zero(self) except -1: 429 """ 430 Returns ``True`` if ``self`` is indistinguishable from zero. 431 432 EXAMPLES:: 433 434 sage: R = ZpCA(7, 5) 435 sage: R(7^5)._is_inexact_zero() 436 True 437 sage: R(0,4)._is_inexact_zero() 438 True 439 sage: R(0)._is_inexact_zero() 440 True 441 """ 442 return ciszero(self.value, self.prime_pow) 443 444 def is_zero(self, absprec = None): 445 r""" 446 Returns whether ``self`` is zero modulo ``p^absprec``. 447 448 INPUT: 449 450 - ``self`` -- a `p`-adic element 451 452 - ``prec`` -- an integer 453 454 OUTPUT: 455 456 - ``boolean`` -- whether self is zero 457 458 EXAMPLES:: 459 460 sage: R = ZpCA(17, 6) 461 sage: R(0).is_zero() 462 True 463 sage: R(17^6).is_zero() 464 True 465 sage: R(17^2).is_zero(absprec=2) 466 True 467 """ 468 cdef bint iszero = ciszero(self.value, self.prime_pow) 469 if absprec is None: 470 return iszero 471 cdef long val = self.valuation_c() 472 if isinstance(absprec, int): 473 if iszero and absprec > self.absprec: 474 raise PrecisionError, "Not enough precision to determine if element is zero" 475 return val >= absprec 476 if not PY_TYPE_CHECK(absprec, Integer): 477 absprec = Integer(absprec) 478 if iszero: 479 if mpz_cmp_si((<Integer>absprec).value, val) > 0: 480 raise PrecisionError, "Not enough precision to determine if element is zero" 481 else: 482 return True 483 return mpz_cmp_si((<Integer>absprec).value, val) <= 0 484 485 def __nonzero__(self): 486 return not ciszero(self.value, self.prime_pow) 487 488 def is_equal_to(self, _right, absprec=None): 489 r""" 490 Returns whether ``self`` is equal to ``right`` modulo ``p^absprec``. 491 492 INPUT: 493 494 - ``self`` -- a `p`-adic element 495 496 - ``right`` -- a `p`-adic element with the same parent 497 498 - ``absprec`` -- an integer 499 500 OUTPUT: 501 502 - ``boolean`` -- whether ``self`` is equal to ``right`` 503 504 EXAMPLES:: 505 506 sage: R = ZpCA(2, 6) 507 sage: R(13).is_equal_to(R(13)) 508 True 509 sage: R(13).is_equal_to(R(13+2^10)) 510 True 511 sage: R(13).is_equal_to(R(17), 2) 512 True 513 sage: R(13).is_equal_to(R(17), 5) 514 False 515 """ 516 cdef CAElement right 517 cdef long aprec, rprec, sval, rval 518 if self.parent() is _right.parent(): 519 right = <CAElement>_right 520 else: 521 right = <CAElement>self.parent()(_right) 522 if absprec is None: 523 aprec = min(self.absprec, right.absprec) 524 else: 525 if not PY_TYPE_CHECK(absprec, Integer): 526 absprec = Integer(absprec) 527 if mpz_fits_slong_p((<Integer>absprec).value) == 0: 528 if mpz_sgn((<Integer>absprec).value) < 0: 529 return True 530 else: 531 raise PrecisionError, "Elements not known to enough precision" 532 aprec = mpz_get_si((<Integer>absprec).value) 533 if aprec > self.absprec or aprec > right.absprec: 534 raise PrecisionError, "Elements not known to enough precision" 535 return ccmp(self.value, right.value, aprec, aprec < self.absprec, aprec < right.absprec, self.prime_pow) == 0 536 537 cdef int _cmp_units(self, pAdicGenericElement _right): 538 cdef CAElement right = <CAElement>_right 539 cdef long aprec = min(self.absprec, right.absprec) 540 if aprec == 0: 541 return 0 542 return ccmp(self.value, right.value, aprec, aprec < self.absprec, aprec < right.absprec, self.prime_pow) 543 544 cdef pAdicTemplateElement lift_to_precision_c(self, long absprec): 545 if absprec <= self.absprec: 546 return self 547 cdef CAElement ans = self._new_c() 548 ccopy(ans.value, self.value, ans.prime_pow) 549 ans.absprec = absprec 550 return ans 551 552 def list(self, lift_mode = 'simple'): 553 """ 554 Returns a list of coefficients of `p` starting with `p^0` 555 556 INPUT: 557 558 - ``self`` -- a `p`-adic element 559 560 - ``lift_mode`` -- ``'simple'``, ``'smallest'`` or 561 ``'teichmuller'`` (default ``'simple'``) 562 563 OUTPUT: 564 565 - ``list`` -- the list of coefficients of ``self`` 566 567 NOTES: 568 569 - Returns a list `[a_0, a_1, \ldots, a_n]` so that: 570 571 + If ``lift_mode = 'simple'``, `a_i` is an integer with `0 572 \le a_i < p`. 573 574 + If ``lift_mode = 'smallest'``, `a_i` is an integer with 575 `-p/2 < a_i \le p/2`. 576 577 + If ``lift_mode = 'teichmuller'``, `a_i` has the same 578 parent as `self` and `a_i^p \equiv a_i` modulo 579 ``p^(self.precision_absolute() - i)`` 580 581 - `\sum_{i = 0}^n a_i \cdot p^i =` ``self``, modulo the 582 precision of ``self``. 583 584 585 EXAMPLES:: 586 587 sage: R = ZpCA(7,6); a = R(12837162817); a 588 3 + 4*7 + 4*7^2 + 4*7^4 + O(7^6) 589 sage: L = a.list(); L 590 [3, 4, 4, 0, 4] 591 sage: sum([L[i] * 7^i for i in range(len(L))]) == a 592 True 593 sage: L = a.list('smallest'); L 594 [3, -3, -2, 1, -3, 1] 595 sage: sum([L[i] * 7^i for i in range(len(L))]) == a 596 True 597 sage: L = a.list('teichmuller'); L 598 [3 + 4*7 + 6*7^2 + 3*7^3 + 2*7^5 + O(7^6), 599 O(7^5), 600 5 + 2*7 + 3*7^3 + O(7^4), 601 1 + O(7^3), 602 3 + 4*7 + O(7^2), 603 5 + O(7)] 604 sage: sum([L[i] * 7^i for i in range(len(L))]) 605 3 + 4*7 + 4*7^2 + 4*7^4 + O(7^6) 606 """ 607 if ciszero(self.value, self.prime_pow): 608 return [] 609 if lift_mode == 'teichmuller': 610 return self.teichmuller_list() 611 elif lift_mode == 'simple': 612 return clist(self.value, self.absprec, True, self.prime_pow) 613 elif lift_mode == 'smallest': 614 return clist(self.value, self.absprec, False, self.prime_pow) 615 else: 616 raise ValueError, "unknown lift_mode" 617 618 def teichmuller_list(self): 619 r""" 620 Returns a list `[a_0, a_1,\ldots, a_n]` such that 621 622 - `a_i^p = a_i` 623 624 - ``self`` equals `\sum_{i = 0}^n a_i p^i` 625 626 - if `a_i \ne 0`, the absolute precision of `a_i` is 627 ``self.precision_relative() - i`` 628 629 EXAMPLES:: 630 631 sage: R = ZpCA(5,5); R(14).list('teichmuller') #indirect doctest 632 [4 + 4*5 + 4*5^2 + 4*5^3 + 4*5^4 + O(5^5), 633 3 + 3*5 + 2*5^2 + 3*5^3 + O(5^4), 634 2 + 5 + 2*5^2 + O(5^3), 635 1 + O(5^2), 636 4 + O(5)] 637 """ 638 ans = PyList_New(0) 639 if ciszero(self.value, self.prime_pow): 640 return ans 641 cdef long curpower = self.absprec 642 cdef CAElement list_elt 643 cdef CAElement tmp = self._new_c() 644 ccopy(tmp.value, self.value, self.prime_pow) 645 while not ciszero(tmp.value, tmp.prime_pow) and curpower > 0: 646 list_elt = self._new_c() 647 cteichmuller(list_elt.value, tmp.value, curpower, self.prime_pow) 648 if ciszero(list_elt.value, self.prime_pow): 649 cshift0(tmp.value, tmp.value, -1, curpower-1, self.prime_pow) 650 else: 651 csub(tmp.value, tmp.value, list_elt.value, curpower, self.prime_pow) 652 cshift0(tmp.value, tmp.value, -1, curpower-1, self.prime_pow) 653 creduce(tmp.value, tmp.value, curpower-1, self.prime_pow) 654 list_elt.absprec = curpower 655 curpower -= 1 656 PyList_Append(ans, list_elt) 657 return ans 658 659 def _teichmuller_set(self): 660 """ 661 Sets ``self`` to be the Teichmuller representative with the 662 same residue as ``self``. 663 664 WARNING: 665 666 This function modifies ``self``, which is not safe. Elements 667 are supposed to be immutable. 668 669 EXAMPLES:: 670 671 sage: R = ZpCA(17,5); a = R(11) 672 sage: a 673 11 + O(17^5) 674 sage: a._teichmuller_set(); a 675 11 + 14*17 + 2*17^2 + 12*17^3 + 15*17^4 + O(17^5) 676 sage: a.list('teichmuller') 677 [11 + 14*17 + 2*17^2 + 12*17^3 + 15*17^4 + O(17^5)] 678 """ 679 if self.valuation_c() > 0: 680 csetzero(self.value, self.prime_pow) 681 self.absprec = self.prime_pow.prec_cap 682 elif self.absprec == 0: 683 raise ValueError("not enough precision") 684 else: 685 cteichmuller(self.value, self.value, self.absprec, self.prime_pow) 686 687 def precision_absolute(self): 688 """ 689 Returns the absolute precision of ``self``. 690 691 This is the power of the maximal ideal modulo which this 692 element is defined. 693 694 INPUT: 695 696 - ``self`` -- a `p`-adic element 697 698 OUTPUT: 699 700 - ``integer`` -- the absolute precision of ``self`` 701 702 EXAMPLES:: 703 704 sage: R = Zp(7,4,'capped-abs'); a = R(7); a.precision_absolute() 705 4 706 """ 707 cdef Integer ans = PY_NEW(Integer) 708 mpz_set_si(ans.value, self.absprec) 709 return ans 710 711 def precision_relative(self): 712 """ 713 Returns the relative precision of ``self``. 714 715 This is the power of the maximal ideal modulo which the unit 716 part of ``self`` is defined. 717 718 INPUT: 719 720 - ``self`` -- a `p`-adic element 721 722 OUTPUT: 723 724 - ``integer`` -- the relative precision of ``self`` 725 726 EXAMPLES:: 727 728 sage: R = Zp(7,4,'capped-abs'); a = R(7); a.precision_relative() 729 3 730 """ 731 cdef Integer ans = PY_NEW(Integer) 732 mpz_set_si(ans.value, self.absprec - self.valuation_c()) 733 return ans 734 735 cpdef pAdicTemplateElement unit_part(CAElement self): 736 r""" 737 Returns the unit part of ``self``. 738 739 INPUT: 740 741 - ``self`` -- a `p`-adic element 742 743 OUTPUT: 744 745 - `p`-adic element -- the unit part of ``self`` 746 747 EXAMPLES:: 748 749 sage: R = Zp(17,4,'capped-abs', 'val-unit') 750 sage: a = R(18*17) 751 sage: a.unit_part() 752 18 + O(17^3) 753 sage: type(a) 754 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCappedAbsoluteElement'> 755 """ 756 cdef CAElement ans = (<CAElement>self)._new_c() 757 cdef long val = cremove(ans.value, (<CAElement>self).value, (<CAElement>self).absprec, (<CAElement>self).prime_pow) 758 ans.absprec = (<CAElement>self).absprec - val 759 return ans 760 761 cdef long valuation_c(self): 762 """ 763 Returns the valuation of this element. 764 765 TESTS:: 766 767 sage: R = ZpCA(5) 768 sage: R(5^5*1827).valuation() 769 5 770 sage: R(1).valuation() 771 0 772 sage: R(2).valuation() 773 0 774 sage: R(5).valuation() 775 1 776 sage: R(10).valuation() 777 1 778 sage: R(25).valuation() 779 2 780 sage: R(50).valuation() 781 2 782 sage: R(0).valuation() 783 20 784 sage: R(0,6).valuation() 785 6 786 """ 787 # for backward compatibility 788 return cvaluation(self.value, self.absprec, self.prime_pow) 789 790 cpdef val_unit(self): 791 """ 792 Returns a 2-tuple, the first element set to the valuation of 793 ``self``, and the second to the unit part of ``self``. 794 795 If ``self = 0``, then the unit part is ``O(p^0)``. 796 797 EXAMPLES:: 798 799 sage: R = ZpCA(5) 800 sage: a = R(75, 6); b = a - a 801 sage: a.val_unit() 802 (2, 3 + O(5^4)) 803 sage: b.val_unit() 804 (6, O(5^0)) 805 """ 806 cdef CAElement unit = self._new_c() 807 cdef Integer valuation = PY_NEW(Integer) 808 cdef long val = cremove(unit.value, self.value, self.absprec, self.prime_pow) 809 mpz_set_si(valuation.value, val) 810 unit.absprec = self.absprec - val 811 return valuation, unit 812 813 def __hash__(self): 814 """ 815 Hashing. 816 817 EXAMPLES:: 818 819 sage: R = ZpCA(11, 5) 820 sage: hash(R(3)) == hash(3) 821 True 822 """ 823 return chash(self.value, 0, self.absprec, self.prime_pow) 824 825 cdef class pAdicCoercion_ZZ_CA(RingHomomorphism_coercion): 826 """ 827 The canonical inclusion from ZZ to a capped absolute ring. 828 829 EXAMPLES:: 830 831 sage: f = ZpCA(5).coerce_map_from(ZZ); f 832 Ring Coercion morphism: 833 From: Integer Ring 834 To: 5-adic Ring with capped absolute precision 20 835 """ 836 def __init__(self, R): 837 """ 838 Initialization. 839 840 EXAMPLES:: 841 842 sage: f = ZpCA(5).coerce_map_from(ZZ); type(f) 843 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCoercion_ZZ_CA'> 844 """ 845 RingHomomorphism_coercion.__init__(self, ZZ.Hom(R), check=False) 846 self._zero = R._element_constructor(R, 0) 847 self._section = pAdicConvert_CA_ZZ(R) 848 849 cpdef Element _call_(self, x): 850 """ 851 Evaluation. 852 853 EXAMPLES:: 854 855 sage: f = ZpCA(5).coerce_map_from(ZZ) 856 sage: f(0).parent() 857 5-adic Ring with capped absolute precision 20 858 sage: f(5) 859 5 + O(5^20) 860 """ 861 if mpz_sgn((<Integer>x).value) == 0: 862 return self._zero 863 cdef CAElement ans = self._zero._new_c() 864 ans.absprec = ans.prime_pow.prec_cap 865 cconv_mpzt(ans.value, (<Integer>x).value, ans.absprec, True, ans.prime_pow) 866 return ans 867 868 cpdef Element _call_with_args(self, x, args=(), kwds={}): 869 """ 870 This function is used when some precision cap is passed in (relative or absolute or both). 871 872 See the documentation for pAdicCappedAbsoluteElement.__init__ for more details. 873 874 EXAMPLES:: 875 876 sage: R = ZpCA(5,4) 877 sage: type(R(10,2)) 878 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCappedAbsoluteElement'> 879 sage: R(10,2) 880 2*5 + O(5^2) 881 sage: R(10,3,1) 882 2*5 + O(5^2) 883 sage: R(10,absprec=2) 884 2*5 + O(5^2) 885 sage: R(10,relprec=2) 886 2*5 + O(5^3) 887 sage: R(10,absprec=1) 888 O(5) 889 sage: R(10,empty=True) 890 O(5^0) 891 """ 892 cdef long val, aprec, rprec 893 cdef CAElement ans 894 _process_args_and_kwds(&aprec, &rprec, args, kwds, True, self._zero.prime_pow) 895 if mpz_sgn((<Integer>x).value) == 0: 896 if aprec >= self._zero.prime_pow.prec_cap: 897 return self._zero 898 ans = self._zero._new_c() 899 csetzero(ans.value, ans.prime_pow) 900 ans.absprec = aprec 901 else: 902 val = get_ordp(x, self._zero.prime_pow) 903 ans = self._zero._new_c() 904 if aprec <= val: 905 csetzero(ans.value, ans.prime_pow) 906 ans.absprec = aprec 907 else: 908 ans.absprec = min(aprec, val + rprec) 909 cconv_mpzt(ans.value, (<Integer>x).value, ans.absprec, True, self._zero.prime_pow) 910 return ans 911 912 def section(self): 913 """ 914 Returns a map back to ZZ that approximates an element of Zp by an integer. 915 916 EXAMPLES:: 917 918 sage: f = ZpCA(5).coerce_map_from(ZZ).section() 919 sage: f(ZpCA(5)(-1)) - 5^20 920 -1 921 """ 922 return self._section 923 924 cdef class pAdicConvert_CA_ZZ(RingMap): 925 """ 926 The map from a capped absolute ring back to ZZ that returns the the smallest non-negative integer 927 approximation to its input which is accurate up to the precision. 928 929 If the input is not in the closure of the image of ZZ, raises a ValueError. 930 931 EXAMPLES:: 932 933 sage: f = ZpCA(5).coerce_map_from(ZZ).section(); f 934 Set-theoretic ring morphism: 935 From: 5-adic Ring with capped absolute precision 20 936 To: Integer Ring 937 """ 938 def __init__(self, R): 939 """ 940 Initialization. 941 942 EXAMPLES:: 943 944 sage: f = ZpCA(5).coerce_map_from(ZZ).section(); type(f) 945 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicConvert_CA_ZZ'> 946 sage: f.category() 947 Category of hom sets in Category of sets 948 """ 949 if R.degree() > 1 or R.characteristic() != 0 or R.residue_characteristic() == 0: 950 RingMap.__init__(self, Hom(R, ZZ, SetsWithPartialMaps())) 951 else: 952 RingMap.__init__(self, Hom(R, ZZ, Sets())) 953 954 cpdef Element _call_(self, _x): 955 """ 956 Evaluation. 957 958 EXAMPLES:: 959 960 sage: f = ZpCA(5).coerce_map_from(ZZ).section() 961 sage: f(ZpCA(5)(-1)) - 5^20 962 -1 963 sage: f(ZpCA(5)(0)) 964 0 965 """ 966 cdef Integer ans = PY_NEW(Integer) 967 cdef CAElement x = <CAElement>_x 968 cconv_mpzt_out(ans.value, x.value, 0, x.absprec, x.prime_pow) 969 return ans 970 971 cdef class pAdicConvert_QQ_CA(Morphism): 972 """ 973 The inclusion map from QQ to a capped absolute ring that is defined 974 on all elements with non-negative p-adic valuation. 975 976 EXAMPLES:: 977 978 sage: f = ZpCA(5).convert_map_from(QQ); f 979 Generic morphism: 980 From: Rational Field 981 To: 5-adic Ring with capped absolute precision 20 982 """ 983 def __init__(self, R): 984 """ 985 Initialization. 986 987 EXAMPLES:: 988 989 sage: f = ZpCA(5).convert_map_from(QQ); type(f) 990 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicConvert_QQ_CA'> 991 """ 992 Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) 993 self._zero = R._element_constructor(R, 0) 994 995 cpdef Element _call_(self, x): 996 """ 997 Evaluation. 998 999 EXAMPLES:: 1000 1001 sage: f = ZpCA(5,4).convert_map_from(QQ) 1002 sage: f(1/7) 1003 3 + 3*5 + 2*5^3 + O(5^4) 1004 sage: f(0) 1005 O(5^4) 1006 """ 1007 if mpq_sgn((<Rational>x).value) == 0: 1008 return self._zero 1009 cdef CAElement ans = self._zero._new_c() 1010 cconv_mpqt(ans.value, (<Rational>x).value, ans.prime_pow.prec_cap, True, ans.prime_pow) 1011 ans.absprec = ans.prime_pow.prec_cap 1012 return ans 1013 1014 cpdef Element _call_with_args(self, x, args=(), kwds={}): 1015 """ 1016 This function is used when some precision cap is passed in (relative or absolute or both). 1017 1018 See the documentation for pAdicCappedAbsoluteElement.__init__ for more details. 1019 1020 EXAMPLES:: 1021 1022 sage: R = ZpCA(5,4) 1023 sage: type(R(10/3,2)) 1024 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCappedAbsoluteElement'> 1025 sage: R(10/3,2) 1026 4*5 + O(5^2) 1027 sage: R(10/3,3,1) 1028 4*5 + O(5^2) 1029 sage: R(10/3,absprec=2) 1030 4*5 + O(5^2) 1031 sage: R(10/3,relprec=2) 1032 4*5 + 5^2 + O(5^3) 1033 sage: R(10/3,absprec=1) 1034 O(5) 1035 sage: R(10/3,empty=True) 1036 O(5^0) 1037 sage: R(3/100,relprec=3) 1038 Traceback (most recent call last): 1039 ... 1040 ValueError: p divides denominator 1041 """ 1042 cdef long val, aprec, rprec 1043 cdef CAElement ans 1044 _process_args_and_kwds(&aprec, &rprec, args, kwds, True, self._zero.prime_pow) 1045 if mpq_sgn((<Rational>x).value) == 0: 1046 if aprec >= self._zero.prime_pow.prec_cap: 1047 return self._zero 1048 ans = self._zero._new_c() 1049 csetzero(ans.value, ans.prime_pow) 1050 ans.absprec = aprec 1051 else: 1052 val = get_ordp(x, self._zero.prime_pow) 1053 ans = self._zero._new_c() 1054 if aprec <= val: 1055 csetzero(ans.value, ans.prime_pow) 1056 ans.absprec = aprec 1057 else: 1058 ans.absprec = min(aprec, val + rprec) 1059 cconv_mpqt(ans.value, (<Rational>x).value, ans.absprec, True, self._zero.prime_pow) 1060 return ans 1061 1062 def unpickle_cae_v2(cls, parent, value, absprec): 1063 cdef CAElement ans = PY_NEW(cls) 1064 ans._parent = parent 1065 ans.prime_pow = <PowComputer_class?>parent.prime_pow 1066 cconstruct(ans.value, ans.prime_pow) 1067 cunpickle(ans.value, value, ans.prime_pow) 1068 ans.absprec = absprec 1069 return ans -
new file sage/rings/padics/CA_template_header.pxi
diff --git a/sage/rings/padics/CA_template_header.pxi b/sage/rings/padics/CA_template_header.pxi new file mode 100644
- + 1 2 3 include "padic_template_element_header.pxi" 4 5 from sage.categories.morphism cimport Morphism 6 from sage.rings.morphism cimport RingHomomorphism_coercion, RingMap 7 8 cdef class CAElement(pAdicTemplateElement): 9 cdef celement value 10 cdef long absprec 11 12 cdef CAElement _new_c(self) 13 14 cdef class pAdicCoercion_ZZ_CA(RingHomomorphism_coercion): 15 cdef CAElement _zero 16 cdef RingMap _section 17 cdef class pAdicConvert_CA_ZZ(RingMap): 18 pass 19 cdef class pAdicConvert_QQ_CA(Morphism): 20 cdef CAElement _zero 21 cdef RingMap _section 22 # There should also be a pAdicConvert_CA_QQ for extension rings.... -
sage/rings/padics/padic_capped_absolute_element.pxd
diff --git a/sage/rings/padics/padic_capped_absolute_element.pxd b/sage/rings/padics/padic_capped_absolute_element.pxd
a b 1 1 include "../../ext/cdefs.pxi" 2 2 3 from sage.rings.padics.padic_base_generic_element cimport pAdicBaseGenericElement 4 from sage.structure.element cimport CommutativeRingElement, RingElement, ModuleElement, Element 5 from sage.rings.padics.pow_computer cimport PowComputer_class 6 from sage.rings.integer cimport Integer 7 from sage.rings.rational cimport Rational 3 ctypedef mpz_t celement 4 from sage.libs.pari.gen cimport gen as pari_gen 8 5 9 cdef class pAdicCappedAbsoluteElement(pAdicBaseGenericElement): 10 cdef mpz_t value 11 cdef unsigned long absprec 6 include "CA_template_header.pxi" 12 7 13 cdef pAdicCappedAbsoluteElement _new_c(self) 14 cpdef RingElement _invert_c_impl(self) 15 cpdef ModuleElement _neg_(self) 16 cdef pAdicCappedAbsoluteElement _lshift_c(pAdicCappedAbsoluteElement self, long shift) 17 cdef pAdicCappedAbsoluteElement _rshift_c(pAdicCappedAbsoluteElement self, long shift) 18 cdef object teichmuller_list(pAdicCappedAbsoluteElement self) 19 cpdef pAdicCappedAbsoluteElement unit_part(self) 20 cpdef Integer lift(self) 8 cdef class pAdicCappedAbsoluteElement(CAElement): 9 cdef lift_c(self) 10 cdef pari_gen _to_gen(self) -
sage/rings/padics/padic_capped_absolute_element.pyx
diff --git a/sage/rings/padics/padic_capped_absolute_element.pyx b/sage/rings/padics/padic_capped_absolute_element.pyx
a b 1 1 """ 2 `p`-Adic Capped Absolute Element 2 `p`-Adic Capped Absolute Elements 3 3 4 4 Elements of `p`-Adic Rings with Absolute Precision Cap 5 5 … … 11 11 """ 12 12 13 13 #***************************************************************************** 14 # Copyright (C) 2007 David Roe <roed@math.harvard.edu>15 # William Stein <wstein@gmail.com>14 # Copyright (C) 2007-2012 David Roe <roed.math@gmail.com> 15 # William Stein <wstein@gmail.com> 16 16 # 17 17 # Distributed under the terms of the GNU General Public License (GPL) 18 18 # 19 19 # http://www.gnu.org/licenses/ 20 20 #***************************************************************************** 21 21 22 include "../../libs/ntl/decl.pxi" 23 include "../../ext/gmp.pxi" 24 include "../../ext/interrupt.pxi" 25 include "../../ext/stdsage.pxi" 22 include "../../libs/linkages/padics/mpz.pxi" 23 include "CA_template.pxi" 26 24 27 cimport sage.rings.padics.padic_generic_element 25 from sage.libs.pari.gen cimport PariInstance 26 cdef PariInstance P = sage.libs.pari.all.pari 27 from sage.rings.finite_rings.integer_mod import Mod 28 28 29 cimport sage.rings.rational 30 cimport sage.rings.padics.pow_computer 31 from sage.rings.padics.pow_computer cimport PowComputer_base 32 from sage.rings.padics.padic_printing cimport pAdicPrinter_class 33 from sage.rings.padics.padic_generic_element cimport pAdicGenericElement 34 35 import sage.rings.padics.padic_generic_element 36 import sage.rings.finite_rings.integer_mod 37 import sage.libs.pari.gen 38 import sage.rings.integer 39 import sage.rings.rational 40 41 from sage.rings.infinity import infinity 42 from sage.rings.finite_rings.integer_mod import Mod 43 from sage.rings.padics.precision_error import PrecisionError 44 45 pari = sage.libs.pari.gen.pari 46 pari_gen = sage.libs.pari.gen.gen 47 PariError = sage.libs.pari.gen.PariError 48 49 cdef class pAdicCappedAbsoluteElement(pAdicBaseGenericElement): 50 def __init__(pAdicCappedAbsoluteElement self, parent, x, absprec=infinity, relprec = infinity, empty=False): 51 """ 52 EXAMPLES:: 29 cdef class pAdicCappedAbsoluteElement(CAElement): 30 """ 31 EXAMPLES:: 53 32 54 sage: R = ZpCA(3, 5) 55 sage: R(2) 56 2 + O(3^5) 57 sage: R(2, absprec=2) 58 2 + O(3^2) 59 sage: R(3, relprec=2) 60 3 + O(3^3) 61 sage: R(Qp(3)(10)) 62 1 + 3^2 + O(3^5) 63 sage: R(pari(6)) 64 2*3 + O(3^5) 65 sage: R(pari(1/2)) 66 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5) 67 sage: R(1/2) 68 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5) 69 sage: R(mod(-1, 3^7)) 70 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + O(3^5) 71 sage: R(mod(-1, 3^2)) 72 2 + 2*3 + O(3^2) 73 sage: R(3 + O(3^2)) 74 3 + O(3^2) 75 """ 76 mpz_init(self.value) 77 pAdicBaseGenericElement.__init__(self,parent) 78 if empty: 79 return 80 if absprec is infinity or absprec > parent.precision_cap(): 81 absprec = parent.precision_cap() 82 elif not PY_TYPE_CHECK(absprec, Integer): 83 absprec = Integer(absprec) 84 if relprec is not infinity and not PY_TYPE_CHECK(relprec, Integer): 85 relprec = Integer(relprec) 86 if PY_TYPE_CHECK(x, pAdicGenericElement): 87 if x.valuation() < 0: 88 raise ValueError, "element valuation cannot be negative." 89 if parent.prime() != x.parent().prime(): 90 raise TypeError, "Cannot coerce between p-adic parents with different primes" 91 #if isinstance(x, pAdicLazyElement): 92 # # We may be doing unnecessary precision increases here... 93 # if relprec is infinity: 94 # try: 95 # x.set_precision_absolute(absprec) 96 # except PrecisionError: 97 # pass 98 # else: 99 # try: 100 # x.set_precision_relative(relprec) 101 # except PrecisionError: 102 # try: 103 # x.set_precision_absolute(absprec) 104 # except PrecisionError: 105 # pass 106 cdef mpz_t modulus 107 cdef Integer tmp 108 cdef unsigned long k 109 if PY_TYPE_CHECK(x, pAdicBaseGenericElement): 110 self._set_from_Integer(x._integer_(), min(absprec, x.precision_absolute()), relprec) 111 return 112 elif isinstance(x, (int, long)): 113 x = Integer(x) 114 elif isinstance(x, pari_gen): 115 if x.type() == "t_PADIC": 116 if x.variable() != self.prime_pow.prime: 117 raise TypeError, "Cannot coerce a pari p-adic with the wrong prime." 118 absprec = min(Integer(x.padicprec(parent.prime())), absprec) 119 x = x.lift() 120 if x.type() == "t_INT": 121 x = Integer(x) 122 elif x.type() == "t_FRAC": 123 x = Rational(x) 124 else: 125 raise TypeError, "unsupported coercion from pari: only p-adics, integers and rationals allowed" 126 127 elif sage.rings.finite_rings.integer_mod.is_IntegerMod(x): 128 mpz_init_set(modulus, (<Integer>x.modulus()).value) 129 k = mpz_remove(modulus, modulus, self.prime_pow.prime.value) 130 if mpz_cmp_ui(modulus, 1) == 0: 131 if mpz_cmp_ui((<Integer>absprec).value, k) > 0: 132 absprec = PY_NEW(Integer) 133 mpz_set_ui((<Integer>absprec).value, k) 134 x = x.lift() 135 mpz_clear(modulus) 136 else: 137 mpz_clear(modulus) 138 raise TypeError, "cannot coerce from the given integer mod ring (not a power of the same prime)" 139 if PY_TYPE_CHECK(x, Integer): 140 self._set_from_Integer(x, absprec, relprec) 141 return 142 if PY_TYPE_CHECK(x, Rational): 143 self._set_from_Rational(x, absprec, relprec) 144 return 145 self._set_from_Rational(Rational(x), absprec, relprec) 146 147 def __dealloc__(self): 148 """ 149 Deallocation. 150 151 TESTS:: 152 153 sage: R = ZpCA(5) 154 sage: a = R(17) 155 sage: del(a) 156 """ 157 mpz_clear(self.value) 158 159 def __reduce__(self): 160 """ 161 Pickling. 162 163 TESTS:: 164 165 sage: a = ZpCA(5)(-3) 166 sage: type(a) 167 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCappedAbsoluteElement'> 168 sage: loads(dumps(a)) == a 169 True 170 """ 171 return make_pAdicCappedAbsoluteElement, (self.parent(), self.lift(), self.absprec) 172 173 cdef bint _set_prec_abs(self, long absprec) except -1: 174 """ 175 Sets ``self.absprec``. 176 177 TESTS:: 178 179 sage: R = ZpCA(5) 180 sage: a = R(17,5); a #indirect doctest 181 2 + 3*5 + O(5^5) 182 """ 183 self.absprec = absprec 184 185 cdef bint _set_prec_both(self, long absprec, long relprec) except -1: 186 """ 187 Sets ``self.absprec``. 188 189 TESTS:: 190 191 sage: R = ZpCA(5) 192 sage: a = R(75, absprec = 5, relprec = 4); a #indirect doctest 193 3*5^2 + O(5^5) 194 """ 195 self.absprec = absprec 196 cdef long ordp 197 if relprec < absprec: 198 ordp = self.valuation_c() 199 if ordp + relprec < absprec: 200 self.absprec = ordp + relprec 201 202 cdef int _set_from_Integer(pAdicCappedAbsoluteElement self, Integer x, absprec, relprec) except -1: 203 """ 204 Set ``self.value`` and ``self.absprec``. 205 206 ``absprec`` must be positive. 207 208 TESTS:: 209 210 sage: R = ZpCA(5) 211 sage: a = R(75, absprec = 5, relprec = 4); a #indirect doctest 212 3*5^2 + O(5^5) 213 """ 214 if relprec is not infinity and mpz_sgn((<Integer>relprec).value) == -1: 215 raise ValueError, "relprec must be positive" 216 if absprec is not infinity and mpz_sgn((<Integer>absprec).value) == -1: 217 raise ValueError, "absprec must be positive" 218 if relprec is infinity or mpz_fits_ulong_p((<Integer>relprec).value) == 0: 219 if absprec is infinity or mpz_cmp_ui((<Integer>absprec).value, self.prime_pow.prec_cap) >= 0: 220 return self._set_from_mpz_abs(x.value, self.prime_pow.prec_cap) 221 else: 222 return self._set_from_mpz_abs(x.value, mpz_get_si((<Integer>absprec).value)) 223 else: 224 if absprec is infinity or mpz_cmp_ui((<Integer>absprec).value, self.prime_pow.prec_cap) >= 0: 225 return self._set_from_mpz_both(x.value, self.prime_pow.prec_cap, mpz_get_si((<Integer>relprec).value)) 226 else: 227 return self._set_from_mpz_both(x.value, mpz_get_si((<Integer>absprec).value), mpz_get_si((<Integer>relprec).value)) 228 229 cdef int _set_from_Rational(pAdicCappedAbsoluteElement self, Rational x, absprec, relprec) except -1: 230 """ 231 Set ``self.value`` and ``self.absprec``. 232 ``absprec`` must be positive. 233 234 TESTS:: 235 236 sage: R = ZpCA(5) 237 sage: a = R(25/9, absprec = 5, relprec = 4); a #indirect doctest 238 4*5^2 + 2*5^3 + O(5^5) 239 """ 240 if relprec is not infinity and mpz_sgn((<Integer>relprec).value) == -1: 241 raise ValueError, "relprec must be positive" 242 if absprec is not infinity and mpz_sgn((<Integer>absprec).value) == -1: 243 raise ValueError, "absprec must be positive" 244 if relprec is infinity or mpz_fits_ulong_p((<Integer>relprec).value) == 0: 245 if absprec is infinity or mpz_cmp_ui((<Integer>absprec).value, self.prime_pow.prec_cap) >= 0: 246 return self._set_from_mpq_abs(x.value, self.prime_pow.prec_cap) 247 else: 248 return self._set_from_mpq_abs(x.value, mpz_get_si((<Integer>absprec).value)) 249 else: 250 if absprec is infinity or mpz_cmp_ui((<Integer>absprec).value, self.prime_pow.prec_cap) >= 0: 251 return self._set_from_mpq_both(x.value, self.prime_pow.prec_cap, mpz_get_si((<Integer>relprec).value)) 252 else: 253 return self._set_from_mpq_both(x.value, mpz_get_si((<Integer>absprec).value), mpz_get_si((<Integer>relprec).value)) 254 255 cdef int _set_from_mpz_abs(self, mpz_t x, long absprec) except -1: 256 """ 257 ``self.prime_pow`` must already be set. 258 259 TESTS:: 260 261 sage: R = ZpCA(5) 262 sage: a = R(17,5); a #indirect doctest 263 2 + 3*5 + O(5^5) 264 """ 265 self._set_prec_abs(absprec) 266 if mpz_sgn(x) == -1 or mpz_cmp(x, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0]) >= 0: 267 sig_on() 268 mpz_mod(self.value, x, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0]) 269 sig_off() 270 else: 271 mpz_set(self.value, x) 272 return 0 273 274 cdef int _set_from_mpz_both(self, mpz_t x, long absprec, long relprec) except -1: 275 """ 276 ``self.prime_pow`` must already be set 277 278 TESTS:: 279 280 sage: R = ZpCA(5) 281 sage: a = R(75, absprec = 5, relprec = 4); a #indirect doctest 282 3*5^2 + O(5^5) 283 """ 284 if mpz_sgn(x) == 0: 285 mpz_set(self.value, x) 286 return 0 287 mpz_set(self.value, x) 288 self._set_prec_both(absprec, relprec) 289 if mpz_sgn(x) == -1 or mpz_cmp(x, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0]) >= 0: 290 sig_on() 291 mpz_mod(self.value, x, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0]) 292 sig_off() 293 return 0 294 295 cdef int _set_from_mpq_abs(self, mpq_t x, long absprec) except -1: 296 """ 297 ``self.prime_pow`` must already be set. 298 299 TESTS:: 300 301 sage: R = ZpCA(5) 302 sage: a = R(25/9, absprec = 5); a #indirect doctest 303 4*5^2 + 2*5^3 + O(5^5) 304 """ 305 self._set_prec_abs(absprec) 306 if mpz_divisible_p(mpq_denref(x), self.prime_pow.prime.value): 307 raise ValueError, "p divides denominator" 308 sig_on() 309 mpz_invert(self.value, mpq_denref(x), self.prime_pow.pow_mpz_t_tmp(absprec)[0]) 310 mpz_mul(self.value, self.value, mpq_numref(x)) 311 mpz_mod(self.value, self.value, self.prime_pow.pow_mpz_t_tmp(absprec)[0]) 312 sig_off() 313 return 0 314 315 cdef int _set_from_mpq_both(self, mpq_t x, long absprec, long relprec) except -1: 316 """ 317 ``self.prime_pow`` must already be set 318 319 TESTS:: 320 321 sage: R = ZpCA(5) 322 sage: a = R(25/9, absprec = 5, relprec = 4); a #indirect doctest 323 4*5^2 + 2*5^3 + O(5^5) 324 """ 325 cdef long k 326 cdef mpz_t tmp 327 if mpq_sgn(x) == 0: 328 mpz_set_ui(self.value, 0) 329 return 0 330 mpz_init(tmp) 331 sig_on() 332 k = mpz_remove(tmp, mpq_numref(x), self.prime_pow.prime.value) 333 sig_off() 334 mpz_clear(tmp) 335 self.absprec = k + relprec 336 if self.absprec > absprec: 337 self.absprec = absprec 338 return self._set_from_mpq_abs(x, self.absprec) 339 340 cdef int _set_mpz_into(pAdicCappedAbsoluteElement self, mpz_t dest) except -1: 341 """ 342 Sets ``dest`` to a lift of ``self``. 343 344 TESTS:: 345 346 sage: R = ZpCA(5); S.<a> = ZqCA(25) 347 sage: S(R(17)) 348 2 + 3*5 + O(5^20) 349 """ 350 mpz_set(dest, self.value) 351 return 0 352 353 cdef int _set_mpq_into(pAdicCappedAbsoluteElement self, mpq_t dest) except -1: 354 """ 355 Sets ``dest`` to a lift of ``self``. 356 357 Not currently used internally. 358 """ 359 mpq_set_z(dest, self.value) 360 return 0 361 362 cdef pAdicCappedAbsoluteElement _new_c(self): 363 """ 364 Creates a new element with the same basic info. 365 366 TESTS:: 367 368 sage: R = ZpCA(5); R(6,5) * R(7,8) #indirect doctest 369 2 + 3*5 + 5^2 + O(5^5) 370 """ 371 cdef pAdicCappedAbsoluteElement x 372 x = PY_NEW(pAdicCappedAbsoluteElement) 373 x._parent = self._parent 374 x.prime_pow = self.prime_pow 375 mpz_init(x.value) 376 return x 377 378 cpdef bint _is_inexact_zero(self) except -1: 379 """ 380 Returns ``True`` if ``self`` is indistinguishable from zero. 381 382 EXAMPLES:: 383 384 sage: R = ZpCA(7, 5) 385 sage: R(7^5)._is_inexact_zero() 386 True 387 sage: R(0,4)._is_inexact_zero() 388 True 389 sage: R(0)._is_inexact_zero() 390 True 391 """ 392 return mpz_sgn(self.value) == 0 393 394 def __richcmp__(left, right, op): 395 """ 396 Comparison. 397 398 TESTS:: 399 400 sage: R = ZpCA(5) 401 sage: a = R(17) 402 sage: b = R(21) 403 sage: a == b 404 False 405 sage: a < b 406 True 407 """ 408 return (<Element>left)._richcmp(right, op) 409 410 def __invert__(self): 411 """ 412 Returns the multiplicative inverse of ``self``. 413 414 EXAMPLES:: 415 416 sage: R = ZpCA(17) 417 sage: ~R(-1) == R(-1) 418 True 419 sage: ~R(5) * 5 420 1 + O(17^20) 421 sage: ~R(5) 422 7 + 3*17 + 10*17^2 + 13*17^3 + 6*17^4 + 3*17^5 + 10*17^6 + 13*17^7 + 6*17^8 + 3*17^9 + 10*17^10 + 13*17^11 + 6*17^12 + 3*17^13 + 10*17^14 + 13*17^15 + 6*17^16 + 3*17^17 + 10*17^18 + 13*17^19 + O(17^20) 423 """ 424 return self._invert_c_impl() 425 426 cpdef RingElement _invert_c_impl(self): 427 """ 428 Returns the multiplicative inverse of ``self``. 429 430 EXAMPLES:: 431 432 sage: R = ZpCA(17) 433 sage: ~R(-1) == R(-1) #indirect doctest 434 True 435 """ 436 return self.parent().fraction_field()(self).__invert__() 437 438 cpdef ModuleElement _neg_(self): 439 """ 440 Returns the negation of self. 441 442 EXAMPLES:: 443 444 sage: R = Zp(5, prec=10, type='capped-abs') 445 sage: a = R(1) 446 sage: -a #indirect doctest 447 4 + 4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + 4*5^6 + 4*5^7 + 4*5^8 + 4*5^9 + O(5^10) 448 """ 449 if mpz_sgn(self.value) == 0: 450 return self 451 cdef pAdicCappedAbsoluteElement ans 452 ans = self._new_c() 453 ans.absprec = self.absprec 454 mpz_sub(ans.value, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0], self.value) 455 return ans 456 457 def __pow__(pAdicCappedAbsoluteElement self, right, dummy): 458 """ 459 Exponentiation. 460 461 EXAMPLES:: 462 463 sage: R = ZpCA(11, 5) 464 sage: R(1/2)^5 465 10 + 7*11 + 11^2 + 5*11^3 + 4*11^4 + O(11^5) 466 sage: R(1/32) 467 10 + 7*11 + 11^2 + 5*11^3 + 4*11^4 + O(11^5) 468 sage: R(1/2)^5 == R(1/32) 469 True 470 sage: R(3)^1000 471 1 + 4*11^2 + 3*11^3 + 7*11^4 + O(11^5) 472 """ 473 # p-adic exponents and correct precisions!!! 474 if not self and not right: 475 raise ArithmeticError, "0^0 is undefined." 476 cdef Integer new, absprec 477 cdef long val 478 new = Integer(right) #Need to make sure that this works for p-adic exponents 479 val = self.valuation_c() 480 if (val > 0) and isinstance(right, pAdicBaseGenericElement): 481 raise ValueError, "Can only have p-adic exponent if base is a unit" 482 if (new < 0): 483 return (~self).__pow__(-new) 484 cdef pAdicCappedAbsoluteElement ans 485 cdef Integer preccap 486 preccap = <Integer>self.parent().precision_cap() 487 ans = self._new_c() 488 if val > 0: 489 if new * val >= preccap: 490 ans._set_from_Integer(Integer(0), preccap, infinity) 491 else: 492 absprec = <Integer> min(self.precision_relative() + new * val, preccap) 493 ans._set_prec_abs(mpz_get_ui(absprec.value)) 494 sig_on() 495 mpz_powm(ans.value, self.value, new.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) 496 sig_off() 497 else: 498 ans.absprec = self.absprec 499 sig_on() 500 mpz_powm(ans.value, self.value, new.value, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0]) 501 sig_off() 502 return ans 503 504 cpdef ModuleElement _add_(self, ModuleElement _right): 505 """ 506 Addition. 507 508 EXAMPLES:: 509 510 sage: R = ZpCA(13, 4) 511 sage: R(2) + R(3) #indirect doctest 512 5 + O(13^4) 513 sage: R(12) + R(1) 514 13 + O(13^4) 515 """ 516 cdef pAdicCappedAbsoluteElement ans 517 cdef pAdicCappedAbsoluteElement right = <pAdicCappedAbsoluteElement> _right 518 ans = self._new_c() 519 if self.absprec < right.absprec: 520 ans.absprec = self.absprec 521 else: 522 ans.absprec = right.absprec 523 mpz_add(ans.value, self.value, right.value) 524 if mpz_cmp(ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) >= 0: 525 mpz_mod(ans.value, ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) 526 return ans 527 528 cpdef RingElement _div_(self, RingElement right): 529 """ 530 Division. 531 532 EXAMPLES:: 533 534 sage: R = ZpCA(13, 4) 535 sage: R(2) / R(3) # indirect doctest 536 5 + 4*13 + 4*13^2 + 4*13^3 + O(13^4) 537 sage: a = R(169 * 2) / R(13); a 538 2*13 + O(13^3) 539 sage: R(13) / R(169 * 2) 540 7*13^-1 + 6 + O(13) 541 sage: ~a 542 7*13^-1 + 6 + O(13) 543 sage: 1 / a 544 7*13^-1 + 6 + O(13) 545 """ 546 return self * (~right) 547 548 def __lshift__(pAdicCappedAbsoluteElement self, shift): 549 """ 550 Multiplies ``self`` by ``p^shift``. 551 552 If ``shift < -self.ordp()``, digits will be truncated. See 553 ``__rshift__`` for details. 554 555 EXAMPLES: 556 557 We create a capped absolute ring:: 558 559 sage: R = Zp(5, 20, 'capped-abs'); a = R(1000); a 560 3*5^3 + 5^4 + O(5^20) 561 562 Shifting to the right is the same as dividing by a power of 563 the uniformizer `p` of the `p`-adic ring.:: 564 565 sage: a >> 1 566 3*5^2 + 5^3 + O(5^19) 567 568 Shifting to the left is the same as multiplying by a power of 569 `p`:: 570 571 sage: a << 2 572 3*5^5 + 5^6 + O(5^20) 573 sage: a*5^2 574 3*5^5 + 5^6 + O(5^20) 575 576 Shifting by a negative integer to the left is the same as 577 right shifting by the absolute value:: 578 579 sage: a << -3 580 3 + 5 + O(5^17) 581 sage: a >> 3 582 3 + 5 + O(5^17) 583 """ 584 cdef pAdicCappedAbsoluteElement ans 585 if not PY_TYPE_CHECK(shift, Integer): 586 shift = Integer(shift) 587 if mpz_fits_slong_p((<Integer>shift).value) == 0: 588 ans = self._new_c() 589 mpz_set_ui(ans.value, 0) 590 if mpz_sgn((<Integer>shift).value) == 1: 591 ans._set_prec_abs(self.prime_pow.prec_cap) 592 else: 593 ans._set_prec_abs(0) 594 return ans 595 return self._lshift_c(mpz_get_si((<Integer>shift).value)) 596 597 cdef pAdicCappedAbsoluteElement _lshift_c(pAdicCappedAbsoluteElement self, long shift): 598 """ 599 Multiplies ``self`` by ``p^shift``. 600 601 If ``shift < -self.ordp()``, digits will be truncated. See 602 ``__rshift__`` for details. 603 604 EXAMPLES:: 605 606 sage: R = ZpCA(5); a = R(17); a << 2 607 2*5^2 + 3*5^3 + O(5^20) 608 """ 609 cdef unsigned long prec_cap, ansprec 610 cdef pAdicCappedAbsoluteElement ans 611 cdef PowComputer_class powerer 612 if shift < 0: 613 return self._rshift_c(-shift) 614 prec_cap = self.prime_pow.prec_cap 615 if shift >= prec_cap: # if we ever start caching valuation, this check should change 616 ans = self._new_c() 617 mpz_set_ui(ans.value, 0) 618 ans._set_prec_abs(prec_cap) 619 return ans 620 elif shift > 0: 621 ans = self._new_c() 622 ansprec = shift + self.absprec 623 if ansprec > prec_cap: 624 ansprec = prec_cap 625 ans._set_prec_abs(ansprec) 626 mpz_mul(ans.value, self.value, self.prime_pow.pow_mpz_t_tmp(shift)[0]) 627 if mpz_cmp(ans.value, ans.prime_pow.pow_mpz_t_top()[0]) >= 0: 628 mpz_mod(ans.value, ans.value, ans.prime_pow.pow_mpz_t_top()[0]) 629 return ans 630 else: 631 return self 632 633 def __rshift__(pAdicCappedAbsoluteElement self, shift): 634 """ 635 Divides by ``p^shift``, and truncates. 636 637 EXAMPLES:: 638 639 sage: R = Zp(997, 7, 'capped-abs'); a = R(123456878908); a 640 964*997 + 572*997^2 + 124*997^3 + O(997^7) 641 642 Shifting to the right divides by a power of `p`, but dropping 643 terms with negative valuation:: 644 645 sage: a >> 3 646 124 + O(997^4) 647 648 A negative shift multiplies by that power of `p`.:: 649 650 sage: a >> -3 651 964*997^4 + 572*997^5 + 124*997^6 + O(997^7) 652 """ 653 cdef pAdicCappedAbsoluteElement ans 654 if not PY_TYPE_CHECK(shift, Integer): 655 shift = Integer(shift) 656 if mpz_fits_slong_p((<Integer>shift).value) == 0: 657 ans = self._new_c() 658 mpz_set_ui(ans.value, 0) 659 if mpz_sgn((<Integer>shift).value) == -1: 660 ans._set_prec_abs(self.prime_pow.prec_cap) 661 else: 662 ans._set_prec_abs(0) 663 return ans 664 return self._rshift_c(mpz_get_si((<Integer>shift).value)) 665 666 cdef pAdicCappedAbsoluteElement _rshift_c(pAdicCappedAbsoluteElement self, long shift): 667 """ 668 Divides by ``p^shift`` and truncates. 669 670 EXAMPLES:: 671 672 sage: R = ZpCA(5); a = R(77); a >> 1 673 3*5 + O(5^19) 674 """ 675 cdef unsigned long prec_cap, ansprec 676 cdef pAdicCappedAbsoluteElement ans 677 if shift < 0: 678 return self._lshift_c(-shift) 679 prec_cap = self.prime_pow.prec_cap 680 if shift >= self.absprec: 681 ans = self._new_c() 682 mpz_set_ui(ans.value, 0) 683 ans._set_prec_abs(0) 684 return ans 685 elif shift > 0: 686 ans = self._new_c() 687 ansprec = self.absprec - shift 688 ans._set_prec_abs(ansprec) 689 mpz_fdiv_q(ans.value, self.value, self.prime_pow.pow_mpz_t_tmp(shift)[0]) 690 return ans 691 else: 692 return self 693 694 cpdef RingElement _mul_(self, RingElement _right): 695 """ 696 Multiplication. 697 698 EXAMPLES:: 699 700 sage: R = ZpCA(5) 701 sage: a = R(20,5); b = R(75, 4); a * b #indirect doctest 702 2*5^3 + 2*5^4 + O(5^5) 703 """ 704 cdef pAdicCappedAbsoluteElement ans 705 cdef pAdicCappedAbsoluteElement right = <pAdicCappedAbsoluteElement> _right 706 cdef unsigned long sval, rval, prec1, prec2, prec_cap 707 ans = self._new_c() 708 prec_cap = self.prime_pow.prec_cap 709 sval = self.valuation_c() 710 rval = right.valuation_c() 711 prec1 = sval + right.absprec 712 prec2 = rval + self.absprec 713 if prec1 < prec2: 714 if prec_cap < prec1: 715 ans._set_prec_abs(prec_cap) 716 else: 717 ans._set_prec_abs(prec1) 718 else: 719 if prec_cap < prec2: 720 ans._set_prec_abs(prec_cap) 721 else: 722 ans._set_prec_abs(prec2) 723 mpz_mul(ans.value, self.value, right.value) 724 mpz_mod(ans.value, ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) 725 return ans 726 727 cpdef ModuleElement _sub_(self, ModuleElement _right): 728 """ 729 Subtraction. 730 731 EXAMPLES:: 732 733 sage: R = ZpCA(13, 4) 734 sage: R(10) - R(10) #indirect doctest 735 O(13^4) 736 sage: R(10) - R(11) 737 12 + 12*13 + 12*13^2 + 12*13^3 + O(13^4) 738 """ 739 cdef pAdicCappedAbsoluteElement ans 740 cdef pAdicCappedAbsoluteElement right = <pAdicCappedAbsoluteElement> _right 741 ans = self._new_c() 742 if self.absprec < right.absprec: 743 ans.absprec = self.absprec 744 else: 745 ans.absprec = right.absprec 746 mpz_sub(ans.value, self.value, right.value) 747 if mpz_sgn(ans.value) == -1 or mpz_cmp(ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) >= 0: 748 mpz_mod(ans.value, ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) 749 return ans 750 751 def add_bigoh(pAdicCappedAbsoluteElement self, absprec): 752 """ 753 Returns a new element with absolute precision decreased to 754 ``prec``. The precision never increases. 755 756 INPUT: 757 758 - ``self`` -- a `p`-adic element 759 760 - ``prec`` -- an integer 761 762 OUTPUT: 763 764 - ``element`` -- ``self`` with precision set to the minimum of ``self's`` precision and ``prec`` 765 766 EXAMPLES:: 767 768 sage: R = Zp(7,4,'capped-abs','series'); a = R(8); a.add_bigoh(1) 769 1 + O(7) 770 771 sage: k = ZpCA(3,5) 772 sage: a = k(41); a 773 2 + 3 + 3^2 + 3^3 + O(3^5) 774 sage: a.add_bigoh(7) 775 2 + 3 + 3^2 + 3^3 + O(3^5) 776 sage: a.add_bigoh(3) 777 2 + 3 + 3^2 + O(3^3) 778 """ 779 cdef pAdicCappedAbsoluteElement ans 780 cdef unsigned long newprec 781 cdef Integer _absprec 782 if not PY_TYPE_CHECK(absprec, Integer): 783 _absprec = Integer(absprec) 784 else: 785 _absprec = <Integer>absprec 786 if mpz_fits_ulong_p(_absprec.value) == 0: 787 if mpz_sgn((<Integer>absprec).value) == -1: 788 ans = self._new_c() 789 ans._set_prec_abs(0) 790 mpz_set_ui(ans.value, 0) 791 return ans 792 else: 793 return self 794 newprec = mpz_get_ui(_absprec.value) 795 if newprec >= self.absprec: 796 return self 797 elif newprec <= 0: 798 ans = self._new_c() 799 ans._set_prec_abs(0) 800 mpz_set_ui(ans.value, 0) 801 return ans 802 else: 803 ans = self._new_c() 804 ans._set_prec_abs(newprec) 805 mpz_set(ans.value, self.value) 806 if mpz_cmp(ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) >= 0: 807 mpz_mod(ans.value, ans.value, self.prime_pow.pow_mpz_t_tmp(ans.absprec)[0]) 808 return ans 809 810 def __copy__(pAdicCappedAbsoluteElement self): 811 """ 812 Returns a copy of ``self``. 813 814 EXAMPLES:: 815 816 sage: a = ZpCA(5,6)(17); b = copy(a) 817 sage: a == b 818 True 819 sage: a is b 820 False 821 """ 822 cdef pAdicCappedAbsoluteElement ans 823 ans = self._new_c() 824 ans.absprec = self.absprec 825 mpz_set(ans.value, self.value) 826 return ans 827 828 def is_zero(self, absprec = None): 829 r""" 830 Returns whether ``self`` is zero modulo ``p^absprec``. 831 832 INPUT: 833 834 - ``self`` -- a `p`-adic element 835 836 - ``prec`` -- an integer 837 838 OUTPUT: 839 840 - ``boolean`` -- whether self is zero 841 842 EXAMPLES:: 843 844 sage: R = ZpCA(17, 6) 845 sage: R(0).is_zero() 846 True 847 sage: R(17^6).is_zero() 848 True 849 sage: R(17^2).is_zero(absprec=2) 850 True 851 """ 852 if absprec is None: 853 return mpz_sgn(self.value) == 0 854 cdef Integer _absprec 855 if not PY_TYPE_CHECK(absprec, Integer): 856 _absprec = Integer(absprec) 857 else: 858 _absprec = <Integer>absprec 859 if mpz_cmp_ui(_absprec.value, self.absprec) > 0: 860 raise PrecisionError, "Not enough precision to determine if element is zero" 861 cdef mpz_t tmp 862 mpz_init(tmp) 863 cdef unsigned long aprec 864 aprec = mpz_get_ui(_absprec.value) 865 mpz_mod(tmp, self.value, self.prime_pow.pow_mpz_t_tmp(aprec)[0]) 866 if mpz_sgn(tmp) == 0: 867 mpz_clear(tmp) 868 return True 869 else: 870 mpz_clear(tmp) 871 return False 872 873 def is_equal_to(pAdicCappedAbsoluteElement self, pAdicCappedAbsoluteElement right, absprec = None): 874 r""" 875 Returns whether ``self`` is equal to ``right`` modulo ``p^absprec``. 876 877 INPUT: 878 879 - ``self`` -- a `p`-adic element 880 881 - ``right`` -- a `p`-adic element with the same parent 882 883 - ``absprec`` -- an integer 884 885 OUTPUT: 886 887 - ``boolean`` -- whether ``self`` is equal to ``right`` 888 889 EXAMPLES:: 890 891 sage: R = ZpCA(2, 6) 892 sage: R(13).is_equal_to(R(13)) 893 True 894 sage: R(13).is_equal_to(R(13+2^10)) 895 True 896 sage: R(13).is_equal_to(R(17), 2) 897 True 898 sage: R(13).is_equal_to(R(17), 5) 899 False 900 """ 901 cdef unsigned long aprec 902 if absprec is None: 903 if self.absprec < right.absprec: 904 aprec = self.absprec 905 else: 906 aprec = right.absprec 907 else: 908 if not PY_TYPE_CHECK(absprec, Integer): 909 absprec = Integer(absprec) 910 if mpz_fits_slong_p((<Integer>absprec).value) == 0: 911 if mpz_sgn((<Integer>absprec).value) == 1: 912 raise PrecisionError, "Elements are not known to specified precision" 913 else: 914 return True 915 aprec = mpz_get_ui((<Integer>absprec).value) 916 if aprec > self.absprec or aprec > right.absprec: 917 raise PrecisionError, "Elements are not known to specified precision" 918 cdef mpz_t tmp1, tmp2 919 mpz_init(tmp1) 920 mpz_init(tmp2) 921 mpz_mod(tmp1, self.value, self.prime_pow.pow_mpz_t_tmp(aprec)[0]) 922 mpz_mod(tmp2, (right).value, self.prime_pow.pow_mpz_t_tmp(aprec)[0]) 923 if mpz_cmp(tmp1, tmp2) == 0: 924 mpz_clear(tmp1) 925 mpz_clear(tmp2) 926 return True 927 else: 928 mpz_clear(tmp1) 929 mpz_clear(tmp2) 930 return False 931 932 cpdef Integer lift(self): 33 sage: R = ZpCA(3, 5) 34 sage: R(2) 35 2 + O(3^5) 36 sage: R(2, absprec=2) 37 2 + O(3^2) 38 sage: R(3, relprec=2) 39 3 + O(3^3) 40 sage: R(Qp(3)(10)) 41 1 + 3^2 + O(3^5) 42 sage: R(pari(6)) 43 2*3 + O(3^5) 44 sage: R(pari(1/2)) 45 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5) 46 sage: R(1/2) 47 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5) 48 sage: R(mod(-1, 3^7)) 49 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + O(3^5) 50 sage: R(mod(-1, 3^2)) 51 2 + 2*3 + O(3^2) 52 sage: R(3 + O(3^2)) 53 3 + O(3^2) 54 """ 55 def lift(self): 933 56 """ 934 57 Returns an integer congruent to this `p`-adic element modulo 935 58 ``p^self.absprec()``. … … 942 65 sage: R(-1).lift() 943 66 3486784400 944 67 """ 945 cdef Integer ans 946 ans = PY_NEW(Integer) 68 return self.lift_c() 69 70 cdef lift_c(self): 71 """ 72 Implementation of lift 73 74 TESTS:: 75 76 sage: ZpCA(3,3)(1/4).lift() # indirect doctest 77 7 78 """ 79 cdef Integer ans = PY_NEW(Integer) 947 80 mpz_set(ans.value, self.value) 948 81 return ans 949 82 950 def lift_to_precision(self, absprec):83 def _pari_(self): 951 84 """ 952 Returns a `p`-adic integer congruent to this `p`-adic element 953 modulo ``p^absprec`` with precision at least ``absprec``. 85 Conversion to pari. 954 86 955 If such lifting would yield an element with precision greater 956 than allowed by the precision cap of ``self``'s parent, an 957 error is raised. 958 87 EXAMPLES:: 88 89 sage: R = ZpCA(5) 90 sage: pari(R(1777)) #indirect doctest 91 2 + 5^2 + 4*5^3 + 2*5^4 + O(5^20) 92 sage: pari(R(0,0)) 93 O(5^0) 94 """ 95 return self._to_gen() 96 97 cdef pari_gen _to_gen(self): 98 """ 99 Converts this element to an equivalent pari element. 100 959 101 EXAMPLES:: 960 102 961 sage: R = ZpCA(17) 962 sage: R(-1,2).lift_to_precision(10) 963 16 + 16*17 + O(17^10) 964 sage: R(1,15).lift_to_precision(10) 965 1 + O(17^15) 966 sage: R(1,15).lift_to_precision(30) 967 Traceback (most recent call last): 968 ... 969 PrecisionError: Precision higher than allowed by the precision cap. 103 sage: R = Zp(5, 10); a = R(17); pari(a) #indirect doctest 104 2 + 3*5 + O(5^10) 105 sage: pari(R(0)) 106 0 107 sage: pari(R(0,5)) 108 O(5^5) 970 109 """ 971 cdef pAdicCappedAbsoluteElement ans 972 cdef unsigned long prec_cap 973 cdef unsigned long dest_prec 974 prec_cap = self.prime_pow.prec_cap 975 if not PY_TYPE_CHECK(absprec, Integer): 976 absprec = Integer(absprec) 977 if mpz_fits_ulong_p((<Integer>absprec).value) == 0: 978 ans = self._new_c() 979 ans._set_prec_abs(prec_cap) 980 mpz_set(ans.value, self.value) 981 else: 982 dest_prec = mpz_get_ui((<Integer>absprec).value) 983 if prec_cap < dest_prec: 984 raise PrecisionError, "Precision higher than allowed by the precision cap." 985 if dest_prec <= self.absprec: 986 return self 987 else: 988 ans = self._new_c() 989 ans._set_prec_abs(dest_prec) 990 mpz_set(ans.value, self.value) 991 return ans 110 # holder is defined in the linkage file 111 cdef long val = mpz_remove(holder.value, self.value, self.prime_pow.prime.value) 112 return P.new_gen_from_padic(val, self.absprec - val, 113 self.prime_pow.prime.value, 114 self.prime_pow.pow_mpz_t_tmp(self.absprec - val)[0], 115 holder.value) 992 116 993 def list(pAdicCappedAbsoluteElement self, lift_mode = 'simple'): 117 def _integer_(self, Z=None): 118 r""" 119 Converts self to an integer 120 121 TESTS:: 122 123 sage: R = ZpCA(5, prec = 4); a = R(642); a 124 2 + 3*5 + O(5^4) 125 sage: a._integer_() 126 17 994 127 """ 995 Returns a list of coefficients of `p` starting with `p^0` 996 128 return self.lift_c() 129 130 def residue(self, absprec=1): 131 r""" 132 Reduces ``self`` modulo ``p^absprec`` 133 997 134 INPUT: 998 135 999 136 - ``self`` -- a `p`-adic element 1000 137 1001 - ``lift_mode`` -- ``'simple'``, ``'smallest'`` or 1002 ``'teichmuller'`` (default ``'simple'``) 1003 138 - ``absprec`` - an integer 139 1004 140 OUTPUT: 1005 141 1006 - ``list`` -- the list of coefficients of ``self`` 1007 1008 NOTES: 1009 1010 - Returns a list `[a_0, a_1, \ldots, a_n]` so that: 1011 1012 + If ``lift_mode = 'simple'``, `a_i` is an integer with `0 1013 \le a_i < p`. 1014 1015 + If ``lift_mode = 'smallest'``, `a_i` is an integer with 1016 `-p/2 < a_i \le p/2`. 1017 1018 + If ``lift_mode = 'teichmuller'``, `a_i` has the same 1019 parent as `self` and `a_i^p \equiv a_i` modulo 1020 ``p^(self.precision_absolute() - i)`` 1021 1022 - `\sum_{i = 0}^n a_i \cdot p^i =` ``self``, modulo the 1023 precision of ``self``. 1024 142 - element of `\mathbb{Z}/p^{\mbox{absprec}} \mathbb{Z}` -- 143 ``self`` reduced modulo ``p^absprec``. 1025 144 1026 145 EXAMPLES:: 1027 146 1028 sage: R = ZpCA(7,6); a = R(12837162817); a 1029 3 + 4*7 + 4*7^2 + 4*7^4 + O(7^6) 1030 sage: L = a.list(); L 1031 [3, 4, 4, 0, 4] 1032 sage: sum([L[i] * 7^i for i in range(len(L))]) == a 1033 True 1034 sage: L = a.list('smallest'); L 1035 [3, -3, -2, 1, -3, 1] 1036 sage: sum([L[i] * 7^i for i in range(len(L))]) == a 1037 True 1038 sage: L = a.list('teichmuller'); L 1039 [3 + 4*7 + 6*7^2 + 3*7^3 + 2*7^5 + O(7^6), 1040 O(7^5), 1041 5 + 2*7 + 3*7^3 + O(7^4), 1042 1 + O(7^3), 1043 3 + 4*7 + O(7^2), 1044 5 + O(7)] 1045 sage: sum([L[i] * 7^i for i in range(len(L))]) 1046 3 + 4*7 + 4*7^2 + 4*7^4 + O(7^6) 147 sage: R = Zp(7,4,'capped-abs'); a = R(8); a.residue(1) 148 1 1047 149 """ 1048 if lift_mode == 'teichmuller': 1049 return self.teichmuller_list() 1050 if lift_mode == 'simple': 1051 return (<pAdicPrinter_class>self.parent()._printer).base_p_list(self.value, True) 1052 elif lift_mode == 'smallest': 1053 return (<pAdicPrinter_class>self.parent()._printer).base_p_list(self.value, False) 1054 else: 1055 raise ValueError 1056 1057 cdef object teichmuller_list(pAdicCappedAbsoluteElement self): 1058 r""" 1059 Returns a list `[a_0, a_1,\ldots, a_n]` such that 1060 1061 - `a_i^p = a_i` 1062 1063 - ``self`` equals `\sum_{i = 0}^n a_i p^i` 1064 1065 - if `a_i \ne 0`, the absolute precision of `a_i` is 1066 ``self.precision_relative() - i`` 1067 1068 EXAMPLES:: 1069 1070 sage: R = ZpFM(5,5); R(14).list('teichmuller') #indirect doctest 1071 [4 + 4*5 + 4*5^2 + 4*5^3 + 4*5^4 + O(5^5), 1072 3 + 3*5 + 2*5^2 + 3*5^3 + 5^4 + O(5^5), 1073 2 + 5 + 2*5^2 + 5^3 + 3*5^4 + O(5^5), 1074 1 + O(5^5), 1075 4 + 4*5 + 4*5^2 + 4*5^3 + 4*5^4 + O(5^5)] 1076 """ 1077 # May eventually want to add a dict to store teichmuller lifts already seen, if p small enough 1078 cdef unsigned long curpower 1079 cdef mpz_t tmp, tmp2 1080 cdef pAdicCappedAbsoluteElement list_elt 1081 ans = PyList_New(0) 1082 curpower = self.absprec 1083 mpz_init_set(tmp, self.value) 1084 mpz_init(tmp2) 1085 while mpz_sgn(tmp) != 0: 1086 list_elt = self._new_c() 1087 list_elt._set_prec_abs(curpower) 1088 mpz_mod(list_elt.value, tmp, self.prime_pow.prime.value) 1089 mpz_set(tmp2, self.prime_pow.pow_mpz_t_tmp(curpower)[0]) 1090 self.teichmuller_set_c(list_elt.value, tmp2) 1091 mpz_sub(tmp, tmp, list_elt.value) 1092 mpz_divexact(tmp, tmp, self.prime_pow.prime.value) 1093 curpower -= 1 1094 mpz_mod(tmp, tmp, self.prime_pow.pow_mpz_t_tmp(curpower)[0]) 1095 PyList_Append(ans, list_elt) 1096 mpz_clear(tmp2) 1097 mpz_clear(tmp) 1098 return ans 1099 1100 def _teichmuller_set(self): 1101 """ 1102 Sets ``self`` to be the Teichmuller representative with the 1103 same residue as ``self``. 1104 1105 WARNING: 1106 1107 This function modifies ``self``, which is not safe. Elements 1108 are supposed to be immutable. 1109 1110 EXAMPLES:: 1111 1112 sage: R = ZpCA(17,5); a = R(11) 1113 sage: a 1114 11 + O(17^5) 1115 sage: a._teichmuller_set(); a 1116 11 + 14*17 + 2*17^2 + 12*17^3 + 15*17^4 + O(17^5) 1117 sage: a.list('teichmuller') 1118 [11 + 14*17 + 2*17^2 + 12*17^3 + 15*17^4 + O(17^5)] 1119 """ 1120 cdef mpz_t tmp 1121 mpz_init_set(tmp, self.prime_pow.pow_mpz_t_tmp(self.absprec)[0]) 1122 self.teichmuller_set_c(self.value, tmp) 1123 mpz_clear(tmp) 150 cdef Integer selfvalue, modulus 151 if not PY_TYPE_CHECK(absprec, Integer): 152 absprec = Integer(absprec) 153 if mpz_cmp_si((<Integer>absprec).value, self.absprec) > 0: 154 raise PrecisionError, "Not enough precision known in order to compute residue." 155 elif mpz_sgn((<Integer>absprec).value) < 0: 156 raise ValueError, "cannot reduce modulo a negative power of p" 157 cdef long aprec = mpz_get_ui((<Integer>absprec).value) 158 modulus = PY_NEW(Integer) 159 mpz_set(modulus.value, self.prime_pow.pow_mpz_t_tmp(aprec)[0]) 160 selfvalue = PY_NEW(Integer) 161 mpz_set(selfvalue.value, self.value) 162 return Mod(selfvalue, modulus) 1124 163 1125 164 def multiplicative_order(self): 1126 165 r""" … … 1176 215 mpz_clear(ppow_minus_one) 1177 216 return infinity 1178 217 1179 def padded_list(self, n, list_mode = 'simple'):1180 """1181 Returns a list of coefficients of `p` starting with `p^0` up1182 to `p^n` exclusive (padded with zeros if needed)1183 1184 INPUT:1185 1186 - ``self`` -- a `p`-adic element1187 1188 - ``n`` - an integer1189 1190 OUTPUT:1191 1192 - ``list`` -- the list of coefficients of ``self``1193 1194 EXAMPLES::1195 1196 sage: R = Zp(7,4,'capped-abs'); a = R(2*7+7**2); a.padded_list(5)1197 [0, 2, 1, 0, 0]1198 1199 NOTE:1200 1201 this differs from the padded_list method of padic_field_element1202 1203 the slice operators throw an error if asked for a slice above1204 the precision, while this function works1205 """1206 if list_mode == 'simple' or list_mode == 'smallest':1207 zero = Integer(0)1208 else:1209 zero = self.parent()(0, 0)1210 L = self.list()1211 return L[:n] + [zero] * (n - len(L))1212 1213 def precision_absolute(self):1214 """1215 Returns the absolute precision of ``self``.1216 1217 This is the power of the maximal ideal modulo which this1218 element is defined.1219 1220 INPUT:1221 1222 - ``self`` -- a `p`-adic element1223 1224 OUTPUT:1225 1226 - ``integer`` -- the absolute precision of ``self``1227 1228 EXAMPLES::1229 1230 sage: R = Zp(7,4,'capped-abs'); a = R(7); a.precision_absolute()1231 41232 """1233 cdef Integer ans1234 ans = PY_NEW(Integer)1235 mpz_set_si(ans.value, self.absprec)1236 return ans1237 1238 def precision_relative(self):1239 """1240 Returns the relative precision of ``self``.1241 1242 This is the power of the maximal ideal modulo which the unit1243 part of ``self`` is defined.1244 1245 INPUT:1246 1247 - ``self`` -- a `p`-adic element1248 1249 OUTPUT:1250 1251 - ``integer`` -- the relative precision of ``self``1252 1253 EXAMPLES::1254 1255 sage: R = Zp(7,4,'capped-abs'); a = R(7); a.precision_relative()1256 31257 """1258 cdef Integer ans1259 ans = PY_NEW(Integer)1260 mpz_set_si(ans.value, self.absprec - self.valuation_c())1261 return ans1262 1263 def residue(self, absprec = 1):1264 r"""1265 Reduces ``self`` modulo ``p^absprec``1266 1267 INPUT:1268 1269 - ``self`` -- a `p`-adic element1270 1271 - ``absprec`` - an integer1272 1273 OUTPUT:1274 1275 - element of `\mathbb{Z}/p^{\mbox{absprec}} \mathbb{Z}` --1276 ``self`` reduced modulo ``p^absprec``.1277 1278 EXAMPLES::1279 1280 sage: R = Zp(7,4,'capped-abs'); a = R(8); a.residue(1)1281 11282 """1283 if absprec > self.precision_absolute():1284 raise PrecisionError, "Not enough precision known in order to compute residue."1285 elif absprec < 0:1286 raise ValueError, "cannot reduce modulo a negative power of p"1287 cdef Integer selfvalue1288 selfvalue = PY_NEW(Integer)1289 mpz_set(selfvalue.value, self.value)1290 return Mod(selfvalue, self.parent().prime_pow(absprec))1291 1292 1293 218 #def square_root(self): 1294 219 # r""" 1295 220 # Returns the square root of this p-adic number … … 1334 259 # except PariError: 1335 260 # raise ValueError, "element is not a square" # should eventually change to return an element of an extension field 1336 261 1337 cpdef pAdicCappedAbsoluteElement unit_part(self):1338 r"""1339 Returns the unit part of ``self``.1340 1341 INPUT:1342 1343 - ``self`` -- a `p`-adic element1344 1345 OUTPUT:1346 1347 - `p`-adic element -- the unit part of ``self``1348 1349 EXAMPLES::1350 1351 sage: R = Zp(17,4,'capped-abs', 'val-unit')1352 sage: a = R(18*17)1353 sage: a.unit_part()1354 18 + O(17^3)1355 sage: type(a)1356 <type 'sage.rings.padics.padic_capped_absolute_element.pAdicCappedAbsoluteElement'>1357 """1358 cdef pAdicCappedAbsoluteElement ans1359 cdef unsigned long v1360 if mpz_sgn(self.value) == 0:1361 ans = self._new_c()1362 mpz_set_ui(ans.value, 0)1363 ans._set_prec_abs(0)1364 return ans1365 elif mpz_divisible_p(self.value, self.prime_pow.prime.value):1366 ans = self._new_c()1367 sig_on()1368 v = mpz_remove(ans.value, self.value, self.prime_pow.prime.value)1369 sig_off()1370 ans._set_prec_abs(self.absprec - v)1371 return ans1372 else:1373 return self1374 1375 def valuation(self):1376 """1377 Returns the valuation of ``self``, ie the largest power of `p`1378 dividing ``self``.1379 1380 EXAMPLES::1381 1382 sage: R = ZpCA(5)1383 sage: R(5^5*1827).valuation()1384 51385 1386 TESTS::1387 1388 sage: R(1).valuation()1389 01390 sage: R(2).valuation()1391 01392 sage: R(5).valuation()1393 11394 sage: R(10).valuation()1395 11396 sage: R(25).valuation()1397 21398 sage: R(50).valuation()1399 21400 sage: R(0).valuation()1401 201402 """1403 # We override this, rather than using the valuation in1404 # padic_generic_element, for speed reasons.1405 1406 cdef Integer ans1407 ans = PY_NEW(Integer)1408 mpz_set_ui(ans.value, self.valuation_c())1409 return ans1410 1411 cdef long valuation_c(self):1412 """1413 Returns the valuation of ``self``, ie the largest power of `p`1414 dividing ``self``.1415 1416 EXAMPLES::1417 1418 sage: R = ZpCA(5)1419 sage: a = R(0,6)1420 sage: a.valuation() #indirect doctest1421 61422 """1423 if mpz_sgn(self.value) == 0:1424 return self.absprec1425 cdef mpz_t tmp1426 cdef long ans1427 mpz_init(tmp)1428 ans = mpz_remove(tmp, self.value, self.prime_pow.prime.value)1429 mpz_clear(tmp)1430 return ans1431 1432 cpdef val_unit(self):1433 """1434 Returns a 2-tuple, the first element set to the valuation of1435 ``self``, and the second to the unit part of ``self``.1436 1437 If ``self = 0``, then the unit part is ``O(p^0)``.1438 1439 EXAMPLES::1440 1441 sage: R = ZpCA(5)1442 sage: a = R(75, 6); b = a - a1443 sage: a.val_unit()1444 (2, 3 + O(5^4))1445 sage: b.val_unit()1446 (6, O(5^0))1447 """1448 cdef pAdicCappedAbsoluteElement unit1449 cdef Integer val1450 cdef unsigned long v1451 val = PY_NEW(Integer)1452 if mpz_sgn(self.value) == 0:1453 unit = self._new_c()1454 mpz_set_ui(unit.value, 0)1455 unit._set_prec_abs(0)1456 mpz_set_ui(val.value, self.absprec)1457 return (val, unit)1458 elif mpz_divisible_p(self.value, self.prime_pow.prime.value):1459 unit = self._new_c()1460 v = mpz_remove(unit.value, self.value, self.prime_pow.prime.value)1461 unit._set_prec_abs(self.absprec - v)1462 mpz_set_ui(val.value, v)1463 return (val, unit)1464 else:1465 mpz_set_ui(val.value, 0)1466 return (val, self)1467 1468 def __hash__(self):1469 """1470 Hashing.1471 1472 EXAMPLES::1473 1474 sage: R = ZpCA(11, 5)1475 sage: hash(R(3)) == hash(3)1476 True1477 """1478 return hash(self.lift())1479 1480 262 def make_pAdicCappedAbsoluteElement(parent, x, absprec): 1481 263 """ 1482 264 Unpickles a capped absolute element. … … 1488 270 sage: a = make_pAdicCappedAbsoluteElement(R, 17*25, 5); a 1489 271 2*5^2 + 3*5^3 + O(5^5) 1490 272 """ 1491 return parent(x, absprec=absprec)273 return unpickle_cae_v2(pAdicCappedAbsoluteElement, parent, x, absprec)
