r"""
This example illustrates how to use external includes and libraries
from spyx files. In particular, we show how to use GMP.
NOTE -- in the compilation anything from the following libraries
is linked in:
'mpfr', 'gmp', 'gmpxx', 'stdc++', 'pari', 'm', 'mwrank'
Modify sage/misc/pyrex.py to add more.
Note that *every* function from an external library that you use must
be explicitly declared. The declaration has to be good enough for the
Pyrex program to correctly convert this code to C. However, your C
compiler and the actual C code will only see the actual headers from
the original include files.
# TODO: The factorial below is actually three times as fast as
what's built into SAGE... which means I should move
this into SAGE.
EXAMPLES:
sage: time n = factorial(100000)
CPU times: user 6.93 s, sys: 0.00 s, total: 6.93 s
Wall time: 6.95
sage: time n=factorial_ZZ(100000)
CPU times: user 8.56 s, sys: 2.22 s, total: 10.79 s
Wall time: 10.83
sage: time n = magma('Factorial(100000)')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 9.02
sage: time n=factorial_pure_python(100000)
CPU times: user 78.72 s, sys: 2.64 s, total: 81.37 s
Wall time: 94.89
"""
# If __no_preparse__ is in the file, the SAGE pre-processor
# is not run on the file, so the ^'s are xor and int literals
# are ints, etc.
#__no_preparse__
cdef extern from "gmp.h":
ctypedef void* mpz_t
void mpz_init(mpz_t integer)
void mpz_set_si(mpz_t integer, signed long int n)
void mpz_mul_si (mpz_t rop, mpz_t op1, long int op2)
char *mpz_get_str(char *str, int base, mpz_t op)
cdef extern from "stdlib.h":
void free(void *ptr)
def factorial_gmp(int n):
cdef mpz_t f
cdef int i
cdef char* s
mpz_init(f)
mpz_set_si(f, n)
# The _sig_on / _sig_off commands make it so
# this calculation is Ctrl-C interruptable.
# These should *only* be used to wrap code
# that compiles to pure C, i.e., doesn't access
# any of the Python library.
_sig_on
for i from 2 <= i <= n-1:
mpz_mul_si(f, f, i)
s = mpz_get_str(NULL, 32, f)
_sig_off
r = ZZ(0)
r.set_str(s, 32)
free(s)
return r