创建预编译代码

在数学计算中,速度是非常关键的。虽然Python是一种非常方便的高级语言,但是某些微积分运算如果用静态的编译语言实现肯定会比Python快几个数量级。如果完全用Python编写的话,Sage的某些运算就会太慢了。

为了解决这个问题,Sage支持一种编译型的Python,叫Cython(Cython和Pyrex)。Cython既像Python又像C。多数Python的结构,包括列表,条件表达式,象+=这样的代码都是可用的。也可以导入你已经写好的其他Python模块中的代码。并且还可以声明任意的C变量,可以直接调用任意的C语言库。最终的代码被转化为C语言,并使用C编译器编译。

为了编译你自己的编译型Sage代码,文件要用扩展名.spyx(而不是.sage)。如果是用命令行,可以跟解释型代码一样,附加和运行编译型代码(当前版本notebook界面下不能附加或运行Cython的代码)。实际的编译过程是后台完成的,不需要你明确的做什么。编译后的共享对象库保存在$HOME/.sage/temp/hostname/pid/spyx.这些文件在你退出Sage时会被删除。

对于spyx文件不会进行预分词,如,在spyx文件中,1/3会得到0而不是有理数$1/3$。 如果foo是Sage库中的一个函数, 要在spyx文件中使用,需要导入sage.all并且使用sage.all.foo

  1. import sage.all
  2. def foo(n):
  3. return sage.all.factorial(n)

在访问单文件中的C语言函数

访问定义在单独的*.c文件中的C语言函数也是很容易的。这有一个例子。在同一个目录下新建文件test.ctest.spyx, 包含以下内容:

纯C代码:test.c

  1. int add_one(int n) {
  2. return n + 1;
  3. }

Cython代码:test.spyx:

  1. cdef extern from "test.c":
  2. int add_one(int n)
  3. def test(n):
  4. return add_one(n)

下面这样做:

  1. sage: attach "test.spyx"
  2. Compiling (...)/test.spyx...
  3. sage: test(10)
  4. 11

如果在Cython文件中编译C代码还要用到另外一个foo库,在Cython源码中加一行clib foo。类似的, 可以用声明cfile bar来包含一个C文件bar