def _create_(k, R): """ Initialization. We have to implement this as a static method in order to call ``__make_element_class__``. INPUT: - ``k`` -- the residue field of ``R``, or a residue ring of ``R``. - ``R`` -- a `p`-adic ring or field. EXAMPLES:: sage: f = Zp(3).convert_map_from(Zmod(81)) sage: TestSuite(f).run() """ from sage.categories.sets_cat import Sets from sage.categories.homset import Hom kfield = R.residue_field() N = k.cardinality() q = kfield.cardinality() n = N.exact_log(q) if N != q**n: raise RuntimeError("N must be a power of q") H = Hom(k, R, Sets()) f = H.__make_element_class__(ResidueLiftingMap)(H) f._n = n return f
def _convert_map_from_(self, R): """ Finds conversion maps from R to this ring. Currently, a conversion exists if the defining polynomial is the same. EXAMPLES:: sage: R.<a> = Zq(125) sage: S = R.change(type='capped-abs', prec=40, print_mode='terse', print_pos=False) sage: S(a - 15) -15 + a + O(5^20) We get conversions from the exact field:: sage: K = R.exact_field(); K Number Field in a with defining polynomial x^3 + 3*x + 3 sage: R(K.gen()) a + O(5^20) and its maximal order:: sage: OK = K.maximal_order() sage: R(OK.gen(1)) a + O(5^20) """ cat = None if self._implementation == 'NTL' and R == QQ: # Want to use DefaultConvertMap_unique return None if isinstance(R, pAdicExtensionGeneric) and R.prime() == self.prime( ) and R.defining_polynomial(exact=True) == self.defining_polynomial( exact=True): if R.is_field() and not self.is_field(): cat = SetsWithPartialMaps() elif R.category() is self.category(): cat = R.category() else: cat = EuclideanDomains() & MetricSpaces().Complete() elif isinstance(R, Order) and R.number_field().defining_polynomial( ) == self.defining_polynomial(): cat = IntegralDomains() elif isinstance(R, NumberField) and R.defining_polynomial( ) == self.defining_polynomial(): if self.is_field(): cat = Fields() else: cat = SetsWithPartialMaps() else: k = self.residue_field() if R is k: return ResidueLiftingMap._create_(R, self) if cat is not None: H = Hom(R, self, cat) return H.__make_element_class__(DefPolyConversion)(H)
def _convert_map_from_(self, R): """ Finds conversion maps from R to this ring. Currently, a conversion exists if the defining polynomial is the same. EXAMPLES:: sage: R.<a> = Zq(125) sage: S = R.change(type='capped-abs', prec=40, print_mode='terse', print_pos=False) sage: S(a - 15) -15 + a + O(5^20) We get conversions from the exact field:: sage: K = R.exact_field(); K Number Field in a with defining polynomial x^3 + 3*x + 3 sage: R(K.gen()) a + O(5^20) and its maximal order:: sage: OK = K.maximal_order() sage: R(OK.gen(1)) a + O(5^20) """ cat = None if self._implementation == 'NTL' and R == QQ: # Want to use DefaultConvertMap return None if isinstance(R, pAdicExtensionGeneric) and R.defining_polynomial(exact=True) == self.defining_polynomial(exact=True): if R.is_field() and not self.is_field(): cat = SetsWithPartialMaps() else: cat = R.category() elif isinstance(R, Order) and R.number_field().defining_polynomial() == self.defining_polynomial(): cat = IntegralDomains() elif isinstance(R, NumberField) and R.defining_polynomial() == self.defining_polynomial(): if self.is_field(): cat = Fields() else: cat = SetsWithPartialMaps() else: k = self.residue_field() if R is k: return ResidueLiftingMap._create_(R, self) if cat is not None: H = Hom(R, self, cat) return H.__make_element_class__(DefPolyConversion)(H)
def section(self): r""" Return the inverse map of this isomorphism. EXAMPLES:: sage: K = QQ['x'].fraction_field() sage: L = K.function_field() sage: f = L.coerce_map_from(K) sage: f.section() Isomorphism: From: Rational function field in x over Rational Field To: Fraction Field of Univariate Polynomial Ring in x over Rational Field """ from sage.categories.all import Hom parent = Hom(self.codomain(), self.domain()) return parent.__make_element_class__(FunctionFieldToFractionField)(parent)
def _create_(R, k): """ Initialization. We have to implement this as a static method in order to call ``__make_element_class__``. INPUT: - ``R`` -- a `p`-adic ring or field. - ``k`` -- the residue field of ``R``, or a residue ring of ``R``. EXAMPLES:: sage: f = Zmod(49).convert_map_from(Zp(7)) sage: TestSuite(f).run() sage: K.<a> = Qq(125); k = K.residue_field(); f = k.convert_map_from(K) sage: TestSuite(f).run() """ if R.is_field(): from sage.categories.sets_with_partial_maps import SetsWithPartialMaps cat = SetsWithPartialMaps() else: from sage.categories.rings import Rings cat = Rings() from sage.categories.homset import Hom kfield = R.residue_field() N = k.cardinality() q = kfield.cardinality() n = N.exact_log(q) if N != q**n: raise RuntimeError("N must be a power of q") H = Hom(R, k, cat) f = H.__make_element_class__(ResidueReductionMap)(H) f._n = n if kfield is k: f._field = True else: f._field = False return f
def free_module(self, base=None, basis=None, map=True): """ Return a free module `V` over a specified base ring together with maps to and from `V`. INPUT: - ``base`` -- a subring `R` so that this ring/field is isomorphic to a finite-rank free `R`-module `V` - ``basis`` -- a basis for this ring/field over the base - ``map`` -- boolean (default ``True``), whether to return `R`-linear maps to and from `V` OUTPUT: - A finite-rank free `R`-module `V` - An `R`-module isomorphism from `V` to this ring/field (only included if ``map`` is ``True``) - An `R`-module isomorphism from this ring/field to `V` (only included if ``map`` is ``True``) EXAMPLES:: sage: R.<x> = ZZ[] sage: K.<a> = Qq(125) sage: L.<pi> = K.extension(x^2-5) sage: V, from_V, to_V = K.free_module() sage: W, from_W, to_W = L.free_module() sage: W0, from_W0, to_W0 = L.free_module(base=Qp(5)) sage: to_V(a + O(5^7)) (O(5^7), 1 + O(5^7), O(5^7)) sage: to_W(a) (a + O(5^20), O(5^20)) sage: to_W0(a + O(5^7)) (O(5^7), 1 + O(5^7), O(5^7), O(5^7), O(5^7), O(5^7)) sage: to_W(pi) (O(5^21), 1 + O(5^20)) sage: to_W0(pi + O(pi^11)) (O(5^6), O(5^6), O(5^6), 1 + O(5^5), O(5^5), O(5^5)) sage: X, from_X, to_X = K.free_module(K) sage: to_X(a) (a + O(5^20)) """ if basis is not None: raise NotImplementedError B = self.base_ring() if base is None: base = B A = B.base_ring() d = self.relative_degree() if base is B: # May eventually want to take advantage of the fact that precision is flat V = B**d from_V = MapFreeModuleToOneStep to_V = MapOneStepToFreeModule elif base is A: d *= B.relative_degree() V = A**d from_V = MapFreeModuleToTwoStep to_V = MapTwoStepToFreeModule elif base is self: return super(pAdicExtensionGeneric, self).free_module(base=base, basis=basis, map=map) else: raise NotImplementedError FromV = Hom(V, self) ToV = Hom(self, V) from_V = FromV.__make_element_class__(from_V)(FromV) to_V = ToV.__make_element_class__(to_V)(ToV) return V, from_V, to_V