From 169cb08369fc0dda69badcbeae5c41e13304a54d Mon Sep 17 00:00:00 2001 From: Luis Felipe Tabera Alonso Date: Wed, 12 Feb 2014 10:54:18 +0100 Subject: [PATCH] Make global lift_centered function fallback to lift if the object has no lift_centered method. Add lift_centered methods to vectors and matrices. --- src/sage/matrix/matrix1.pyx | 42 +++++++++++++++++ src/sage/modules/free_module_element.pyx | 38 ++++++++++++++- src/sage/rings/arith.py | 52 +++++++++++++++++---- src/sage/rings/finite_rings/integer_mod.pyx | 2 +- 4 files changed, 124 insertions(+), 10 deletions(-) diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index eb42a18cc9e..17ab6442cf1 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -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 ############################################################################################# diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 9f4bf9358b7..5df05cfbb43 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -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 @@ -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): """ diff --git a/src/sage/rings/arith.py b/src/sage/rings/arith.py index 50964562af9..bf30876769c 100644 --- a/src/sage/rings/arith.py +++ b/src/sage/rings/arith.py @@ -2186,7 +2186,7 @@ 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: @@ -2194,7 +2194,7 @@ def lift_centered(p): 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. @@ -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. = 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) + + + 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. = 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): """ diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index f208654c1a5..036934ce6e5 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -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::