133
133
sage: f = 1 - 5*s^29 - 5*s^28*t + 4*s^18*t^35 + \
134
134
4*s^17*t^36 - s^45*t^25 - s^44*t^26 + s^7*t^83 + \
135
135
s^6*t^84 + R.O(101)
136
- sage: h = 1/ f; h
136
+ sage: h = ~ f; h
137
137
1 + 5*s^29 + 5*s^28*t - 4*s^18*t^35 - 4*s^17*t^36 + 25*s^58 + 50*s^57*t
138
138
+ 25*s^56*t^2 + s^45*t^25 + s^44*t^26 - 40*s^47*t^35 - 80*s^46*t^36
139
139
- 40*s^45*t^37 + 125*s^87 + 375*s^86*t + 375*s^85*t^2 + 125*s^84*t^3
159
159
# http://www.gnu.org/licenses/
160
160
#*****************************************************************************
161
161
162
-
163
162
from sage .rings .power_series_ring_element import PowerSeries
164
163
165
164
from sage .rings .polynomial .all import is_PolynomialRing
@@ -580,11 +579,11 @@ def _latex_(self):
580
579
sage: f._latex_()
581
580
'- t_{0}^{4} t_{1}^{3} t_{2}^{4} + 3 t_{0} t_{1}^{4} t_{2}^{7} +
582
581
2 t_{1} t_{2}^{12} + 2 t_{0}^{7} t_{1}^{5} t_{2}^{2}
583
- + O(t0, t1, t2)^15 '
582
+ + O(t0, t1, t2)^{15} '
584
583
"""
585
584
if self ._prec == infinity :
586
585
return "%s" % self ._value ()
587
- return "%(val)s + O(%(gens)s)^%(prec)s" \
586
+ return "%(val)s + O(%(gens)s)^{ %(prec)s} " \
588
587
% {'val' :self ._value ()._latex_ (),
589
588
'gens' :', ' .join (g ._latex_ () for g in self .parent ().gens ()),
590
589
'prec' :self ._prec }
@@ -647,7 +646,7 @@ def __invert__(self):
647
646
648
647
sage: R.<a,b,c> = PowerSeriesRing(ZZ)
649
648
sage: f = 1 + a + b - a*b - b*c - a*c + R.O(4)
650
- sage: 1/ f
649
+ sage: ~ f
651
650
1 - a - b + a^2 + 3*a*b + a*c + b^2 + b*c - a^3 - 5*a^2*b
652
651
- 2*a^2*c - 5*a*b^2 - 4*a*b*c - b^3 - 2*b^2*c + O(a, b, c)^4
653
652
"""
@@ -786,26 +785,142 @@ def _lmul_(self, c):
786
785
f = c * self ._bg_value
787
786
return MPowerSeries (self .parent (), f , prec = f .prec ())
788
787
789
- def _div_ (self , denom_r ):
788
+ def trailing_monomial (self ):
790
789
"""
791
- Division by a unit works, but cancellation doesn't.
790
+ Return the trailing monomial of ``self``
791
+
792
+ EXAMPLE::
793
+
794
+ sage: R.<a,b,c> = PowerSeriesRing(ZZ)
795
+ sage: f = 1 + a + b - a*b + R.O(3)
796
+ sage: f.trailing_monomial()
797
+ 1
798
+ sage: f = a^2*b^3*f; f
799
+ a^2*b^3 + a^3*b^3 + a^2*b^4 - a^3*b^4 + O(a, b, c)^8
800
+ sage: f.trailing_monomial()
801
+ a^2*b^3
792
802
793
803
TESTS::
794
804
805
+ sage: (f-f).trailing_monomial()
806
+ 0
807
+ """
808
+ return self .polynomial ().lt ()
809
+
810
+ def quo_rem (self , other ):
811
+ r"""
812
+ Quotient and remainder for increassing power division
813
+
814
+ INPUT: ``other`` - an element of the same power series ring as ``self``
815
+
816
+ EXAMPLE::
817
+
818
+ sage: R.<a,b,c> = PowerSeriesRing(ZZ)
819
+ sage: f = 1 + a + b - a*b + R.O(3)
820
+ sage: g = 1 + 2*a - 3*a*b + R.O(3)
821
+ sage: q, r = f.quo_rem(g); q, r
822
+ (1 - a + b + 2*a^2 + O(a, b, c)^3, 0 + O(a, b, c)^3)
823
+ sage: f == q*g+r
824
+ True
825
+
826
+ sage: q, r = (a*f).quo_rem(g); q, r
827
+ (a - a^2 + a*b + 2*a^3 + O(a, b, c)^4, 0 + O(a, b, c)^4)
828
+ sage: a*f == q*g+r
829
+ True
830
+
831
+ sage: q, r = (a*f).quo_rem(a*g); q, r
832
+ (1 - a + b + 2*a^2 + O(a, b, c)^3, 0 + O(a, b, c)^4)
833
+ sage: a*f == q*(a*g)+r
834
+ True
835
+
836
+ sage: q, r = (a*f).quo_rem(b*g); q, r
837
+ (a - 3*a^2 + O(a, b, c)^3, a + a^2 + O(a, b, c)^4)
838
+ sage: a*f == q*(b*g)+r
839
+ True
840
+
841
+ TESTS::
842
+
843
+ sage: (f).quo_rem(R.zero())
844
+ Traceback (most recent call last):
845
+ ...
846
+ ZeroDivisionError
847
+
848
+ sage: (f).quo_rem(R.zero().add_bigoh(2))
849
+ Traceback (most recent call last):
850
+ ...
851
+ ZeroDivisionError
852
+ """
853
+ if other .parent () is not self .parent ():
854
+ raise ValueError , "Don't know how to divide by a element of %s" % (other .parent ())
855
+ other_tt = other .trailing_monomial ()
856
+ if not other_tt :
857
+ raise ZeroDivisionError ()
858
+ mprec = min (self .prec (), other .prec ())
859
+ rem = self .parent ().zero ().add_bigoh (self .prec ())
860
+ quo = self .parent ().zero ().add_bigoh (self .prec ()- other .valuation ())
861
+ while self :
862
+ self_tt = self .trailing_monomial ()
863
+ assert self_tt
864
+ if not other_tt .divides (self_tt ):
865
+ self -= self_tt
866
+ rem += self_tt
867
+ else :
868
+ d = self_tt // other_tt
869
+ self -= d * other
870
+ quo += d
871
+ quo = quo .add_bigoh (self .prec ()- other_tt .degree ())
872
+ return quo , rem
873
+
874
+ def _div_ (self , denom_r ):
875
+ r"""
876
+ Division in the ring of power series.
877
+
878
+ EXAMPLE::
879
+
795
880
sage: R.<a,b,c> = PowerSeriesRing(ZZ)
796
881
sage: f = 1 + a + b - a*b + R.O(3)
797
882
sage: g = 1/f; g #indirect doctest
798
883
1 - a - b + a^2 + 3*a*b + b^2 + O(a, b, c)^3
799
884
sage: g in R
800
885
True
801
- sage: g = a/(a*f)
886
+ sage: g == ~f
887
+ True
888
+
889
+ When possible, division by non unit also works::
890
+
891
+ sage: a/(a*f)
892
+ 1 - a - b + a^2 + 3*a*b + b^2 + O(a, b, c)^3
893
+
894
+ sage: a/(R.zero())
895
+ Traceback (most recent call last):
896
+ ZeroDivisionError
897
+
898
+ sage: (a*f)/f
899
+ a + O(a, b, c)^4
900
+ sage: f/(a*f)
802
901
Traceback (most recent call last):
803
902
...
804
- TypeError: denominator must be a unit
903
+ ValueError: Not divisible
904
+
905
+ An example where one looses precision::
906
+
907
+ sage: ((1+a)*f - f) / a*f
908
+ 1 + 2*a + 2*b + O(a, b, c)^2
805
909
910
+ TESTS::
911
+
912
+ sage: ((a+b)*f) / f == (a+b)
913
+ True
914
+ sage: ((a+b)*f) / (a+b) == f
915
+ True
806
916
"""
807
- f = self ._bg_value / denom_r ._bg_value
808
- return MPowerSeries (self .parent (), f , prec = f .prec ())
917
+ if denom_r .is_unit (): # faster if denom_r is a unit
918
+ return self * ~ denom_r
919
+ quo , rem = self .quo_rem (denom_r )
920
+ if rem :
921
+ raise ValueError ("Not divisible" )
922
+ else :
923
+ return quo
809
924
810
925
# def _r_action_(self, c):
811
926
# # multivariate power series rings are assumed to be commutative
@@ -1318,7 +1433,7 @@ def derivative(self, *args):
1318
1433
The formal derivative of this power series, with respect to
1319
1434
variables supplied in ``args``.
1320
1435
1321
- TESTS ::
1436
+ EXAMPLES ::
1322
1437
1323
1438
sage: T.<a,b> = PowerSeriesRing(ZZ,2)
1324
1439
sage: f = a + b + a^2*b + T.O(5)
@@ -1342,6 +1457,124 @@ def derivative(self, *args):
1342
1457
new_prec = max (self .prec ()- len (variables ), 0 )
1343
1458
return R (deriv ) + R .O (new_prec )
1344
1459
1460
+ def integral (self , * args ):
1461
+ """
1462
+ The formal integral of this multivariate power series, with respect to
1463
+ variables supplied in ``args``.
1464
+
1465
+ EXAMPLES::
1466
+
1467
+ sage: T.<a,b> = PowerSeriesRing(QQ,2)
1468
+ sage: f = a + b + a^2*b + T.O(5)
1469
+ sage: f.integral(a, 2)
1470
+ 1/6*a^3 + 1/2*a^2*b + 1/12*a^4*b + O(a, b)^7
1471
+ sage: f.integral(a, b)
1472
+ 1/2*a^2*b + 1/2*a*b^2 + 1/6*a^3*b^2 + O(a, b)^7
1473
+ sage: f.integral(a, 5)
1474
+ 1/720*a^6 + 1/120*a^5*b + 1/2520*a^7*b + O(a, b)^10
1475
+
1476
+ Only integration with respect to variables works::
1477
+
1478
+ sage: f.integral(a+b)
1479
+ Traceback (most recent call last):
1480
+ ...
1481
+ ValueError: a + b is not a variable
1482
+
1483
+ .. warning:: Coefficient division.
1484
+
1485
+ If the base ring is not a field (e.g. `ZZ`), or if it has a non
1486
+ zero characteristic, (e.g. `ZZ/3ZZ`), integration is not always
1487
+ possible, while staying with the same base ring. In the first
1488
+ case, Sage will report that it hasn't been able to coerce some
1489
+ coefficient to the base ring::
1490
+
1491
+ sage: T.<a,b> = PowerSeriesRing(ZZ,2)
1492
+ sage: f = a + T.O(5)
1493
+ sage: f.integral(a)
1494
+ Traceback (most recent call last):
1495
+ ...
1496
+ TypeError: no conversion of this rational to integer
1497
+
1498
+ One can get the correct result by changing the base ring first::
1499
+
1500
+ sage: f.change_ring(QQ).integral(a)
1501
+ 1/2*a^2 + O(a, b)^6
1502
+
1503
+ However, a correct result is returned if the denominator cancels::
1504
+
1505
+ sage: f = 2*b + T.O(5)
1506
+ sage: f.integral(b)
1507
+ b^2 + O(a, b)^6
1508
+
1509
+ In non zero characteristic, Sage will report that a zero division
1510
+ occurred ::
1511
+
1512
+ sage: T.<a,b> = PowerSeriesRing(Zmod(3),2)
1513
+ sage: (a^3).integral(a)
1514
+ a^4
1515
+ sage: (a^2).integral(a)
1516
+ Traceback (most recent call last):
1517
+ ...
1518
+ ZeroDivisionError: Inverse does not exist.
1519
+ """
1520
+ from sage .misc .derivative import derivative_parse
1521
+ res = self
1522
+ for v in derivative_parse (args ):
1523
+ res = res ._integral (v )
1524
+ return res
1525
+
1526
+ def _integral (self , xx ):
1527
+ """
1528
+ Formal integral for multivariate power series
1529
+
1530
+ INPUT: ``xx`` a generator of the power series ring
1531
+
1532
+ EXAMPLES::
1533
+
1534
+ sage: T.<a,b> = PowerSeriesRing(QQ,2)
1535
+ sage: f = a + b + a^2*b + T.O(5)
1536
+ sage: f._integral(a)
1537
+ 1/2*a^2 + a*b + 1/3*a^3*b + O(a, b)^6
1538
+ sage: f._integral(b)
1539
+ a*b + 1/2*b^2 + 1/2*a^2*b^2 + O(a, b)^6
1540
+
1541
+ TESTS:
1542
+
1543
+ We try to recognise variables even if they are not recognized as
1544
+ genrators of the rings::
1545
+
1546
+ sage: T.<a,b> = PowerSeriesRing(QQ,2)
1547
+ sage: a.is_gen()
1548
+ True
1549
+ sage: (a+0).is_gen()
1550
+ False
1551
+ sage: (a+b).integral(a+0)
1552
+ 1/2*a^2 + a*b
1553
+
1554
+ sage: T.<a,b> = PowerSeriesRing(ZZ,2)
1555
+ sage: aa = a.change_ring(Zmod(5))
1556
+ sage: aa.is_gen()
1557
+ False
1558
+ sage: aa.integral(aa)
1559
+ -2*a^2
1560
+ sage: aa.integral(a)
1561
+ -2*a^2
1562
+ """
1563
+ P = self .parent ()
1564
+ R = P .base_ring ()
1565
+ xx = P (xx )
1566
+ if not xx .is_gen ():
1567
+ for g in P .gens (): # try to find a generator equal to xx
1568
+ if g == xx :
1569
+ xx = g
1570
+ break
1571
+ else :
1572
+ raise ValueError , "%s is not a variable" % (xx )
1573
+ xxe = xx .exponents ()[0 ]
1574
+ pos = [i for i , c in enumerate (xxe ) if c != 0 ][0 ] # get the position of the variable
1575
+ res = { mon .eadd (xxe ) : R (co / (mon [pos ]+ 1 )) for mon , co in self .dict ().iteritems () }
1576
+ return P ( res ).add_bigoh (self .prec ()+ 1 )
1577
+
1345
1578
def ogf (self ):
1346
1579
"""
1347
1580
Method from univariate power series not yet implemented
0 commit comments