{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# The Need for Speed: An Introduction to Cython\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Do you really need the speed?\n", "\n", "* Write your Python program.\n", "* Ensure it executes correctly and does what it is supposed to.\n", "* Is it fast enough?\n", "* If yes: Ignore the rest of the presentation.\n", "* If no:\n", " 1. Get it right.\n", " 2. Test it's right.\n", " 3. Profile if slow.\n", " 4. Optimise (C/C++ or use Cython and save yourself the pain).\n", " 5. Repeat from 2.\n", " \n", "> We *should forget* about small efficiencies, say about 97% of the time: **premature optimization is the root of all evil**.\n", "\n", "> Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only **after** that code has been identified.\n", "\n", "
**Donald Knuth**
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# What is Cython?\n", "\n", "* Cython is a superset of the Python language.\n", "* Cython translates Python code to equivalent C code.\n", "* This code is executed within the CPython runtime environment, but at the speed of compiled C and with the ability to call directly into C libraries. \n", "* At the same time, it keeps the original interface of the Python source code, which makes it directly usable from Python code.\n", "* This enables Cython's two major use cases:\n", " 1. Extending the CPython interpreter with fast binary modules.\n", " 2. Interfacing Python code with external C libraries.\n", "* While Cython can compile (most) regular Python code, the generated C code usually gains major (and sometime impressive) speed improvements from optional static type declarations for both Python and C types." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Why is Python slow?\n", "\n", "* Contrary to popular belief, Python is **not** slow because it is interpreted. You could use Cython to convert Python to C and compile it and you would gain minimal speedups.\n", "* The main reason that Python is slow is that it's **dynamically** typed.\n", "* At the time the program executes, the interpreter *doesn't know the type of the variables* that are defined. Everything is an *object*, everything is in a *box* which results in **boxing–unboxing overhead**.\n", "* There is also significant overhead on attribute lookups. For instance, calling a method `f` on an object `a` will cause possible lookups in `__dict__`, calls to `__getattr__`, etc, then finally call `__call__` on the callable object `f`. This process cannot be optimised for the reason metioned above." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Building Cython code\n", "\n", "Cython code must, unlike Python, be compiled. This happens in two stages:\n", "* A `.pyx` file is compiled by Cython to a `.c` file, containing the code of a Python extension module,\n", "* The `.c` file is compiled by a `C` compiler to a `.so` file (or `.pyd` on Windows) which can be imported directly into a Python session.\n", " \n", "There are several ways to build Cython code:\n", "* Write a distutils (or setuptools) `setup.py`.\n", "* Use `pyximport`, importing Cython `.pyx` files as if they were `.py` files (using distutils to compile and build in the background).\n", "* Run the cython command-line utility manually to produce the `.c` file from the `.pyx` file, then manually compiling the `.c` file into a shared object library or DLL suitable for import from Python. (These manual steps are mostly for debugging and experimentation.)\n", "* Use the [Jupyter notebook](http://cython.readthedocs.io/en/latest/src/quickstart/build.html#jupyter), which allows Cython code inline." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Cython workflow\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# Cython Hello World\n", "\n", "1. Create a `helloworld.pyx`:\n", "```Python\n", "print(\"Hello World\")\n", "```\n", "2. Create a `setup.py`, which is like a Python makefile:\n", "```Python\n", "from distutils.core import setup\n", "from Cython.Build import cythonize\n", "setup(ext_modules = cythonize('helloworld.pyx'))\n", "```\n", "3. Build the Cython file:\n", "```Bash\n", "python setup.py build_ext --inplace\n", "```\n", "4. This will leave a file in your local directory called `helloworld.so` in unix or `helloworld.pyd` in Windows. To use this file, simply import it as if it was a regular python module:\n", "```Python\n", ">>> import helloworld\n", "Hello World\n", "```" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# `pyximport`: Cython compilation the easy way\n", "\n", "If your module doesn't require any extra C libraries or a special build setup, then you can use the `pyximport` module to load `.pyx` files directly on import, without having to write a `setup.py` file:\n", "```Python\n", ">>> import pyximport; pyximport.install()\n", ">>> import helloworld\n", "Hello World\n", "```\n", "It is also possible to compile new `.py` modules that are being imported (including the standard library and installed packages). For using this feature, just tell that to `pyximport`:\n", "```Python\n", ">>> pyximport.install(pyimport=True)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Cython file types\n", "\n", "There are three file types in Cython:\n", "1. **Implementation** files carry a `.pyx` suffix. Can contain basically anything Cythonic.\n", "2. **Definition** files carry a `.pxd` suffix. They work like C header files and contain Cython declarations (and sometimes code sections), which are only meant for inclusion by Cython modules. A `.pxd` file is imported into a `.pyx` module by using the `cimport` keyword. Use `cimport` as you would Python’s import statement, to access these files from other definition or implementation files.\n", "3. **Include** files which carry a `.pxi` suffix. Can contain any Cythonic code, because the entire file is textually embedded at the location you prescribe. Include the `.pxi` file with an `include` statement like: `include \"spamstuff.pxi\"`\n", "`cimport`\n" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# Variable and type definitions\n", "\n", "The `cdef` statement is used to declare C variables, either local or module-level\n", "```Cython\n", "cdef int i, j, k\n", "cdef float f, g[42], *h\n", "```\n", "and C `struct`, `union` or `enum` types:\n", "```Cython\n", "cdef struct Grail:\n", " int age\n", " float volume\n", "\n", "cdef union Food:\n", " char *spam\n", " float *eggs\n", "\n", "cdef enum CheeseType:\n", " cheddar, edam,\n", " camembert\n", "\n", "cdef enum CheeseState:\n", " hard = 1\n", " soft = 2\n", " runny = 3\n", "```\n", "Grouping multiple C declarations:\n", "```Cython\n", "cdef:\n", " struct Spam:\n", " int tons\n", "\n", " int i\n", " float a\n", " Spam *p\n", "\n", " void f(Spam *s):\n", " print(s.tons, \"Tons of spam\")\n", "```" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# Functions and Methods\n", "\n", "1. `def`: callable from Python.\n", " * Declared with the `def` statement.\n", " * Called with Python objects.\n", " * Return Python objects. \n", "Generated by Cython 0.25.2
\n", "\n",
" Yellow lines hint at Python interaction.
\n",
" Click on a line that starts with a \"+
\" to see the C code that Cython generated for it.\n",
"
+01: def py_fib(n):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_02d5c366cee2bfe4761d328976839617_1py_fib(PyObject *__pyx_self, PyObject *__pyx_v_n); /*proto*/\n", "static PyMethodDef __pyx_mdef_46_cython_magic_02d5c366cee2bfe4761d328976839617_1py_fib = {\"py_fib\", (PyCFunction)__pyx_pw_46_cython_magic_02d5c366cee2bfe4761d328976839617_1py_fib, METH_O, 0};\n", "static PyObject *__pyx_pw_46_cython_magic_02d5c366cee2bfe4761d328976839617_1py_fib(PyObject *__pyx_self, PyObject *__pyx_v_n) {\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"py_fib (wrapper)\", 0);\n", " __pyx_r = __pyx_pf_46_cython_magic_02d5c366cee2bfe4761d328976839617_py_fib(__pyx_self, ((PyObject *)__pyx_v_n));\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_02d5c366cee2bfe4761d328976839617_py_fib(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_n) {\n", " PyObject *__pyx_v_a = NULL;\n", " PyObject *__pyx_v_b = NULL;\n", " CYTHON_UNUSED PyObject *__pyx_v_i = NULL;\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"py_fib\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L1_error:;\n", " __Pyx_XDECREF(__pyx_t_1);\n", " __Pyx_XDECREF(__pyx_t_2);\n", " __Pyx_XDECREF(__pyx_t_5);\n", " __Pyx_AddTraceback(\"_cython_magic_02d5c366cee2bfe4761d328976839617.py_fib\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __pyx_r = NULL;\n", " __pyx_L0:;\n", " __Pyx_XDECREF(__pyx_v_a);\n", " __Pyx_XDECREF(__pyx_v_b);\n", " __Pyx_XDECREF(__pyx_v_i);\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple_ = PyTuple_Pack(4, __pyx_n_s_n, __pyx_n_s_a, __pyx_n_s_b, __pyx_n_s_i); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_tuple_);\n", " __Pyx_GIVEREF(__pyx_tuple_);\n", "/* … */\n", " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_02d5c366cee2bfe4761d328976839617_1py_fib, NULL, __pyx_n_s_cython_magic_02d5c366cee2bfe476); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_py_fib, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_C_Users_telis_ipython_cython__cy, __pyx_n_s_py_fib, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 1, __pyx_L1_error)\n", "
+02: a, b = 1, 1\n", "
__pyx_t_1 = __pyx_int_1;\n", " __Pyx_INCREF(__pyx_t_1);\n", " __pyx_t_2 = __pyx_int_1;\n", " __Pyx_INCREF(__pyx_t_2);\n", " __pyx_v_a = __pyx_t_1;\n", " __pyx_t_1 = 0;\n", " __pyx_v_b = __pyx_t_2;\n", " __pyx_t_2 = 0;\n", "
+03: for i in range(n):\n", "
__pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __Pyx_INCREF(__pyx_v_n);\n", " __Pyx_GIVEREF(__pyx_v_n);\n", " PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_n);\n", " __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n", " if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {\n", " __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;\n", " __pyx_t_4 = NULL;\n", " } else {\n", " __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " }\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " for (;;) {\n", " if (likely(!__pyx_t_4)) {\n", " if (likely(PyList_CheckExact(__pyx_t_2))) {\n", " if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " } else {\n", " if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " }\n", " } else {\n", " __pyx_t_1 = __pyx_t_4(__pyx_t_2);\n", " if (unlikely(!__pyx_t_1)) {\n", " PyObject* exc_type = PyErr_Occurred();\n", " if (exc_type) {\n", " if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n", " else __PYX_ERR(0, 3, __pyx_L1_error)\n", " }\n", " break;\n", " }\n", " __Pyx_GOTREF(__pyx_t_1);\n", " }\n", " __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);\n", " __pyx_t_1 = 0;\n", "/* … */\n", " }\n", " __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n", "
+04: a, b = a + b, a\n", "
__pyx_t_1 = PyNumber_Add(__pyx_v_a, __pyx_v_b); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_t_5 = __pyx_v_a;\n", " __Pyx_INCREF(__pyx_t_5);\n", " __Pyx_DECREF_SET(__pyx_v_a, __pyx_t_1);\n", " __pyx_t_1 = 0;\n", " __Pyx_DECREF_SET(__pyx_v_b, __pyx_t_5);\n", " __pyx_t_5 = 0;\n", "
+05: return a\n", "
__Pyx_XDECREF(__pyx_r);\n", " __Pyx_INCREF(__pyx_v_a);\n", " __pyx_r = __pyx_v_a;\n", " goto __pyx_L0;\n", "
06:
\n",
"+07: def cy_fib(int n):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_02d5c366cee2bfe4761d328976839617_3cy_fib(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n", "static PyMethodDef __pyx_mdef_46_cython_magic_02d5c366cee2bfe4761d328976839617_3cy_fib = {\"cy_fib\", (PyCFunction)__pyx_pw_46_cython_magic_02d5c366cee2bfe4761d328976839617_3cy_fib, METH_O, 0};\n", "static PyObject *__pyx_pw_46_cython_magic_02d5c366cee2bfe4761d328976839617_3cy_fib(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n", " int __pyx_v_n;\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cy_fib (wrapper)\", 0);\n", " assert(__pyx_arg_n); {\n", " __pyx_v_n = __Pyx_PyInt_As_int(__pyx_arg_n); if (unlikely((__pyx_v_n == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 7, __pyx_L3_error)\n", " }\n", " goto __pyx_L4_argument_unpacking_done;\n", " __pyx_L3_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_02d5c366cee2bfe4761d328976839617.cy_fib\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __Pyx_RefNannyFinishContext();\n", " return NULL;\n", " __pyx_L4_argument_unpacking_done:;\n", " __pyx_r = __pyx_pf_46_cython_magic_02d5c366cee2bfe4761d328976839617_2cy_fib(__pyx_self, ((int)__pyx_v_n));\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_02d5c366cee2bfe4761d328976839617_2cy_fib(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n", " CYTHON_UNUSED int __pyx_v_i;\n", " int __pyx_v_a;\n", " int __pyx_v_b;\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cy_fib\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L1_error:;\n", " __Pyx_XDECREF(__pyx_t_5);\n", " __Pyx_AddTraceback(\"_cython_magic_02d5c366cee2bfe4761d328976839617.cy_fib\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __pyx_r = NULL;\n", " __pyx_L0:;\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple__3 = PyTuple_Pack(5, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_i, __pyx_n_s_a, __pyx_n_s_b); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_tuple__3);\n", " __Pyx_GIVEREF(__pyx_tuple__3);\n", "/* … */\n", " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_02d5c366cee2bfe4761d328976839617_3cy_fib, NULL, __pyx_n_s_cython_magic_02d5c366cee2bfe476); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_cy_fib, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
08: cdef int i, a, b\n", "
+09: a, b = 1, 1\n", "
__pyx_t_1 = 1;\n", " __pyx_t_2 = 1;\n", " __pyx_v_a = __pyx_t_1;\n", " __pyx_v_b = __pyx_t_2;\n", "
+10: for i in range(n):\n", "
__pyx_t_2 = __pyx_v_n;\n", " for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_2; __pyx_t_1+=1) {\n", " __pyx_v_i = __pyx_t_1;\n", "
+11: a, b = a + b, a\n", "
__pyx_t_3 = (__pyx_v_a + __pyx_v_b);\n", " __pyx_t_4 = __pyx_v_a;\n", " __pyx_v_a = __pyx_t_3;\n", " __pyx_v_b = __pyx_t_4;\n", " }\n", "
+12: return a\n", "
__Pyx_XDECREF(__pyx_r);\n", " __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_a); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 12, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_5);\n", " __pyx_r = __pyx_t_5;\n", " __pyx_t_5 = 0;\n", " goto __pyx_L0;\n", "
Generated by Cython 0.25.2
\n", "\n",
" Yellow lines hint at Python interaction.
\n",
" Click on a line that starts with a \"+
\" to see the C code that Cython generated for it.\n",
"
+01: def cy_primes(int kmax):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_0ced8f83c564d45ab78425accda8735b_1cy_primes(PyObject *__pyx_self, PyObject *__pyx_arg_kmax); /*proto*/\n", "static char __pyx_doc_46_cython_magic_0ced8f83c564d45ab78425accda8735b_cy_primes[] = \"Calculation of prime numbers in Cython.\";\n", "static PyMethodDef __pyx_mdef_46_cython_magic_0ced8f83c564d45ab78425accda8735b_1cy_primes = {\"cy_primes\", (PyCFunction)__pyx_pw_46_cython_magic_0ced8f83c564d45ab78425accda8735b_1cy_primes, METH_O, __pyx_doc_46_cython_magic_0ced8f83c564d45ab78425accda8735b_cy_primes};\n", "static PyObject *__pyx_pw_46_cython_magic_0ced8f83c564d45ab78425accda8735b_1cy_primes(PyObject *__pyx_self, PyObject *__pyx_arg_kmax) {\n", " int __pyx_v_kmax;\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cy_primes (wrapper)\", 0);\n", " assert(__pyx_arg_kmax); {\n", " __pyx_v_kmax = __Pyx_PyInt_As_int(__pyx_arg_kmax); if (unlikely((__pyx_v_kmax == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L3_error)\n", " }\n", " goto __pyx_L4_argument_unpacking_done;\n", " __pyx_L3_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_0ced8f83c564d45ab78425accda8735b.cy_primes\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __Pyx_RefNannyFinishContext();\n", " return NULL;\n", " __pyx_L4_argument_unpacking_done:;\n", " __pyx_r = __pyx_pf_46_cython_magic_0ced8f83c564d45ab78425accda8735b_cy_primes(__pyx_self, ((int)__pyx_v_kmax));\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_0ced8f83c564d45ab78425accda8735b_cy_primes(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_kmax) {\n", " int __pyx_v_n;\n", " int __pyx_v_k;\n", " int __pyx_v_i;\n", " int __pyx_v_p[0x3E8];\n", " PyObject *__pyx_v_result = NULL;\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cy_primes\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L1_error:;\n", " __Pyx_XDECREF(__pyx_t_1);\n", " __Pyx_AddTraceback(\"_cython_magic_0ced8f83c564d45ab78425accda8735b.cy_primes\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __pyx_r = NULL;\n", " __pyx_L0:;\n", " __Pyx_XDECREF(__pyx_v_result);\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple_ = PyTuple_Pack(7, __pyx_n_s_kmax, __pyx_n_s_kmax, __pyx_n_s_n, __pyx_n_s_k, __pyx_n_s_i, __pyx_n_s_p, __pyx_n_s_result); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_tuple_);\n", " __Pyx_GIVEREF(__pyx_tuple_);\n", "/* … */\n", " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_0ced8f83c564d45ab78425accda8735b_1cy_primes, NULL, __pyx_n_s_cython_magic_0ced8f83c564d45ab7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_cy_primes, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(1, 0, 7, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_C_Users_telis_ipython_cython__cy, __pyx_n_s_cy_primes, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 1, __pyx_L1_error)\n", "
02: """Calculation of prime numbers in Cython."""\n", "
03: cdef int n, k, i\n", "
04: cdef int p[1000]\n", "
+05: result = []\n", "
__pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_v_result = ((PyObject*)__pyx_t_1);\n", " __pyx_t_1 = 0;\n", "
+06: if kmax > 1000:\n", "
__pyx_t_2 = ((__pyx_v_kmax > 0x3E8) != 0);\n", " if (__pyx_t_2) {\n", "/* … */\n", " }\n", "
+07: kmax = 10000\n", "
__pyx_v_kmax = 0x2710;\n", "
+08: k = 0\n", "
__pyx_v_k = 0;\n", "
+09: n = 2\n", "
__pyx_v_n = 2;\n", "
+10: while k < kmax:\n", "
while (1) {\n", " __pyx_t_2 = ((__pyx_v_k < __pyx_v_kmax) != 0);\n", " if (!__pyx_t_2) break;\n", "
+11: i = 0\n", "
__pyx_v_i = 0;\n", "
+12: while i < k and n % p[i] != 0:\n", "
while (1) {\n",
" __pyx_t_3 = ((__pyx_v_i < __pyx_v_k) != 0);\n",
" if (__pyx_t_3) {\n",
" } else {\n",
" __pyx_t_2 = __pyx_t_3;\n",
" goto __pyx_L8_bool_binop_done;\n",
" }\n",
" if (unlikely((__pyx_v_p[__pyx_v_i]) == 0)) {\n",
" PyErr_SetString(PyExc_ZeroDivisionError, \"integer division or modulo by zero\");\n",
" __PYX_ERR(0, 12, __pyx_L1_error)\n",
" }\n",
" __pyx_t_3 = ((__Pyx_mod_int(__pyx_v_n, (__pyx_v_p[__pyx_v_i])) != 0) != 0);\n",
" __pyx_t_2 = __pyx_t_3;\n",
" __pyx_L8_bool_binop_done:;\n",
" if (!__pyx_t_2) break;\n",
"
+13: i = i + 1\n", "
__pyx_v_i = (__pyx_v_i + 1);\n", " }\n", "
+14: if i == k:\n", "
__pyx_t_2 = ((__pyx_v_i == __pyx_v_k) != 0);\n", " if (__pyx_t_2) {\n", "/* … */\n", " }\n", "
+15: p[k] = n\n", "
(__pyx_v_p[__pyx_v_k]) = __pyx_v_n;\n", "
+16: k = k + 1\n", "
__pyx_v_k = (__pyx_v_k + 1);\n", "
+17: result.append(n)\n", "
__pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_n); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 17, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_t_4 = __Pyx_PyList_Append(__pyx_v_result, __pyx_t_1); if (unlikely(__pyx_t_4 == -1)) __PYX_ERR(0, 17, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
+18: n = n + 1\n", "
__pyx_v_n = (__pyx_v_n + 1);\n", " }\n", "
+19: return result\n", "
__Pyx_XDECREF(__pyx_r);\n", " __Pyx_INCREF(__pyx_v_result);\n", " __pyx_r = __pyx_v_result;\n", " goto __pyx_L0;\n", "
20:
\n",
"+21: print(cy_primes(10))\n", "
__pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_cy_primes); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 21, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __Pyx_GIVEREF(__pyx_t_2);\n", " PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);\n", " __pyx_t_2 = 0;\n", " __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_print, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 21, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n", "
Generated by Cython 0.25.2
\n", "\n",
" Yellow lines hint at Python interaction.
\n",
" Click on a line that starts with a \"+
\" to see the C code that Cython generated for it.\n",
"
+01: def cy_levenshtein(s, t):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_09178397f426d86b92ac0473b4709898_1cy_levenshtein(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n", "static PyMethodDef __pyx_mdef_46_cython_magic_09178397f426d86b92ac0473b4709898_1cy_levenshtein = {\"cy_levenshtein\", (PyCFunction)__pyx_pw_46_cython_magic_09178397f426d86b92ac0473b4709898_1cy_levenshtein, METH_VARARGS|METH_KEYWORDS, 0};\n", "static PyObject *__pyx_pw_46_cython_magic_09178397f426d86b92ac0473b4709898_1cy_levenshtein(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n", " PyObject *__pyx_v_s = 0;\n", " PyObject *__pyx_v_t = 0;\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cy_levenshtein (wrapper)\", 0);\n", " {\n", " static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_s,&__pyx_n_s_t,0};\n", " PyObject* values[2] = {0,0};\n", " if (unlikely(__pyx_kwds)) {\n", " Py_ssize_t kw_args;\n", " const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n", " switch (pos_args) {\n", " case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n", " case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n", " case 0: break;\n", " default: goto __pyx_L5_argtuple_error;\n", " }\n", " kw_args = PyDict_Size(__pyx_kwds);\n", " switch (pos_args) {\n", " case 0:\n", " if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_s)) != 0)) kw_args--;\n", " else goto __pyx_L5_argtuple_error;\n", " case 1:\n", " if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_t)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"cy_levenshtein\", 1, 2, 2, 1); __PYX_ERR(0, 1, __pyx_L3_error)\n", " }\n", " }\n", " if (unlikely(kw_args > 0)) {\n", " if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"cy_levenshtein\") < 0)) __PYX_ERR(0, 1, __pyx_L3_error)\n", " }\n", " } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {\n", " goto __pyx_L5_argtuple_error;\n", " } else {\n", " values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n", " values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n", " }\n", " __pyx_v_s = values[0];\n", " __pyx_v_t = values[1];\n", " }\n", " goto __pyx_L4_argument_unpacking_done;\n", " __pyx_L5_argtuple_error:;\n", " __Pyx_RaiseArgtupleInvalid(\"cy_levenshtein\", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1, __pyx_L3_error)\n", " __pyx_L3_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_09178397f426d86b92ac0473b4709898.cy_levenshtein\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __Pyx_RefNannyFinishContext();\n", " return NULL;\n", " __pyx_L4_argument_unpacking_done:;\n", " __pyx_r = __pyx_pf_46_cython_magic_09178397f426d86b92ac0473b4709898_cy_levenshtein(__pyx_self, __pyx_v_s, __pyx_v_t);\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_09178397f426d86b92ac0473b4709898_cy_levenshtein(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_s, PyObject *__pyx_v_t) {\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cy_levenshtein\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L1_error:;\n", " __Pyx_XDECREF(__pyx_t_5);\n", " __Pyx_AddTraceback(\"_cython_magic_09178397f426d86b92ac0473b4709898.cy_levenshtein\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __pyx_r = NULL;\n", " __pyx_L0:;\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple_ = PyTuple_Pack(2, __pyx_n_s_s, __pyx_n_s_t); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_tuple_);\n", " __Pyx_GIVEREF(__pyx_tuple_);\n", "/* … */\n", " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_09178397f426d86b92ac0473b4709898_1cy_levenshtein, NULL, __pyx_n_s_cython_magic_09178397f426d86b92); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_cy_levenshtein, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
+02: return lev(s, len(s), t, len(t))\n", "
__Pyx_XDECREF(__pyx_r);\n", " __pyx_t_1 = __Pyx_PyObject_AsString(__pyx_v_s); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __pyx_t_2 = PyObject_Length(__pyx_v_s); if (unlikely(__pyx_t_2 == -1)) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __pyx_t_3 = __Pyx_PyObject_AsString(__pyx_v_t); if (unlikely((!__pyx_t_3) && PyErr_Occurred())) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __pyx_t_4 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_4 == -1)) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_lev(__pyx_t_1, __pyx_t_2, __pyx_t_3, __pyx_t_4)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_5);\n", " __pyx_r = __pyx_t_5;\n", " __pyx_t_5 = 0;\n", " goto __pyx_L0;\n", "
03:
\n",
"+04: cdef int lev(char *s, int len_s, char *t, int len_t):\n", "
static int __pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_lev(char *__pyx_v_s, int __pyx_v_len_s, char *__pyx_v_t, int __pyx_v_len_t) {\n", " int __pyx_v_lev_s;\n", " int __pyx_v_lev_t;\n", " int __pyx_v_lev_b;\n", " int __pyx_r;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"lev\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L0:;\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "
+05: if len_s == 0 or len_t == 0:\n", "
__pyx_t_2 = ((__pyx_v_len_s == 0) != 0);\n", " if (!__pyx_t_2) {\n", " } else {\n", " __pyx_t_1 = __pyx_t_2;\n", " goto __pyx_L4_bool_binop_done;\n", " }\n", " __pyx_t_2 = ((__pyx_v_len_t == 0) != 0);\n", " __pyx_t_1 = __pyx_t_2;\n", " __pyx_L4_bool_binop_done:;\n", " if (__pyx_t_1) {\n", "/* … */\n", " }\n", "
+06: return len_s or len_t\n", "
if (!__pyx_v_len_s) {\n", " } else {\n", " __pyx_t_3 = __pyx_v_len_s;\n", " goto __pyx_L6_bool_binop_done;\n", " }\n", " __pyx_t_3 = __pyx_v_len_t;\n", " __pyx_L6_bool_binop_done:;\n", " __pyx_r = __pyx_t_3;\n", " goto __pyx_L0;\n", "
07: cdef:\n", "
+08: int lev_s = lev(s, len_s-1, t, len_t ) + 1\n", "
__pyx_v_lev_s = (__pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_lev(__pyx_v_s, (__pyx_v_len_s - 1), __pyx_v_t, __pyx_v_len_t) + 1);\n", "
+09: int lev_t = lev(s, len_s, t, len_t-1) + 1\n", "
__pyx_v_lev_t = (__pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_lev(__pyx_v_s, __pyx_v_len_s, __pyx_v_t, (__pyx_v_len_t - 1)) + 1);\n", "
+10: int lev_b = lev(s, len_s-1, t, len_t-1) + cost(s, len_s, t, len_t)\n", "
__pyx_v_lev_b = (__pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_lev(__pyx_v_s, (__pyx_v_len_s - 1), __pyx_v_t, (__pyx_v_len_t - 1)) + __pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_cost(__pyx_v_s, __pyx_v_len_s, __pyx_v_t, __pyx_v_len_t));\n", "
+11: if lev_s < lev_t and lev_s < lev_b:\n", "
__pyx_t_2 = ((__pyx_v_lev_s < __pyx_v_lev_t) != 0);\n", " if (__pyx_t_2) {\n", " } else {\n", " __pyx_t_1 = __pyx_t_2;\n", " goto __pyx_L9_bool_binop_done;\n", " }\n", " __pyx_t_2 = ((__pyx_v_lev_s < __pyx_v_lev_b) != 0);\n", " __pyx_t_1 = __pyx_t_2;\n", " __pyx_L9_bool_binop_done:;\n", " if (__pyx_t_1) {\n", "/* … */\n", " }\n", "
+12: return lev_s\n", "
__pyx_r = __pyx_v_lev_s;\n", " goto __pyx_L0;\n", "
+13: elif lev_t < lev_s and lev_t < lev_b:\n", "
__pyx_t_2 = ((__pyx_v_lev_t < __pyx_v_lev_s) != 0);\n", " if (__pyx_t_2) {\n", " } else {\n", " __pyx_t_1 = __pyx_t_2;\n", " goto __pyx_L11_bool_binop_done;\n", " }\n", " __pyx_t_2 = ((__pyx_v_lev_t < __pyx_v_lev_b) != 0);\n", " __pyx_t_1 = __pyx_t_2;\n", " __pyx_L11_bool_binop_done:;\n", " if (__pyx_t_1) {\n", "/* … */\n", " }\n", "
+14: return lev_t\n", "
__pyx_r = __pyx_v_lev_t;\n", " goto __pyx_L0;\n", "
15: else:\n", "
+16: return lev_b\n", "
/*else*/ {\n", " __pyx_r = __pyx_v_lev_b;\n", " goto __pyx_L0;\n", " }\n", "
17:
\n",
"+18: cdef int cost(char *s, int len_s, char *t, int len_t):\n", "
static int __pyx_f_46_cython_magic_09178397f426d86b92ac0473b4709898_cost(char *__pyx_v_s, int __pyx_v_len_s, char *__pyx_v_t, int __pyx_v_len_t) {\n", " int __pyx_r;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"cost\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L0:;\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "
+19: return s[len_s-1] != t[len_t-1]\n", "
__pyx_r = ((__pyx_v_s[(__pyx_v_len_s - 1)]) != (__pyx_v_t[(__pyx_v_len_t - 1)]));\n", " goto __pyx_L0;\n", "