Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Make global lift_centered function fallback to lift if the object
Browse files Browse the repository at this point in the history
has no lift_centered method.

Add lift_centered methods to vectors and matrices.
  • Loading branch information
lftabera committed Feb 12, 2014
1 parent e6bd63b commit 169cb08
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 10 deletions.
42 changes: 42 additions & 0 deletions src/sage/matrix/matrix1.pyx
Expand Up @@ -603,6 +603,48 @@ 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.
If self is a matrix over `Integers(n)`, this method returns the unique
matrix `m` such that `m` is congruent to `self` mod `n` and for every
i, j we have `-n/2 < m[i,j] \leq n/2`.
EXAMPLES::
sage: M = Matrix(Integers(7), 2, 2, [5, 9, 13, 15]) ; M
[5 2]
[6 1]
sage: M.lift_centered()
[-2 2]
[-1 1]
sage: parent(M.lift_centered())
Full MatrixSpace of 2 by 2 dense matrices over Integer Ring
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
"""
if hasattr(self._base_ring, 'cover_ring'):
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])
return self

#############################################################################################
# rows, columns, sparse_rows, sparse_columns, dense_rows, dense_columns, row, column
#############################################################################################
Expand Down
38 changes: 37 additions & 1 deletion src/sage/modules/free_module_element.pyx
Expand Up @@ -1718,6 +1718,11 @@ cdef class FreeModuleElement(element_Vector): # abstract base class

def lift(self):
"""
Return a lift of self to the covering ring of the base ring `R`,
which is by definition the ring returned by calling
cover_ring() on `R`, or just `R` itself if the cover_ring method
is not defined.
EXAMPLES::
sage: V = vector(Integers(7), [5, 9, 13, 15]) ; V
Expand All @@ -1726,8 +1731,39 @@ cdef class FreeModuleElement(element_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
"""
if hasattr(self.base_ring(),'cover_ring'):
return self.change_ring(self.base_ring().cover_ring())
from copy import copy
return copy(self)

def lift_centered(self):
"""
Lift self to the unique vector ``v`` over `\ZZ` 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
52 changes: 44 additions & 8 deletions src/sage/rings/arith.py
Expand Up @@ -2186,15 +2186,15 @@ def rational_reconstruction(a, m, algorithm='fast'):

def lift_centered(p):
r"""
Compute a representative of the element `p` mod `n` in `(-n/2 , n/2]`
Compute a representative of the element `p` mod `n` in `(-n/2 , n/2]`.
INPUT:
- ``p`` -- an integer mod `n`
OUTPUT:
- An integer `r` in `\ZZ` such that `-n/2 < r \leq n/2`
- An integer `r` such that `-n/2 < r \leq n/2`
For specific classes, check the `p.lift_centered` attribute.
Expand All @@ -2206,15 +2206,51 @@ def lift_centered(p):
sage: p = Mod(3,4)
sage: lift_centered(p)
-1
If `p` does not have a lift_centered attribute, fallback to the lift method::
sage: K.<x,y,z> = QQ[]
sage: I = Ideal(x*y,x*z,y*z)
sage: R =K.quotient_ring(I)
sage: f = R(x+y+z)^2
sage: lift_centered(f)
x^2 + y^2 + z^2
Note that the type of `r` may vary depending on the input::
sage: c = ntl.ZZ_pContext(12)
sage: p = ntl.ZZ_p(10,c)
sage: r = lift_centered(p); r
-2
sage: type(r)
<type 'sage.libs.ntl.ntl_ZZ.ntl_ZZ'>
The function can be applied to vectors or matrices::
sage: v = vector(Integers(9),range(9)); v
(0, 1, 2, 3, 4, 5, 6, 7, 8)
sage: lift_centered(v)
(0, 1, 2, 3, 4, -4, -3, -2, -1)
sage: m = matrix(Integers(6),2,3,range(6)); m
[0 1 2]
[3 4 5]
sage: lift_centered(m)
[ 0 1 2]
[ 3 -2 -1]
An example with polynomials::
sage: K.<x> = GF(7)[]
sage: f = 1 + 2*x + 5*x^2
sage: f1 = f.map_coefficients(lift_centered, new_base_ring=ZZ); f1
-2*x^2 + 2*x + 1
sage: f1.parent()
Univariate Polynomial Ring in x over Integer Ring
"""
try:
return ZZ(p.lift_centered())
return p.lift_centered()
except(AttributeError):
pass
r = p.lift()
if r*2 > p.modulus():
r -= p.modulus()
return ZZ(r)
return p.lift()

def _rational_reconstruction_python(a,m):
"""
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/finite_rings/integer_mod.pyx
Expand Up @@ -726,7 +726,7 @@ cdef class IntegerMod_abstract(FiniteRingElement):

def lift_centered(self):
r"""
Lift ``self`` to an integer `i` such that `n/2 < i <= n/2`
Lift ``self`` to an integer `i` such that `-n/2 < i \leq n/2`
(where `n` denotes the modulus).
EXAMPLES::
Expand Down

0 comments on commit 169cb08

Please sign in to comment.