{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Cython\n", "====\n", "\n", "Cython is an \"optimizing static compiler \" that combines Python with C to generate optimized code. Since Cython is a superset of Python, all valid Python programs are also valid Cython programs. However, by providing hints and static typing, we can get much faster programs. Note that while `numba` often provides similar speedups with less work,, an advantage of Cython is that it is easy to distribute optimized Cython modules since they can be built with the standard Python `setup.py` script.\n", "\n", "We have already seen how to use Cython to wrap C and C++ functions from existing libraries. Here we will see how to use Cython to speed up Python functions. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Resources\n", "\n", "- [Cython documentation](http://docs.cython.org/index.html)\n", "- [Cython: A guide for Python programmers](http://www.amazon.com/Cython-Kurt-W-Smith/dp/1491901551)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Utility function for timing functions**" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import time" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def timer(f, *args, **kwargs):\n", " start = time.clock()\n", " ans = f(*args, **kwargs)\n", " return ans, time.clock() - start" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def report(fs, *args, **kwargs):\n", " ans, t = timer(fs[0], *args, **kwargs)\n", " for f in fs[1:]:\n", " ans_, t_ = timer(f, *args, **kwargs)\n", " print('%s: %.1f' % (f.__name__, t/t_))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Incremental improvements\n", "----\n", "\n", "Generally, we start with a pure Python function, run it through Cython with the annotate `-a` flag, and incrementally modify the code until the yellow parts are minimized." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to build Cython modules\n", "----\n", "\n", "From [official docs](http://docs.cython.org/index.html)\n", "\n", "Using Cython consists of these steps:\n", "\n", "- Write a .pyx source file\n", "- Run the Cython compiler to generate a C file\n", "- Run a C compiler to generate a compiled library\n", "- Run the Python interpreter and ask it to import the module\n", "\n", "In the Jupyter notebook, we can use the `%%cython` cell magic to automate these steps." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Matrix multiplication example" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def matrix_multiply(u, v, res):\n", " m, n = u.shape\n", " n, p = v.shape\n", " for i in range(m):\n", " for j in range(p):\n", " res[i,j] = 0\n", " for k in range(n):\n", " res[i,j] += u[i,k] * v[k,j]\n", " return res" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "u = np.random.random((10,20))\n", "v = np.random.random((20,5))" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[5.01831911, 6.40293451, 5.5038414 , 4.99304128, 5.97976906],\n", " [4.18707838, 5.87563576, 5.10038408, 4.61406588, 4.2804353 ],\n", " [5.06256383, 6.24723612, 5.14117837, 5.07813226, 4.96928749],\n", " [4.50139166, 4.65340855, 4.41861766, 3.64584341, 4.26597205],\n", " [5.09491234, 7.04108964, 4.47186301, 4.9964343 , 5.34349475],\n", " [5.22547847, 6.31225445, 5.25028767, 4.70792007, 5.65586095],\n", " [4.30378289, 4.79784667, 5.31914983, 3.94759734, 5.24973078],\n", " [4.23407889, 5.73001969, 4.41423978, 3.83398252, 5.13700985],\n", " [5.18740285, 5.99355594, 5.24546337, 4.27474217, 5.33722259],\n", " [4.34096839, 4.91933762, 4.02151991, 3.87813887, 4.483152 ]])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res = np.zeros((u.shape[0], v.shape[1]))\n", "matrix_multiply(u, v, res)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "807 µs ± 20.5 µs per loop (mean ± std. dev. of 3 runs, 3 loops each)\n" ] } ], "source": [ "res = np.zeros((u.shape[0], v.shape[1]))\n", "%timeit -r3 -n3 matrix_multiply(u, v, res)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using Cython annnotations to identify bottlenecks" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", " \n", "Generated by Cython 0.28
\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:
\n",
"+02: import numpy as np\n", "
__pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
03:
\n",
"+04: def matrix_multiply1(u, v, res):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n", "static PyMethodDef __pyx_mdef_46_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c_1matrix_multiply1 = {\"matrix_multiply1\", (PyCFunction)__pyx_pw_46_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c_1matrix_multiply1, METH_VARARGS|METH_KEYWORDS, 0};\n", "static PyObject *__pyx_pw_46_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n", " PyObject *__pyx_v_u = 0;\n", " PyObject *__pyx_v_v = 0;\n", " PyObject *__pyx_v_res = 0;\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"matrix_multiply1 (wrapper)\", 0);\n", " {\n", " static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_u,&__pyx_n_s_v,&__pyx_n_s_res,0};\n", " PyObject* values[3] = {0,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 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n", " CYTHON_FALLTHROUGH;\n", " case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n", " CYTHON_FALLTHROUGH;\n", " case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n", " CYTHON_FALLTHROUGH;\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] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;\n", " else goto __pyx_L5_argtuple_error;\n", " CYTHON_FALLTHROUGH;\n", " case 1:\n", " if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_v)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 1); __PYX_ERR(0, 4, __pyx_L3_error)\n", " }\n", " CYTHON_FALLTHROUGH;\n", " case 2:\n", " if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_res)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 2); __PYX_ERR(0, 4, __pyx_L3_error)\n", " }\n", " }\n", " if (unlikely(kw_args > 0)) {\n", " if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"matrix_multiply1\") < 0)) __PYX_ERR(0, 4, __pyx_L3_error)\n", " }\n", " } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {\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", " values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n", " }\n", " __pyx_v_u = values[0];\n", " __pyx_v_v = values[1];\n", " __pyx_v_res = values[2];\n", " }\n", " goto __pyx_L4_argument_unpacking_done;\n", " __pyx_L5_argtuple_error:;\n", " __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4, __pyx_L3_error)\n", " __pyx_L3_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c.matrix_multiply1\", __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_cbf427599dd7e0fdc4e0aa8eb128c59c_matrix_multiply1(__pyx_self, __pyx_v_u, __pyx_v_v, __pyx_v_res);\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c_matrix_multiply1(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_u, PyObject *__pyx_v_v, PyObject *__pyx_v_res) {\n", " PyObject *__pyx_v_m = NULL;\n", " PyObject *__pyx_v_n = NULL;\n", " PyObject *__pyx_v_p = NULL;\n", " PyObject *__pyx_v_i = NULL;\n", " PyObject *__pyx_v_j = NULL;\n", " PyObject *__pyx_v_k = NULL;\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"matrix_multiply1\", 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_3);\n", " __Pyx_XDECREF(__pyx_t_4);\n", " __Pyx_XDECREF(__pyx_t_12);\n", " __Pyx_XDECREF(__pyx_t_13);\n", " __Pyx_XDECREF(__pyx_t_14);\n", " __Pyx_XDECREF(__pyx_t_15);\n", " __Pyx_AddTraceback(\"_cython_magic_cbf427599dd7e0fdc4e0aa8eb128c59c.matrix_multiply1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __pyx_r = NULL;\n", " __pyx_L0:;\n", " __Pyx_XDECREF(__pyx_v_m);\n", " __Pyx_XDECREF(__pyx_v_n);\n", " __Pyx_XDECREF(__pyx_v_p);\n", " __Pyx_XDECREF(__pyx_v_i);\n", " __Pyx_XDECREF(__pyx_v_j);\n", " __Pyx_XDECREF(__pyx_v_k);\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple_ = PyTuple_Pack(9, __pyx_n_s_u, __pyx_n_s_v, __pyx_n_s_res, __pyx_n_s_m, __pyx_n_s_n, __pyx_n_s_p, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_k); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 4, __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_cbf427599dd7e0fdc4e0aa8eb128c59c_1matrix_multiply1, NULL, __pyx_n_s_cython_magic_cbf427599dd7e0fdc4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_matrix_multiply1, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
+05: m, n = u.shape\n", "
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_u, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {\n", " PyObject* sequence = __pyx_t_1;\n", " Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);\n", " if (unlikely(size != 2)) {\n", " if (size > 2) __Pyx_RaiseTooManyValuesError(2);\n", " else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);\n", " __PYX_ERR(0, 5, __pyx_L1_error)\n", " }\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " if (likely(PyTuple_CheckExact(sequence))) {\n", " __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); \n", " __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); \n", " } else {\n", " __pyx_t_2 = PyList_GET_ITEM(sequence, 0); \n", " __pyx_t_3 = PyList_GET_ITEM(sequence, 1); \n", " }\n", " __Pyx_INCREF(__pyx_t_2);\n", " __Pyx_INCREF(__pyx_t_3);\n", " #else\n", " __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 5, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 5, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_3);\n", " #endif\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " } else {\n", " Py_ssize_t index = -1;\n", " __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 5, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_4);\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext;\n", " index = 0; __pyx_t_2 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed;\n", " __Pyx_GOTREF(__pyx_t_2);\n", " index = 1; __pyx_t_3 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L3_unpacking_failed;\n", " __Pyx_GOTREF(__pyx_t_3);\n", " if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < 0) __PYX_ERR(0, 5, __pyx_L1_error)\n", " __pyx_t_5 = NULL;\n", " __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n", " goto __pyx_L4_unpacking_done;\n", " __pyx_L3_unpacking_failed:;\n", " __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n", " __pyx_t_5 = NULL;\n", " if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);\n", " __PYX_ERR(0, 5, __pyx_L1_error)\n", " __pyx_L4_unpacking_done:;\n", " }\n", " __pyx_v_m = __pyx_t_2;\n", " __pyx_t_2 = 0;\n", " __pyx_v_n = __pyx_t_3;\n", " __pyx_t_3 = 0;\n", "
+06: n, p = v.shape\n", "
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_v, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {\n", " PyObject* sequence = __pyx_t_1;\n", " Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);\n", " if (unlikely(size != 2)) {\n", " if (size > 2) __Pyx_RaiseTooManyValuesError(2);\n", " else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);\n", " __PYX_ERR(0, 6, __pyx_L1_error)\n", " }\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " if (likely(PyTuple_CheckExact(sequence))) {\n", " __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); \n", " __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); \n", " } else {\n", " __pyx_t_3 = PyList_GET_ITEM(sequence, 0); \n", " __pyx_t_2 = PyList_GET_ITEM(sequence, 1); \n", " }\n", " __Pyx_INCREF(__pyx_t_3);\n", " __Pyx_INCREF(__pyx_t_2);\n", " #else\n", " __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_3);\n", " __pyx_t_2 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " #endif\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " } else {\n", " Py_ssize_t index = -1;\n", " __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_4);\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext;\n", " index = 0; __pyx_t_3 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L5_unpacking_failed;\n", " __Pyx_GOTREF(__pyx_t_3);\n", " index = 1; __pyx_t_2 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_2)) goto __pyx_L5_unpacking_failed;\n", " __Pyx_GOTREF(__pyx_t_2);\n", " if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < 0) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __pyx_t_5 = NULL;\n", " __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n", " goto __pyx_L6_unpacking_done;\n", " __pyx_L5_unpacking_failed:;\n", " __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n", " __pyx_t_5 = NULL;\n", " if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);\n", " __PYX_ERR(0, 6, __pyx_L1_error)\n", " __pyx_L6_unpacking_done:;\n", " }\n", " __Pyx_DECREF_SET(__pyx_v_n, __pyx_t_3);\n", " __pyx_t_3 = 0;\n", " __pyx_v_p = __pyx_t_2;\n", " __pyx_t_2 = 0;\n", "
+07: for i in range(m):\n", "
__pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_v_m); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\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_6 = 0;\n", " __pyx_t_7 = NULL;\n", " } else {\n", " __pyx_t_6 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __pyx_t_7 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " }\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " for (;;) {\n", " if (likely(!__pyx_t_7)) {\n", " if (likely(PyList_CheckExact(__pyx_t_2))) {\n", " if (__pyx_t_6 >= 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_6); __Pyx_INCREF(__pyx_t_1); __pyx_t_6++; if (unlikely(0 < 0)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " } else {\n", " if (__pyx_t_6 >= 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_6); __Pyx_INCREF(__pyx_t_1); __pyx_t_6++; if (unlikely(0 < 0)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " }\n", " } else {\n", " __pyx_t_1 = __pyx_t_7(__pyx_t_2);\n", " if (unlikely(!__pyx_t_1)) {\n", " PyObject* exc_type = PyErr_Occurred();\n", " if (exc_type) {\n", " if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n", " else __PYX_ERR(0, 7, __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", "
+08: for j in range(p):\n", "
__pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_v_p); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {\n", " __pyx_t_3 = __pyx_t_1; __Pyx_INCREF(__pyx_t_3); __pyx_t_8 = 0;\n", " __pyx_t_9 = NULL;\n", " } else {\n", " __pyx_t_8 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_3);\n", " __pyx_t_9 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " }\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " for (;;) {\n", " if (likely(!__pyx_t_9)) {\n", " if (likely(PyList_CheckExact(__pyx_t_3))) {\n", " if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_3)) break;\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " } else {\n", " if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_3)) break;\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " }\n", " } else {\n", " __pyx_t_1 = __pyx_t_9(__pyx_t_3);\n", " if (unlikely(!__pyx_t_1)) {\n", " PyObject* exc_type = PyErr_Occurred();\n", " if (exc_type) {\n", " if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n", " else __PYX_ERR(0, 8, __pyx_L1_error)\n", " }\n", " break;\n", " }\n", " __Pyx_GOTREF(__pyx_t_1);\n", " }\n", " __Pyx_XDECREF_SET(__pyx_v_j, __pyx_t_1);\n", " __pyx_t_1 = 0;\n", "/* … */\n", " }\n", " __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n", "
+09: res[i,j] = 0\n", "
__pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __Pyx_INCREF(__pyx_v_i);\n", " __Pyx_GIVEREF(__pyx_v_i);\n", " PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_i);\n", " __Pyx_INCREF(__pyx_v_j);\n", " __Pyx_GIVEREF(__pyx_v_j);\n", " PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_j);\n", " if (unlikely(PyObject_SetItem(__pyx_v_res, __pyx_t_1, __pyx_int_0) < 0)) __PYX_ERR(0, 9, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
+10: for k in range(n):\n", "
__pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_v_n); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {\n", " __pyx_t_4 = __pyx_t_1; __Pyx_INCREF(__pyx_t_4); __pyx_t_10 = 0;\n", " __pyx_t_11 = NULL;\n", " } else {\n", " __pyx_t_10 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_4);\n", " __pyx_t_11 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " }\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " for (;;) {\n", " if (likely(!__pyx_t_11)) {\n", " if (likely(PyList_CheckExact(__pyx_t_4))) {\n", " if (__pyx_t_10 >= PyList_GET_SIZE(__pyx_t_4)) break;\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_10); __Pyx_INCREF(__pyx_t_1); __pyx_t_10++; if (unlikely(0 < 0)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " } else {\n", " if (__pyx_t_10 >= PyTuple_GET_SIZE(__pyx_t_4)) break;\n", " #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n", " __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_10); __Pyx_INCREF(__pyx_t_1); __pyx_t_10++; if (unlikely(0 < 0)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " #else\n", " __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " #endif\n", " }\n", " } else {\n", " __pyx_t_1 = __pyx_t_11(__pyx_t_4);\n", " if (unlikely(!__pyx_t_1)) {\n", " PyObject* exc_type = PyErr_Occurred();\n", " if (exc_type) {\n", " if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n", " else __PYX_ERR(0, 10, __pyx_L1_error)\n", " }\n", " break;\n", " }\n", " __Pyx_GOTREF(__pyx_t_1);\n", " }\n", " __Pyx_XDECREF_SET(__pyx_v_k, __pyx_t_1);\n", " __pyx_t_1 = 0;\n", "/* … */\n", " }\n", " __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n", "
+11: res[i,j] += u[i,k] * v[k,j]\n", "
__pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __Pyx_INCREF(__pyx_v_i);\n", " __Pyx_GIVEREF(__pyx_v_i);\n", " PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_i);\n", " __Pyx_INCREF(__pyx_v_j);\n", " __Pyx_GIVEREF(__pyx_v_j);\n", " PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_j);\n", " __pyx_t_12 = __Pyx_PyObject_GetItem(__pyx_v_res, __pyx_t_1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_12);\n", " __pyx_t_13 = PyTuple_New(2); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_13);\n", " __Pyx_INCREF(__pyx_v_i);\n", " __Pyx_GIVEREF(__pyx_v_i);\n", " PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_v_i);\n", " __Pyx_INCREF(__pyx_v_k);\n", " __Pyx_GIVEREF(__pyx_v_k);\n", " PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_v_k);\n", " __pyx_t_14 = __Pyx_PyObject_GetItem(__pyx_v_u, __pyx_t_13); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_14);\n", " __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;\n", " __pyx_t_13 = PyTuple_New(2); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_13);\n", " __Pyx_INCREF(__pyx_v_k);\n", " __Pyx_GIVEREF(__pyx_v_k);\n", " PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_v_k);\n", " __Pyx_INCREF(__pyx_v_j);\n", " __Pyx_GIVEREF(__pyx_v_j);\n", " PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_v_j);\n", " __pyx_t_15 = __Pyx_PyObject_GetItem(__pyx_v_v, __pyx_t_13); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_15);\n", " __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;\n", " __pyx_t_13 = PyNumber_Multiply(__pyx_t_14, __pyx_t_15); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_13);\n", " __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;\n", " __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;\n", " __pyx_t_15 = PyNumber_InPlaceAdd(__pyx_t_12, __pyx_t_13); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_15);\n", " __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;\n", " __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;\n", " if (unlikely(PyObject_SetItem(__pyx_v_res, __pyx_t_1, __pyx_t_15) < 0)) __PYX_ERR(0, 11, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
+12: return res\n", "
__Pyx_XDECREF(__pyx_r);\n", " __Pyx_INCREF(__pyx_v_res);\n", " __pyx_r = __pyx_v_res;\n", " goto __pyx_L0;\n", "
Generated by Cython 0.28
\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:
\n",
"+02: import cython\n", "
__pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
03:
\n",
"04: @cython.boundscheck(False)\n", "
05: @cython.wraparound(False)\n", "
+06: def matrix_multiply1(double[:,:] u, double[:, :] v, double[:, :] res):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_3b93eefe1a195a60a80664de1e8480ae_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n", "static PyMethodDef __pyx_mdef_46_cython_magic_3b93eefe1a195a60a80664de1e8480ae_1matrix_multiply1 = {\"matrix_multiply1\", (PyCFunction)__pyx_pw_46_cython_magic_3b93eefe1a195a60a80664de1e8480ae_1matrix_multiply1, METH_VARARGS|METH_KEYWORDS, 0};\n", "static PyObject *__pyx_pw_46_cython_magic_3b93eefe1a195a60a80664de1e8480ae_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n", " __Pyx_memviewslice __pyx_v_u = { 0, 0, { 0 }, { 0 }, { 0 } };\n", " __Pyx_memviewslice __pyx_v_v = { 0, 0, { 0 }, { 0 }, { 0 } };\n", " __Pyx_memviewslice __pyx_v_res = { 0, 0, { 0 }, { 0 }, { 0 } };\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"matrix_multiply1 (wrapper)\", 0);\n", " {\n", " static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_u,&__pyx_n_s_v,&__pyx_n_s_res,0};\n", " PyObject* values[3] = {0,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 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n", " CYTHON_FALLTHROUGH;\n", " case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n", " CYTHON_FALLTHROUGH;\n", " case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n", " CYTHON_FALLTHROUGH;\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] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;\n", " else goto __pyx_L5_argtuple_error;\n", " CYTHON_FALLTHROUGH;\n", " case 1:\n", " if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_v)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 1); __PYX_ERR(0, 6, __pyx_L3_error)\n", " }\n", " CYTHON_FALLTHROUGH;\n", " case 2:\n", " if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_res)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 2); __PYX_ERR(0, 6, __pyx_L3_error)\n", " }\n", " }\n", " if (unlikely(kw_args > 0)) {\n", " if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"matrix_multiply1\") < 0)) __PYX_ERR(0, 6, __pyx_L3_error)\n", " }\n", " } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {\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", " values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n", " }\n", " __pyx_v_u = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_u.memview)) __PYX_ERR(0, 6, __pyx_L3_error)\n", " __pyx_v_v = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_v.memview)) __PYX_ERR(0, 6, __pyx_L3_error)\n", " __pyx_v_res = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[2], PyBUF_WRITABLE); if (unlikely(!__pyx_v_res.memview)) __PYX_ERR(0, 6, __pyx_L3_error)\n", " }\n", " goto __pyx_L4_argument_unpacking_done;\n", " __pyx_L5_argtuple_error:;\n", " __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 6, __pyx_L3_error)\n", " __pyx_L3_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_3b93eefe1a195a60a80664de1e8480ae.matrix_multiply1\", __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_3b93eefe1a195a60a80664de1e8480ae_matrix_multiply1(__pyx_self, __pyx_v_u, __pyx_v_v, __pyx_v_res);\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_3b93eefe1a195a60a80664de1e8480ae_matrix_multiply1(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_u, __Pyx_memviewslice __pyx_v_v, __Pyx_memviewslice __pyx_v_res) {\n", " int __pyx_v_i;\n", " int __pyx_v_j;\n", " int __pyx_v_k;\n", " int __pyx_v_m;\n", " int __pyx_v_n;\n", " int __pyx_v_p;\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"matrix_multiply1\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n", " __PYX_XDEC_MEMVIEW(&__pyx_v_u, 1);\n", " __PYX_XDEC_MEMVIEW(&__pyx_v_v, 1);\n", " __PYX_XDEC_MEMVIEW(&__pyx_v_res, 1);\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple__22 = PyTuple_Pack(9, __pyx_n_s_u, __pyx_n_s_v, __pyx_n_s_res, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_k, __pyx_n_s_m, __pyx_n_s_n, __pyx_n_s_p); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_tuple__22);\n", " __Pyx_GIVEREF(__pyx_tuple__22);\n", "/* … */\n", " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_3b93eefe1a195a60a80664de1e8480ae_1matrix_multiply1, NULL, __pyx_n_s_cython_magic_3b93eefe1a195a60a8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_matrix_multiply1, __pyx_t_1) < 0) __PYX_ERR(0, 6, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(3, 0, 9, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_cliburn_ipython_cython__c, __pyx_n_s_matrix_multiply1, 6, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) __PYX_ERR(0, 6, __pyx_L1_error)\n", "
07: cdef int i, j, k\n", "
08: cdef int m, n, p\n", "
09:
\n",
"+10: m = u.shape[0]\n", "
__pyx_v_m = (__pyx_v_u.shape[0]);\n", "
+11: n = u.shape[1]\n", "
__pyx_v_n = (__pyx_v_u.shape[1]);\n", "
+12: p = v.shape[1]\n", "
__pyx_v_p = (__pyx_v_v.shape[1]);\n", "
13:
\n",
"+14: with cython.nogil:\n", "
{\n", " #ifdef WITH_THREAD\n", " PyThreadState *_save;\n", " Py_UNBLOCK_THREADS\n", " __Pyx_FastGIL_Remember();\n", " #endif\n", " /*try:*/ {\n", "/* … */\n", " /*finally:*/ {\n", " /*normal exit:*/{\n", " #ifdef WITH_THREAD\n", " __Pyx_FastGIL_Forget();\n", " Py_BLOCK_THREADS\n", " #endif\n", " goto __pyx_L5;\n", " }\n", " __pyx_L5:;\n", " }\n", " }\n", "
+15: for i in range(m):\n", "
__pyx_t_1 = __pyx_v_m;\n", " __pyx_t_2 = __pyx_t_1;\n", " for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {\n", " __pyx_v_i = __pyx_t_3;\n", "
+16: for j in range(p):\n", "
__pyx_t_4 = __pyx_v_p;\n", " __pyx_t_5 = __pyx_t_4;\n", " for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {\n", " __pyx_v_j = __pyx_t_6;\n", "
+17: res[i,j] = 0\n", "
__pyx_t_7 = __pyx_v_i;\n", " __pyx_t_8 = __pyx_v_j;\n", " *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_res.data + __pyx_t_7 * __pyx_v_res.strides[0]) ) + __pyx_t_8 * __pyx_v_res.strides[1]) )) = 0.0;\n", "
+18: for k in range(n):\n", "
__pyx_t_9 = __pyx_v_n;\n", " __pyx_t_10 = __pyx_t_9;\n", " for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n", " __pyx_v_k = __pyx_t_11;\n", "
+19: res[i,j] += u[i,k] * v[k,j]\n", "
__pyx_t_12 = __pyx_v_i;\n", " __pyx_t_13 = __pyx_v_k;\n", " __pyx_t_14 = __pyx_v_k;\n", " __pyx_t_15 = __pyx_v_j;\n", " __pyx_t_16 = __pyx_v_i;\n", " __pyx_t_17 = __pyx_v_j;\n", " *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_res.data + __pyx_t_16 * __pyx_v_res.strides[0]) ) + __pyx_t_17 * __pyx_v_res.strides[1]) )) += ((*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_u.data + __pyx_t_12 * __pyx_v_u.strides[0]) ) + __pyx_t_13 * __pyx_v_u.strides[1]) ))) * (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_v.data + __pyx_t_14 * __pyx_v_v.strides[0]) ) + __pyx_t_15 * __pyx_v_v.strides[1]) ))));\n", " }\n", " }\n", " }\n", " }\n", "
Generated by Cython 0.28
\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:
\n",
"+02: cimport cython\n", "
__pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", "
03:
\n",
"04: cdef extern from "complex.h":\n", "
05: double cabs(double complex)\n", "
06:
\n",
"07: # color function for point at (x, y)\n", "
+08: cdef unsigned char mandel_cython(double x, double y, int max_iters):\n", "
static unsigned char __pyx_f_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_mandel_cython(double __pyx_v_x, double __pyx_v_y, int __pyx_v_max_iters) {\n", " __pyx_t_double_complex __pyx_v_c;\n", " __pyx_t_double_complex __pyx_v_z;\n", " int __pyx_v_i;\n", " unsigned char __pyx_r;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"mandel_cython\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_L0:;\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "
09: cdef double complex c, z\n", "
10:
\n",
"+11: c = x + y*1j\n", "
__pyx_v_c = __Pyx_c_sum_double(__pyx_t_double_complex_from_parts(__pyx_v_x, 0), __Pyx_c_prod_double(__pyx_t_double_complex_from_parts(__pyx_v_y, 0), __pyx_t_double_complex_from_parts(0, 1.0)));\n", "
+12: z = 0.0j\n", "
__pyx_v_z = __pyx_t_double_complex_from_parts(0, 0.0);\n", "
+13: for i in range(max_iters):\n", "
__pyx_t_1 = __pyx_v_max_iters;\n", " __pyx_t_2 = __pyx_t_1;\n", " for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {\n", " __pyx_v_i = __pyx_t_3;\n", "
+14: z = z*z + c\n", "
__pyx_v_z = __Pyx_c_sum_double(__Pyx_c_prod_double(__pyx_v_z, __pyx_v_z), __pyx_v_c);\n", "
+15: if cabs(z) >= 2:\n", "
__pyx_t_4 = ((cabs(__pyx_v_z) >= 2.0) != 0);\n", " if (__pyx_t_4) {\n", "/* … */\n", " }\n", " }\n", "
+16: return i\n", "
__pyx_r = __pyx_v_i;\n", " goto __pyx_L0;\n", "
+17: return max_iters\n", "
__pyx_r = __pyx_v_max_iters;\n", " goto __pyx_L0;\n", "
18:
\n",
"19: @cython.cdivision(True)\n", "
+20: def create_fractal_cython(double xmin, double xmax, double ymin, double ymax, unsigned char[:, :] image, int iters):\n", "
/* Python wrapper */\n", "static PyObject *__pyx_pw_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_1create_fractal_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n", "static PyMethodDef __pyx_mdef_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_1create_fractal_cython = {\"create_fractal_cython\", (PyCFunction)__pyx_pw_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_1create_fractal_cython, METH_VARARGS|METH_KEYWORDS, 0};\n", "static PyObject *__pyx_pw_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_1create_fractal_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n", " double __pyx_v_xmin;\n", " double __pyx_v_xmax;\n", " double __pyx_v_ymin;\n", " double __pyx_v_ymax;\n", " __Pyx_memviewslice __pyx_v_image = { 0, 0, { 0 }, { 0 }, { 0 } };\n", " int __pyx_v_iters;\n", " PyObject *__pyx_r = 0;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"create_fractal_cython (wrapper)\", 0);\n", " {\n", " static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_xmin,&__pyx_n_s_xmax,&__pyx_n_s_ymin,&__pyx_n_s_ymax,&__pyx_n_s_image,&__pyx_n_s_iters,0};\n", " PyObject* values[6] = {0,0,0,0,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 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);\n", " CYTHON_FALLTHROUGH;\n", " case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);\n", " CYTHON_FALLTHROUGH;\n", " case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n", " CYTHON_FALLTHROUGH;\n", " case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n", " CYTHON_FALLTHROUGH;\n", " case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n", " CYTHON_FALLTHROUGH;\n", " case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n", " CYTHON_FALLTHROUGH;\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] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmin)) != 0)) kw_args--;\n", " else goto __pyx_L5_argtuple_error;\n", " CYTHON_FALLTHROUGH;\n", " case 1:\n", " if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xmax)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 1); __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " CYTHON_FALLTHROUGH;\n", " case 2:\n", " if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymin)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 2); __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " CYTHON_FALLTHROUGH;\n", " case 3:\n", " if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ymax)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 3); __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " CYTHON_FALLTHROUGH;\n", " case 4:\n", " if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_image)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 4); __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " CYTHON_FALLTHROUGH;\n", " case 5:\n", " if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_iters)) != 0)) kw_args--;\n", " else {\n", " __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 5); __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " }\n", " if (unlikely(kw_args > 0)) {\n", " if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"create_fractal_cython\") < 0)) __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " } else if (PyTuple_GET_SIZE(__pyx_args) != 6) {\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", " values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n", " values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n", " values[4] = PyTuple_GET_ITEM(__pyx_args, 4);\n", " values[5] = PyTuple_GET_ITEM(__pyx_args, 5);\n", " }\n", " __pyx_v_xmin = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_xmin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n", " __pyx_v_xmax = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_xmax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n", " __pyx_v_ymin = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_ymin == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n", " __pyx_v_ymax = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_ymax == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n", " __pyx_v_image = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_char(values[4], PyBUF_WRITABLE); if (unlikely(!__pyx_v_image.memview)) __PYX_ERR(0, 20, __pyx_L3_error)\n", " __pyx_v_iters = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_iters == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error)\n", " }\n", " goto __pyx_L4_argument_unpacking_done;\n", " __pyx_L5_argtuple_error:;\n", " __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 20, __pyx_L3_error)\n", " __pyx_L3_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_398dd2d9765ef6fa57363ca88b604510.create_fractal_cython\", __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_398dd2d9765ef6fa57363ca88b604510_create_fractal_cython(__pyx_self, __pyx_v_xmin, __pyx_v_xmax, __pyx_v_ymin, __pyx_v_ymax, __pyx_v_image, __pyx_v_iters);\n", "\n", " /* function exit code */\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "\n", "static PyObject *__pyx_pf_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_create_fractal_cython(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, __Pyx_memviewslice __pyx_v_image, int __pyx_v_iters) {\n", " int __pyx_v_x;\n", " int __pyx_v_y;\n", " int __pyx_v_height;\n", " int __pyx_v_width;\n", " double __pyx_v_pixel_size_x;\n", " double __pyx_v_pixel_size_y;\n", " double __pyx_v_real;\n", " double __pyx_v_imag;\n", " unsigned char __pyx_v_color;\n", " PyObject *__pyx_r = NULL;\n", " __Pyx_RefNannyDeclarations\n", " __Pyx_RefNannySetupContext(\"create_fractal_cython\", 0);\n", "/* … */\n", " /* function exit code */\n", " __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n", " goto __pyx_L0;\n", " __pyx_L1_error:;\n", " __Pyx_AddTraceback(\"_cython_magic_398dd2d9765ef6fa57363ca88b604510.create_fractal_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", " __pyx_r = NULL;\n", " __pyx_L0:;\n", " __PYX_XDEC_MEMVIEW(&__pyx_v_image, 1);\n", " __Pyx_XGIVEREF(__pyx_r);\n", " __Pyx_RefNannyFinishContext();\n", " return __pyx_r;\n", "}\n", "/* … */\n", " __pyx_tuple__22 = PyTuple_Pack(15, __pyx_n_s_xmin, __pyx_n_s_xmax, __pyx_n_s_ymin, __pyx_n_s_ymax, __pyx_n_s_image, __pyx_n_s_iters, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_height, __pyx_n_s_width, __pyx_n_s_pixel_size_x, __pyx_n_s_pixel_size_y, __pyx_n_s_real, __pyx_n_s_imag, __pyx_n_s_color); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(0, 20, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_tuple__22);\n", " __Pyx_GIVEREF(__pyx_tuple__22);\n", "/* … */\n", " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_1create_fractal_cython, NULL, __pyx_n_s_cython_magic_398dd2d9765ef6fa57); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 20, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " if (PyDict_SetItem(__pyx_d, __pyx_n_s_create_fractal_cython, __pyx_t_1) < 0) __PYX_ERR(0, 20, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(6, 0, 15, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_cliburn_ipython_cython__c, __pyx_n_s_create_fractal_cython, 20, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) __PYX_ERR(0, 20, __pyx_L1_error)\n", "
21:
\n",
"22: cdef int x, y\n", "
23: cdef int height, width\n", "
24: cdef double pixel_size_x, pixel_size_y\n", "
25: cdef double real, imag\n", "
26: cdef unsigned char color\n", "
27:
\n",
"+28: height = image.shape[0]\n", "
__pyx_v_height = (__pyx_v_image.shape[0]);\n", "
+29: width = image.shape[1]\n", "
__pyx_v_width = (__pyx_v_image.shape[1]);\n", "
30:
\n",
"+31: pixel_size_x = (xmax - xmin)/width\n", "
__pyx_v_pixel_size_x = ((__pyx_v_xmax - __pyx_v_xmin) / ((double)__pyx_v_width));\n", "
+32: pixel_size_y = (ymax - ymin)/height\n", "
__pyx_v_pixel_size_y = ((__pyx_v_ymax - __pyx_v_ymin) / ((double)__pyx_v_height));\n", "
33:
\n",
"+34: for x in range(width):\n", "
__pyx_t_1 = __pyx_v_width;\n", " __pyx_t_2 = __pyx_t_1;\n", " for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {\n", " __pyx_v_x = __pyx_t_3;\n", "
+35: real = xmin + x*pixel_size_x\n", "
__pyx_v_real = (__pyx_v_xmin + (__pyx_v_x * __pyx_v_pixel_size_x));\n", "
+36: for y in range(height):\n", "
__pyx_t_4 = __pyx_v_height;\n", " __pyx_t_5 = __pyx_t_4;\n", " for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {\n", " __pyx_v_y = __pyx_t_6;\n", "
+37: imag = ymin + y*pixel_size_y\n", "
__pyx_v_imag = (__pyx_v_ymin + (__pyx_v_y * __pyx_v_pixel_size_y));\n", "
+38: color = mandel_cython(real, imag, iters)\n", "
__pyx_v_color = __pyx_f_46_cython_magic_398dd2d9765ef6fa57363ca88b604510_mandel_cython(__pyx_v_real, __pyx_v_imag, __pyx_v_iters);\n", "
+39: image[y, x] = color\n", "
__pyx_t_7 = __pyx_v_y;\n", " __pyx_t_8 = __pyx_v_x;\n", " __pyx_t_9 = -1;\n", " if (__pyx_t_7 < 0) {\n", " __pyx_t_7 += __pyx_v_image.shape[0];\n", " if (unlikely(__pyx_t_7 < 0)) __pyx_t_9 = 0;\n", " } else if (unlikely(__pyx_t_7 >= __pyx_v_image.shape[0])) __pyx_t_9 = 0;\n", " if (__pyx_t_8 < 0) {\n", " __pyx_t_8 += __pyx_v_image.shape[1];\n", " if (unlikely(__pyx_t_8 < 0)) __pyx_t_9 = 1;\n", " } else if (unlikely(__pyx_t_8 >= __pyx_v_image.shape[1])) __pyx_t_9 = 1;\n", " if (unlikely(__pyx_t_9 != -1)) {\n", " __Pyx_RaiseBufferIndexError(__pyx_t_9);\n", " __PYX_ERR(0, 39, __pyx_L1_error)\n", " }\n", " *((unsigned char *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_image.data + __pyx_t_7 * __pyx_v_image.strides[0]) ) + __pyx_t_8 * __pyx_v_image.strides[1]) )) = __pyx_v_color;\n", " }\n", " }\n", "