Skip to content

Commit

Permalink
Trac #23851: Fix memoryleak introduced in #11670
Browse files Browse the repository at this point in the history
In #11670 the following leak was introduced:
{{{
        sage: u=id(NumberField(x^2-5,'a').absolute_field('b'))
        sage: import gc
        sage: gc.collect() #random
        10
        sage: [id(v) for v in gc.get_objects() if id(v) == u]
}}}

See Nils's explanation in comment:14:ticket:23807 and the surrounding
discussion, where this bug was found.

URL: https://trac.sagemath.org/23851
Reported by: nbruin
Ticket author(s): Nils Bruin, Peter Bruin
Reviewer(s): Sébastien Labbé
  • Loading branch information
Release Manager authored and vbraun committed May 17, 2018
2 parents f23c426 + b7e1042 commit 4dc912c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 47 deletions.
17 changes: 8 additions & 9 deletions src/sage/rings/number_field/number_field.py
Expand Up @@ -2261,7 +2261,6 @@ def is_relative(self):
"""
return not self.is_absolute()


def quadratic_defect(self, a, p):
r"""
Return the valuation of the quadratic defect of `a` at `p`.
Expand Down Expand Up @@ -2334,21 +2333,21 @@ def quadratic_defect(self, a, p):
return v + w
return Infinity

