Cython support functions - Utilities

Skip to content
Back to top
View this page
Edit this page

# Cython support functions

AUTHORS:

- William Stein (2006-01-18): initial version

- William Stein (2007-07-28): update from sagex to cython

- Martin Albrecht & William Stein (2011-08): cfile & cargs

sage.misc.cython.compile_and_load(code, **kwds)

  INPUT:

  - `code` – string containing code that could be in a .pyx file that is attached or put in a %cython block in the notebook

  See the function `sage.misc.cython.cython()` for documentation for the other inputs.

  OUTPUT: a module, which results from compiling the given code and importing it

  EXAMPLES:

  Sage

      sage: from sage.misc.cython import compile_and_load
      sage: module = compile_and_load("def f(int n):\n    return n*n")
      sage: module.f(10)
      100

  Python

      >>> from sage.all import *
      >>> from sage.misc.cython import compile_and_load
      >>> module = compile_and_load("def f(int n):\n    return n*n")
      >>> module.f(Integer(10))
      100

sage.misc.cython.cython(filename, verbose=0, compile_message=False, use_cache=False, create_local_c_file=False, annotate=True, view_annotate=False, view_annotate_callback=None, sage_namespace=True, create_local_so_file=False)

  Compile a Cython file. This converts a Cython file to a C (or C++ file), and then compiles that. The .c file and the .so file are created in a temporary directory.

  INPUT:

  - `filename` – the name of the file to be compiled; should end with ‘pyx’

  - `verbose` – integer (default: 0); level of verbosity. A negative value ensures complete silence.

  - `compile_message` – boolean (default: `False`); if `True`, print `'Compiling <filename>...'` to the standard error

  - `use_cache` – boolean (default: `False`); if `True`, check the temporary build directory to see if there is already a corresponding .so file. If so, and if the .so file is newer than the Cython file, don’t recompile, just reuse the .so file.

  - `create_local_c_file` – boolean (default: `False`); if `True`, save a copy of the `.c` or `.cpp` file in the current directory

  - `annotate` – boolean (default: `True`); if `True`, create an html file which annotates the conversion from .pyx to .c. By default this is only created in the temporary directory, but if `create_local_c_file` is also True, then save a copy of the .html file in the current directory.

  - `view_annotate` – boolean (default: `False`); if `True`, open the annotated html file in a web browser

  - `view_annotate_callback` – function; a function that takes a string being the path to the html file. This can be overridden to change what to do with the annotated html file. Have no effect unless `view_annotate` is `True`. By default, the html file is opened in a web browser.

  - `sage_namespace` – boolean (default: `True`); if `True`, import `sage.all`

  - `create_local_so_file` – boolean (default: `False`); if `True`, save a copy of the compiled .so file in the current directory

  OUTPUT: a tuple `(name, dir)` where `name` is the name of the compiled module and `dir` is the directory containing the generated files.

sage.misc.cython.cython_compile(code, **kwds)

  Given a block of Cython code (as a text string), this function compiles it using a C compiler, and includes it into the global namespace.

  AUTHOR: William Stein, 2006-10-31

  Warning

  Only use this from Python code, not from extension code, since from extension code you would change the global scope (i.e., of the Sage interpreter). And it would be stupid, since you’re already writing Cython!

  Also, never use this in the standard Sage library. Any code that uses this can only run on a system that has a C compiler installed, and we want to avoid making that assumption for casual Sage usage. Also, any code that uses this in the library would greatly slow down startup time, since currently there is no caching.

  Todo

  Need to create a clever caching system so code only gets compiled once.

sage.misc.cython.cython_import(filename, **kwds)

  Compile a file containing Cython code, then import and return the module. Raises an `ImportError` if anything goes wrong.

  INPUT:

  - `filename` – string; name of a file that contains Cython code

  See the function `sage.misc.cython.cython()` for documentation for the other inputs.

  OUTPUT: the module that contains the compiled Cython code

sage.misc.cython.cython_import_all(filename, globals, **kwds)

  Imports all non-private (i.e., not beginning with an underscore) attributes of the specified Cython module into the given context. This is similar to:

      from module import *

  Raises an `ImportError` exception if anything goes wrong.

  INPUT:

  - `filename` – string; name of a file that contains Cython code

  See the function `sage.misc.cython.cython()` for documentation for the other inputs.

sage.misc.cython.cython_lambda(vars, expr, verbose=0, **kwds)

  Create a compiled function which evaluates `expr` assuming machine values for `vars`.

  INPUT:

  - `vars` – list of pairs (variable name, c-data type), where the variable names and data types are strings, OR a string such as `'double x, int y, int z'`

  - `expr` – an expression involving the vars and constants; you can access objects defined in the current module scope `globals()` using `sage.object_name`.

  Warning

  Accessing `globals()` doesn’t actually work, see Issue #12446.

  EXAMPLES:

  We create a Lambda function in pure Python (using the r to make sure the 3.2 is viewed as a Python float):

  Sage

      sage: f = lambda x,y: x*x + y*y + x + y + 17r*x + 3.2r

  Python

      >>> from sage.all import *
      >>> f = lambda x,y: x*x + y*y + x + y + 17*x + 3.2

  We make the same Lambda function, but in a compiled form.

  Sage

      sage: g = cython_lambda('double x, double y', 'x*x + y*y + x + y + 17*x + 3.2')
      sage: g(2,3)
      55.2
      sage: g(0,0)
      3.2

  [Python]

      >>> from sage.all import *
      >>> g = cython_lambda('double x, double y', 'x*x + y*y + x + y + 17*x + 3.2')
      >>> g(Integer(2),Integer(3))
      55.2
      >>> g(Integer(0),Integer(0))
      3.2

  In order to access Sage globals, prefix them with `sage.`:

  Sage

      sage: f = cython_lambda('double x', 'sage.sin(x) + sage.a')
      sage: f(0)
      Traceback (most recent call last):
      ...
      NameError: global 'a' is not defined
      sage: a = 25
      sage: f(10)
      24.45597888911063
      sage: a = 50
      sage: f(10)
      49.45597888911063

  Python

      >>> from sage.all import *
      >>> f = cython_lambda('double x', 'sage.sin(x) + sage.a')
      >>> f(Integer(0))
      Traceback (most recent call last):
      ...
      NameError: global 'a' is not defined
      >>> a = Integer(25)
      >>> f(Integer(10))
      24.45597888911063
      >>> a = Integer(50)
      >>> f(Integer(10))
      49.45597888911063

sage.misc.cython.sanitize(f)

  Given a filename `f`, replace it by a filename that is a valid Python module name.

  This means that the characters are all alphanumeric or `_`’s and doesn’t begin with a numeral.

  EXAMPLES:

  Sage

      sage: from sage.misc.cython import sanitize
      sage: sanitize('abc')
      'abc'
      sage: sanitize('abc/def')
      'abc_def'
      sage: sanitize('123/def-hij/file.py')
      '_123_def_hij_file_py'

  Python

      >>> from sage.all import *
      >>> from sage.misc.cython import sanitize
      >>> sanitize('abc')
      'abc'
      >>> sanitize('abc/def')
      'abc_def'
      >>> sanitize('123/def-hij/file.py')
      '_123_def_hij_file_py'