# HG changeset patch
# User Simon King <simon.king@uni-jena.de>
# Date 1298032666 -3600
# Node ID 354a8e5d9902e4c0bd240da9c9fe50950b963c33
# Parent f9f2d5576c71552ef0cc1f814d062defb663bbef
#8972: Fractions of power series and Laurent series.
* * *
Fixing various errors related with inverses of power series.
* * *
Improving the timings after bugfixing power series and Laurent series
* * *
Improving timings for sqrt, further bug fixes, more doc tests.
* * *
Bugfix for LaurentSeries._div_
* * *
#8972 referee patch
* * *
Fixing some remaining bugs of Laurent/power series arithmetic; fixing doc tests on elliptic curves.
diff --git a/sage/modular/modform/find_generators.py b/sage/modular/modform/find_generators.py
a
|
b
|
|
112 | 112 | |
113 | 113 | K = v[0].parent().base_ring() |
114 | 114 | V = K**n |
115 | | B = [V(g.padded_list(n)) for g in v] |
| 115 | B = [V(g.padded_list(n) if hasattr(g,'padded_list') else g.power_series().padded_list(n)) for g in v] |
116 | 116 | if basis: |
117 | 117 | M = V.span_of_basis(B) |
118 | 118 | else: |
diff --git a/sage/rings/laurent_series_ring.py b/sage/rings/laurent_series_ring.py
a
|
b
|
|
50 | 50 | sage: Frac(GF(5)['y']) |
51 | 51 | Fraction Field of Univariate Polynomial Ring in y over Finite Field of size 5 |
52 | 52 | |
53 | | Here the fraction field is not just the Laurent series ring, so you |
54 | | can't use the ``Frac`` notation to make the Laurent |
55 | | series ring. |
| 53 | After fixing ticket #8972, this also works if the base ring is not |
| 54 | a field. In this case, the ``Frac`` constructor returns the Laurent |
| 55 | series ring over the fraction field of the base ring. |
56 | 56 | |
57 | 57 | :: |
58 | 58 | |
59 | 59 | sage: Frac(ZZ[['t']]) |
60 | | Fraction Field of Power Series Ring in t over Integer Ring |
| 60 | Laurent Series Ring in t over Rational Field |
61 | 61 | |
62 | 62 | Laurent series rings are determined by their variable and the base |
63 | 63 | ring, and are globally unique. |
… |
… |
|
121 | 121 | commutative_ring.CommutativeRing.__init__(self, base_ring, names=name, category=_Fields) |
122 | 122 | self.__sparse = sparse |
123 | 123 | |
| 124 | def one(self): |
| 125 | from sage.all import LaurentSeries,PowerSeriesRing |
| 126 | if self._one_element is None: |
| 127 | B = self.base().base_ring() |
| 128 | if hasattr(B,'ring_of_integers'): |
| 129 | B = B.ring_of_integers() |
| 130 | x = PowerSeriesRing(B,self.variable_name(),default_prec=self.default_prec()).one() |
| 131 | x = LaurentSeries(self,x,check=False) |
| 132 | self._one_element = x |
| 133 | return x |
| 134 | return self._one_element |
| 135 | |
| 136 | def zero(self): |
| 137 | from sage.all import LaurentSeries,PowerSeriesRing |
| 138 | if self._zero_element is None: |
| 139 | B = self.base().base_ring() |
| 140 | if hasattr(B,'ring_of_integers'): |
| 141 | B = B.ring_of_integers() |
| 142 | x = PowerSeriesRing(B,self.variable_name(),default_prec=self.default_prec()).zero() |
| 143 | x = LaurentSeries(self,x,check=False) |
| 144 | self._zero_element = x |
| 145 | return x |
| 146 | return self._zero_element |
| 147 | |
124 | 148 | def base_extend(self, R): |
125 | 149 | """ |
126 | 150 | Returns the laurent series ring over R in the same variable as |
… |
… |
|
236 | 260 | n += x._valp() |
237 | 261 | bigoh = n + x.length() |
238 | 262 | x = self(self.polynomial_ring()(x.Vec())) |
239 | | return (x << n).add_bigoh(bigoh) |
| 263 | return x.add_bigoh(bigoh-n) << n |
240 | 264 | else: # General case, pretend to be a polynomial |
241 | 265 | return self(self.polynomial_ring()(x)) << n |
242 | 266 | elif is_FractionFieldElement(x) and \ |
… |
… |
|
245 | 269 | x = self(x.numerator())/self(x.denominator()) |
246 | 270 | return (x << n) |
247 | 271 | else: |
248 | | return laurent_series_ring_element.LaurentSeries(self, x, n) |
| 272 | try: |
| 273 | if self.power_series_ring().has_coerce_map_from(x.parent()): |
| 274 | if self.power_series_ring().base_ring().has_coerce_map_from(x.parent()): |
| 275 | return laurent_series_ring_element.LaurentSeries(self, x*self.one().power_series(internal=True), n,check=False) |
| 276 | if x.is_zero(): |
| 277 | return laurent_series_ring_element.LaurentSeries(self, x, n, check=False) |
| 278 | v = x.valuation() |
| 279 | return laurent_series_ring_element.LaurentSeries(self, x>>v, v+n,check=False) |
| 280 | except: |
| 281 | pass |
| 282 | return laurent_series_ring_element.LaurentSeries(self, x, n) |
249 | 283 | |
250 | 284 | def _coerce_impl(self, x): |
251 | 285 | """ |
diff --git a/sage/rings/laurent_series_ring_element.pyx b/sage/rings/laurent_series_ring_element.pyx
a
|
b
|
|
50 | 50 | - Robert Bradshaw (2007-04): optimizations, shifting |
51 | 51 | |
52 | 52 | - Robert Bradshaw: Cython version |
| 53 | |
| 54 | - Simon King (2010-05): optimizations, some doc tests |
53 | 55 | """ |
54 | 56 | |
55 | 57 | import operator |
… |
… |
|
78 | 80 | """ |
79 | 81 | A Laurent Series. |
80 | 82 | """ |
81 | | |
82 | | def __init__(self, parent, f, n=0): |
| 83 | # check=False means: The user asserts that f is |
| 84 | # a power series that coerces into the power series |
| 85 | # ring of self and is of valuation zero. |
| 86 | def __init__(self, parent, f, n=0,check=True): |
83 | 87 | r""" |
84 | 88 | Create the Laurent series `t^n \cdot f`. The default is |
85 | 89 | n=0. |
… |
… |
|
118 | 122 | """ |
119 | 123 | AlgebraElement.__init__(self, parent) |
120 | 124 | |
| 125 | if not check: |
| 126 | # the user assures that f coerces into parent.power_series_ring() |
| 127 | # and is of valuation zero |
| 128 | if not f: |
| 129 | if n == infinity: |
| 130 | self.__n = 0 |
| 131 | self.__u = parent.power_series_ring()(0) |
| 132 | else: |
| 133 | self.__n = n |
| 134 | self.__u = f |
| 135 | else: |
| 136 | self.__n = n # power of the variable |
| 137 | self.__u = f # unit part |
| 138 | return |
| 139 | |
121 | 140 | if PY_TYPE_CHECK(f, LaurentSeries): |
122 | 141 | n += (<LaurentSeries>f).__n |
123 | 142 | if (<LaurentSeries>f).__u._parent is parent.power_series_ring(): |
… |
… |
|
129 | 148 | ## now this is a power series, over a different ring ... |
130 | 149 | ## requires that power series rings with same vars over the |
131 | 150 | ## same parent are unique. |
132 | | elif parent is not f.parent(): |
| 151 | elif parent.power_series_ring() is not f.parent(): |
133 | 152 | f = parent.power_series_ring()(f) |
134 | 153 | |
135 | 154 | |
… |
… |
|
176 | 195 | sage: f = 2 + s^2 + O(s^10) |
177 | 196 | sage: f.is_unit() |
178 | 197 | False |
| 198 | |
| 199 | Before ticket #8972, the following used to raise an error. |
| 200 | But now, the inverse of any non-zero element exists, and |
| 201 | the inverse is always an element of the fraction field:: |
| 202 | |
179 | 203 | sage: 1/f |
180 | | Traceback (most recent call last): |
181 | | ... |
182 | | ArithmeticError: division not defined |
| 204 | 1/2 - 1/4*s^2 + 1/8*s^4 - 1/16*s^6 + 1/32*s^8 + O(s^10) |
183 | 205 | |
184 | 206 | ALGORITHM: A Laurent series is a unit if and only if its "unit |
185 | 207 | part" is a unit. |
… |
… |
|
401 | 423 | """ |
402 | 424 | return iter(self.__u) |
403 | 425 | |
404 | | |
| 426 | def exp(self): |
| 427 | """ |
| 428 | Return the exponential of ``self``. |
| 429 | |
| 430 | ASSUMPTION: |
| 431 | |
| 432 | ``self`` must in fact be a power series |
| 433 | (non-negative valuation). |
| 434 | |
| 435 | EXAMPLES:: |
| 436 | |
| 437 | sage: R.<t> = ZZ[[]] |
| 438 | sage: p = t/(2+t) |
| 439 | sage: p.exp() |
| 440 | 1 + 1/2*t - 1/8*t^2 + 1/48*t^3 + 1/384*t^4 - 19/3840*t^5 + 151/46080*t^6 - 1091/645120*t^7 + 7841/10321920*t^8 - 56519/185794560*t^9 + 396271/3715891200*t^10 - 2442439/81749606400*t^11 + 7701409/1961990553600*t^12 + 145269541/51011754393600*t^13 - 4833158329/1428329123020800*t^14 + 104056218421/42849873690624000*t^15 - 2002667085119/1371195958099968000*t^16 + 37109187217649/46620662575398912000*t^17 - 679877731030049/1678343852714360832000*t^18 + 12440309297451121/63777066403145711616000*t^19 + O(t^20) |
| 441 | sage: q = 2/(2*t+t^3) |
| 442 | sage: q.exp() |
| 443 | Traceback (most recent call last): |
| 444 | ... |
| 445 | ArithmeticError: self is a not a power series |
| 446 | |
| 447 | """ |
| 448 | return self.parent()(self.power_series().exp()) |
| 449 | |
405 | 450 | def list(self): |
406 | 451 | """ |
407 | 452 | EXAMPLES:: |
… |
… |
|
503 | 548 | """ |
504 | 549 | cdef LaurentSeries right = <LaurentSeries>right_m |
505 | 550 | cdef long m |
506 | | |
| 551 | |
507 | 552 | # 1. Special case when one or the other is 0. |
508 | 553 | if not right: |
509 | 554 | return self.add_bigoh(right.prec()) |
… |
… |
|
513 | 558 | # 2. Align the unit parts. |
514 | 559 | if self.__n < right.__n: |
515 | 560 | m = self.__n |
516 | | f1 = self.__u |
517 | | f2 = right.__u << right.__n - m |
| 561 | out = self.__u + (right.__u << right.__n - m) |
518 | 562 | elif self.__n > right.__n: |
519 | 563 | m = right.__n |
520 | | f1 = self.__u << self.__n - m |
521 | | f2 = right.__u |
| 564 | out = (self.__u << self.__n - m) + right.__u |
522 | 565 | else: |
523 | 566 | m = self.__n |
524 | | f1 = self.__u |
525 | | f2 = right.__u |
| 567 | out = self.__u + right.__u |
526 | 568 | # 3. Add |
527 | | return LaurentSeries(self._parent, f1 + f2, m) |
| 569 | if out.is_zero(): |
| 570 | return LaurentSeries(self._parent, out, m, check=False) |
| 571 | v = out.valuation() |
| 572 | return LaurentSeries(self._parent, out>>v, m+v, check=False) |
528 | 573 | |
529 | 574 | cpdef ModuleElement _iadd_(self, ModuleElement right_m): |
530 | 575 | """ |
… |
… |
|
570 | 615 | # 2. Align the unit parts. |
571 | 616 | if self.__n < right.__n: |
572 | 617 | m = self.__n |
573 | | f1 = self.__u |
574 | | f2 = right.__u << right.__n - m |
| 618 | out = self.__u - (right.__u << right.__n - m) |
| 619 | #f2 = right.__u << right.__n - m |
575 | 620 | else: |
576 | 621 | m = right.__n |
577 | | f1 = self.__u << self.__n - m |
578 | | f2 = right.__u |
| 622 | out = (self.__u << self.__n - m) - right.__u |
| 623 | #f2 = right.__u |
579 | 624 | # 3. Subtract |
580 | | return LaurentSeries(self._parent, f1 - f2, m) |
| 625 | # We want to keep the parent of f1-f2 as simple as |
| 626 | # possible. Therefore, we work a little more here, |
| 627 | # and use the option check=False |
| 628 | if out.is_zero(): |
| 629 | return LaurentSeries(self._parent, out, m, check=False) |
| 630 | v = out.valuation() |
| 631 | return LaurentSeries(self._parent, out>>v, m+v, check=False) |
| 632 | #return LaurentSeries(self._parent, f1 - f2, m) |
581 | 633 | |
582 | 634 | |
583 | 635 | def add_bigoh(self, prec): |
584 | 636 | """ |
| 637 | Add ``O(t^prec)`` to ``self``. |
| 638 | |
| 639 | INPUT: |
| 640 | |
| 641 | prec -- integer, the precision to obtain |
| 642 | |
585 | 643 | EXAMPLES:: |
586 | 644 | |
587 | 645 | sage: R.<t> = LaurentSeriesRing(QQ) |
… |
… |
|
589 | 647 | t^2 + t^3 + O(t^10) |
590 | 648 | sage: f.add_bigoh(5) |
591 | 649 | t^2 + t^3 + O(t^5) |
| 650 | |
| 651 | TEST: |
| 652 | |
| 653 | sage: P = QQ['t'] |
| 654 | sage: p = P('2+t^3+4*t^15') |
| 655 | sage: p + O(t^10) # indirect doctest |
| 656 | 2 + t^3 + O(t^10) |
592 | 657 | """ |
593 | 658 | if prec == infinity or prec >= self.prec(): |
594 | 659 | return self |
595 | | u = self.__u.add_bigoh(prec - self.__n) |
596 | | return LaurentSeries(self._parent, u, self.__n) |
| 660 | try: |
| 661 | u = self.__u.add_bigoh(prec - self.__n) |
| 662 | except AttributeError: # perhaps self.__u is just a polynomial |
| 663 | u = self.power_series().add_bigoh(prec - self.__n) |
| 664 | return LaurentSeries(self._parent, u, self.__n,check=False) |
597 | 665 | |
598 | 666 | def degree(self): |
599 | 667 | """ |
… |
… |
|
623 | 691 | sage: -(1/(1+t+O(t^5))) |
624 | 692 | -1 + t - t^2 + t^3 - t^4 + O(t^5) |
625 | 693 | """ |
626 | | return LaurentSeries(self._parent, -self.__u, self.__n) |
| 694 | return LaurentSeries(self._parent, -self.__u, self.__n, check=False) |
627 | 695 | |
628 | 696 | cpdef RingElement _mul_(self, RingElement right_r): |
629 | 697 | """ |
… |
… |
|
638 | 706 | cdef LaurentSeries right = <LaurentSeries>right_r |
639 | 707 | return LaurentSeries(self._parent, |
640 | 708 | self.__u * right.__u, |
641 | | self.__n + right.__n) |
| 709 | self.__n + right.__n,check=False) |
642 | 710 | |
643 | 711 | cpdef RingElement _imul_(self, RingElement right_r): |
644 | 712 | """ |
… |
… |
|
656 | 724 | return self |
657 | 725 | |
658 | 726 | cpdef ModuleElement _rmul_(self, RingElement c): |
659 | | return LaurentSeries(self._parent, self.__u._rmul_(c), self.__n) |
| 727 | # This is incorrect, since self.__u is not necessarily |
| 728 | # an element of self.parent.power_series_ring() (though |
| 729 | # there is a coercion). Hence, it is not safe to call |
| 730 | # _rmul_ directly. |
| 731 | #return LaurentSeries(self._parent, self.__u._rmul_(c), self.__n) |
| 732 | return LaurentSeries(self._parent, self.__u*c, self.__n) |
660 | 733 | |
661 | 734 | cpdef ModuleElement _lmul_(self, RingElement c): |
662 | | return LaurentSeries(self._parent, self.__u._lmul_(c), self.__n) |
| 735 | #return LaurentSeries(self._parent, self.__u._lmul_(c), self.__n) |
| 736 | return LaurentSeries(self._parent, c*self.__u, self.__n) |
663 | 737 | |
664 | 738 | cpdef ModuleElement _ilmul_(self, RingElement c): |
665 | 739 | self.__u *= c |
… |
… |
|
681 | 755 | right=int(r) |
682 | 756 | if right != r: |
683 | 757 | raise ValueError, "exponent must be an integer" |
684 | | return LaurentSeries(self._parent, self.__u**right, self.__n*right) |
| 758 | return LaurentSeries(self._parent, self.__u**right, self.__n*right,check=False) |
685 | 759 | |
686 | 760 | def shift(self, k): |
687 | 761 | r""" |
… |
… |
|
714 | 788 | |
715 | 789 | - Robert Bradshaw (2007-04-18) |
716 | 790 | """ |
717 | | return LaurentSeries(self._parent, self.__u, self.__n + k) |
| 791 | return LaurentSeries(self._parent, self.__u, self.__n + k,check=False) |
718 | 792 | |
719 | 793 | def __lshift__(LaurentSeries self, k): |
720 | | return LaurentSeries(self._parent, self.__u, self.__n + k) |
| 794 | """ |
| 795 | Despite the fact that higher order terms are printed to the |
| 796 | right in a power series, left shifting increases the powers |
| 797 | of `t`. This is to be consistent with polynomials, integers, |
| 798 | etc. |
| 799 | |
| 800 | TEST:: |
| 801 | |
| 802 | sage: R.<t> = LaurentSeriesRing(QQ['y']) |
| 803 | sage: f = (t+t^-1)^4; f |
| 804 | t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4 |
| 805 | sage: (f + O(t^5)) << 2 |
| 806 | t^-2 + 4 + 6*t^2 + 4*t^4 + t^6 + O(t^7) |
| 807 | |
| 808 | """ |
| 809 | return LaurentSeries(self._parent, self.__u, self.__n + k,check=False) |
721 | 810 | |
722 | 811 | def __rshift__(LaurentSeries self, k): |
723 | | return LaurentSeries(self._parent, self.__u, self.__n - k) |
| 812 | """ |
| 813 | Despite the fact that higher order terms are printed to the |
| 814 | right in a power series, right shifting decreases the powers |
| 815 | of `t`. This is to be consistent with polynomials, integers, |
| 816 | etc. |
| 817 | |
| 818 | TEST:: |
| 819 | |
| 820 | sage: R.<t> = LaurentSeriesRing(QQ['y']) |
| 821 | sage: f = (t+t^-1)^4; f |
| 822 | t^-4 + 4*t^-2 + 6 + 4*t^2 + t^4 |
| 823 | sage: f >> 3 |
| 824 | t^-7 + 4*t^-5 + 6*t^-3 + 4*t^-1 + t |
| 825 | sage: (f + O(t^5)) >> 2 |
| 826 | t^-6 + 4*t^-4 + 6*t^-2 + 4 + t^2 + O(t^3) |
| 827 | sage: (f + O(t^2)) >> 5 |
| 828 | t^-9 + 4*t^-7 + 6*t^-5 + O(t^-3) |
| 829 | |
| 830 | """ |
| 831 | return LaurentSeries(self._parent, self.__u, self.__n - k,check=False) |
724 | 832 | |
725 | 833 | def truncate(self, long n): |
726 | 834 | r""" |
727 | 835 | Returns the laurent series of degree ` < n` which is |
728 | 836 | equivalent to self modulo `x^n`. |
| 837 | |
| 838 | EXAMPLE:: |
| 839 | |
| 840 | sage: R.<I> = ZZ[[]] |
| 841 | sage: f = (1-I)/(1+I+O(I^8)); f |
| 842 | 1 - 2*I + 2*I^2 - 2*I^3 + 2*I^4 - 2*I^5 + 2*I^6 - 2*I^7 + O(I^8) |
| 843 | sage: f.truncate(5) |
| 844 | 1 - 2*I + 2*I^2 - 2*I^3 + 2*I^4 + O(I^5) |
| 845 | |
729 | 846 | """ |
730 | 847 | if n <= self.__n: |
731 | 848 | return LaurentSeries(self._parent, 0) |
732 | 849 | else: |
733 | | return LaurentSeries(self._parent, self.__u.truncate_powerseries(n - self.__n), self.__n) |
| 850 | return LaurentSeries(self._parent, self.__u.truncate_powerseries(n - self.__n), self.__n,check=False) |
734 | 851 | |
735 | 852 | def truncate_neg(self, long n): |
736 | 853 | r""" |
… |
… |
|
739 | 856 | |
740 | 857 | This is equivalent to |
741 | 858 | ```self - self.truncate(n)```. |
| 859 | |
| 860 | EXAMPLE:: |
| 861 | |
| 862 | sage: R.<I> = ZZ[[]] |
| 863 | sage: f = (1-I)/(1+I+O(I^8)); f |
| 864 | 1 - 2*I + 2*I^2 - 2*I^3 + 2*I^4 - 2*I^5 + 2*I^6 - 2*I^7 + O(I^8) |
| 865 | sage: f.truncate_neg(5) |
| 866 | -2*I^5 + 2*I^6 - 2*I^7 + O(I^8) |
| 867 | |
742 | 868 | """ |
743 | | return LaurentSeries(self._parent, self.__u >> (n - self.__n), n) |
| 869 | return LaurentSeries(self._parent, self.__u >> (n - self.__n), n,check=False) |
744 | 870 | |
745 | 871 | cpdef RingElement _div_(self, RingElement right_r): |
746 | 872 | """ |
… |
… |
|
753 | 879 | 1 + x + 3*x^3 + O(x^6) |
754 | 880 | sage: f/g |
755 | 881 | x^8 + x^9 + 3*x^11 + O(x^14) |
| 882 | |
| 883 | TEST: |
| 884 | |
| 885 | The following was fixed in ticket #8972:: |
| 886 | |
| 887 | sage: L.<x> = LaurentSeriesRing(ZZ) |
| 888 | sage: 1/(2+x) |
| 889 | 1/2 - 1/4*x + 1/8*x^2 - 1/16*x^3 + 1/32*x^4 - 1/64*x^5 + 1/128*x^6 - 1/256*x^7 + 1/512*x^8 - 1/1024*x^9 + 1/2048*x^10 - 1/4096*x^11 + 1/8192*x^12 - 1/16384*x^13 + 1/32768*x^14 - 1/65536*x^15 + 1/131072*x^16 - 1/262144*x^17 + 1/524288*x^18 - 1/1048576*x^19 + O(x^20) |
| 890 | |
| 891 | sage: R.<x> = ZZ[[]] |
| 892 | sage: y = (3*x+2)/(1+x) |
| 893 | sage: y/x |
| 894 | 2*x^-1 + 1 - x + x^2 - x^3 + x^4 - x^5 + x^6 - x^7 + x^8 - x^9 + x^10 - x^11 + x^12 - x^13 + x^14 - x^15 + x^16 - x^17 + x^18 + O(x^19) |
| 895 | |
756 | 896 | """ |
757 | 897 | cdef LaurentSeries right = <LaurentSeries>right_r |
| 898 | cdef LaurentSeries out |
758 | 899 | if right.__u.is_zero(): |
759 | 900 | raise ZeroDivisionError |
760 | 901 | try: |
761 | | return LaurentSeries(self._parent, |
762 | | self.__u / right.__u, |
763 | | self.__n - right.__n) |
| 902 | inv = ~self._parent.power_series_ring()(right.__u) |
| 903 | new_base = inv.parent().base() |
| 904 | old_base = self._parent.base() |
| 905 | if (new_base is old_base) or old_base.has_coerce_map_from(new_base): |
| 906 | return LaurentSeries(self._parent, self.__u * inv, self.__n - right.__n, check=False) |
| 907 | # need to go to the fraction field |
| 908 | return LaurentSeries(self._parent.base_extend(new_base), self.__u.base_extend(new_base) * inv, self.__n - right.__n, check=False) |
764 | 909 | except TypeError, msg: |
765 | | # todo: this could also make something in the formal fraction field. |
766 | 910 | raise ArithmeticError, "division not defined" |
767 | 911 | |
768 | 912 | |
… |
… |
|
951 | 1095 | return self.__u.prec() + self.__n |
952 | 1096 | |
953 | 1097 | def __copy__(self): |
954 | | return LaurentSeries(self._parent, self.__u.copy(), self.__n) |
| 1098 | return LaurentSeries(self._parent, self.__u.copy(), self.__n, check=False) |
955 | 1099 | |
956 | 1100 | |
957 | 1101 | def derivative(self, *args): |
… |
… |
|
1099 | 1243 | return LaurentSeries(self._parent, u, n+1) |
1100 | 1244 | |
1101 | 1245 | |
1102 | | def power_series(self): |
| 1246 | def power_series(self, internal=False): |
1103 | 1247 | """ |
| 1248 | If ``self`` is of non-negative valuation, return the underlying power series |
| 1249 | |
| 1250 | INPUT: |
| 1251 | |
| 1252 | - ``internal`` (optional bool, default ``False``): Return the power series |
| 1253 | as it is stored internally; with this option, the result might be over a |
| 1254 | base ring that is different from the base ring of the Laurent series ring. |
| 1255 | |
| 1256 | OUTPUT: |
| 1257 | |
| 1258 | - a power series, or an ``ArithmeticError`` if the valuation is negative. |
| 1259 | |
1104 | 1260 | EXAMPLES:: |
1105 | 1261 | |
1106 | 1262 | sage: R.<t> = LaurentSeriesRing(ZZ) |
… |
… |
|
1115 | 1271 | Traceback (most recent call last): |
1116 | 1272 | ... |
1117 | 1273 | ArithmeticError: self is a not a power series |
| 1274 | |
| 1275 | TEST: |
| 1276 | |
| 1277 | Since ticket #8972, the fraction field of a power series ring is |
| 1278 | a Laurent series ring over the fraction field of the base ring:: |
| 1279 | |
| 1280 | sage: P.<t> = ZZ[[]] |
| 1281 | sage: F = Frac(P); F |
| 1282 | Laurent Series Ring in t over Rational Field |
| 1283 | |
| 1284 | Although internally ``1/(1+t)`` is stored as a power series over |
| 1285 | the integers in order to speed up computations, the power series |
| 1286 | returned by this method is over the rationals:: |
| 1287 | |
| 1288 | sage: g = 1/(1+t); g |
| 1289 | 1 - t + t^2 - t^3 + t^4 - t^5 + t^6 - t^7 + t^8 - t^9 + t^10 - t^11 + t^12 - t^13 + t^14 - t^15 + t^16 - t^17 + t^18 - t^19 + O(t^20) |
| 1290 | sage: g.power_series().parent() |
| 1291 | Power Series Ring in t over Rational Field |
| 1292 | sage: g.power_series(internal=True).parent() |
| 1293 | Power Series Ring in t over Integer Ring |
| 1294 | |
1118 | 1295 | """ |
1119 | 1296 | if self.__n < 0: |
1120 | 1297 | raise ArithmeticError, "self is a not a power series" |
1121 | 1298 | u = self.__u |
1122 | 1299 | t = u.parent().gen() |
1123 | | return t**(self.__n) * u |
| 1300 | if internal: |
| 1301 | return t**(self.__n) * u |
| 1302 | return self._parent.power_series_ring()(t**(self.__n) * u) |
1124 | 1303 | |
1125 | 1304 | def __call__(self, *x): |
1126 | 1305 | """ |
… |
… |
|
1143 | 1322 | |
1144 | 1323 | |
1145 | 1324 | def make_element_from_parent(parent, *args): |
| 1325 | """ |
| 1326 | An auxiliary function, that makes an element of a given parent structure |
| 1327 | |
| 1328 | INPUT: |
| 1329 | |
| 1330 | - ``parent``, a parent structure |
| 1331 | - some further arguments |
| 1332 | |
| 1333 | OUTPUT: |
| 1334 | |
| 1335 | ``parent`` is called with the given arguments |
| 1336 | |
| 1337 | EXAMPLE:: |
| 1338 | |
| 1339 | sage: from sage.rings.laurent_series_ring_element import make_element_from_parent |
| 1340 | sage: P.<t> = ZZ[[]] |
| 1341 | sage: F = Frac(P) |
| 1342 | sage: make_element_from_parent(P,[1,2,3]) |
| 1343 | 1 + 2*t + 3*t^2 |
| 1344 | sage: make_element_from_parent(P,[1,2,3],5) |
| 1345 | 1 + 2*t + 3*t^2 + O(t^5) |
| 1346 | sage: make_element_from_parent(F,[1,2,3],-4) |
| 1347 | t^-4 + 2*t^-3 + 3*t^-2 |
| 1348 | |
| 1349 | """ |
1146 | 1350 | return parent(*args) |
diff --git a/sage/rings/power_series_poly.pyx b/sage/rings/power_series_poly.pyx
a
|
b
|
|
585 | 585 | EXAMPLES:: |
586 | 586 | |
587 | 587 | sage: R.<I> = GF(2)[[]] |
588 | | sage: f = 1/(1+I+O(I^8)); f |
| 588 | sage: f = (1/(1+I+O(I^8))).power_series(); f |
589 | 589 | 1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8) |
590 | 590 | sage: f.truncate(5) |
591 | 591 | I^4 + I^3 + I^2 + I + 1 |
… |
… |
|
616 | 616 | EXAMPLES:: |
617 | 617 | |
618 | 618 | sage: R.<I> = GF(2)[[]] |
619 | | sage: f = 1/(1+I+O(I^8)); f |
| 619 | sage: f = (1/(1+I+O(I^8))).power_series(); f |
620 | 620 | 1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8) |
621 | 621 | sage: f.truncate_powerseries(5) |
622 | 622 | 1 + I + I^2 + I^3 + I^4 + O(I^5) |
… |
… |
|
841 | 841 | ... |
842 | 842 | ValueError: Series must have valuation one for reversion. |
843 | 843 | |
844 | | |
845 | | |
846 | 844 | """ |
847 | 845 | if self.valuation() != 1: |
848 | 846 | raise ValueError("Series must have valuation one for reversion.") |
… |
… |
|
893 | 891 | t = f.parent().gen() |
894 | 892 | R = f.parent().base_ring() |
895 | 893 | |
896 | | h = t/f |
| 894 | # Since trac ticket #8972, t/f is not a power series but a Laurent |
| 895 | # polynomial. Hence, for getting the padded list, we first need |
| 896 | # to get the power series out of it |
| 897 | h = (t/f).power_series() |
897 | 898 | k = 1 |
898 | 899 | g = 0 |
899 | 900 | for i in range(1, out_prec): |
diff --git a/sage/rings/power_series_ring.py b/sage/rings/power_series_ring.py
a
|
b
|
|
94 | 94 | |
95 | 95 | - Niles Johnson (2010-09): implement multivariate power series |
96 | 96 | |
| 97 | - Simon King (2010-05): make fraction_field be a cached method; conversion |
| 98 | of a Laurent series of non-negative valuation into a power series. |
| 99 | |
97 | 100 | TESTS:: |
98 | 101 | |
99 | 102 | sage: R.<t> = PowerSeriesRing(QQ) |
… |
… |
|
618 | 621 | sage: R(x + x^2 + x^3 + x^5, 3) |
619 | 622 | t + t^2 + O(t^3) |
620 | 623 | """ |
| 624 | try: |
| 625 | f = f.power_series() |
| 626 | except: |
| 627 | pass |
621 | 628 | if isinstance(f, power_series_ring_element.PowerSeries) and f.parent() is self: |
622 | 629 | if prec >= f.prec(): |
623 | 630 | return f |
… |
… |
|
644 | 651 | from sage.categories.pushout import CompletionFunctor |
645 | 652 | return CompletionFunctor(self._names[0], self.default_prec()), self._poly_ring() |
646 | 653 | |
| 654 | def is_integral_domain(self, **kwds): |
| 655 | return self.base().is_integral_domain(**kwds) |
| 656 | |
| 657 | def fraction_field(self): |
| 658 | """ |
| 659 | Return the fraction field of this power series ring, which |
| 660 | is the same as the Laurent series ring over the fraction |
| 661 | field of the base ring of ``self``. |
| 662 | |
| 663 | EXAMPLE:: |
| 664 | |
| 665 | sage: R.<x> = ZZ.quo(53)[[]] |
| 666 | sage: FractionField(R) |
| 667 | Laurent Series Ring in x over Ring of integers modulo 53 |
| 668 | sage: 1/x in FractionField(R) |
| 669 | True |
| 670 | """ |
| 671 | from sage.all import LaurentSeriesRing |
| 672 | return LaurentSeriesRing(self.base().fraction_field(),self.variable_names()) |
| 673 | |
647 | 674 | def _coerce_impl(self, x): |
648 | 675 | """ |
649 | 676 | Return canonical coercion of x into self. |
… |
… |
|
957 | 984 | sage: S.<s> = PowerSeriesRing(ZZ) |
958 | 985 | sage: s in R |
959 | 986 | False |
| 987 | |
| 988 | TEST: |
| 989 | |
| 990 | The following was fixed in ticket #8972. If a Laurent |
| 991 | series is in fact a power series that can be interpreted |
| 992 | in ``self`` then it is considered an element of ``self``:: |
| 993 | |
| 994 | sage: R.<x> = ZZ[[]] |
| 995 | sage: y = (1+x)/(1-4*x) |
| 996 | sage: y in R |
| 997 | True |
| 998 | sage: y.parent() |
| 999 | Laurent Series Ring in x over Rational Field |
| 1000 | sage: (1+x)/(2-x) in R |
| 1001 | False |
| 1002 | sage: 2/2 in R |
| 1003 | True |
| 1004 | |
960 | 1005 | """ |
961 | 1006 | if x.parent() == self: |
962 | 1007 | return True |
| 1008 | # first case: x coerces into self |
963 | 1009 | try: |
964 | 1010 | self._coerce_(x) |
| 1011 | return True |
965 | 1012 | except TypeError: |
| 1013 | pass |
| 1014 | # second case: x is a (ducktyped) Laurent series of non-negative valuation |
| 1015 | try: |
| 1016 | self(x.power_series()) |
| 1017 | return True |
| 1018 | except (TypeError,AttributeError,ArithmeticError): |
| 1019 | pass |
| 1020 | # third case: x is anything else that can be interpreted in self |
| 1021 | try: |
| 1022 | self.fraction_field()._coerce_(x) |
| 1023 | self(x) |
| 1024 | return True |
| 1025 | except: |
966 | 1026 | return False |
967 | | return True |
968 | 1027 | |
969 | 1028 | def is_atomic_repr(self): |
970 | 1029 | """ |
… |
… |
|
1029 | 1088 | self.base_ring(), self.variable_name(), sparse=self.is_sparse()) |
1030 | 1089 | return self.__laurent_series_ring |
1031 | 1090 | |
| 1091 | from sage.misc.cachefunc import cached_method |
1032 | 1092 | class PowerSeriesRing_domain(PowerSeriesRing_generic, integral_domain.IntegralDomain): |
1033 | | pass |
1034 | | |
| 1093 | @cached_method |
| 1094 | def fraction_field(self): |
| 1095 | """ |
| 1096 | Return the fraction field of this power series ring, which |
| 1097 | is the same as the Laurent series ring over the fraction |
| 1098 | field of the base ring of ``self``. |
| 1099 | |
| 1100 | EXAMPLE:: |
| 1101 | |
| 1102 | sage: R1.<x> = ZZ[[]] |
| 1103 | sage: FractionField(R1) |
| 1104 | Laurent Series Ring in x over Rational Field |
| 1105 | sage: R2.<x> = GF(3)['t'][[]] |
| 1106 | sage: 1/x in FractionField(R2) |
| 1107 | True |
| 1108 | """ |
| 1109 | from sage.all import LaurentSeriesRing |
| 1110 | return LaurentSeriesRing(self.base().fraction_field(),self.variable_names()) #self.laurent_series_ring().base_extend(self.base().fraction_field()) |
| 1111 | |
1035 | 1112 | class PowerSeriesRing_over_field(PowerSeriesRing_domain): |
| 1113 | @cached_method |
1036 | 1114 | def fraction_field(self): |
1037 | 1115 | """ |
1038 | 1116 | Return the fraction field of this power series ring, which is |
diff --git a/sage/rings/power_series_ring_element.pyx b/sage/rings/power_series_ring_element.pyx
a
|
b
|
|
14 | 14 | |
15 | 15 | - Robert Bradshaw (2007-04): Cython version |
16 | 16 | |
| 17 | - Simon King (2010-05): optimizations; quotients of power series are *always* Laurent series |
| 18 | |
17 | 19 | EXAMPLE:: |
18 | 20 | |
19 | 21 | sage: R.<x> = PowerSeriesRing(ZZ) |
… |
… |
|
617 | 619 | sage: f = 1/(1+I+O(I^8)); f |
618 | 620 | 1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8) |
619 | 621 | sage: f.truncate(5) |
620 | | I^4 + I^3 + I^2 + I + 1 |
| 622 | 1 + I + I^2 + I^3 + I^4 + O(I^5) |
621 | 623 | """ |
622 | 624 | if prec is infinity: |
623 | 625 | prec = self._prec |
… |
… |
|
796 | 798 | |
797 | 799 | def __invert__(self): |
798 | 800 | """ |
799 | | Inverse of the power series (i.e. a series Y such that XY = 1). The |
800 | | first nonzero coefficient must be a unit in the coefficient ring. |
| 801 | Inverse of the power series (i.e. a series Y such that XY = 1). |
801 | 802 | If the valuation of the series is positive, this function will |
802 | | return a Laurent series. |
| 803 | return a Laurent series, otherwise it returns a power series. |
| 804 | If the first coefficient is a unit then the base ring of the |
| 805 | output is the same as the base ring of ``self``; otherwise, it |
| 806 | is the fraction field. |
803 | 807 | |
804 | 808 | ALGORITHM: Uses Newton's method. Complexity is around |
805 | 809 | `O(M(n) \log n)`, where `n` is the precision and |
… |
… |
|
838 | 842 | :: |
839 | 843 | |
840 | 844 | sage: 1/(2 + q) |
841 | | 1/2 - 1/4*q + 1/8*q^2 - 1/16*q^3 + 1/32*q^4 + O(q^5) |
| 845 | 1/2 - 1/4*q + 1/8*q^2 - 1/16*q^3 + 1/32*q^4 + O(q^5) |
842 | 846 | |
843 | 847 | :: |
844 | 848 | |
… |
… |
|
858 | 862 | 1/17 - 3/289*t^2 + 9/4913*t^4 - 27/83521*t^6 + 81/1419857*t^8 - 1587142/24137569*t^10 + O(t^12) |
859 | 863 | sage: u*v |
860 | 864 | 1 + O(t^12) |
861 | | |
| 865 | |
| 866 | TEST: |
| 867 | |
| 868 | The following was fixed in ticket #8972:: |
| 869 | |
| 870 | sage: P.<t> = ZZ[[]] |
| 871 | sage: 1 / (2+t) |
| 872 | 1/2 - 1/4*t + 1/8*t^2 - 1/16*t^3 + 1/32*t^4 - 1/64*t^5 + 1/128*t^6 - 1/256*t^7 + 1/512*t^8 - 1/1024*t^9 + 1/2048*t^10 - 1/4096*t^11 + 1/8192*t^12 - 1/16384*t^13 + 1/32768*t^14 - 1/65536*t^15 + 1/131072*t^16 - 1/262144*t^17 + 1/524288*t^18 - 1/1048576*t^19 + O(t^20) |
| 873 | |
862 | 874 | AUTHORS: |
863 | 875 | |
864 | 876 | - David Harvey (2006-09-09): changed to use Newton's method |
| 877 | - Simon King (2010-05): change to the fraction field of the coefficient ring, if necessary. |
865 | 878 | """ |
866 | 879 | if self == 1: |
867 | 880 | return self |
868 | 881 | prec = self.prec() |
869 | 882 | if prec is infinity and self.degree() > 0: |
870 | 883 | prec = self._parent.default_prec() |
871 | | if self.valuation() > 0: |
872 | | u = ~self.valuation_zero_part() # inverse of unit part |
873 | | R = self._parent.laurent_series_ring() |
874 | | return R(u, -self.valuation()) |
| 884 | v = self.valuation() |
| 885 | if v > 0: |
| 886 | try: |
| 887 | u = ~(self>>v) # inverse of unit part |
| 888 | except: |
| 889 | u = ~((self>>v)*self._parent.base().fraction_field()(1)) |
| 890 | try: |
| 891 | R = self._parent.fraction_field() |
| 892 | except TypeError: # no integral domain |
| 893 | R = self._parent.laurent_series_ring() |
| 894 | from sage.all import LaurentSeries |
| 895 | return LaurentSeries(R,u,-v,check=False)# R(u, -self.valuation()) |
875 | 896 | |
876 | 897 | # Use Newton's method, i.e. start with single term approximation, |
877 | 898 | # and then iteratively compute $x' = 2x - Ax^2$, where $A$ is the |
… |
… |
|
887 | 908 | |
888 | 909 | A = self.truncate() |
889 | 910 | R = A.parent() # R is the corresponding polynomial ring |
890 | | current = R(first_coeff) |
| 911 | try: |
| 912 | current = R(first_coeff) |
| 913 | fracfield = False |
| 914 | except TypeError: |
| 915 | fracfield = True |
| 916 | R = R.base_extend(R.base().fraction_field()) |
| 917 | current = R(first_coeff) |
891 | 918 | |
892 | 919 | # todo: in the case that the underlying polynomial ring is |
893 | 920 | # implemented via NTL, the truncate() method should use NTL's |
… |
… |
|
901 | 928 | z = current.square() * A.truncate(next_prec) |
902 | 929 | current = 2*current - z.truncate(next_prec) |
903 | 930 | |
904 | | return self._parent(current, prec=prec) |
| 931 | if not fracfield: |
| 932 | return self._parent(current, prec=prec) |
| 933 | return self._parent.base_extend(R.base())(current, prec=prec) |
905 | 934 | |
906 | 935 | # Here is the old code, which uses a simple recursion, and is |
907 | 936 | # asymptotically inferior: |
… |
… |
|
976 | 1005 | t + O(t^21) |
977 | 1006 | sage: (t^5/(t^2 - 2)) * (t^2 -2 ) |
978 | 1007 | t^5 + O(t^25) |
| 1008 | |
| 1009 | TEST: |
| 1010 | |
| 1011 | The following tests against bugs that were fixed in |
| 1012 | ticket #8972:: |
| 1013 | |
| 1014 | sage: P.<t> = ZZ[] |
| 1015 | sage: R.<x> = P[[]] |
| 1016 | sage: 1/(t*x) |
| 1017 | 1/t*x^-1 |
| 1018 | sage: R.<t> = PowerSeriesRing(ZZ.quo(15)) |
| 1019 | sage: t/(1+t) |
| 1020 | t + 14*t^2 + t^3 + 14*t^4 + t^5 + 14*t^6 + t^7 + 14*t^8 + t^9 + 14*t^10 + t^11 + 14*t^12 + t^13 + 14*t^14 + t^15 + 14*t^16 + t^17 + 14*t^18 + t^19 + 14*t^20 + O(t^21) |
| 1021 | sage: t/(3+t) |
| 1022 | Traceback (most recent call last): |
| 1023 | ... |
| 1024 | ZeroDivisionError: Inverse does not exist. |
| 1025 | |
979 | 1026 | """ |
980 | 1027 | denom = <PowerSeries>denom_r |
981 | 1028 | if denom.is_zero(): |
982 | 1029 | raise ZeroDivisionError, "Can't divide by something indistinguishable from 0" |
983 | | u = denom.valuation_zero_part() |
984 | | inv = ~u # inverse |
985 | | |
986 | | v = denom.valuation() |
987 | | if v > self.valuation(): |
988 | | R = self._parent.laurent_series_ring() |
989 | | return R(self)/R(denom) |
990 | | |
| 1030 | try: |
| 1031 | F = self._parent.fraction_field() |
| 1032 | except: |
| 1033 | # Inverses may not always exist. So, we try, |
| 1034 | # and if the result exists, it will be in the |
| 1035 | # parent of self. |
| 1036 | return self* ~denom |
991 | 1037 | # Algorithm: Cancel common factors of q from top and bottom, |
992 | 1038 | # then invert the denominator. We do the cancellation first |
993 | 1039 | # because we can only invert a unit (and remain in the ring |
994 | | # of power series). |
995 | | |
996 | | if v > 0: |
997 | | num = self >> v |
998 | | else: |
999 | | num = self |
1000 | | return num*inv |
| 1040 | # of power series). |
| 1041 | from sage.all import LaurentSeries |
| 1042 | if self.is_zero(): |
| 1043 | return F.zero_element() |
| 1044 | v = denom.valuation() |
| 1045 | w = self.valuation() |
| 1046 | u = denom>>v#denom.valuation_zero_part() |
| 1047 | try: |
| 1048 | inv = ~u |
| 1049 | except: # need to change to the fraction field of the base |
| 1050 | inv = ~(u*F.base().one()) |
| 1051 | return LaurentSeries(F,(self>>w)*inv,w-v,check=False) |
1001 | 1052 | |
1002 | 1053 | def __mod__(self, other): |
1003 | 1054 | """ |
… |
… |
|
1186 | 1237 | - Robert Bradshaw |
1187 | 1238 | |
1188 | 1239 | - William Stein |
| 1240 | |
1189 | 1241 | """ |
1190 | 1242 | if self.is_zero(): |
1191 | 1243 | ans = self._parent(0).O(self.prec()/2) |
… |
… |
|
1257 | 1309 | s = a.parent()([s]) |
1258 | 1310 | for cur_prec in sage.misc.misc.newton_method_sizes(prec)[1:]: |
1259 | 1311 | (<PowerSeries>s)._prec = cur_prec |
1260 | | s = half * (s + a/s) |
| 1312 | s = half * (s + (a * ~s)) |
1261 | 1313 | |
1262 | 1314 | ans = s |
1263 | 1315 | if val != 0: |
diff --git a/sage/schemes/elliptic_curves/ell_wp.py b/sage/schemes/elliptic_curves/ell_wp.py
a
|
b
|
|
321 | 321 | True |
322 | 322 | |
323 | 323 | """ |
324 | | a_recip = 1/a |
| 324 | a_recip = ~a # 1/a |
325 | 325 | B = b * a_recip |
326 | 326 | C = c * a_recip |
327 | 327 | int_B = B.integral() |
328 | 328 | J = int_B.exp() |
329 | | J_recip = 1/J |
| 329 | J_recip = ~J # 1/J |
330 | 330 | CJ = C * J |
331 | 331 | int_CJ = CJ.integral() |
332 | 332 | f = J_recip * (alpha + int_CJ) |
diff --git a/sage/schemes/elliptic_curves/formal_group.py b/sage/schemes/elliptic_curves/formal_group.py
a
|
b
|
|
300 | 300 | return y + O(t**prec) |
301 | 301 | w = self.w(prec+6) # XXX why 6? |
302 | 302 | t = w.parent().gen() |
303 | | y = -(w**(-1)) + O(t**prec) |
| 303 | y = O(t**prec) - (~w) |
| 304 | #y = -(w**(-1)) + O(t**prec) |
304 | 305 | self.__y = (prec, y) |
305 | 306 | return self.__y[1] |
306 | 307 | |
diff --git a/sage/schemes/elliptic_curves/padics.py b/sage/schemes/elliptic_curves/padics.py
a
|
b
|
|
1633 | 1633 | ... g = [R.random_element() for i in range(N)] |
1634 | 1634 | ... g[0] = R(1) |
1635 | 1635 | ... g = Rx(g, len(g)) |
1636 | | ... f = g.derivative() / g |
| 1636 | ... f = g.derivative() * ~g |
1637 | 1637 | ... # perturb f by something whose integral is in I |
1638 | 1638 | ... err = [R.random_element() * p**(N-i) for i in range(N+1)] |
1639 | 1639 | ... err = Rx(err, len(err)) |
… |
… |
|
1661 | 1661 | G = Rx(G.list(), s) |
1662 | 1662 | |
1663 | 1663 | # extend current approximation to be correct to s terms |
1664 | | H = G.derivative() / G - F |
| 1664 | H = G.derivative() * ~G - F# / G - F |
1665 | 1665 | # Do the integral of H over QQ[x] to avoid division by p problems |
1666 | 1666 | H = Rx(Qx(H).integral()) |
1667 | 1667 | G = G * (1 - H) |
diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
a
|
b
|
|
1810 | 1810 | raise ZeroDivisionError, "Cannot divide by zero" |
1811 | 1811 | else: |
1812 | 1812 | raise TypeError, arith_error_message(self, right, div) |
| 1813 | except TypeError: |
| 1814 | try: |
| 1815 | if self._parent.fraction_field() is not self._parent: |
| 1816 | return self._parent.fraction_field()(self)/self._parent.fraction_field()(right) |
| 1817 | else: |
| 1818 | raise RuntimeError |
| 1819 | except: |
| 1820 | if not right: |
| 1821 | raise ZeroDivisionError, "Cannot divide by zero" |
| 1822 | else: |
| 1823 | raise TypeError, arith_error_message(self, right, div) |
| 1824 | |
1813 | 1825 | |
1814 | 1826 | def __idiv__(self, right): |
1815 | 1827 | """ |