Skip to content

Commit

Permalink
Trac #15804: Add lift_centered for more classes
Browse files Browse the repository at this point in the history
This ticket is a split of #8558 for easier review and merging.

Add a lift_centered method to ntl_mod_p elements and a generic function.

If p  is an integer mod n, returns r congruent to p mod n such that -n/2
< r <= n/2

It also deprecates the use of centerlift for lift_centered. The
discussion is in #8558

URL: http://trac.sagemath.org/15804
Reported by: lftabera
Ticket author(s): Luis Felipe Tabera Alonso, Jeroen Demeyer
Reviewer(s): Vincent Delecroix
  • Loading branch information
Release Manager authored and vbraun committed Dec 25, 2015
2 parents 89235a8 + c2255e5 commit 5da70ff
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 21 deletions.
28 changes: 28 additions & 0 deletions src/sage/libs/ntl/ntl_ZZ_p.pyx
Expand Up @@ -413,6 +413,34 @@ cdef class ntl_ZZ_p(object):
ZZ_p_modulus( &r.x, &self.x )
return r

def lift_centered(self):
"""
Compute a representative of ``self`` in `(-n/2 , n/2]` as an
``ntl.ZZ`` object.
OUTPUT:
- A ``ntl.ZZ`` object `r` such that `-n/2 < r \\leq n/2` and `Mod(r, n) == self`.
EXAMPLES::
sage: x = ntl.ZZ_p(8, 18)
sage: x.lift_centered()
8
sage: type(x.lift_centered())
<type 'sage.libs.ntl.ntl_ZZ.ntl_ZZ'>
sage: x = ntl.ZZ_p(12, 18)
sage: x.lift_centered()
-6
sage: type(x.lift_centered())
<type 'sage.libs.ntl.ntl_ZZ.ntl_ZZ'>
"""
cdef ntl_ZZ r = self.lift()
cdef ntl_ZZ m = self.modulus()
if r*2 > m:
r -= m
return r

def _integer_(self, ZZ=None):
"""
Return a lift of self as a Sage integer.
Expand Down
20 changes: 14 additions & 6 deletions src/sage/libs/pari/gen.pyx
Expand Up @@ -3158,18 +3158,19 @@ cdef class gen(gen_auto):

def centerlift(gen x, v=-1):
"""
centerlift(x,v): Centered lift of x. This function returns exactly
the same thing as lift, except if x is an integer mod.
Centered lift of x. This function returns exactly the same thing as lift,
except if x is an integer mod.
INPUT:
- ``x`` -- gen
- ``x`` - gen
- ``v`` - var (default: x)
- ``v`` -- var (default: x)
OUTPUT:
OUTPUT: gen
- `r` -- gen. If `x` is an integer mod `n`, return the unique element `r` congruent
to `x` mod `n` such that `-n/2 < r \\leq n/2`.
EXAMPLES::
Expand All @@ -3190,10 +3191,17 @@ cdef class gen(gen_auto):
x - y
sage: f.centerlift('y')
Mod(x - y, x^2 + 1)
For compatibility with other classes in Sage, there is an alias
``lift_centered``::
sage: pari("Mod(3,5)").lift_centered()
-2
"""
pari_catch_sig_on()
return P.new_gen(centerlift0(x.g, P.get_var(v)))

lift_centered = centerlift

def component(gen x, long n):
"""
Expand Down
56 changes: 54 additions & 2 deletions src/sage/matrix/matrix1.pyx
Expand Up @@ -605,6 +605,58 @@ cdef class Matrix(matrix0.Matrix):
return self.change_ring(S)
return self

def lift_centered(self):
"""
Apply the lift_centered method to every entry of self.
OUTPUT:
If self is a matrix over the Integers mod `n`, this method returns the
unique matrix `m` such that `m` is congruent to self mod `n` and for
every entry `m[i,j]` we have `-n/2 < m[i,j] \\leq n/2`. If the
coefficient ring does not have a cover_ring method, return self.
EXAMPLES::
sage: M = Matrix(Integers(8), 2, 4, range(8)) ; M
[0 1 2 3]
[4 5 6 7]
sage: L = M.lift_centered(); L
[ 0 1 2 3]
[ 4 -3 -2 -1]
sage: parent(L)
Full MatrixSpace of 2 by 4 dense matrices over Integer Ring
The returned matrix is congruent to M modulo 8.::
sage: L.mod(8)
[0 1 2 3]
[4 5 6 7]
The field QQ doesn't have a cover_ring method::
sage: hasattr(QQ, 'cover_ring')
False
So lifting a matrix over QQ gives back the same exact matrix.
::
sage: B = matrix(QQ, 2, [1..4])
sage: B.lift_centered()
[1 2]
[3 4]
sage: B.lift_centered() is B
True
"""
try:
S = self._base_ring.cover_ring()
if S is not self._base_ring:
return self.parent().change_ring(S)([v.lift_centered() for v in self])
except AttributeError:
pass
return self

#############################################################################################
# rows, columns, sparse_rows, sparse_columns, dense_rows, dense_columns, row, column
#############################################################################################
Expand Down Expand Up @@ -1370,7 +1422,7 @@ cdef class Matrix(matrix0.Matrix):
self = self.change_ring(R)
if bottom_ring is not R:
other = other.change_ring(R)

