diff --git a/README.md b/README.md index b5c8dfa0291cef1299fb41bf22d9ed0d1cca385d..60356af941d43e5f8d3649a67ff392b5771aa751 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ To try this out you will need: python 3, cython compilation for you, you can by the way see the C code generated in test.c, the function call starts something like: + :::C static double __pyx_f_4test_integrand(CYTHON_UNUSED int __pyx_v_n, double *__pyx_v_args) [`CYTHON_UNUSED` _I think_ because the argument n is not used in `integrand()`, but the standard rubric for `LowLevelCallable.from_cython()` needs it] @@ -115,6 +116,77 @@ I didn't quite figure out how to make this work with NumPy data types. But maybe that doesn't matter. + +Update 7.4.2020: some tips on getting Cython to generate native C code +---------------------------------------------------------------------- + +1. If you employ float division, use the Cython decorator + `@cython.cdivision(True)` before a `cdef` function: + + import cython + + ... + + # The decorator stops division by zero checking + @cython.cdivision(True) + cdef double C1(double t, double t_cut, double t_0): + + ... etc ... + + to avoid Python checking for a `DivisionByZeroError`. Note that + you will need `import cython` to get access to this decorator. + +2. You can find [Cython version of Scipy special + functions](https://docs.scipy.org/doc/scipy/reference/special.cython_special.html) + in `scipy.special.cython_special`, for the Bessel function + normally given by [`scipy.special.jv`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.jv.html) + we needed to do: + + from scipy.special.cython_special cimport jv + +3. Similarly, Cython makes available C versions of many common C + library functions ([read more + here](https://cython.readthedocs.io/en/latest/src/tutorial/external.html)): + + from libc.math cimport sqrt, exp, sin, cos + +4. Note that although Cython knows about the C99 complex numbers, I + still haven't quite worked out how to do fast mathematics with + them directly (but using the real and imaginary parts separately + is ok). + +5. Keep checking the yellow-highlighted 'annotation' HTML file Cython + generates, and don't panic if something is still yellow (meaning + it may be calling interpreted Python still). Click the `+` to the + left of the line number to see what is actually happening. + + Even after doing the above things, we were using + + :::python + return result.real + + which led to some yellow highlighting. But the underlying code + contained the following preprocessor stuff: + + + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif + #else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) + #endif + + Comparing this with [the GCC + documentation](http://gcc.gnu.org/onlinedocs/gcc/Complex.html), it + seems we are generating native C code after all, but Cython can't + tell that. + Further reading --------------- @@ -137,3 +209,9 @@ Further reading Cython](https://stackoverflow.com/questions/4495420/passing-numpy-arrays-to-c-code-wrapped-with-cython) is a StackOverflow question of potential reference to getting NumPy to play along. + +* [Introduction to Cython for Solving Differential + Equations](http://hplgit.github.io/teamods/cyode/main_cyode.html) + by Hans Petter Langtangen does not cover the + scipy.LowLevelCallable integration, but has lots of other useful + tidbits.