Skip to content

Commit e7399bf

Browse files
author
Release Manager
committed
Trac #8972: Inversion and fraction fields for power series rings
This ticket is about at least three bugs related with inversion of elements of power series rings. Here is the first: {{{ sage: R.<x> = ZZ[[]] sage: (1/x).parent() Laurent Series Ring in x over Integer Ring sage: (x/x).parent() Power Series Ring in x over Integer Ring }}} ''Both'' parents are wrong. Usually, the parent of ``a/b`` is the fraction field of the parent of ``a,b``, even if ``a==b``. And neither above parent is a field. Next bug: {{{ sage: (1/(2*x)).parent() ERROR: An unexpected error occurred while tokenizing input The following traceback may be corrupted or invalid The error message is: ('EOF in multi-line statement', (919, 0)) ------------------------------------------------------------------------ --- TypeError Traceback (most recent call last) ... very long traceback TypeError: no conversion of this rational to integer }}} And the third: {{{ sage: F = FractionField(R) sage: 1/x in F False }}} With the proposed patch, we solve all bugs except {{{ sage: (x/x).parent() Power Series Ring in x over Integer Ring }}} ---- Apply (old): * [attachment:trac-8972_fraction_of_power_series_combined.patch] URL: https://trac.sagemath.org/8972 Reported by: SimonKing Ticket author(s): Simon King, Michael Jung Reviewer(s): Robert Bradshaw, Travis Scrimshaw
2 parents df91b09 + 5aca068 commit e7399bf

4 files changed

+59
-13
lines changed

src/sage/rings/laurent_series_ring_element.pyx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,8 @@ cdef class LaurentSeries(AlgebraElement):
10801080
raise ZeroDivisionError
10811081
try:
10821082
return type(self)(self._parent,
1083-
self.__u / right.__u,
1084-
self.__n - right.__n)
1083+
self.__u / right.__u,
1084+
self.__n - right.__n)
10851085
except TypeError as msg:
10861086
# todo: this could also make something in the formal fraction field.
10871087
raise ArithmeticError("division not defined")

src/sage/rings/power_series_poly.pyx

+30-7
Original file line numberDiff line numberDiff line change
@@ -610,8 +610,9 @@ cdef class PowerSeries_poly(PowerSeries):
610610
that `XY = 1`).
611611
612612
The first nonzero coefficient must be a unit in
613-
the coefficient ring. If the valuation of the series is positive,
614-
this function will return a :doc:`laurent_series_ring_element`.
613+
the coefficient ring. If the valuation of the series is positive or
614+
`X` is not a unit, this function will return a
615+
:class:`sage.rings.laurent_series_ring_element.LaurentSeries`.
615616
616617
EXAMPLES::
617618
@@ -666,15 +667,32 @@ cdef class PowerSeries_poly(PowerSeries):
666667
sage: u*v
667668
1 + O(t^12)
668669
669-
We try a non-zero, non-unit leading coefficient::
670+
If we try a non-zero, non-unit constant term, we end up in
671+
the fraction field, i.e. the Laurent series ring::
670672
671673
sage: R.<t> = PowerSeriesRing(ZZ)
672674
sage: ~R(2)
673-
Traceback (most recent call last):
674-
...
675-
ValueError: constant term is not a unit
675+
1/2
676+
sage: parent(~R(2))
677+
Laurent Series Ring in t over Rational Field
678+
679+
As for units, we stay in the power series ring::
680+
676681
sage: ~R(-1)
677682
-1
683+
sage: parent(~R(-1))
684+
Power Series Ring in t over Integer Ring
685+
686+
However, inversion of non-unit elements must fail when the underlying
687+
ring is not an integral domain::
688+
689+
sage: R = IntegerModRing(8)
690+
sage: P.<s> = R[[]]
691+
sage: ~P(2)
692+
Traceback (most recent call last):
693+
...
694+
ValueError: must be an integral domain
695+
678696
"""
679697
if self.is_one():
680698
return self
@@ -686,7 +704,12 @@ cdef class PowerSeries_poly(PowerSeries):
686704
# constant series
687705
a = self[0]
688706
if not a.is_unit():
689-
raise ValueError("constant term is not a unit")
707+
from sage.categories.integral_domains import IntegralDomains
708+
if self._parent in IntegralDomains():
709+
R = self._parent.fraction_field()
710+
return 1 / R(a)
711+
else:
712+
raise ValueError('must be an integral domain')
690713
try:
691714
a = a.inverse_unit()
692715
except (AttributeError, NotImplementedError):

src/sage/rings/power_series_ring.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,8 @@ def _element_constructor_(self, f, prec=infinity, check=True):
730730
sage: R(1/x, 5)
731731
Traceback (most recent call last):
732732
...
733-
TypeError: no canonical coercion from Laurent Series Ring in t over Integer Ring to Power Series Ring in t over Integer Ring
733+
TypeError: no canonical coercion from Laurent Series Ring in t over
734+
Rational Field to Power Series Ring in t over Integer Ring
734735
735736
sage: PowerSeriesRing(PowerSeriesRing(QQ,'x'),'y')(x)
736737
x
@@ -860,7 +861,8 @@ def _coerce_impl(self, x):
860861
sage: R._coerce_(1/t)
861862
Traceback (most recent call last):
862863
...
863-
TypeError: no canonical coercion from Laurent Series Ring in t over Integer Ring to Power Series Ring in t over Integer Ring
864+
TypeError: no canonical coercion from Laurent Series Ring in t over
865+
Rational Field to Power Series Ring in t over Integer Ring
864866
sage: R._coerce_(5)
865867
5
866868
sage: tt = PolynomialRing(ZZ,'t').gen()

src/sage/rings/power_series_ring_element.pyx

+23-2
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,24 @@ cdef class PowerSeries(AlgebraElement):
10641064
t + O(t^21)
10651065
sage: (t^5/(t^2 - 2)) * (t^2 -2 )
10661066
t^5 + O(t^25)
1067+
1068+
TESTS:
1069+
1070+
The following tests against bugs that were fixed in :trac:`8972`::
1071+
1072+
sage: P.<t> = ZZ[]
1073+
sage: R.<x> = P[[]]
1074+
sage: 1/(t*x)
1075+
1/t*x^-1
1076+
sage: R.<x> = ZZ[[]]
1077+
sage: (1/x).parent()
1078+
Laurent Series Ring in x over Rational Field
1079+
sage: F = FractionField(R)
1080+
sage: 1/x in F
1081+
True
1082+
sage: (1/(2*x)).parent()
1083+
Laurent Series Ring in x over Rational Field
1084+
10671085
"""
10681086
denom = <PowerSeries>denom_r
10691087
if denom.is_zero():
@@ -1073,8 +1091,11 @@ cdef class PowerSeries(AlgebraElement):
10731091

10741092
v = denom.valuation()
10751093
if v > self.valuation():
1076-
R = self._parent.laurent_series_ring()
1077-
return R(self)/R(denom)
1094+
try:
1095+
R = self._parent.fraction_field()
1096+
except (TypeError, NotImplementedError): # no integral domain
1097+
R = self._parent.laurent_series_ring()
1098+
return R(self) / R(denom)
10781099

10791100
# Algorithm: Cancel common factors of q from top and bottom,
10801101
# then invert the denominator. We do the cancellation first

0 commit comments

Comments
 (0)