| Home | Trees | Indices | Help |
|---|
|
|
File: sage/structure/element.pyx (starting at line 1)
Elements
AUTHORS:
-- David Harvey (2006-10-16): changed CommutativeAlgebraElement to derive
from CommutativeRingElement instead of AlgebraElement
-- David Harvey (2006-10-29): implementation and documentation of new
arithmetic architecture
-- William Stein (2006-11): arithmetic architecture -- pushing it through to completion.
-- Gonzalo Tornaria (2007-06): recursive base extend for coercion -- lots of tests
\subsection{The Abstract Element Class Hierarchy}
This is the abstract class hierarchy, i.e., these are all
abstract base classes.
\begin{verbatim}
SageObject
Element
ModuleElement
RingElement
CommutativeRingElement
IntegralDomainElement
DedekindDomainElement
PrincipalIdealDomainElement
EuclideanDomainElement
FieldElement
FiniteFieldElement
CommutativeAlgebraElement
AlgebraElement (note -- can't derive from module, since no multiple inheritence)
CommutativeAlgebra ??? (should be removed from element.pxd)
Matrix
InfinityElement
PlusInfinityElement
MinusInfinityElement
AdditiveGroupElement
Vector
MonoidElement
MultiplicativeGroupElement
\end{verbatim}
\subsection{How to Define a New Element Class}
Elements typically define a method \code{_new_c}, e.g.,
\begin{verbatim}
cdef _new_c(self, defining data):
cdef FreeModuleElement_generic_dense x
x = PY_NEW(FreeModuleElement_generic_dense)
x._parent = self._parent
x._entries = v
\end{verbatim}
that creates a new sibling very quickly from defining data
with assumed properties.
SAGE has a special system in place for handling arithmetic operations
for all Element subclasses. There are various rules that must be
followed by both arithmetic implementors and callers.
A quick summary for the impatient:
\begin{itemize}
\item DO NOT OVERRIDE _add_c. EVER. THANKS.
\item DO NOT CALL _add_c_impl DIRECTLY.
\item To implement addition for a python class, override def _add_().
\item To implement addition for a pyrex class, override cdef _add_c_impl().
\item If you want to add x and y, whose parents you know are IDENTICAL,
you may call _add_(x, y) (from python or pyrex) or _add_c(x, y) (from
pyrex -- this will be faster). This will be the fastest way to guarantee
that the correct implementation gets called. Of course you can still
always use "x + y".
\end{itemize}
Now in more detail. The aims of this system are to provide (1) an efficient
calling protocol from both python and pyrex, (2) uniform coercion semantics
across SAGE, (3) ease of use, (4) readability of code.
We will take addition of RingElements as an example; all other operators
and classes are similar. There are four relevant functions.
{\bf def RingElement.__add__}
This function is called by python or pyrex when the binary "+" operator
is encountered. It ASSUMES that at least one of its arguments is a
RingElement; only a really twisted programmer would violate this
condition. It has a fast pathway to deal with the most common case
where the arguments have the same parent. Otherwise, it uses the coercion
module to work out how to make them have the same parent. After any
necessary coercions have been performed, it calls _add_c to dispatch to
the correct underlying addition implementation.
Note that although this function is declared as def, it doesn't have the
usual overheads associated with python functions (either for the caller
or for __add__ itself). This is because python has optimised calling
protocols for such special functions.
{\bf cdef RingElement._add_c}
DO ***NOT*** OVERRIDE THIS FUNCTION.
The two arguments to this function MUST have the SAME PARENT.
Its return value MUST have the SAME PARENT as its arguments.
If you want to add two objects from pyrex, and you know that their
parents are the same object, you are encouraged to call this function
directly, instead of using "x + y".
This function dispatches to either _add_ or _add_c_impl as appropriate.
It takes necessary steps to decide whether a pyrex implementation of
_add_c_impl has been overridden by some python implementation of _add_.
The code is optimised in favour of reaching _add_c_impl as soon as
possible.
{\bf def RingElement._add_}
This is the function you should override to implement addition in a
python subclass of RingElement.
WARNING: if you override this in a *pyrex* class, it won't get called.
You should override _add_c_impl instead. It is especially important to
keep this in mind whenever you move a class down from python to pyrex.
The two arguments to this function are guaranteed to have the
SAME PARENT. Its return value MUST have the SAME PARENT as its
arguments.
If you want to add two objects from python, and you know that their
parents are the same object, you are encouraged to call this function
directly, instead of using "x + y".
The default implementation of this function is to call _add_c_impl,
so if no-one has defined a python implementation, the correct pyrex
implementation will get called.
{\bf cdef RingElement._add_c_impl}
This is the function you should override to implement addition in a
pyrex subclass of RingElement.
The two arguments to this function are guaranteed to have the
SAME PARENT. Its return value MUST have the SAME PARENT as its
arguments.
DO ***NOT*** CALL THIS FUNCTION DIRECTLY.
(Exception: you know EXACTLY what you are doing, and you know exactly
which implementation you are trying to call; i.e. you're not trying to
write generic code. In particular, if you call this directly, your code
will not work correctly if you run it on a python class derived from
a pyrex class where someone has redefined _add_ in python.)
The default implementation of this function is to raise a
NotImplementedError, which will happen if no-one has supplied
implementations of either _add_ or _add_c_impl.
For speed, there are also {\bf inplace} version of the arithmetic commands.
DD NOT call them directly, they may mutate the object and will be called
when and only when it has been determined that the old object will no longer
be accessible from the calling function after this operation.
{\bf def RingElement._iadd_}
This is the function you should override to inplace implement addition
in a python subclass of RingElement.
WARNING: if you override this in a *pyrex* class, it won't get called.
You should override _iadd_c_impl instead. It is especially important to
keep this in mind whenever you move a class down from python to pyrex.
The two arguments to this function are guaranteed to have the
SAME PARENT. Its return value MUST have the SAME PARENT as its
arguments.
The default implementation of this function is to call _add_c_impl,
so if no-one has defined a python implementation, the correct pyrex
implementation will get called.
{\bf cdef RingElement._iadd_c_impl}
This is the function you should override to inplace implement addition
in a pyrex subclass of RingElement.
The two arguments to this function are guaranteed to have the
SAME PARENT. Its return value MUST have the SAME PARENT as its
arguments.
The default implementation of this function is to call _add_c
|
|||
|
AdditiveGroupElement File: sage/structure/element.pyx (starting at line 1149) Generic element of an additive group. |
|||
| AlgebraElement | |||
|
CoercionModel File: sage/structure/element.pyx (starting at line 2948) Most basic coersion scheme. |
|||
| CommutativeAlgebra | |||
| CommutativeAlgebraElement | |||
| CommutativeRingElement | |||
| DedekindDomainElement | |||
|
Element File: sage/structure/element.pyx (starting at line 259) Generic element of a structure. |
|||
| EuclideanDomainElement | |||
| FieldElement | |||
| FiniteFieldElement | |||
| InfinityElement | |||
| IntegralDomainElement | |||
| Matrix | |||
| MinusInfinityElement | |||
|
ModuleElement File: sage/structure/element.pyx (starting at line 683) Generic element of a module. |
|||
|
MonoidElement File: sage/structure/element.pyx (starting at line 1065) Generic element of a monoid. |
|||
|
MultiplicativeGroupElement File: sage/structure/element.pyx (starting at line 1182) Generic element of a multiplicative group. |
|||
| PlusInfinityElement | |||
| PrincipalIdealDomainElement | |||
| RingElement | |||
| Vector | |||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
File: sage/structure/element.pyx (starting at line 2712)
canonical_coercion(x,y) is what is called before doing an
arithmetic operation between x and y. It returns a pair (z,w)
such that z is got from x and w from y via canonical coercion and
the parents of z and w are identical.
EXAMPLES:
sage: A = Matrix([[0,1],[1,0]])
sage: canonical_coercion(A,1)
([0 1]
[1 0], [1 0]
[0 1])
|
File: sage/structure/element.pyx (starting at line 3023)
Computes $a^n$, where $n$ is an integer, and $a$ is an object which
supports multiplication. Optionally an additional argument,
which is used in the case that n == 0:
one: the "unit" element, returned directly (can be anything)
If this is not supplied, int(1) is returned.
EXAMPLES:
sage: from sage.structure.element import generic_power
sage: generic_power(int(12),int(0))
1
sage: generic_power(int(0),int(100))
0
sage: generic_power(Integer(10),Integer(0))
1
sage: generic_power(Integer(0),Integer(23))
0
sage: sum([generic_power(2,i) for i in range(17)]) #test all 4-bit combinations
131071
sage: F = Zmod(5)
sage: a = generic_power(F(2), 5); a
2
sage: a.parent() is F
True
sage: a = generic_power(F(1), 2)
sage: a.parent() is F
True
sage: generic_power(int(5), 0)
1
|
File: sage/structure/element.pyx (starting at line 2978) Return the global coercion model. EXAMPLES: sage: import sage.structure.element as e sage: cm = e.get_coercion_model() sage: cm <sage.structure.coerce.CoercionModel_cache_maps object at ...> |
File: sage/structure/element.pyx (starting at line 247)
Return True if x is of type Element.
EXAMPLES:
sage: is_Element(2/3)
True
sage: is_Element(QQ^3)
False
|
File: sage/structure/element.pyx (starting at line 666)
Return True if x is of type ModuleElement.
This is even faster than using isinstance inline.
EXAMPLES:
sage: is_ModuleElement(2/3)
True
sage: is_ModuleElement((QQ^3).0)
True
sage: is_ModuleElement('a')
False
|
File: sage/structure/element.pyx (starting at line 220) Used for unpickling Element objects (and subclasses). This should work for any Python class deriving from Element, as long as it doesn't implement some screwy __new__() method. See also Element.__reduce__(). |
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0beta1 on Thu Jul 17 04:23:29 2008 | http://epydoc.sourceforge.net |