@cached_method
def absolute_field(self, names):
"""
Returns self as an absolute extension over QQ.
Return ``self`` as an absolute number field.
OUTPUT:
INPUT:
- ``names`` -- string; name of generator of the absolute field
- ``K`` - this number field (since it is already
absolute)
OUTPUT:
- ``K`` -- this number field (since it is already absolute)
Also, ``K.structure()`` returns from_K and to_K,
where from_K is an isomorphism from K to self and to_K is an
isomorphism from self to K.
Also, ``K.structure()`` returns ``from_K`` and ``to_K``, where
``from_K`` is an isomorphism from `K` to ``self`` and ``to_K``
is an isomorphism from ``self`` to `K`.
EXAMPLES::
Expand Down
15 changes: 7 additions & 8 deletions src/sage/rings/number_field/number_field_rel.py
Expand Up @@ -1744,22 +1744,21 @@ def absolute_generator(self):
self.__abs_gen = self._element_class(self, QQ['x'].gen())
return self.__abs_gen

@cached_method
def absolute_field(self, names):
r"""
Return an absolute number field `K` that is isomorphic to this
field along with a field-theoretic bijection from self to `K`
and from `K` to self.
"""
Return ``self`` as an absolute number field.
INPUT:
- ``names`` -- string; name of generator of the absolute field
OUTPUT: an absolute number field
OUTPUT:
An absolute number field `K` that is isomorphic to this field.
Also, ``K.structure()`` returns ``from_K`` and ``to_K``, where
``from_K`` is an isomorphism from `K` to self and ``to_K`` is
an isomorphism from self to `K`.
``from_K`` is an isomorphism from `K` to ``self`` and ``to_K``
is an isomorphism from ``self`` to `K`.
EXAMPLES::
Expand Down
9 changes: 9 additions & 0 deletions src/sage/rings/number_field/structure.py
Expand Up @@ -152,6 +152,15 @@ class NameChange(NumberFieldStructure):
sage: NameChange(K)
<sage.rings.number_field.structure.NameChange object at 0x...>
Check for memory leaks:
sage: u=id(NumberField(x^2-5,'a').absolute_field('b'))
sage: import gc
sage: gc.collect() #random
10
sage: [id(v) for v in gc.get_objects() if id(v) == u]
[]
"""
def create_structure(self, field):
r"""
Expand Down
59 changes: 29 additions & 30 deletions src/sage/rings/polynomial/polynomial_quotient_ring.py
Expand Up @@ -1386,37 +1386,36 @@ def S_units(self, S, proof=True):
sage: K.unit_group()
Unit group with structure C6 of Number Field in a with defining polynomial x^2 + 3
sage: K.<a> = QQ['x'].quotient(x^2 + 3)
sage: u,o = K.S_units([])[0]; u, o
(-1/2*a + 1/2, 6)
sage: u,o = K.S_units([])[0]; o
6
sage: 2*u - 1 in {a, -a}
True
sage: u^6
1
sage: u^3
-1
sage: u^2
-1/2*a - 1/2
sage: 2*u^2 + 1 in {a, -a}
True
::
sage: K.<a> = QuadraticField(-3)
sage: y = polygen(K)
sage: L.<b> = K['y'].quotient(y^3 + 5); L
Univariate Quotient Polynomial Ring in b over Number Field in a with defining polynomial x^2 + 3 with modulus y^3 + 5
sage: L.S_units([])
[(-1/2*a + 1/2, 6),
((-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2, +Infinity),
(2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2, +Infinity)]
sage: L.S_units([K.ideal(1/2*a - 3/2)])
[((-1/6*a - 1/2)*b^2 + (1/3*a - 1)*b + 4/3*a, +Infinity),
(-1/2*a + 1/2, 6),
((-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2, +Infinity),
(2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2, +Infinity)]
sage: L.S_units([K.ideal(2)])
[((1/2*a - 1/2)*b^2 + (a + 1)*b + 3, +Infinity),
((1/6*a + 1/2)*b^2 + (-1/3*a + 1)*b - 5/6*a + 1/2, +Infinity),
((1/6*a + 1/2)*b^2 + (-1/3*a + 1)*b - 5/6*a - 1/2, +Infinity),
(-1/2*a + 1/2, 6),
((-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2, +Infinity),
(2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2, +Infinity)]
sage: [u for u, o in L.S_units([]) if o is Infinity]
[(-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2,
2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2]
sage: [u for u, o in L.S_units([K.ideal(1/2*a - 3/2)]) if o is Infinity]
[(-1/6*a - 1/2)*b^2 + (1/3*a - 1)*b + 4/3*a,
(-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2,
2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2]
sage: [u for u, o in L.S_units([K.ideal(2)]) if o is Infinity]
[(1/2*a - 1/2)*b^2 + (a + 1)*b + 3,
(1/6*a + 1/2)*b^2 + (-1/3*a + 1)*b - 5/6*a + 1/2,
(1/6*a + 1/2)*b^2 + (-1/3*a + 1)*b - 5/6*a - 1/2,
(-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2,
2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2]
Note that all the returned values live where we expect them to::
Expand Down Expand Up @@ -1473,14 +1472,15 @@ def units(self, proof=True):
sage: K.unit_group()
Unit group with structure C6 of Number Field in a with defining polynomial x^2 + 3
sage: K.<a> = QQ['x'].quotient(x^2 + 3)
sage: u = K.units()[0][0]; u
-1/2*a + 1/2
sage: u = K.units()[0][0]
sage: 2*u - 1 in {a, -a}
True
sage: u^6
1
sage: u^3
-1
sage: u^2
-1/2*a - 1/2
sage: 2*u^2 + 1 in {a, -a}
True
sage: K.<a> = QQ['x'].quotient(x^2 + 5)
sage: K.units(())
[(-1, 2)]
Expand All @@ -1491,17 +1491,16 @@ def units(self, proof=True):
sage: y = polygen(K)
sage: L.<b> = K['y'].quotient(y^3 + 5); L
Univariate Quotient Polynomial Ring in b over Number Field in a with defining polynomial x^2 + 3 with modulus y^3 + 5
sage: L.units()
[(-1/2*a + 1/2, 6),
((-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2, +Infinity),
(2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2, +Infinity)]
sage: [u for u, o in L.units() if o is Infinity]
[(-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2,
2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2]
sage: L.<b> = K.extension(y^3 + 5)
sage: L.unit_group()
Unit group with structure C6 x Z x Z of Number Field in b with defining polynomial x^3 + 5 over its base field
sage: L.unit_group().gens() # abstract generators
(u0, u1, u2)
sage: L.unit_group().gens_values()
[1/2*a + 1/2, (-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2, 2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2]
sage: L.unit_group().gens_values()[1:]
[(-1/3*a - 1)*b^2 - 4/3*a*b - 5/6*a + 7/2, 2/3*a*b^2 + (2/3*a - 2)*b - 5/6*a - 7/2]
Note that all the returned values live where we expect them to::
Expand Down

0 comments on commit 4dc912c

Please sign in to comment.