if type(self) is not type(other):
# If one of the matrices is sparse, return a sparse matrix
if self.is_sparse_c() and not other.is_sparse_c():
Expand All @@ -1386,7 +1438,7 @@ cdef class Matrix(matrix0.Matrix):
cdef _stack_impl(self, bottom):
"""
Implementation of :meth:`stack`.
Assume that ``self`` and ``other`` are compatible in the sense
that they have the same base ring and that both are either
dense or sparse.
Expand Down
2 changes: 1 addition & 1 deletion src/sage/matrix/matrix2.pyx
Expand Up @@ -1434,7 +1434,7 @@ cdef class Matrix(matrix1.Matrix):
d = R(self._pari_().matdet())
else:
# Lift to ZZ and compute there.
d = R(self.apply_map(lambda x : x.centerlift()).det())
d = R(self.apply_map(lambda x : x.lift_centered()).det())
self.cache('det', d)
return d

Expand Down
53 changes: 52 additions & 1 deletion src/sage/modules/free_module_element.pyx
Expand Up @@ -1920,6 +1920,17 @@ cdef class FreeModuleElement(Vector): # abstract base class

def lift(self):
"""
Lift ``self`` to the cover ring.
OUTPUT:
Return a lift of self to the covering ring of the base ring `R`,
which is by definition the ring returned by calling
:meth:`~sage.rings.quotient_ring.QuotientRing_nc.cover_ring`
on `R`, or just `R` itself if the
:meth:`~sage.rings.quotient_ring.QuotientRing_nc.cover_ring`
method is not defined.
EXAMPLES::
sage: V = vector(Integers(7), [5, 9, 13, 15]) ; V
Expand All @@ -1928,8 +1939,48 @@ cdef class FreeModuleElement(Vector): # abstract base class
(5, 2, 6, 1)
sage: parent(V.lift())
Ambient free module of rank 4 over the principal ideal domain Integer Ring
If the base ring does not have a cover method, return a copy of the vector::
sage: W = vector(QQ, [1, 2, 3])
sage: W1 = W.lift()
sage: W is W1
False
sage: parent(W1)
Vector space of dimension 3 over Rational Field
"""
try:
return self.change_ring(self.base_ring().cover_ring())
except AttributeError:
from copy import copy
return copy(self)

def lift_centered(self):
"""
Lift to a congruent, centered vector.
INPUT:
- ``self`` A vector with coefficients in `Integers(n)`.
OUTPUT:
- The unique integer vector `v` such that foreach `i`,
`Mod(v[i],n) = Mod(self[i],n)` and `-n/2 < v[i] \leq n/2`.
EXAMPLES::
sage: V = vector(Integers(7), [5, 9, 13, 15]) ; V
(5, 2, 6, 1)
sage: V.lift_centered()
(-2, 2, -1, 1)
sage: parent(V.lift_centered())
Ambient free module of rank 4 over the principal ideal domain Integer Ring
"""
return self.change_ring(self.base_ring().cover_ring())
R = self.base_ring().cover_ring()
l = [foo.lift_centered() for foo in self]
P = self.parent().change_ring(R)
return P(l)

def __pos__(self):
"""
Expand Down
29 changes: 18 additions & 11 deletions src/sage/rings/finite_rings/integer_mod.pyx
Expand Up @@ -105,6 +105,7 @@ from sage.categories.morphism cimport Morphism
from sage.categories.map cimport Map

from sage.structure.sage_object import register_unpickle_override
from sage.misc.superseded import deprecated_function_alias

from sage.structure.parent cimport Parent

Expand All @@ -129,7 +130,7 @@ def Mod(n, m, parent=None):
2
Illustrates that trac #5971 is fixed. Consider `n` modulo `m` when
`m = 0`. Then `\ZZ/0\ZZ` is isomorphic to `\ZZ` so `n` modulo `0` is
`m = 0`. Then `\ZZ/0\ZZ` is isomorphic to `\ZZ` so `n` modulo `0`
is equivalent to `n` for any integer value of `n`::
sage: Mod(10, 0)
Expand Down Expand Up @@ -748,28 +749,32 @@ cdef class IntegerMod_abstract(FiniteRingElement):
"""
return self

def centerlift(self):
def lift_centered(self):
r"""
Lift ``self`` to an integer `i` such that `n/2 < i <= n/2`
Lift ``self`` to a centered congruent integer.
OUTPUT:
The unique integer `i` such that `-n/2 < i \leq n/2` and `i = self \mod n`
(where `n` denotes the modulus).
EXAMPLES::
sage: Mod(0,5).centerlift()
sage: Mod(0,5).lift_centered()
0
sage: Mod(1,5).centerlift()
sage: Mod(1,5).lift_centered()
1
sage: Mod(2,5).centerlift()
sage: Mod(2,5).lift_centered()
2
sage: Mod(3,5).centerlift()
sage: Mod(3,5).lift_centered()
-2
sage: Mod(4,5).centerlift()
sage: Mod(4,5).lift_centered()
-1
sage: Mod(50,100).centerlift()
sage: Mod(50,100).lift_centered()
50
sage: Mod(51,100).centerlift()
sage: Mod(51,100).lift_centered()
-49
sage: Mod(-1,3^100).centerlift()
sage: Mod(-1,3^100).lift_centered()
-1
"""
n = self.modulus()
Expand All @@ -779,6 +784,8 @@ cdef class IntegerMod_abstract(FiniteRingElement):
else:
return x - n

centerlift = deprecated_function_alias(15804,lift_centered)

cpdef bint is_one(self):
raise NotImplementedError

Expand Down

0 comments on commit 5da70ff

Please sign in to comment.