Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/sage/categories/pushout.py
Original file line number Diff line number Diff line change
Expand Up @@ -2466,12 +2466,12 @@ class CompletionFunctor(ConstructionFunctor):
True

sage: P.<x> = ZZ[]
sage: Px = P.completion(x) # currently the only implemented completion of P
sage: Px = P.completion(x)
sage: Px
Power Series Ring in x over Integer Ring
Completion of Univariate Polynomial Ring in x over Integer Ring at x
sage: F3 = Px.construction()[0]
sage: F3(GF(3)['x'])
Power Series Ring in x over Finite Field of size 3
Completion of Univariate Polynomial Ring in x over Finite Field of size 3 at x

TESTS::

Expand All @@ -2484,7 +2484,7 @@ class CompletionFunctor(ConstructionFunctor):
(1 + O(5^20))*a + 3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 2*5^8 + 2*5^9 + 2*5^10 + 2*5^11 + 2*5^12 + 2*5^13 + 2*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 2*5^18 + 2*5^19 + O(5^20)
"""
rank = 4
_real_types = ['Interval', 'Ball', 'MPFR', 'RDF', 'RLF', 'RR']
_real_types = [None, 'Interval', 'Ball', 'MPFR', 'RDF', 'RLF', 'RR']
_dvr_types = [None, 'fixed-mod', 'floating-point', 'capped-abs', 'capped-rel', 'lattice-cap', 'lattice-float', 'relaxed']

def __init__(self, p, prec, extras=None):
Expand Down Expand Up @@ -2541,7 +2541,7 @@ def __init__(self, p, prec, extras=None):
from sage.rings.infinity import Infinity
if self.p == Infinity:
if self.type not in self._real_types:
raise ValueError("completion type must be one of %s" % (", ".join(self._real_types)))
raise ValueError("completion type must be one of %s" % (", ".join(self._real_types[1:])))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When can the type be None?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When called with a polynomial ring and Infinity (which was not implemented beforehand).

elif self.type not in self._dvr_types:
raise ValueError("completion type must be one of %s" % (", ".join(self._dvr_types[1:])))

Expand Down Expand Up @@ -2777,9 +2777,9 @@ def commutes(self, other):
functors in opposite order works. It does::

sage: P.<x> = ZZ[]
sage: C = P.completion(x).construction()[0]
sage: C = P.completion('x').construction()[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does P.completion(x) no longer work? It ought to work right?

Copy link
Contributor Author

@xcaruso xcaruso Aug 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.completion(x) works but it now returns a CompletionPolynomialRing.
This doctest actually fails without the modification but IMO, it is the fault of the doctest that pretends that completion commutes with localization, which is not true.
In this precise example, for example, the fraction field of the completion of $\mathbb Z[x]$ is a strict subfield of $\mathbb Q((x))$ (= the completion of the fraction field of $\mathbb Z[x]$).

sage: R = FractionField(P)
sage: hasattr(R,'completion')
sage: hasattr(R, 'completion')
False
sage: C(R) is Frac(C(P))
True
Expand Down
2 changes: 1 addition & 1 deletion src/sage/monoids/trace_monoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ def number_of_words(self, length):
sage: M.number_of_words(3) # needs sage.graphs
48
"""
psr = PowerSeriesRing(ZZ, default_prec=length + 1)
psr = PowerSeriesRing(ZZ, 'x', default_prec=length + 1)
return psr(self.dependence_polynomial()).coefficients()[length]

@cached_method
Expand Down
39 changes: 31 additions & 8 deletions src/sage/rings/big_oh.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

lazy_import('sage.rings.padics.factory', ['Qp', 'Zp'])
from sage.rings.polynomial.polynomial_element import Polynomial
from sage.rings.fraction_field_element import FractionFieldElement
from sage.rings.fraction_field_FpT import FpTElement

try:
from .puiseux_series_ring_element import PuiseuxSeries
Expand Down Expand Up @@ -47,6 +49,16 @@ def O(*x, **kwds):
O(x^100)
sage: 1/(1+x+O(x^5))
1 - x + x^2 - x^3 + x^4 + O(x^5)

Completion at other places also works::

sage: x^3 + O((x^2 + 1)^10)
-x + x*(x^2 + 1) + O((x^2 + 1)^10)
sage: x^3 + O(1/x^10) # completion at infinity
x^3 + O(x^-10)

An example with several variables::

sage: R.<u,v> = QQ[[]]
sage: 1 + u + v^2 + O(u, v)^5
1 + u + v^2 + O(u, v)^5
Expand Down Expand Up @@ -126,11 +138,6 @@ def O(*x, **kwds):

::

sage: R.<x> = QQ[]
sage: O(2*x)
Traceback (most recent call last):
...
NotImplementedError: completion only currently defined for the maximal ideal (x)
sage: R.<x> = LazyPowerSeriesRing(QQ)
sage: O(x^5)
O(x^5)
Expand Down Expand Up @@ -169,13 +176,29 @@ def O(*x, **kwds):
if isinstance(x, power_series_ring_element.PowerSeries):
return x.parent()(0, x.degree(), **kwds)

if isinstance(x, (FractionFieldElement, FpTElement)):
if x.denominator().is_one():
x = x.numerator()
elif x.numerator().is_one():
x = x.denominator()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels fishy, what if the element is like (x^2+1)^(-2)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the numerator is $1$, no?
The point is that, if we have at the same time a numerator and a denominator, then it's not a valid completion.

if isinstance(x, Polynomial) and x.is_monomial():
from sage.rings.infinity import infinity
C = x.parent().completion(infinity)
n = x.degree()
return C.zero().add_bigoh(n)

if isinstance(x, Polynomial):
if x.parent().ngens() != 1:
A = x.parent()
if A.ngens() != 1:
raise NotImplementedError("completion only currently defined "
"for univariate polynomials")
if x.is_monomial():
C = A.completion(A.variable_name())
n = x.degree()
if not x.is_monomial():
raise NotImplementedError("completion only currently defined "
"for the maximal ideal (x)")
p, n = x.perfect_power()
C = A.completion(p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test where p is not a perfect power of an irreducible and ensure that an error is raised.

Maybe also add a test where elements from two different parents are added, make sure they are not implicitly coercible.

Copy link
Contributor Author

@xcaruso xcaruso Aug 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, for functoriality, it is nice to have completion at nonmaximal ideals.

return C.zero().add_bigoh(n)

if isinstance(x, (int, Integer, Rational)):
# p-adic number
Expand Down
Loading
Loading