# HG changeset patch
# User Jeroen Demeyer
# Date 1286698026 7200
# Node ID c71d80ffb1708656bdadc8948b8adeb399ef4eda
# Parent f4492d13c481a29cedaf000bb1b9ae4d86648a98
Document sig_on() in the developer manual.
Also split off a new file coding_in_cython.rst from coding_in_other.rst
diff r f4492d13c481 r c71d80ffb170 doc/en/developer/coding_in_cython.rst
 /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/en/developer/coding_in_cython.rst Sun Oct 10 10:07:06 2010 +0200
@@ 0,0 +1,479 @@
+.. _chaptercython:
+
+================
+Coding in Cython
+================
+
+This chapter discusses Cython, which is a
+compiled language based on Python.
+The major advantage it has over Python is that code can be
+much faster (sometimes orders of magnitude).
+
+Cython also allows Sage to interface with C and C++, as well
+as other languages. See the Python documentation at
+http://www.python.org/doc/ for more details. In particular, the
+section "Extending and Embedding the Python Interpreter", available at
+http://docs.python.org/ext/ext.html, describes how to write C or
+C++ modules for use in Python.
+
+Cython is a compiled version of Python. It is based on Pyrex
+(http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/). To a
+large degree, Cython has changed based on what Sage's developers
+needed; Cython has been developed in concert with Sage. However, it is
+an independent project now, which is used beyond the scope of Sage.
+
+As such, it is a young, but developing language, with young, but
+developing documentation. See its web page,
+http://www.cython.org/, for the most uptodate information.
+
+Python is an interpreted language and has no declared data types for
+variables. These features make it easy to write and debug, but Python
+code can sometimes be slow. Cython code can look a lot like Python,
+but it gets translated into C code (often very efficient C code) and
+then compiled. Thus it offers a language which is familiar to Python
+developers, but with the potential for much greater speed.
+
+
+Writing Cython code in Sage
+===========================
+
+There are several ways to create and build Cython code in Sage.
+
+#. In the Sage Notebook, begin any cell with ``%cython``. When you
+ evaluate that cell,
+
+ #. It is saved to a file.
+
+ #. Cython is run on it with all the standard Sage libraries
+ automatically linked if necessary.
+
+ #. The resulting ``.so`` file is then loaded into your running
+ instance of Sage.
+
+ #. The functionality defined in that cell is now available for you
+ to use in the notebook. Also, the output cell has a link to the C
+ program that was compiled to create the ``.so`` file.
+
+#. Create an ``.spyx`` file and attach or load it from the command
+ line. This is similar to creating a ``%cython`` cell in the
+ notebook but works completely from the command line (and not from
+ the notebook).
+
+#. Create a ``.pyx`` file and add it to the Sage library.
+
+ #. First, add a listing for the Cython extension to the variable
+ ``ext_modules`` in the file
+ ``SAGE_ROOT/devel/sage/module_list.py``. See the
+ ``distutils.extension.Extension`` class for more information on
+ creating a new Cython extension.
+
+ #. Then, if you created a new directory for your ``.pyx`` file, add
+ the directory name to the ``packages`` list in the file
+ ``SAGE_ROOT/devel/sage/setup.py``. (See also the section on
+ "Creating a new directory" in :ref:`chapterpython`.)
+
+ #. Run ``sage b`` to rebuild Sage.
+
+ For example, the file
+ ``SAGE_ROOT/devel/sage/sage/graphs/chrompoly.pyx`` has the lines
+
+ ::
+
+ Extension('sage.graphs.chrompoly',
+ sources = ['sage/graphs/chrompoly.pyx']),
+
+ in ``module_list.py``. In addition, ``sage.graphs`` is included in
+ the ``packages`` list under the Distutils section of ``setup.py``
+ since ``chrompoly.pyx`` is contained in the directory
+ ``sage/graphs``.
+
+
+Special pragmas
+===============
+
+If Cython code is either attached or loaded as a ``.spyx`` file or
+loaded from the notebook as a ``%cython`` block, the following
+pragmas are available:
+
+* clang  may be either c or c++ indicating whether a C or C++
+ compiler should be used.
+
+* clib  additional libraries to be linked in, the space separated
+ list is split and passed to distutils.
+
+* cinclude  additional directories to search for header files. The
+ space separated list is split and passed to distutils.
+
+For example::
+
+ #clang C++
+ #clib givaro
+ #cinclude /usr/local/include/
+
+
+Attaching or loading .spyx files
+================================
+
+The easiest way to try out Cython without having to learn anything
+about distutils, etc., is to create a file with the extension
+``spyx``, which stands for "Sage Pyrex":
+
+#. Create a file ``power2.spyx``.
+
+#. Put the following in it:
+
+ ::
+
+ def is2pow(n):
+ while n != 0 and n%2 == 0:
+ n = n >> 1
+ return n == 1
+
+#. Start the Sage command line interpreter and load the ``spyx`` file
+ (this will fail if you do not have a C compiler installed).
+
+ .. skip
+
+ ::
+
+ sage: load "power2.spyx"
+ Compiling power2.spyx...
+ sage: is2pow(12)
+ False
+
+Note that you can change ``power2.spyx``, then load it again and it
+will be recompiled on the fly. You can also attach ``power2.spyx`` so
+it is reloaded whenever you make changes:
+
+.. skip
+
+::
+
+ sage: attach "power2.spyx"
+
+Cython is used for its speed. Here is a timed test on a 2.6 GHz
+Opteron:
+
+.. skip
+
+::
+
+ sage: %time [n for n in range(10^5) if is2pow(n)]
+ [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
+ CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 s
+ Wall time: 0.60 s
+
+Now, the code in the file ``power2.spyx`` is valid Python, and if we
+copy this to a file ``powerslow.py`` and load that, we get the
+following:
+
+.. skip
+
+::
+
+ sage: load "powerslow.py"
+ sage: %time [n for n in range(10^5) if is2pow(n)]
+ [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
+ CPU times: user 1.01 s, sys: 0.04 s, total: 1.05 s
+ Wall time: 1.05 s
+
+By the way, we could gain even a little more speed with the Cython
+version with a type declaration, by changing ``def is2pow(n):`` to
+``def is2pow(unsigned int n):``.
+
+
+.. _section_sig_on:
+
+Interrupt and signal handling
+===============================================
+
+(This section was written by Jeroen Demeyer.)
+
+When writing Cython code for Sage, special care must be taken to ensure
+the code can be interrupted with ``CTRLC``.
+Since Cython optimizes for speed,
+Cython normally does not check for interrupts.
+For example, code like the following cannot be interrupted:
+
+.. skip
+
+::
+
+ sage: cython('while True: pass') # DON'T DO THIS
+
+While this is running, pressing ``CTRLC`` has no effect. The only
+way out is to kill the Sage process.
+On certain systems, you can still quit Sage by typing ``CTRL\``
+(sending a Quit signal) instead of ``CTRLC``.
+
+Using ``sig_on()`` and ``sig_off()``
+
+
+.. highlight:: cython
+
+To enable interrupt handling, use the ``sig_on()`` and ``sig_off()`` functions.
+You should put ``sig_on()`` *before* and ``sig_off()`` *after* any Cython code
+which could potentially take a long time.
+These two *must always* be called in **pairs**, i.e. every
+``sig_on()`` must be matched by a closing ``sig_off()``.
+
+In practice your function will probably look like::
+
+ def sig_example():
+ # (some harmless initialization)
+ sig_on()
+ # (a long computation here, potentially calling a C library)
+ sig_off()
+ # (some harmless postprocessing)
+ return something
+
+You can put ``sig_on()`` and ``sig_off()`` in all kinds of Cython functions:
+``def``, ``cdef`` or ``cpdef``.
+You cannot put them in pure Python code (i.e. files with extension ``.py``).
+
+It is possible to put ``sig_on()`` and ``sig_off()`` in different functions,
+provided that ``sig_off()`` is called before the function which calls
+``sig_on()`` returns.
+The following code is *invalid*::
+
+ # INVALID code because we return from function foo()
+ # without calling sig_off() first.
+ cdef foo():
+ sig_on()
+
+ def f1():
+ foo()
+ sig_off()
+
+But the following is valid::
+
+ cdef int foo():
+ sig_off()
+ return 2+2
+
+ def f1():
+ sig_on()
+ return foo()
+
+For clarity however, it is best to avoid this.
+One good example where the above makes sense is the ``new_gen()``
+function in :ref:`sectionparilibrary`.
+
+A common mistake is to put ``sig_off()`` towards the end of a
+function (before the ``return``) when the function has multiple
+``return`` statements.
+So make sure there is a ``sig_off()`` before *every* ``return``
+(and also before every ``raise``).
+
+.. WARNING::
+
+ The code inside ``sig_on()`` should be pure C or Cython code.
+ If you call Python code, an interrupt is likely to mess up Python.
+
+ Also, when an interrupt occurs inside ``sig_on()``, code execution
+ immediately stops without cleaning up.
+ For example, any memory allocated inside ``sig_on()`` is lost.
+ See :ref:`advancedsig` for ways to deal with this.
+
+When the user presses ``CTRLC`` inside ``sig_on()``, execution will jump back
+to ``sig_on()`` (the first one if there is a stack) and ``sig_on()``
+will raise ``KeyboardInterrupt``. These can be handled just like other
+Python exceptions::
+
+ def catch_interrupts():
+ try:
+ sig_on() # This MUST be inside the try
+ # (some long computation)
+ sig_off()
+ except KeyboardInterrupt:
+ # (handle interrupt)
+
+Certain C libraries in Sage are written in a way that they will raise
+Python exceptions: NTL and PARI are examples of this.
+NTL can raise ``RuntimeError`` and PARI can raise ``PariError``.
+Since these use the ``sig_on()`` mechanism,
+these exceptions can be caught just like the ``KeyboardInterrupt``
+in the example above.
+
+It is possible to stack ``sig_on()`` and ``sig_off()``.
+If you do this, the effect is exactly the same as if only the outer
+``sig_on()``/``sig_off()`` was there. The inner ones will just change
+a reference counter and otherwise do nothing. Make sure that the number
+of ``sig_on()`` calls equal the number of ``sig_off()`` calls::
+
+ def stack_sig_on():
+ sig_on()
+ sig_on()
+ sig_on()
+ # (some code)
+ sig_off()
+ sig_off()
+ sig_off()
+
+
+Extra care must be taken with exceptions raised inside ``sig_on()``.
+The problem is that, if you do not do anything special, the ``sig_off()``
+will never be called if there is an exception.
+If you need to *raise* an exception yourself, call a ``sig_off()`` before it::
+
+ def raising_an_exception():
+ sig_on()
+ # (some long computation)
+ if (something_failed):
+ sig_off()
+ raise RuntimeError, "something failed"
+ # (some more computation)
+ sig_off()
+ return something
+
+Alternatively, you can use ``try``/``finally`` which will also catch
+exceptions raised by subroutines inside the ``try``::
+
+ def try_finally_example():
+ sig_on()
+ try:
+ # (some long computation, potentially raising exceptions)
+ finally:
+ sig_off()
+ return something
+
+
+Other signals
+
+
+Apart from handling interrupts, ``sig_on()`` provides more general
+signal handling.
+Indeed, if the code inside ``sig_on()`` would generate
+a segmentation fault or call the C function ``abort()``
+(or more generally, raise any of SIGSEGV, SIGILL, SIGABRT, SIGFPE, SIGBUS),
+this is caught by the interrupt framework and a ``RuntimeError`` is raised::
+
+ cdef extern from 'stdlib.h':
+ void abort()
+
+ def abort_example():
+ sig_on()
+ abort()
+ sig_off()
+
+.. codeblock:: python
+
+ sage: abort_example()
+ Traceback (most recent call last):
+ ...
+ RuntimeError: Aborted
+
+This exception can then be caught as explained above.
+This means that ``abort()`` can be used
+as an alternative to exceptions within ``sig_on()``/``sig_off()``.
+A segmentation fault unguarded by ``sig_on()`` would simply terminate Sage.
+
+Instead of ``sig_on()``, there is also a function ``sig_str(s)``,
+which takes a C string ``s`` as argument.
+It behaves the same as ``sig_on()``, except that the string ``s``
+will be used as a string for the exception.
+``sig_str(s)`` should still be closed by ``sig_off()``.
+Example Cython code::
+
+ cdef extern from 'stdlib.h':
+ void abort()
+
+ def abort_example_with_sig_str():
+ sig_str("custom error message")
+ abort()
+ sig_off()
+
+Executing this gives:
+
+.. codeblock:: python
+
+ sage: abort_example_with_sig_str()
+ Traceback (most recent call last):
+ ...
+ RuntimeError: custom error message
+
+With regard to ordinary interrupts (i.e. SIGINT), ``sig_str(s)``
+behaves the same as ``sig_on()``:
+a simple ``KeyboardInterrupt`` is raised.
+
+.. _advancedsig:
+
+Advanced functions
+
+
+There are several more specialized functions for dealing with interrupts.
+The function ``sig_check()`` behaves exactly as ``sig_on(); sig_off()``
+(except that ``sig_check()`` is faster since it does not involve a ``setjmp()`` call).
+
+``sig_check()`` can be used to check for pending interrupts.
+If an interrupt happens outside of a ``sig_on()``/``sig_off()`` block,
+it will be caught by the next ``sig_check()`` or ``sig_on()``.
+
+The typical use case for ``sig_check()`` is within tight loops doing
+complicated stuff
+(mixed Python and Cython code, potentially raising exceptions).
+It gives more control, because a ``KeyboardInterrupt``
+can *only* be raised during ``sig_check()``::
+
+ def sig_check_example():
+ for x in foo:
+ # (one loop iteration which does not take a long time)
+ sig_check()
+
+As mentioned above, ``sig_on()`` makes no attempt to clean anything up
+(restore state or freeing memory) when an interrupt occurs.
+In fact, it would be impossible for ``sig_on()`` to do that.
+If you want to add some cleanup code, use ``sig_on_no_except()``
+for this. This function behaves *exactly* like ``sig_on()``, except that
+any exception raised (either ``KeyboardInterrupt`` or ``RuntimeError``)
+is not yet passed to Python. Essentially, the exception is there, but
+we prevent Cython from looking for the exception.
+Then ``cython_check_exception()`` can be used to make Cython look
+for the exception.
+
+Normally, ``sig_on_no_except()`` returns 1.
+If a signal was caught and an exception raised, ``sig_on_no_except()``
+instead returns 0.
+The following example shows how to use ``sig_on_no_except()``::
+
+ def no_except_example():
+ if not sig_on_no_except():
+ # (clean up messed up internal state)
+
+ # Make Cython realize that there is an exception.
+ # It will look like the exception was actually raised
+ # by cython_check_exception().
+ cython_check_exception()
+ # (some long computation, messing up internal state of objects)
+ sig_off()
+
+There is also a function ``sig_str_no_except(s)``
+which is analogous to ``sig_str(s)``.
+
+.. NOTE::
+
+ See the file :file:`SAGE_ROOT/devel/sage/sage/tests/interrupt.pyx`
+ for more examples of how to use the various ``sig_*()`` functions.
+
+Testing interrupts
+
+
+.. highlight:: python
+
+When writing :ref:`sectiondocstrings`,
+one sometimes wants to check that certain code can be interrupted in a clean way.
+In the module ``sage.tests.interrupt``, there is a function
+``interrupt_after_delay(ms_delay = 500)`` which can be used to test interrupts.
+That function simulates a ``CTRLC`` (by sending SIGINT)
+after ``ms_delay`` milliseconds.
+
+The following is an example of a doctest demonstrating that
+the function ``factor()`` can be interrupted::
+
+ sage: import sage.tests.interrupt
+ sage: try:
+ ... sage.tests.interrupt.interrupt_after_delay()
+ ... factor(10^1000 + 3)
+ ... except KeyboardInterrupt:
+ ... print "ok!"
+ ok!
diff r f4492d13c481 r c71d80ffb170 doc/en/developer/coding_in_other.rst
 a/doc/en/developer/coding_in_other.rst Thu Apr 07 15:44:38 2011 +0200
+++ b/doc/en/developer/coding_in_other.rst Sun Oct 10 10:07:06 2010 +0200
@@ 1,201 +1,23 @@
.. _chaptercython:
+.. _chapterother:
=========================
Coding in Other Languages
=========================
+==============================================
+Coding using external libraries and interfaces
+==============================================
When writing code for Sage, use Python for the basic structure and
interface. For speed, efficiency, or convenience, you can implement
parts of the code using any of the following languages: Cython, C/C++,
Fortran 95, GAP, Common Lisp, Singular, and GP/PARI. You can also use
+parts of the code using any of the following languages:
+:ref:`Cython `, C/C++,
+Fortran 95, GAP, Common Lisp, Singular, and PARI/GP. You can also use
all C/C++ libraries included with Sage [3]_. (And if you are okay
with your code depending on optional Sage packages, you can use
Octave, or even Magma, Mathematica, or Maple.)
The first section of this chapter discusses Cython, which is a
compiled language based on Python. Many components of Sage are written
in Cython. Later sections discuss the interfaces between Sage and
PARI, GAP, and Singular.
+In this chapter, we discuss interfaces between Sage and
+:ref:`PARI `, :ref:`sectiongap` and :ref:`sectionsingular`.
.. _codingincython:
Cython
======

Cython is a compiled version of Python. It is based on Pyrex
(http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/). To a
large degree, Cython has changed based on what Sage's developers
needed; Cython has been developed in concert with Sage. However, it is
an independent project now, which is used beyond the scope of Sage.

As such, it is a young, but developing language, with young, but
developing documentation. See its web page,
http://www.cython.org/, for the most uptodate information.

Python is an interpreted language and has no declared data types for
variables. These features make it easy to write and debug, but Python
code can sometimes be slow. Cython code can look a lot like Python,
but it gets translated into C code (often very efficient C code) and
then compiled. Thus it offers a language which is familiar to Python
developers, but with the potential for much greater speed.

There are several ways to create and build Cython code in Sage.

#. In the Sage Notebook, begin any cell with ``%cython``. When you
 evaluate that cell,

 #. It is saved to a file.

 #. Cython is run on it with all the standard Sage libraries
 automatically linked if necessary.

 #. The resulting ``.so`` file is then loaded into your running
 instance of Sage.

 #. The functionality defined in that cell is now available for you
 to use in the notebook. Also, the output cell has a link to the C
 program that was compiled to create the ``.so`` file.

#. Create an ``.spyx`` file and attach or load it from the command
 line. This is similar to creating a ``%cython`` cell in the
 notebook but works completely from the command line (and not from
 the notebook).

#. Create a ``.pyx`` file and add it to the Sage library.

 #. First, add a listing for the Cython extension to the variable
 ``ext_modules`` in the file
 ``SAGE_ROOT/devel/sage/module_list.py``. See the
 ``distutils.extension.Extension`` class for more information on
 creating a new Cython extension.

 #. Then, if you created a new directory for your ``.pyx`` file, add
 the directory name to the ``packages`` list in the file
 ``SAGE_ROOT/devel/sage/setup.py``. (See also the section on
 "Creating a new directory" in :ref:`chapterpython`.)

 #. Run ``sage b`` to rebuild Sage.

 For example, the file
 ``SAGE_ROOT/devel/sage/sage/graphs/chrompoly.pyx`` has the lines

 ::

 Extension('sage.graphs.chrompoly',
 sources = ['sage/graphs/chrompoly.pyx']),

 in ``module_list.py``. In addition, ``sage.graphs`` is included in
 the ``packages`` list under the Distutils section of ``setup.py``
 since ``chrompoly.pyx`` is contained in the directory
 ``sage/graphs``.


Special pragmas


If Cython code is either attached or loaded as a ``.spyx`` file or
loaded from the notebook as a ``%cython`` block, the following
pragmas are available:

* clang  may be either c or c++ indicating whether a C or C++
 compiler should be used.

* clib  additional libraries to be linked in, the space separated
 list is split and passed to distutils.

* cinclude  additional directories to search for header files. The
 space separated list is split and passed to distutils.

For example:

::

 #clang C++
 #clib givaro
 #cinclude /usr/local/include/


Attaching or loading .spyx


The easiest way to try out Cython without having to learn anything
about distutils, etc., is to create a file with the extension
``spyx``, which stands for "Sage Pyrex":

#. Create a file ``power2.spyx``.

#. Put the following in it:

 ::

 def is2pow(n):
 while n != 0 and n%2 == 0:
 n = n >> 1
 return n == 1

#. Start the Sage command line interpreter and load the ``spyx`` file
 (this will fail if you do not have a C compiler installed).

 .. skip

 ::

 sage: load "power2.spyx"
 Compiling power2.spyx...
 sage: is2pow(12)
 False

Note that you can change ``power2.spyx``, then load it again and it
will be recompiled on the fly. You can also attach ``power2.spyx`` so
it is reloaded whenever you make changes:

.. skip

::

 sage: attach "power2.spyx"

Cython is used for its speed. Here is a timed test on a 2.6 GHz
Opteron:

.. skip

::

 sage: %time [n for n in range(10^5) if is2pow(n)]
 [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
 CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 s
 Wall time: 0.60 s

Now, the code in the file ``power2.spyx`` is valid Python, and if we
copy this to a file ``powerslow.py`` and load that, we get the
following:

.. skip

::

 sage: load "powerslow.py"
 sage: %time [n for n in range(10^5) if is2pow(n)]
 [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
 CPU times: user 1.01 s, sys: 0.04 s, total: 1.05 s
 Wall time: 1.05 s

By the way, we could gain even a little more speed with the Cython
version with a type declaration, by changing ``def is2pow(n):`` to
``def is2pow(unsigned int n):``.


Other languages
===============

Since Sage is based on Python, it interfaces with C and C++, as well
as other languages. See the Python documentation at
http://www.python.org/doc/ for more details. In particular, the
section "Extending and Embedding the Python Interpreter", available at
http://docs.python.org/ext/ext.html, describes how to write C or
C++ modules for use in Python.

+.. _sectionparilibrary:
The PARI C library interface
============================
@@ 214,47 +36,64 @@
direct calls to the PARI C functionsthis is the preferred way
as it is much faster. Thus this section focuses on using PARI.
We will add a new method to the gen class. This is the abstract
+We will add a new method to the ``gen`` class. This is the abstract
representation of all PARI library objects. That means that once we
add a method to this class, every PARI object, whether it is a number,
polynomial or matrix, will have our new method. So you can do
``pari(1).matfrobenius()``, but since PARI wants to apply
``matfrobenius`` to matrices, not numbers, you will receive a
PariError in this case.
+``PariError`` in this case.
The gen class is defined in
``SAGE_ROOT/devel/sage/sage/libs/pari/gen.pyx``, and this is where we
add the method ``matfrobenius``:
+The ``gen`` class is defined in
+:file:`SAGE_ROOT/devel/sage/sage/libs/pari/gen.pyx`, and this is where we
+add the method ``matfrobenius``::
::
+ def matfrobenius(self, flag=0):
+ r"""
+ M.matfrobenius(flag=0): Return the Frobenius form of the square
+ matrix M. If flag is 1, return only the elementary divisors (a list
+ of polynomials). If flag is 2, return a twocomponents vector [F,B]
+ where F is the Frobenius form and B is the basis change so that
+ `M=B^{1} F B`.
+
+ EXAMPLES::
+
+ sage: a = pari('[1,2;3,4]')
+ sage: a.matfrobenius()
+ [0, 2; 1, 5]
+ sage: a.matfrobenius(flag=1)
+ [x^2  5*x  2]
+ sage: a.matfrobenius(2)
+ [[0, 2; 1, 5], [1, 1/3; 0, 1/3]]
+ """
+ sig_on()
+ return self.new_gen(matfrobenius(self.g, flag, 0))
 def matfrobenius(self, flag=0):
 """
 matfrobenius(M,{flag}): Return the Frobenius form of the
 square matrix M. If flag is 1, return only the elementary
 divisors. If flag is 2, return a twocomponents vector [F,B]
 where F is the Frobenius form and B is the basis change
 so that M=B^1*F*B.
 """
 sig_on()
 return self.new_gen(matfrobenius(self.g, flag))
+Note the use of the :ref:`sig_on() statement `.
The ``sig_on()`` statement is some magic for catching segfault signals.
In this way, it prevents SIGSEGVs from the PARI C library crashing the
Sage interpreter. Note that ``self.new_gen()`` calls a closing
``sig_off()`` macro. These two *must always* come in pairs, i.e. every
``sig_on()`` must be matched by a closing ``sig_off()``. The
``self.new_gen()`` call constructs a new Sagepythongen object from a
given pariCgen where the pariCgen is stored as the
Sagepythongen.g attribute. The ``matfrobenius`` call is just a call
+The ``matfrobenius`` call is just a call
to the PARI C library function ``matfrobenius`` with the appropriate
parameters.
+The ``self.new_gen(GEN x)`` call constructs a new Sage ``gen`` object from a
+given PARI ``GEN`` where the PARI ``GEN`` is stored as the
+``.g`` attribute.
+Apart from this, ``self.new_gen()`` calls a closing ``sig_off()`` macro
+and also clears the PARI stack so it is very convenient to use in a
+``return`` statement as illustrated above.
+So after ``self.new_gen()``, all PARI ``GEN``'s which are not converted
+to Sage ``gen``'s are gone.
+There is also ``self.new_gen_noclear(GEN x)`` which does the same as
+``self.new_gen(GEN x)`` except that it does *not* call ``sig_off()`` nor
+clear the PARI stack.
+
The information about which function to call and how to call it can be
retrieved from the PARI user's manual (note: Sage includes the
development version of PARI, so check that version of the user's
manual). Looking for ``matfrobenius`` you can find:
``"The library syntax is matfrobenius(M,flag)"``.
+
+ The library syntax is ``GEN matfrobenius(GEN M, long flag, long v = 1)``,
+ where ``v`` is a variable number.
In case you are familiar with gp, please note that the PARI C function
may have a name that is different from the corresponding gp function
@@ 263,58 +102,63 @@
We can also add a ``frobenius(flag)`` method to the ``matrix_integer``
class where we call the ``matfrobenius()`` method on the PARI object
associated to the matrix after doing some sanity checking. Then we
convert output from PARI to Sage objects:
+convert output from PARI to Sage objects::
::
+ def frobenius(self, flag=0, var='x'):
+ """
+ Return the Frobenius form (rational canonical form) of this
+ matrix.
+
+ INPUT:
+
+  ``flag``  0 (default), 1 or 2 as follows:
+
+  ``0``  (default) return the Frobenius form of this
+ matrix.
+
+  ``1``  return only the elementary divisor
+ polynomials, as polynomials in var.
+
+  ``2``  return a twocomponents vector [F,B] where F
+ is the Frobenius form and B is the basis change so that
+ `M=B^{1}FB`.
+
+  ``var``  a string (default: 'x')
+
+ ALGORITHM: uses PARI's matfrobenius()
+
+ EXAMPLES::
+
+ sage: A = MatrixSpace(ZZ, 3)(range(9))
+ sage: A.frobenius(0)
+ [ 0 0 0]
+ [ 1 0 18]
+ [ 0 1 12]
+ sage: A.frobenius(1)
+ [x^3  12*x^2  18*x]
+ sage: A.frobenius(1, var='y')
+ [y^3  12*y^2  18*y]
+ """
+ if not self.is_square():
+ raise ArithmeticError("frobenius matrix of nonsquare matrix not defined.")
+
+ v = self._pari_().matfrobenius(flag)
+ if flag==0:
+ return self.matrix_space()(v.python())
+ elif flag==1:
+ r = PolynomialRing(self.base_ring(), names=var)
+ retr = []
+ for f in v:
+ retr.append(eval(str(f).replace("^","**"), {'x':r.gen()}, r.gens_dict()))
+ return retr
+ elif flag==2:
+ F = matrix_space.MatrixSpace(QQ, self.nrows())(v[0].python())
+ B = matrix_space.MatrixSpace(QQ, self.nrows())(v[1].python())
+ return F, B
+
+
 def frobenius(self,flag=0):
 """
 If flag is 0 (the default value), return the Frobenius
 form of this matrix.
 If flag is 1, return only the elementary divisors.
 If flag is 2, return a twocomponent vector [F,B]
 where F is the Frobenius form and B is the basis change
 so that M=B^1*F*B.

 INPUT:
 flag  0,1 or 2 as described above

 ALGORITHM: uses pari's matfrobenius()

 EXAMPLE:
 sage: A = MatrixSpace(IntegerRing(), 3)(range(9))
 sage: A.frobenius(0)
 [ 0 0 0]
 [ 1 0 18]
 [ 0 1 12]
 sage: A.frobenius(1)
 [x3  12*x2  18*x]
 sage: A.frobenius(2)
 ([ 0 0 0]
 [ 1 0 18]
 [ 0 1 12],
 [ 1 2 1]
 [ 0 23/15 14/15]
 [ 0 2/15 1/15])
 """
 if self.nrows()!=self.ncols():
 raise ArithmeticError, \
 "frobenius matrix of nonsquare matrix not defined."
 v = self._pari_().matfrobenius(flag)
 if flag==0:
 return self.matrix_space()(v.python())
 elif flag==1:
 r = polynomial_ring.PolynomialRing(self.base_ring())
 #BUG: this should be handled in PolynomialRing not here
 return [eval(str(x).replace("^","**"),{},r.gens_dict())
 for x in v.python_list()]
 elif flag==2:
 F = matrix_space.MatrixSpace(rational_field.RationalField(),
 self.nrows())(v[0].python())
 B = matrix_space.MatrixSpace(rational_field.RationalField(),
 self.nrows())(v[1].python())
 return F,B

+.. _sectiongap:
GAP
===
@@ 358,7 +202,7 @@
The purpose of this section is to use this example to show how one
might write a Python/Sage program whose input is, say, ``('G',2)`` and
whose output is the matrix above (but as a Sage Matrixsee the code
in the directory ``SAGE_ROOT/devel/sage/sage/matrix/`` and the
+in the directory :file:`SAGE_ROOT/devel/sage/sage/matrix/` and the
corresponding parts of the Sage reference manual).
First, the input must be converted into strings consisting of legal
@@ 443,6 +287,8 @@
for this.
+.. _sectionsingular:
+
Singular
========
diff r f4492d13c481 r c71d80ffb170 doc/en/developer/sage_manuals.rst
 a/doc/en/developer/sage_manuals.rst Thu Apr 07 15:44:38 2011 +0200
+++ b/doc/en/developer/sage_manuals.rst Sun Oct 10 10:07:06 2010 +0200
@@ 246,7 +246,7 @@
Syntax highlighting Cython code

If you need to put :ref:`codingincython` code in a ReST file,
+If you need to put :ref:`Cython ` code in a ReST file,
you can either precede the code block by ``.. codeblock:: cython`` instead
of the usual ``::`` if you want to highlight one block of code in Cython,
or you can use ``.. highlight:: cython`` for a whole file.
diff r f4492d13c481 r c71d80ffb170 doc/en/developer/writing_code.rst
 a/doc/en/developer/writing_code.rst Thu Apr 07 15:44:38 2011 +0200
+++ b/doc/en/developer/writing_code.rst Sun Oct 10 10:07:06 2010 +0200
@@ 59,6 +59,7 @@
conventions
coding_in_python
+ coding_in_cython
coding_in_other
doctesting
sage_manuals
diff r f4492d13c481 r c71d80ffb170 sage/matrix/matrix_integer_dense.pyx
 a/sage/matrix/matrix_integer_dense.pyx Thu Apr 07 15:44:38 2011 +0200
+++ b/sage/matrix/matrix_integer_dense.pyx Sun Oct 10 10:07:06 2010 +0200
@@ 2122,36 +2122,30 @@
return D, U, V
 def frobenius(self,flag=0, var='x'):
+ def frobenius(self, flag=0, var='x'):
"""
Return the Frobenius form (rational canonical form) of this
matrix.
 INPUT: flag an integer:


  ``0``  (default) return the Frobenius form of this
 matrix.

  ``1``  return only the elementary divisor
 polynomials, as polynomials in var.

  ``2``  return a twocomponents vector [F,B] where F
 is the Frobenius form and B is the basis change so that
 `M=B^{1}FB`.

  ``var``  a string (default: 'x')


INPUT:

  ``flag``  0 (default), 1 or 2 as described above


 ALGORITHM: uses pari's matfrobenius()

 EXAMPLE::
+  ``flag``  0 (default), 1 or 2 as follows:
+
+  ``0``  (default) return the Frobenius form of this
+ matrix.
+
+  ``1``  return only the elementary divisor
+ polynomials, as polynomials in var.
+
+  ``2``  return a twocomponents vector [F,B] where F
+ is the Frobenius form and B is the basis change so that
+ `M=B^{1}FB`.
+
+  ``var``  a string (default: 'x')
+
+ ALGORITHM: uses PARI's matfrobenius()
+
+ EXAMPLES::
sage: A = MatrixSpace(ZZ, 3)(range(9))
sage: A.frobenius(0)
diff r f4492d13c481 r c71d80ffb170 sage/tests/interrupt.pyx
 a/sage/tests/interrupt.pyx Thu Apr 07 15:44:38 2011 +0200
+++ b/sage/tests/interrupt.pyx Sun Oct 10 10:07:06 2010 +0200
@@ 1,9 +1,9 @@
"""
Test signal handling in Sage.
+Testing signal handling.
AUTHORS:
  Jeroen Demeyer (20100929): initial version
+  Jeroen Demeyer (20100929): initial version (#10030)
"""
#*****************************************************************************
@@ 92,9 +92,9 @@
Send an interrupt signal (``SIGINT``) to the Sage process
after a delay of ``ms_delay`` milliseconds.
 INPUT::
+ INPUT:
  ``ms_delay``  (default: 500) a nonnegative integer indicating
+  ``ms_delay``  (default: 500) a nonnegative integer indicating
how many milliseconds to wait before raising the interrupt signal.
EXAMPLES: