Package sage :: Package structure :: Module element
[hide private]
[frames] | no frames]

Module element



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
   



Classes [hide private]
  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
Functions [hide private]
 
bin_op(...)
File: sage/structure/element.pyx (starting at line 2733)
 
canonical_base_coercion(...)
File: sage/structure/element.pyx (starting at line 2729)
 
canonical_coercion(...)
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.
 
coerce_cmp(...)
File: sage/structure/element.pyx (starting at line 2936)
 
gcd(...)
File: sage/structure/element.pyx (starting at line 3010)
 
generic_power(...)
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.
 
get_coercion_model(...)
File: sage/structure/element.pyx (starting at line 2978) Return the global coercion model.
 
is_AdditiveGroupElement(...)
File: sage/structure/element.pyx (starting at line 1143) Return True if x is of type AdditiveGroupElement.
 
is_AlgebraElement(...)
File: sage/structure/element.pyx (starting at line 2670) Return True if x is of type AlgebraElement.
 
is_CommutativeAlgebraElement(...)
File: sage/structure/element.pyx (starting at line 2679) Return True if x is of type CommutativeAlgebraElement.
 
is_CommutativeRingElement(...)
File: sage/structure/element.pyx (starting at line 1601) Return True if x is of type CommutativeRingElement.
 
is_DedekindDomainElement(...)
File: sage/structure/element.pyx (starting at line 2174) Return True if x is of type DedekindDomainElement.
 
is_Element(...)
File: sage/structure/element.pyx (starting at line 247) Return True if x is of type Element.
 
is_EuclideanDomainElement(...)
File: sage/structure/element.pyx (starting at line 2227) Return True if x is of type EuclideanDomainElement.
 
is_FieldElement(...)
File: sage/structure/element.pyx (starting at line 2289) Return True if x is of type FieldElement.
 
is_InfinityElement(...)
File: sage/structure/element.pyx (starting at line 2688) Return True if x is of type InfinityElement.
 
is_IntegralDomainElement(...)
File: sage/structure/element.pyx (starting at line 2163) Return True if x is of type IntegralDomainElement.
 
is_Matrix(...)
File: sage/structure/element.pyx (starting at line 2160)
 
is_ModuleElement(...)
File: sage/structure/element.pyx (starting at line 666) Return True if x is of type ModuleElement.
 
is_MonoidElement(...)
File: sage/structure/element.pyx (starting at line 1059) Return True if x is of type MonoidElement.
 
is_MultiplicativeGroupElement(...)
File: sage/structure/element.pyx (starting at line 1176) Return True if x is of type MultiplicativeGroupElement.
 
is_PrincipalIdealDomainElement(...)
File: sage/structure/element.pyx (starting at line 2183) Return True if x is of type PrincipalIdealDomainElement.
 
is_RingElement(...)
File: sage/structure/element.pyx (starting at line 1231) Return True if x is of type RingElement.
 
is_Vector(...)
File: sage/structure/element.pyx (starting at line 1964)
 
lcm(...)
File: sage/structure/element.pyx (starting at line 3006)
 
make_element(...)
File: sage/structure/element.pyx (starting at line 220) Used for unpickling Element objects (and subclasses).
 
parent(...)
File: sage/structure/coerce.pxi (starting at line 45)
 
py_scalar_to_element(...)
File: sage/structure/element.pyx (starting at line 234)
 
set_coercion_model(...)
File: sage/structure/element.pyx (starting at line 2990)
 
swap_coercion_model(...)
File: sage/structure/element.pyx (starting at line 2994)
 
xgcd(...)
File: sage/structure/element.pyx (starting at line 3014)
Function Details [hide private]

canonical_coercion(...)

 
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])

generic_power(...)

 
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

get_coercion_model(...)

 
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 ...>

is_Element(...)

 
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

is_ModuleElement(...)

 
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

make_element(...)

 
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__().