@@ -1053,18 +1053,27 @@ def __bool__(self):
1053
1053
sage: L.<z> = LazyLaurentSeriesRing(GF(2))
1054
1054
sage: bool(z - z)
1055
1055
False
1056
- sage: f = 1/(1 - z)
1057
- sage: bool(f)
1056
+ sage: bool(1/(1 - z))
1058
1057
True
1059
1058
sage: M = L(lambda n: n, valuation=0); M
1060
1059
z + z^3 + z^5 + O(z^7)
1061
1060
sage: M.is_zero()
1062
1061
False
1063
1062
sage: M = L(lambda n: 2*n if n < 10 else 1, valuation=0); M
1064
1063
O(z^7)
1065
- sage: bool(M) # optional - sage.rings.finite_rings
1064
+ sage: bool(M)
1066
1065
True
1067
- sage: M[15] # optional - sage.rings.finite_rings
1066
+
1067
+ With the `secure` option, we raise an error if we cannot know
1068
+ whether the series is zero or not::
1069
+
1070
+ sage: # needs sage.rings.finite_rings
1071
+ sage: L.options.secure = True
1072
+ sage: bool(M)
1073
+ Traceback (most recent call last):
1074
+ ...
1075
+ ValueError: undecidable
1076
+ sage: M[15]
1068
1077
1
1069
1078
sage: bool(M)
1070
1079
True
@@ -1073,12 +1082,15 @@ def __bool__(self):
1073
1082
sage: L.<z> = LazyLaurentSeriesRing(GF(2), sparse=True)
1074
1083
sage: M = L(lambda n: 2*n if n < 10 else 1, valuation=0); M
1075
1084
O(z^7)
1076
- sage: bool(M) # optional - sage.rings.finite_rings
1077
- True
1078
- sage: M[15] # optional - sage.rings.finite_rings
1085
+ sage: bool(M)
1086
+ Traceback (most recent call last):
1087
+ ...
1088
+ ValueError: undecidable
1089
+ sage: M[15]
1079
1090
1
1080
1091
sage: bool(M)
1081
1092
True
1093
+ sage: L.options._reset()
1082
1094
1083
1095
Uninitialized series::
1084
1096
@@ -1108,12 +1120,14 @@ def __bool__(self):
1108
1120
1109
1121
Comparison with finite halting precision::
1110
1122
1123
+ sage: # needs sage.rings.finite_rings
1111
1124
sage: M = L(lambda n: 2*n if n < 10 else 0, valuation=0)
1112
1125
sage: bool(M)
1113
1126
True
1114
1127
sage: M.is_zero()
1115
1128
False
1116
1129
1130
+ sage: # needs sage.rings.finite_rings
1117
1131
sage: L.options.halting_precision = 20
1118
1132
sage: bool(M)
1119
1133
False
@@ -1124,12 +1138,14 @@ def __bool__(self):
1124
1138
be indistinguishable from zero until possibly enough
1125
1139
coefficients are computed::
1126
1140
1141
+ sage: # needs sage.rings.finite_rings
1127
1142
sage: L.<z> = LazyLaurentSeriesRing(GF(2))
1128
1143
sage: L.options.halting_precision = 20
1129
1144
sage: f = L(lambda n: 0, valuation=0)
1130
1145
sage: f.is_zero()
1131
1146
True
1132
1147
1148
+ sage: # needs sage.rings.finite_rings
1133
1149
sage: g = L(lambda n: 0 if n < 50 else 1, valuation=2)
1134
1150
sage: bool(g) # checks up to degree 22 = 2 + 20
1135
1151
False
@@ -1364,7 +1380,7 @@ def define(self, s):
1364
1380
sage: E = L(lambda n: s[n], valuation=0)
1365
1381
sage: X = L(s[1])
1366
1382
sage: A = L.undefined()
1367
- sage: A.define(X*E(A, check=False ))
1383
+ sage: A.define(X*E(A))
1368
1384
sage: A[:6]
1369
1385
[m[1],
1370
1386
2*m[1, 1] + m[2],
@@ -1645,8 +1661,8 @@ def _ascii_art_(self):
1645
1661
sage: L.options.display_length = 3
1646
1662
sage: ascii_art(1 / (1 - e[1]*z))
1647
1663
e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3)
1648
- sage: x = L.undefined(valuation=0) # optional - sage.combinat
1649
- sage: ascii_art(x + x^2 - 5) # optional - sage.combinat
1664
+ sage: x = L.undefined(valuation=0)
1665
+ sage: ascii_art(x + x^2 - 5)
1650
1666
Uninitialized Lazy Series
1651
1667
sage: L.options._reset()
1652
1668
"""
@@ -1669,8 +1685,8 @@ def _unicode_art_(self):
1669
1685
sage: L.options.display_length = 3
1670
1686
sage: unicode_art(1 / (1 - e[1]*z))
1671
1687
e[] + e[1]*z + e[1, 1]*z^2 + O(e[]*z^3)
1672
- sage: x = L.undefined(valuation=0) # optional - sage.combinat
1673
- sage: unicode_art(x + x^2 - 5) # optional - sage.combinat
1688
+ sage: x = L.undefined(valuation=0)
1689
+ sage: unicode_art(x + x^2 - 5)
1674
1690
Uninitialized Lazy Series
1675
1691
sage: L.options._reset()
1676
1692
"""
@@ -3267,10 +3283,20 @@ def __invert__(self):
3267
3283
Traceback (most recent call last):
3268
3284
...
3269
3285
ZeroDivisionError: cannot divide by a series of positive valuation
3286
+
3287
+ Check that :issue:`36253` is fixed::
3288
+
3289
+ sage: f = L(lambda n: n)
3290
+ sage: ~f
3291
+ Traceback (most recent call last):
3292
+ ...
3293
+ ZeroDivisionError: cannot divide by a series of positive valuation
3270
3294
"""
3271
3295
P = self .parent ()
3272
3296
coeff_stream = self ._coeff_stream
3273
- if P ._minimal_valuation is not None and coeff_stream ._approximate_order > 0 :
3297
+ if (P ._minimal_valuation is not None
3298
+ and (coeff_stream ._approximate_order > 0
3299
+ or not coeff_stream .is_uninitialized () and not coeff_stream [0 ])):
3274
3300
raise ZeroDivisionError ("cannot divide by a series of positive valuation" )
3275
3301
3276
3302
# the inverse is exact if and only if coeff_stream corresponds to one of
@@ -3425,6 +3451,9 @@ def _div_(self, other):
3425
3451
ZeroDivisionError: cannot divide by 0
3426
3452
sage: L.options._reset()
3427
3453
"""
3454
+ # currently __invert__ and _div_ behave differently with
3455
+ # respect to division by lazy power series of positive
3456
+ # valuation, so we cannot call ~other if self.is_one()
3428
3457
if not other :
3429
3458
raise ZeroDivisionError ("cannot divide by 0" )
3430
3459
@@ -3603,7 +3632,7 @@ def exp(self):
3603
3632
P = self .parent ()
3604
3633
R = self .base_ring ()
3605
3634
coeff_stream = self ._coeff_stream
3606
- # TODO: coefficients should not be checked here, it prevents
3635
+ # coefficients must not be checked here, it prevents
3607
3636
# us from using self.define in some cases!
3608
3637
if ((not coeff_stream .is_uninitialized ())
3609
3638
and any (coeff_stream [i ] for i in range (coeff_stream ._approximate_order , 1 ))):
@@ -3656,7 +3685,7 @@ def log(self):
3656
3685
P = self .parent ()
3657
3686
R = self .base_ring ()
3658
3687
coeff_stream = self ._coeff_stream
3659
- # TODO: coefficients should not be checked here, it prevents
3688
+ # coefficients must not be checked here, it prevents
3660
3689
# us from using self.define in some cases!
3661
3690
if ((not coeff_stream .is_uninitialized ())
3662
3691
and (any (coeff_stream [i ] for i in range (coeff_stream ._approximate_order , 0 ))
@@ -3798,7 +3827,7 @@ def _im_gens_(self, codomain, im_gens, base_map=None):
3798
3827
3799
3828
return codomain (self .map_coefficients (base_map )(im_gens [0 ]))
3800
3829
3801
- def __call__ (self , g , * , check = True ):
3830
+ def __call__ (self , g ):
3802
3831
r"""
3803
3832
Return the composition of ``self`` with ``g``.
3804
3833
@@ -4192,18 +4221,18 @@ def __call__(self, g, *, check=True):
4192
4221
raise NotImplementedError ("can only compose with a lazy series" )
4193
4222
4194
4223
# Perhaps we just don't yet know if the valuation is positive
4195
- if check :
4196
- if g ._coeff_stream ._approximate_order <= 0 :
4197
- if any (g ._coeff_stream [i ] for i in range (g ._coeff_stream ._approximate_order , 1 )):
4198
- raise ValueError ("can only compose with a positive valuation series" )
4199
- g ._coeff_stream ._approximate_order = 1
4224
+ if g . _coeff_stream . _approximate_order <= 0 :
4225
+ if ( not g ._coeff_stream .is_uninitialized ()
4226
+ and any (g ._coeff_stream [i ] for i in range (g ._coeff_stream ._approximate_order , 1 ) )):
4227
+ raise ValueError ("can only compose with a positive valuation series" )
4228
+ g ._coeff_stream ._approximate_order = 1
4200
4229
4201
4230
if isinstance (g , LazyDirichletSeries ):
4202
- if check :
4203
- if g ._coeff_stream ._approximate_order == 1 :
4204
- if g ._coeff_stream [1 ] != 0 :
4205
- raise ValueError ("can only compose with a positive valuation series" )
4206
- g ._coeff_stream ._approximate_order = 2
4231
+ if g . _coeff_stream . _approximate_order == 1 :
4232
+ if ( not g ._coeff_stream .is_uninitialized ()
4233
+ and g ._coeff_stream [1 ] != 0 ) :
4234
+ raise ValueError ("can only compose with a positive valuation series" )
4235
+ g ._coeff_stream ._approximate_order = 2
4207
4236
# we assume that the valuation of self[i](g) is at least i
4208
4237
4209
4238
def coefficient (n ):
@@ -4362,6 +4391,7 @@ def revert(self):
4362
4391
R = P .base_ring ()
4363
4392
# we cannot assume that the last initial coefficient
4364
4393
# and the constant differ, see stream.Stream_exact
4394
+ # TODO: provide example or remove this claim
4365
4395
if (coeff_stream ._degree == 1 + len (coeff_stream ._initial_coefficients )
4366
4396
and coeff_stream ._constant == - R .one ()
4367
4397
and all (c == - R .one () for c in coeff_stream ._initial_coefficients )):
@@ -4785,7 +4815,7 @@ def _im_gens_(self, codomain, im_gens, base_map=None):
4785
4815
4786
4816
return codomain (self .map_coefficients (base_map )(* im_gens ))
4787
4817
4788
- def __call__ (self , * g , check = True ):
4818
+ def __call__ (self , * g ):
4789
4819
r"""
4790
4820
Return the composition of ``self`` with ``g``.
4791
4821
@@ -5038,18 +5068,17 @@ def __call__(self, *g, check=True):
5038
5068
g = [P (h ) for h in g ]
5039
5069
R = P ._internal_poly_ring .base_ring ()
5040
5070
5041
- if check :
5042
- for h in g :
5043
- if h ._coeff_stream ._approximate_order == 0 :
5044
- if h [0 ]:
5045
- raise ValueError ("can only compose with a positive valuation series" )
5046
- h ._coeff_stream ._approximate_order = 1
5071
+ for h in g :
5072
+ if h ._coeff_stream ._approximate_order == 0 :
5073
+ if not h ._coeff_stream .is_uninitialized () and h [0 ]:
5074
+ raise ValueError ("can only compose with a positive valuation series" )
5075
+ h ._coeff_stream ._approximate_order = 1
5047
5076
5048
- if isinstance (h , LazyDirichletSeries ):
5049
- if h ._coeff_stream ._approximate_order == 1 :
5050
- if h ._coeff_stream [1 ] != 0 :
5051
- raise ValueError ("can only compose with a positive valuation series" )
5052
- h ._coeff_stream ._approximate_order = 2
5077
+ if isinstance (h , LazyDirichletSeries ):
5078
+ if h ._coeff_stream ._approximate_order == 1 :
5079
+ if not h . _coeff_stream . is_uninitialized () and h ._coeff_stream [1 ] != 0 :
5080
+ raise ValueError ("can only compose with a positive valuation series" )
5081
+ h ._coeff_stream ._approximate_order = 2
5053
5082
5054
5083
# We now have that every element of g has a _coeff_stream
5055
5084
sorder = self ._coeff_stream ._approximate_order
@@ -5782,7 +5811,7 @@ def is_unit(self):
5782
5811
return False
5783
5812
return self [0 ].is_unit ()
5784
5813
5785
- def __call__ (self , * args , check = True ):
5814
+ def __call__ (self , * args ):
5786
5815
r"""
5787
5816
Return the composition of ``self`` with ``g``.
5788
5817
@@ -5968,10 +5997,10 @@ def __call__(self, *args, check=True):
5968
5997
P = LazySymmetricFunctions (R )
5969
5998
g = P (g )
5970
5999
5971
- if check and not (isinstance (self ._coeff_stream , Stream_exact )
5972
- and not self ._coeff_stream ._constant ):
6000
+ if not (isinstance (self ._coeff_stream , Stream_exact )
6001
+ and not self ._coeff_stream ._constant ):
5973
6002
if g ._coeff_stream ._approximate_order == 0 :
5974
- if g [0 ]:
6003
+ if not g . _coeff_stream . is_uninitialized () and g [0 ]:
5975
6004
raise ValueError ("can only compose with a positive valuation series" )
5976
6005
g ._coeff_stream ._approximate_order = 1
5977
6006
@@ -6254,6 +6283,7 @@ def functorial_composition(self, *args):
6254
6283
6255
6284
The symmetric function `\sum_n h_n` is a left absorbing element::
6256
6285
6286
+ sage: # needs sage.modules
6257
6287
sage: H.functorial_composition(f) - H
6258
6288
O^7
6259
6289
@@ -6370,7 +6400,7 @@ def coefficient(n):
6370
6400
else :
6371
6401
raise NotImplementedError ("only implemented for arity 1" )
6372
6402
6373
- def arithmetic_product (self , * args , check = True ):
6403
+ def arithmetic_product (self , * args ):
6374
6404
r"""
6375
6405
Return the arithmetic product of ``self`` with ``g``.
6376
6406
@@ -6419,9 +6449,6 @@ def arithmetic_product(self, *args, check=True):
6419
6449
6420
6450
- ``g`` -- a cycle index series having the same parent as ``self``
6421
6451
6422
- - ``check`` -- (default: ``True``) a Boolean which, when set
6423
- to ``False``, will cause input checks to be skipped
6424
-
6425
6452
OUTPUT:
6426
6453
6427
6454
The arithmetic product of ``self`` with ``g``.
@@ -6565,15 +6592,11 @@ def arithmetic_product(self, *args, check=True):
6565
6592
and not g ._coeff_stream ._constant ):
6566
6593
gs = g .symmetric_function ()
6567
6594
c += self [0 ].arithmetic_product (gs )
6568
- elif check :
6569
- raise ValueError ("can only take the arithmetic product with a positive valuation series" )
6570
6595
if g [0 ]:
6571
6596
if (isinstance (self ._coeff_stream , Stream_exact )
6572
6597
and not self ._coeff_stream ._constant ):
6573
6598
fs = self .symmetric_function ()
6574
6599
c += fs .arithmetic_product (g [0 ])
6575
- elif check :
6576
- raise ValueError ("can only take the arithmetic product with a positive valuation series" )
6577
6600
6578
6601
p = R .realization_of ().p ()
6579
6602
# TODO: does the following introduce a memory leak?
@@ -6848,7 +6871,7 @@ def __invert__(self):
6848
6871
return P .element_class (P , Stream_dirichlet_invert (self ._coeff_stream ,
6849
6872
P .is_sparse ()))
6850
6873
6851
- def __call__ (self , p , * , check = True ):
6874
+ def __call__ (self , p ):
6852
6875
r"""
6853
6876
Return the composition of ``self`` with a linear polynomial ``p``.
6854
6877
0 commit comments