Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Base class for old-style parent objects
CLASS HIERARCHY:
SageObject Parent ParentWithBase ParentWithGens
TESTS:
This came up in some subtle bug once. ::
sage: gp(2) + gap(3) 5 """
#***************************************************************************** # Copyright (C) 2006 William Stein <wstein@gmail.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import absolute_import, print_function
cimport sage.structure.sage_object as sage_object import operator from .parent import Set_PythonType, Set_PythonType_class from .coerce cimport py_scalar_parent from sage.ext.stdsage cimport HAS_DICTIONARY
from cpython.object cimport * from cpython.bool cimport *
cdef inline check_old_coerce(Parent p):
cdef class Parent(parent.Parent): """ Parents are the SAGE/mathematical analogues of container objects in computer science.
TESTS::
sage: V = VectorSpace(GF(2,'a'),2) sage: V.list() [(0, 0), (1, 0), (0, 1), (1, 1)] sage: MatrixSpace(GF(3), 1, 1).list() [[0], [1], [2]] sage: DirichletGroup(3).list() [Dirichlet character modulo 3 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 3 of conductor 3 mapping 2 |--> -1] sage: K = GF(7^6,'a') sage: K.list()[:10] # long time [0, 1, 2, 3, 4, 5, 6, a, a + 1, a + 2] sage: K.<a> = GF(4) sage: K.list() [0, a, a + 1, 1] """
def __init__(self, coerce_from=None, actions=None, embeddings=None, *, category=None): from sage.misc.superseded import deprecation deprecation(24614, "the 'coerce_from' keyword is deprecated") self._coerce_from_list = list(coerce_from) from sage.misc.superseded import deprecation deprecation(24614, "the 'actions' keyword is deprecated") self._action_list = list(actions)
cdef parent.Parent other from sage.misc.superseded import deprecation deprecation(24614, "the 'embeddings' keyword is deprecated") for mor in embeddings: other = mor.domain() print("embedding", self, " --> ", other) print(mor) other.init_coerce() # TODO remove when we can other._coerce_from_list.append(mor)
# old
################################################################################# # New Coercion support functionality #################################################################################
cpdef coerce_map_from_c(self, S): """ EXAMPLES:
Check to make sure that we handle coerce maps from Python native types correctly::
sage: QQ['q,t'].coerce_map_from(int) Composite map: From: Set of Python objects of class 'int' To: Multivariate Polynomial Ring in q, t over Rational Field Defn: Native morphism: From: Set of Python objects of class 'int' To: Rational Field then Polynomial base injection morphism: From: Rational Field To: Multivariate Polynomial Ring in q, t over Rational Field """ from sage.categories.homset import Hom return Hom(self, self).identity() # non-unique parents from sage.categories.homset import Hom from sage.categories.morphism import CallMorphism return CallMorphism(Hom(S, self)) return self.coerce_map_from_c(S._type) self.init_coerce() cdef object ret pass
mor = sage.categories.morphism.CallMorphism(S, self) mor = None raise TypeError("coerce_map_from_c_impl must return a boolean, None, or an explicit Map")
#Convert Python types to native Sage types
cdef coerce_map_from_c_impl(self, S): cdef parent.Parent R else: R = mor mor = sage.categories.morphism.CallMorphism(Hom(R, self)) i = self._coerce_from_list.index(R) self._coerce_from_list[i] = mor # cache in case we need it again return mor else:
# Piggyback off the old code for now # WARNING: when working on this, make sure circular dependencies aren't introduced! S = Set_PythonType(S) else:
################################################################################# # Coercion support functionality #################################################################################
def _coerce_(self, x): # Call this from Python (do not override!)
cpdef _coerce_c(self, x): # DO NOT OVERRIDE THIS (call it) pass else: return self._coerce_c_impl(x)
cdef _coerce_c_impl(self, x): # OVERRIDE THIS FOR CYTHON CLASSES """ Canonically coerce x in assuming that the parent of x is not equal to self. """ check_old_coerce(self) raise TypeError
def _coerce_impl(self, x): # OVERRIDE THIS FOR PYTHON CLASSES """ Canonically coerce x in assuming that the parent of x is not equal to self. """
def _coerce_try(self, x, v): """ Given a list v of rings, try to coerce x canonically into each one in turn. Return the __call__ coercion of the result into self of the first canonical coercion that succeeds. Raise a TypeError if none of them succeed.
INPUT: x -- Python object v -- parent object or list (iterator) of parent objects """
pass
cpdef has_coerce_map_from_c(self, S): """ Return True if there is a natural map from S to self. Otherwise, return False. """ return True else: pass
cdef has_coerce_map_from_c_impl(self, S):
def _an_element_impl(self): # override this in Python
cdef _an_element_c_impl(self): # override this in Cython """ Returns an element of self. Want it in sufficient generality that poorly-written functions won't work when they're not supposed to. This is cached so doesn't have to be super fast. """ pass
pass
pass
raise NotImplementedError("please implement _an_element_c_impl or _an_element_impl for %s" % self)
def _an_element(self): # do not override this (call from Python) check_old_coerce(self) return self._an_element_c()
cpdef _an_element_c(self): # do not override this (call from Cython) return self._cache_an_element else: self._cache_an_element = self._an_element_c_impl()
############################################################################ # Coercion Compatibility Layer ############################################################################
cpdef _coerce_map_from_(self, S): else:
def _an_element_(self): else:
cpdef _generic_convert_map(self, S, category=None): r""" Return a default conversion from ``S``.
EXAMPLES::
sage: R.<x,y>=QQ[] sage: R._generic_convert_map(QQ).category_for() Category of sets with partial maps
""" else: |