Ticket #10109: 10109_document_sig_on.patch

File 10109_document_sig_on.patch, 35.7 KB (added by Jeroen Demeyer, 11 years ago)
  • new file doc/en/developer/coding_in_cython.rst

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # 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
    - +  
     1.. _chapter-cython:
     2
     3================
     4Coding in Cython
     5================
     6
     7This chapter discusses Cython, which is a
     8compiled language based on Python.
     9The major advantage it has over Python is that code can be
     10much faster (sometimes orders of magnitude).
     11
     12Cython also allows Sage to interface with C and C++, as well
     13as other languages. See the Python documentation at
     14http://www.python.org/doc/ for more details. In particular, the
     15section "Extending and Embedding the Python Interpreter", available at
     16http://docs.python.org/ext/ext.html, describes how to write C or
     17C++ modules for use in Python.
     18
     19Cython is a compiled version of Python. It is based on Pyrex
     20(http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/). To a
     21large degree, Cython has changed based on what Sage's developers
     22needed; Cython has been developed in concert with Sage. However, it is
     23an independent project now, which is used beyond the scope of Sage.
     24
     25As such, it is a young, but developing language, with young, but
     26developing documentation. See its web page,
     27http://www.cython.org/, for the most up-to-date information.
     28
     29Python is an interpreted language and has no declared data types for
     30variables. These features make it easy to write and debug, but Python
     31code can sometimes be slow. Cython code can look a lot like Python,
     32but it gets translated into C code (often very efficient C code) and
     33then compiled. Thus it offers a language which is familiar to Python
     34developers, but with the potential for much greater speed.
     35
     36
     37Writing Cython code in Sage
     38===========================
     39
     40There are several ways to create and build Cython code in Sage.
     41
     42#. In the Sage Notebook, begin any cell with ``%cython``. When you
     43   evaluate that cell,
     44
     45   #. It is saved to a file.
     46
     47   #. Cython is run on it with all the standard Sage libraries
     48      automatically linked if necessary.
     49
     50   #. The resulting ``.so`` file is then loaded into your running
     51      instance of Sage.
     52
     53   #. The functionality defined in that cell is now available for you
     54      to use in the notebook. Also, the output cell has a link to the C
     55      program that was compiled to create the ``.so`` file.
     56
     57#. Create an ``.spyx`` file and attach or load it from the command
     58   line. This is similar to creating a ``%cython`` cell in the
     59   notebook but works completely from the command line (and not from
     60   the notebook).
     61
     62#. Create a ``.pyx`` file and add it to the Sage library.
     63
     64   #. First, add a listing for the Cython extension to the variable
     65      ``ext_modules`` in the file
     66      ``SAGE_ROOT/devel/sage/module_list.py``. See the
     67      ``distutils.extension.Extension`` class for more information on
     68      creating a new Cython extension.
     69
     70   #. Then, if you created a new directory for your ``.pyx`` file, add
     71      the directory name to the ``packages`` list in the file
     72      ``SAGE_ROOT/devel/sage/setup.py``.  (See also the section on
     73      "Creating a new directory" in :ref:`chapter-python`.)
     74
     75   #. Run ``sage -b`` to rebuild Sage.
     76
     77   For example, the file
     78   ``SAGE_ROOT/devel/sage/sage/graphs/chrompoly.pyx`` has the lines
     79
     80   ::
     81
     82     Extension('sage.graphs.chrompoly',
     83               sources = ['sage/graphs/chrompoly.pyx']),
     84
     85   in ``module_list.py``. In addition, ``sage.graphs`` is included in
     86   the ``packages`` list under the Distutils section of ``setup.py``
     87   since ``chrompoly.pyx`` is contained in the directory
     88   ``sage/graphs``.
     89
     90
     91Special pragmas
     92===============
     93
     94If Cython code is either attached or loaded as a ``.spyx`` file or
     95loaded from the notebook as a ``%cython`` block, the following
     96pragmas are available:
     97
     98* clang --- may be either c or c++ indicating whether a C or C++
     99  compiler should be used.
     100
     101* clib --- additional libraries to be linked in, the space separated
     102  list is split and passed to distutils.
     103
     104* cinclude --- additional directories to search for header files. The
     105  space separated list is split and passed to distutils.
     106
     107For example::
     108
     109    #clang C++
     110    #clib givaro
     111    #cinclude /usr/local/include/
     112
     113
     114Attaching or loading .spyx files
     115================================
     116
     117The easiest way to try out Cython without having to learn anything
     118about distutils, etc., is to create a file with the extension
     119``spyx``, which stands for "Sage Pyrex":
     120
     121#. Create a file ``power2.spyx``.
     122
     123#. Put the following in it:
     124
     125   ::
     126
     127       def is2pow(n):
     128           while n != 0 and n%2 == 0:
     129               n = n >> 1
     130           return n == 1
     131
     132#. Start the Sage command line interpreter and load the ``spyx`` file
     133   (this will fail if you do not have a C compiler installed).
     134
     135   .. skip
     136
     137   ::
     138
     139       sage: load "power2.spyx"
     140       Compiling power2.spyx...
     141       sage: is2pow(12)
     142       False
     143
     144Note that you can change ``power2.spyx``, then load it again and it
     145will be recompiled on the fly. You can also attach ``power2.spyx`` so
     146it is reloaded whenever you make changes:
     147
     148.. skip
     149
     150::
     151
     152    sage: attach "power2.spyx"
     153
     154Cython is used for its speed. Here is a timed test on a 2.6 GHz
     155Opteron:
     156
     157.. skip
     158
     159::
     160
     161    sage: %time [n for n in range(10^5) if is2pow(n)]
     162    [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
     163    CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 s
     164    Wall time: 0.60 s
     165
     166Now, the code in the file ``power2.spyx`` is valid Python, and if we
     167copy this to a file ``powerslow.py`` and load that, we get the
     168following:
     169
     170.. skip
     171
     172::
     173
     174    sage: load "powerslow.py"
     175    sage: %time [n for n in range(10^5) if is2pow(n)]
     176    [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
     177    CPU times: user 1.01 s, sys: 0.04 s, total: 1.05 s
     178    Wall time: 1.05 s
     179
     180By the way, we could gain even a little more speed with the Cython
     181version with a type declaration, by changing ``def is2pow(n):`` to
     182``def is2pow(unsigned int n):``.
     183
     184
     185.. _section_sig_on:
     186
     187Interrupt and signal handling
     188===============================================
     189
     190(This section was written by Jeroen Demeyer.)
     191
     192When writing Cython code for Sage, special care must be taken to ensure
     193the code can be interrupted with ``CTRL-C``.
     194Since Cython optimizes for speed,
     195Cython normally does not check for interrupts.
     196For example, code like the following cannot be interrupted:
     197
     198.. skip
     199
     200::
     201
     202    sage: cython('while True: pass')  # DON'T DO THIS
     203
     204While this is running, pressing ``CTRL-C`` has no effect.  The only
     205way out is to kill the Sage process.
     206On certain systems, you can still quit Sage by typing ``CTRL-\``
     207(sending a Quit signal) instead of ``CTRL-C``.
     208
     209Using ``sig_on()`` and ``sig_off()``
     210------------------------------------
     211
     212.. highlight:: cython
     213
     214To enable interrupt handling, use the ``sig_on()`` and ``sig_off()`` functions.
     215You should put ``sig_on()`` *before* and ``sig_off()`` *after* any Cython code
     216which could potentially take a long time.
     217These two *must always* be called in **pairs**, i.e. every
     218``sig_on()`` must be matched by a closing ``sig_off()``.
     219
     220In practice your function will probably look like::
     221
     222    def sig_example():
     223        # (some harmless initialization)
     224        sig_on()
     225        # (a long computation here, potentially calling a C library)
     226        sig_off()
     227        # (some harmless post-processing)
     228        return something
     229
     230You can put ``sig_on()`` and ``sig_off()`` in all kinds of Cython functions:
     231``def``, ``cdef`` or ``cpdef``.
     232You cannot put them in pure Python code (i.e. files with extension ``.py``).
     233
     234It is possible to put ``sig_on()`` and ``sig_off()`` in different functions,
     235provided that ``sig_off()`` is called before the function which calls
     236``sig_on()`` returns.
     237The following code is *invalid*::
     238
     239    # INVALID code because we return from function foo()
     240    # without calling sig_off() first.
     241    cdef foo():
     242        sig_on()
     243
     244    def f1():
     245        foo()
     246        sig_off()
     247
     248But the following is valid::
     249
     250    cdef int foo():
     251        sig_off()
     252        return 2+2
     253
     254    def f1():
     255        sig_on()
     256        return foo()
     257
     258For clarity however, it is best to avoid this.
     259One good example where the above makes sense is the ``new_gen()``
     260function in :ref:`section-pari-library`.
     261
     262A common mistake is to put ``sig_off()`` towards the end of a
     263function (before the ``return``) when the function has multiple
     264``return`` statements.
     265So make sure there is a ``sig_off()`` before *every* ``return``
     266(and also before every ``raise``).
     267
     268.. WARNING::
     269
     270    The code inside ``sig_on()`` should be pure C or Cython code.
     271    If you call Python code, an interrupt is likely to mess up Python.
     272
     273    Also, when an interrupt occurs inside ``sig_on()``, code execution
     274    immediately stops without cleaning up.
     275    For example, any memory allocated inside ``sig_on()`` is lost.
     276    See :ref:`advanced-sig` for ways to deal with this.
     277
     278When the user presses ``CTRL-C`` inside ``sig_on()``, execution will jump back
     279to ``sig_on()`` (the first one if there is a stack) and ``sig_on()``
     280will raise ``KeyboardInterrupt``.  These can be handled just like other
     281Python exceptions::
     282
     283    def catch_interrupts():
     284        try:
     285            sig_on()  # This MUST be inside the try
     286            # (some long computation)
     287            sig_off()
     288        except KeyboardInterrupt:
     289            # (handle interrupt)
     290
     291Certain C libraries in Sage are written in a way that they will raise
     292Python exceptions: NTL and PARI are examples of this.
     293NTL can raise ``RuntimeError`` and PARI can raise ``PariError``.
     294Since these use the ``sig_on()`` mechanism,
     295these exceptions can be caught just like the ``KeyboardInterrupt``
     296in the example above.
     297
     298It is possible to stack ``sig_on()`` and ``sig_off()``.
     299If you do this, the effect is exactly the same as if only the outer
     300``sig_on()``/``sig_off()`` was there.  The inner ones will just change
     301a reference counter and otherwise do nothing.  Make sure that the number
     302of ``sig_on()`` calls equal the number of ``sig_off()`` calls::
     303
     304    def stack_sig_on():
     305        sig_on()
     306        sig_on()
     307        sig_on()
     308        # (some code)
     309        sig_off()
     310        sig_off()
     311        sig_off()
     312
     313
     314Extra care must be taken with exceptions raised inside ``sig_on()``.
     315The problem is that, if you do not do anything special, the ``sig_off()``
     316will never be called if there is an exception.
     317If you need to *raise* an exception yourself, call a ``sig_off()`` before it::
     318
     319    def raising_an_exception():
     320        sig_on()
     321        # (some long computation)
     322        if (something_failed):
     323            sig_off()
     324            raise RuntimeError, "something failed"
     325        # (some more computation)
     326        sig_off()
     327        return something
     328
     329Alternatively, you can use ``try``/``finally`` which will also catch
     330exceptions raised by subroutines inside the ``try``::
     331
     332    def try_finally_example():
     333        sig_on()
     334        try:
     335            # (some long computation, potentially raising exceptions)
     336        finally:
     337            sig_off()
     338        return something
     339
     340
     341Other signals
     342-------------
     343
     344Apart from handling interrupts, ``sig_on()`` provides more general
     345signal handling.
     346Indeed, if the code inside ``sig_on()`` would generate
     347a segmentation fault or call the C function ``abort()``
     348(or more generally, raise any of SIGSEGV, SIGILL, SIGABRT, SIGFPE, SIGBUS),
     349this is caught by the interrupt framework and a ``RuntimeError`` is raised::
     350
     351    cdef extern from 'stdlib.h':
     352        void abort()
     353   
     354    def abort_example():
     355        sig_on()
     356        abort()
     357        sig_off()
     358
     359.. code-block:: python
     360
     361    sage: abort_example()
     362    Traceback (most recent call last):
     363    ...
     364    RuntimeError: Aborted
     365
     366This exception can then be caught as explained above.
     367This means that ``abort()`` can be used
     368as an alternative to exceptions within ``sig_on()``/``sig_off()``.
     369A segmentation fault unguarded by ``sig_on()`` would simply terminate Sage.
     370
     371Instead of ``sig_on()``, there is also a function ``sig_str(s)``,
     372which takes a C string ``s`` as argument.
     373It behaves the same as ``sig_on()``, except that the string ``s``
     374will be used as a string for the exception.
     375``sig_str(s)`` should still be closed by ``sig_off()``.
     376Example Cython code::
     377
     378    cdef extern from 'stdlib.h':
     379        void abort()
     380   
     381    def abort_example_with_sig_str():
     382        sig_str("custom error message")
     383        abort()
     384        sig_off()
     385
     386Executing this gives:
     387
     388.. code-block:: python
     389
     390    sage: abort_example_with_sig_str()
     391    Traceback (most recent call last):
     392    ...
     393    RuntimeError: custom error message
     394
     395With regard to ordinary interrupts (i.e. SIGINT), ``sig_str(s)``
     396behaves the same as ``sig_on()``:
     397a simple ``KeyboardInterrupt`` is raised.
     398
     399.. _advanced-sig:
     400
     401Advanced functions
     402------------------
     403
     404There are several more specialized functions for dealing with interrupts.
     405The function ``sig_check()`` behaves exactly as ``sig_on(); sig_off()``
     406(except that ``sig_check()`` is faster since it does not involve a ``setjmp()`` call).
     407
     408``sig_check()`` can be used to check for pending interrupts.
     409If an interrupt happens outside of a ``sig_on()``/``sig_off()`` block,
     410it will be caught by the next ``sig_check()`` or ``sig_on()``.
     411
     412The typical use case for ``sig_check()`` is within tight loops doing
     413complicated stuff
     414(mixed Python and Cython code, potentially raising exceptions).
     415It gives more control, because a ``KeyboardInterrupt``
     416can *only* be raised during ``sig_check()``::
     417
     418    def sig_check_example():
     419        for x in foo:
     420            # (one loop iteration which does not take a long time)
     421            sig_check()
     422       
     423As mentioned above, ``sig_on()`` makes no attempt to clean anything up
     424(restore state or freeing memory) when an interrupt occurs.
     425In fact, it would be impossible for ``sig_on()`` to do that.
     426If you want to add some cleanup code, use ``sig_on_no_except()``
     427for this. This function behaves *exactly* like ``sig_on()``, except that
     428any exception raised (either ``KeyboardInterrupt`` or ``RuntimeError``)
     429is not yet passed to Python. Essentially, the exception is there, but
     430we prevent Cython from looking for the exception.
     431Then ``cython_check_exception()`` can be used to make Cython look
     432for the exception.
     433
     434Normally, ``sig_on_no_except()`` returns 1.
     435If a signal was caught and an exception raised, ``sig_on_no_except()``
     436instead returns 0.
     437The following example shows how to use ``sig_on_no_except()``::
     438
     439    def no_except_example():
     440        if not sig_on_no_except():
     441            # (clean up messed up internal state)
     442
     443            # Make Cython realize that there is an exception.
     444            # It will look like the exception was actually raised
     445            # by cython_check_exception().
     446            cython_check_exception()
     447        # (some long computation, messing up internal state of objects)
     448        sig_off()
     449
     450There is also a function ``sig_str_no_except(s)``
     451which is analogous to ``sig_str(s)``.
     452
     453.. NOTE::
     454
     455    See the file :file:`SAGE_ROOT/devel/sage/sage/tests/interrupt.pyx`
     456    for more examples of how to use the various ``sig_*()`` functions.
     457
     458Testing interrupts
     459------------------
     460
     461.. highlight:: python
     462
     463When writing :ref:`section-docstrings`,
     464one sometimes wants to check that certain code can be interrupted in a clean way.
     465In the module ``sage.tests.interrupt``, there is a function
     466``interrupt_after_delay(ms_delay = 500)`` which can be used to test interrupts.
     467That function simulates a ``CTRL-C`` (by sending SIGINT)
     468after ``ms_delay`` milliseconds.
     469
     470The following is an example of a doctest demonstrating that
     471the function ``factor()`` can be interrupted::
     472
     473    sage: import sage.tests.interrupt
     474    sage: try:
     475    ...     sage.tests.interrupt.interrupt_after_delay()
     476    ...     factor(10^1000 + 3)
     477    ... except KeyboardInterrupt:
     478    ...     print "ok!"
     479    ok!
  • doc/en/developer/coding_in_other.rst

    diff -r f4492d13c481 -r c71d80ffb170 doc/en/developer/coding_in_other.rst
    a b  
    1 .. _chapter-cython:
     1.. _chapter-other:
    22
    3 =========================
    4 Coding in Other Languages
    5 =========================
     3==============================================
     4Coding using external libraries and interfaces
     5==============================================
    66
    77When writing code for Sage, use Python for the basic structure and
    88interface. For speed, efficiency, or convenience, you can implement
    9 parts of the code using any of the following languages: Cython, C/C++,
    10 Fortran 95, GAP, Common Lisp, Singular, and GP/PARI. You can also use
     9parts of the code using any of the following languages:
     10:ref:`Cython <chapter-cython>`, C/C++,
     11Fortran 95, GAP, Common Lisp, Singular, and PARI/GP. You can also use
    1112all C/C++ libraries included with Sage  [3]_. (And if you are okay
    1213with your code depending on optional Sage packages, you can use
    1314Octave, or even Magma, Mathematica, or Maple.)
    1415
    15 The first section of this chapter discusses Cython, which is a
    16 compiled language based on Python. Many components of Sage are written
    17 in Cython. Later sections discuss the interfaces between Sage and
    18 PARI, GAP, and Singular.
     16In this chapter, we discuss interfaces between Sage and
     17:ref:`PARI <section-pari-library>`, :ref:`section-gap` and :ref:`section-singular`.
    1918
    20 .. _coding-in-cython:
    2119
    22 Cython
    23 ======
    24 
    25 Cython is a compiled version of Python. It is based on Pyrex
    26 (http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/). To a
    27 large degree, Cython has changed based on what Sage's developers
    28 needed; Cython has been developed in concert with Sage. However, it is
    29 an independent project now, which is used beyond the scope of Sage.
    30 
    31 As such, it is a young, but developing language, with young, but
    32 developing documentation. See its web page,
    33 http://www.cython.org/, for the most up-to-date information.
    34 
    35 Python is an interpreted language and has no declared data types for
    36 variables. These features make it easy to write and debug, but Python
    37 code can sometimes be slow. Cython code can look a lot like Python,
    38 but it gets translated into C code (often very efficient C code) and
    39 then compiled. Thus it offers a language which is familiar to Python
    40 developers, but with the potential for much greater speed.
    41 
    42 There are several ways to create and build Cython code in Sage.
    43 
    44 #. In the Sage Notebook, begin any cell with ``%cython``. When you
    45    evaluate that cell,
    46 
    47    #. It is saved to a file.
    48 
    49    #. Cython is run on it with all the standard Sage libraries
    50       automatically linked if necessary.
    51 
    52    #. The resulting ``.so`` file is then loaded into your running
    53       instance of Sage.
    54 
    55    #. The functionality defined in that cell is now available for you
    56       to use in the notebook. Also, the output cell has a link to the C
    57       program that was compiled to create the ``.so`` file.
    58 
    59 #. Create an ``.spyx`` file and attach or load it from the command
    60    line. This is similar to creating a ``%cython`` cell in the
    61    notebook but works completely from the command line (and not from
    62    the notebook).
    63 
    64 #. Create a ``.pyx`` file and add it to the Sage library.
    65 
    66    #. First, add a listing for the Cython extension to the variable
    67       ``ext_modules`` in the file
    68       ``SAGE_ROOT/devel/sage/module_list.py``. See the
    69       ``distutils.extension.Extension`` class for more information on
    70       creating a new Cython extension.
    71 
    72    #. Then, if you created a new directory for your ``.pyx`` file, add
    73       the directory name to the ``packages`` list in the file
    74       ``SAGE_ROOT/devel/sage/setup.py``.  (See also the section on
    75       "Creating a new directory" in :ref:`chapter-python`.)
    76 
    77    #. Run ``sage -b`` to rebuild Sage.
    78 
    79    For example, the file
    80    ``SAGE_ROOT/devel/sage/sage/graphs/chrompoly.pyx`` has the lines
    81 
    82    ::
    83 
    84      Extension('sage.graphs.chrompoly',
    85                sources = ['sage/graphs/chrompoly.pyx']),
    86 
    87    in ``module_list.py``. In addition, ``sage.graphs`` is included in
    88    the ``packages`` list under the Distutils section of ``setup.py``
    89    since ``chrompoly.pyx`` is contained in the directory
    90    ``sage/graphs``.
    91 
    92 
    93 Special pragmas
    94 ---------------
    95 
    96 If Cython code is either attached or loaded as a ``.spyx`` file or
    97 loaded from the notebook as a ``%cython`` block, the following
    98 pragmas are available:
    99 
    100 * clang --- may be either c or c++ indicating whether a C or C++
    101   compiler should be used.
    102 
    103 * clib --- additional libraries to be linked in, the space separated
    104   list is split and passed to distutils.
    105 
    106 * cinclude --- additional directories to search for header files. The
    107   space separated list is split and passed to distutils.
    108 
    109 For example:
    110 
    111 ::
    112 
    113     #clang C++
    114     #clib givaro
    115     #cinclude /usr/local/include/
    116 
    117 
    118 Attaching or loading .spyx
    119 --------------------------
    120 
    121 The easiest way to try out Cython without having to learn anything
    122 about distutils, etc., is to create a file with the extension
    123 ``spyx``, which stands for "Sage Pyrex":
    124 
    125 #. Create a file ``power2.spyx``.
    126 
    127 #. Put the following in it:
    128 
    129    ::
    130 
    131        def is2pow(n):
    132            while n != 0 and n%2 == 0:
    133                n = n >> 1
    134            return n == 1
    135 
    136 #. Start the Sage command line interpreter and load the ``spyx`` file
    137    (this will fail if you do not have a C compiler installed).
    138 
    139    .. skip
    140 
    141    ::
    142 
    143        sage: load "power2.spyx"
    144        Compiling power2.spyx...
    145        sage: is2pow(12)
    146        False
    147 
    148 Note that you can change ``power2.spyx``, then load it again and it
    149 will be recompiled on the fly. You can also attach ``power2.spyx`` so
    150 it is reloaded whenever you make changes:
    151 
    152 .. skip
    153 
    154 ::
    155 
    156     sage: attach "power2.spyx"
    157 
    158 Cython is used for its speed. Here is a timed test on a 2.6 GHz
    159 Opteron:
    160 
    161 .. skip
    162 
    163 ::
    164 
    165     sage: %time [n for n in range(10^5) if is2pow(n)]
    166     [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
    167     CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 s
    168     Wall time: 0.60 s
    169 
    170 Now, the code in the file ``power2.spyx`` is valid Python, and if we
    171 copy this to a file ``powerslow.py`` and load that, we get the
    172 following:
    173 
    174 .. skip
    175 
    176 ::
    177 
    178     sage: load "powerslow.py"
    179     sage: %time [n for n in range(10^5) if is2pow(n)]
    180     [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]
    181     CPU times: user 1.01 s, sys: 0.04 s, total: 1.05 s
    182     Wall time: 1.05 s
    183 
    184 By the way, we could gain even a little more speed with the Cython
    185 version with a type declaration, by changing ``def is2pow(n):`` to
    186 ``def is2pow(unsigned int n):``.
    187 
    188 
    189 Other languages
    190 ===============
    191 
    192 Since Sage is based on Python, it interfaces with C and C++, as well
    193 as other languages. See the Python documentation at
    194 http://www.python.org/doc/ for more details. In particular, the
    195 section "Extending and Embedding the Python Interpreter", available at
    196 http://docs.python.org/ext/ext.html, describes how to write C or
    197 C++ modules for use in Python.
    198 
     20.. _section-pari-library:
    19921
    20022The PARI C library interface
    20123============================
     
    21436direct calls to the PARI C functions---this is the preferred way
    21537as it is much faster. Thus this section focuses on using PARI.
    21638
    217 We will add a new method to the gen class. This is the abstract
     39We will add a new method to the ``gen`` class. This is the abstract
    21840representation of all PARI library objects. That means that once we
    21941add a method to this class, every PARI object, whether it is a number,
    22042polynomial or matrix, will have our new method. So you can do
    22143``pari(1).matfrobenius()``, but since PARI wants to apply
    22244``matfrobenius`` to matrices, not numbers, you will receive a
    223 PariError in this case.
     45``PariError`` in this case.
    22446
    225 The gen class is defined in
    226 ``SAGE_ROOT/devel/sage/sage/libs/pari/gen.pyx``, and this is where we
    227 add the method ``matfrobenius``:
     47The ``gen`` class is defined in
     48:file:`SAGE_ROOT/devel/sage/sage/libs/pari/gen.pyx`, and this is where we
     49add the method ``matfrobenius``::
    22850
    229 ::
     51    def matfrobenius(self, flag=0):
     52        r"""
     53        M.matfrobenius(flag=0): Return the Frobenius form of the square
     54        matrix M. If flag is 1, return only the elementary divisors (a list
     55        of polynomials). If flag is 2, return a two-components vector [F,B]
     56        where F is the Frobenius form and B is the basis change so that
     57        `M=B^{-1} F B`.
     58       
     59        EXAMPLES::
     60       
     61            sage: a = pari('[1,2;3,4]')
     62            sage: a.matfrobenius()
     63            [0, 2; 1, 5]
     64            sage: a.matfrobenius(flag=1)
     65            [x^2 - 5*x - 2]
     66            sage: a.matfrobenius(2)
     67            [[0, 2; 1, 5], [1, -1/3; 0, 1/3]]
     68        """
     69        sig_on()
     70        return self.new_gen(matfrobenius(self.g, flag, 0))
    23071
    231         def matfrobenius(self, flag=0):
    232             """
    233             matfrobenius(M,{flag}): Return the Frobenius form of the
    234             square matrix M. If flag is 1, return only the elementary
    235             divisors. If flag is 2, return a two-components vector [F,B]
    236             where F is the Frobenius form and B is the basis change
    237             so that M=B^-1*F*B.
    238             """
    239             sig_on()
    240             return self.new_gen(matfrobenius(self.g, flag))
     72Note the use of the :ref:`sig_on() statement <section_sig_on>`.
    24173
    242 The ``sig_on()`` statement is some magic for catching segfault signals.
    243 In this way, it prevents SIGSEGVs from the PARI C library crashing the
    244 Sage interpreter. Note that ``self.new_gen()`` calls a closing
    245 ``sig_off()`` macro. These two *must always* come in pairs, i.e. every
    246 ``sig_on()`` must be matched by a closing ``sig_off()``. The
    247 ``self.new_gen()`` call constructs a new Sage-python-gen object from a
    248 given pari-C-gen where the pari-C-gen is stored as the
    249 Sage-python-gen.g attribute. The ``matfrobenius`` call is just a call
     74The ``matfrobenius`` call is just a call
    25075to the PARI C library function ``matfrobenius`` with the appropriate
    25176parameters.
    25277
     78The ``self.new_gen(GEN x)`` call constructs a new Sage ``gen`` object from a
     79given PARI ``GEN`` where the PARI ``GEN`` is stored as the
     80``.g`` attribute.
     81Apart from this, ``self.new_gen()`` calls a closing ``sig_off()`` macro
     82and also clears the PARI stack so it is very convenient to use in a
     83``return`` statement as illustrated above.
     84So after ``self.new_gen()``, all PARI ``GEN``'s which are not converted
     85to Sage ``gen``'s are gone.
     86There is also ``self.new_gen_noclear(GEN x)`` which does the same as
     87``self.new_gen(GEN x)`` except that it does *not* call ``sig_off()`` nor
     88clear the PARI stack.
     89
    25390The information about which function to call and how to call it can be
    25491retrieved from the PARI user's manual (note: Sage includes the
    25592development version of PARI, so check that version of the user's
    25693manual). Looking for ``matfrobenius`` you can find:
    257 ``"The library syntax is matfrobenius(M,flag)"``.
     94
     95    The library syntax is ``GEN matfrobenius(GEN M, long flag, long v = -1)``,
     96    where ``v`` is a variable number.
    25897
    25998In case you are familiar with gp, please note that the PARI C function
    26099may have a name that is different from the corresponding gp function
     
    263102We can also add a ``frobenius(flag)`` method to the ``matrix_integer``
    264103class where we call the ``matfrobenius()`` method on the PARI object
    265104associated to the matrix after doing some sanity checking. Then we
    266 convert output from PARI to Sage objects:
     105convert output from PARI to Sage objects::
    267106
    268 ::
     107    def frobenius(self, flag=0, var='x'):
     108        """
     109        Return the Frobenius form (rational canonical form) of this
     110        matrix.
     111       
     112        INPUT:
     113       
     114        -  ``flag`` -- 0 (default), 1 or 2 as follows:
     115       
     116            -  ``0`` -- (default) return the Frobenius form of this
     117               matrix.
     118           
     119            -  ``1`` -- return only the elementary divisor
     120               polynomials, as polynomials in var.
     121           
     122            -  ``2`` -- return a two-components vector [F,B] where F
     123               is the Frobenius form and B is the basis change so that
     124               `M=B^{-1}FB`.
     125       
     126        -  ``var`` -- a string (default: 'x')
     127       
     128        ALGORITHM: uses PARI's matfrobenius()
     129       
     130        EXAMPLES::
     131       
     132            sage: A = MatrixSpace(ZZ, 3)(range(9))
     133            sage: A.frobenius(0)
     134            [ 0  0  0]
     135            [ 1  0 18]
     136            [ 0  1 12]
     137            sage: A.frobenius(1)
     138            [x^3 - 12*x^2 - 18*x]
     139            sage: A.frobenius(1, var='y')
     140            [y^3 - 12*y^2 - 18*y]
     141        """
     142        if not self.is_square():
     143            raise ArithmeticError("frobenius matrix of non-square matrix not defined.")
     144       
     145        v = self._pari_().matfrobenius(flag)
     146        if flag==0:
     147            return self.matrix_space()(v.python())
     148        elif flag==1:
     149            r = PolynomialRing(self.base_ring(), names=var)
     150            retr = []
     151            for f in v:
     152                retr.append(eval(str(f).replace("^","**"), {'x':r.gen()}, r.gens_dict()))
     153            return retr
     154        elif flag==2:
     155            F = matrix_space.MatrixSpace(QQ, self.nrows())(v[0].python())
     156            B = matrix_space.MatrixSpace(QQ, self.nrows())(v[1].python())
     157            return F, B
     158       
     159       
    269160
    270         def frobenius(self,flag=0):
    271             """
    272             If flag is 0 (the default value), return the Frobenius
    273                 form of this matrix.
    274             If flag is 1, return only the elementary divisors.
    275             If flag is 2, return a two-component vector [F,B]
    276                 where F is the Frobenius form and B is the basis change
    277                 so that M=B^-1*F*B.
    278 
    279             INPUT:
    280                flag -- 0,1 or 2 as described above
    281 
    282             ALGORITHM: uses pari's matfrobenius()
    283 
    284             EXAMPLE:
    285                sage: A = MatrixSpace(IntegerRing(), 3)(range(9))
    286                sage: A.frobenius(0)
    287                [ 0  0  0]
    288                [ 1  0 18]
    289                [ 0  1 12]
    290                sage: A.frobenius(1)
    291                [x3 - 12*x2 - 18*x]
    292                sage: A.frobenius(2)
    293                ([ 0  0  0]
    294                [ 1  0 18]
    295                [ 0  1 12],
    296                [    -1      2     -1]
    297                [     0  23/15 -14/15]
    298                [     0  -2/15   1/15])
    299             """
    300             if self.nrows()!=self.ncols():
    301                 raise ArithmeticError, \
    302                 "frobenius matrix of non-square matrix not defined."
    303             v = self._pari_().matfrobenius(flag)
    304             if flag==0:
    305                 return self.matrix_space()(v.python())
    306             elif flag==1:
    307                 r = polynomial_ring.PolynomialRing(self.base_ring())
    308                 #BUG: this should be handled in PolynomialRing not here
    309                 return [eval(str(x).replace("^","**"),{},r.gens_dict())
    310                         for x in v.python_list()]
    311             elif flag==2:
    312                 F = matrix_space.MatrixSpace(rational_field.RationalField(),
    313                                              self.nrows())(v[0].python())
    314                 B = matrix_space.MatrixSpace(rational_field.RationalField(),
    315                                              self.nrows())(v[1].python())
    316                 return F,B
    317 
     161.. _section-gap:
    318162
    319163GAP
    320164===
     
    358202The purpose of this section is to use this example to show how one
    359203might write a Python/Sage program whose input is, say, ``('G',2)`` and
    360204whose output is the matrix above (but as a Sage Matrix---see the code
    361 in the directory ``SAGE_ROOT/devel/sage/sage/matrix/`` and the
     205in the directory :file:`SAGE_ROOT/devel/sage/sage/matrix/` and the
    362206corresponding parts of the Sage reference manual).
    363207
    364208First, the input must be converted into strings consisting of legal
     
    443287  for this.
    444288
    445289
     290.. _section-singular:
     291
    446292Singular
    447293========
    448294
  • doc/en/developer/sage_manuals.rst

    diff -r f4492d13c481 -r c71d80ffb170 doc/en/developer/sage_manuals.rst
    a b  
    246246Syntax highlighting Cython code
    247247-------------------------------
    248248
    249 If you need to put :ref:`coding-in-cython` code in a ReST file,
     249If you need to put :ref:`Cython <chapter-cython>` code in a ReST file,
    250250you can either precede the code block by ``.. code-block:: cython`` instead
    251251of the usual ``::`` if you want to highlight one block of code in Cython,
    252252or you can use ``.. highlight:: cython`` for a whole file.
  • doc/en/developer/writing_code.rst

    diff -r f4492d13c481 -r c71d80ffb170 doc/en/developer/writing_code.rst
    a b  
    5959
    6060   conventions
    6161   coding_in_python
     62   coding_in_cython
    6263   coding_in_other
    6364   doctesting
    6465   sage_manuals
  • sage/matrix/matrix_integer_dense.pyx

    diff -r f4492d13c481 -r c71d80ffb170 sage/matrix/matrix_integer_dense.pyx
    a b  
    21222122           
    21232123        return D, U, V
    21242124
    2125     def frobenius(self,flag=0, var='x'):
     2125    def frobenius(self, flag=0, var='x'):
    21262126        """
    21272127        Return the Frobenius form (rational canonical form) of this
    21282128        matrix.
    21292129       
    2130         INPUT: flag -an integer:
    2131        
    2132        
    2133         -  ``0`` - (default) return the Frobenius form of this
    2134            matrix.
    2135        
    2136         -  ``1`` - return only the elementary divisor
    2137            polynomials, as polynomials in var.
    2138        
    2139         -  ``2`` - return a two-components vector [F,B] where F
    2140            is the Frobenius form and B is the basis change so that
    2141            `M=B^{-1}FB`.
    2142        
    2143         -  ``var`` - a string (default: 'x')
    2144        
    2145        
    21462130        INPUT:
    21472131       
    2148        
    2149         -  ``flag`` - 0 (default), 1 or 2 as described above
    2150        
    2151        
    2152         ALGORITHM: uses pari's matfrobenius()
    2153        
    2154         EXAMPLE::
     2132        -  ``flag`` -- 0 (default), 1 or 2 as follows:
     2133       
     2134            -  ``0`` -- (default) return the Frobenius form of this
     2135               matrix.
     2136           
     2137            -  ``1`` -- return only the elementary divisor
     2138               polynomials, as polynomials in var.
     2139           
     2140            -  ``2`` -- return a two-components vector [F,B] where F
     2141               is the Frobenius form and B is the basis change so that
     2142               `M=B^{-1}FB`.
     2143       
     2144        -  ``var`` -- a string (default: 'x')
     2145       
     2146        ALGORITHM: uses PARI's matfrobenius()
     2147       
     2148        EXAMPLES::
    21552149       
    21562150            sage: A = MatrixSpace(ZZ, 3)(range(9))
    21572151            sage: A.frobenius(0)
  • sage/tests/interrupt.pyx

    diff -r f4492d13c481 -r c71d80ffb170 sage/tests/interrupt.pyx
    a b  
    11"""
    2 Test signal handling in Sage.
     2Testing signal handling.
    33
    44AUTHORS:
    55
    6  - Jeroen Demeyer (2010-09-29): initial version
     6 - Jeroen Demeyer (2010-09-29): initial version (#10030)
    77
    88"""
    99#*****************************************************************************
     
    9292    Send an interrupt signal (``SIGINT``) to the Sage process
    9393    after a delay of ``ms_delay`` milliseconds.
    9494
    95     INPUT::
     95    INPUT:
    9696   
    97     - ``ms_delay`` - (default: 500) a nonnegative integer indicating
     97    - ``ms_delay`` -- (default: 500) a nonnegative integer indicating
    9898      how many milliseconds to wait before raising the interrupt signal.
    9999
    100100    EXAMPLES: