# These are shared inline functions.
#################################################################################
# fast tests to verify no coercion is needed
#################################################################################
cdef inline bint have_same_parent(left, right):
"""
Return nonzero true value if and only if left and right are
elements and have the same parent.
"""
# (We know at least one of the arguments is an Element. So if
# their types are *equal* (fast to check) then they are both
# Elements. Otherwise use the slower test via PY_TYPE_CHECK.)
if PY_TYPE(left) is PY_TYPE(right):
return (<Element>left)._parent is (<Element>right)._parent
if PY_TYPE_CHECK(right, Element) and PY_TYPE_CHECK(left, Element):
return (<Element>left)._parent is (<Element>right)._parent
return 0
cdef inline _verify_canonical_coercion_c(x, y):
if not have_same_parent(x,y):
raise RuntimeError, """There is a bug in the coercion code in SAGE.
Both x (=%s) and y (=%s) are supposed to have identical parents but they don't.
In fact, x has parent '%s'
whereas y has parent '%s'"""%(x,y,parent_c(x),parent_c(y))
return x, y
cdef inline bint have_same_base(Element x, Element y):
return x._parent._base is y._parent._base
#################################################################################
# parent
#################################################################################
cdef inline parent_c(x):
if PY_TYPE_CHECK(x, Element):
return (<Element>x)._parent
elif hasattr(x, 'parent'):
return x.parent()
else:
return <object>PY_TYPE(x)
def parent(x):
return parent_c(x)
#################################################################################
# operators
#################################################################################
cdef add, sub, mul, div, iadd, isub, imul, idiv
from operator import add, sub, mul, div, iadd, isub, imul, idiv
cdef inline inplace_op(op):
return operator.__dict__['i'+op.__name__]
cdef inline no_inplace_op(op):
return operator.__dict__[op.__name__[1:]]
#################################################################################
# errors
#################################################################################
cdef _coerce_op_symbols = {'mul':'*', 'add':'+', 'sub':'-', 'div':'/', 'imul': '*', 'iadd': '+', 'isub':'-', 'idiv':'/'}
cdef inline arith_error_message(x, y, op):
try:
n = _coerce_op_symbols[op.__name__]
except KeyError:
n = op.__name__
return "unsupported operand parent(s) for '%s': '%s' and '%s'"%(n, parent_c(x), parent_c(y))
cdef enum:
# 3 references: handle, scope container, and arithmetic call stack
inplace_threshold = 0