{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true, "nbpresent": { "id": "d84a79e5-1ef9-4dea-9e2e-690a912553b4" }, "slideshow": { "slide_type": "slide" } }, "source": [ "# CFFI, Ctypes, Cython, Cppyy: \n", "# Wrapping C code from Python\n", "\n", "\n", "## Matti Picus\n", "\n", "### Follow along at https://github.com/mattip/c_from_python" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "0cfda04e-01da-4674-a90f-b132bbebf844" }, "slideshow": { "slide_type": "slide" } }, "source": [ "## Who am I?\n", "\n", "- Core PyPy developer (ask me later)\n", "- Working on NumPy 2018 - 2020\n", "- Experienced (old?) programmer, been doing image processing on and off since 1980\n", "- Open Source evangelist" ] }, { "cell_type": "markdown", "metadata": { "nbpresent": { "id": "7a62ed08-bb60-4ebb-b5f2-fbb7af3a0b6e" } }, "source": [ "## Thanks for tuning in.\n", "\n", "Here is what we will do\n", "\n", "
\n", "Generated by Cython 0.28.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: \n",
"+02: cdef extern from 'create_fractal.h':\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: ctypedef struct Img:\n", "
04: int width\n", "
05: int height\n", "
06: unsigned char * data\n", "
07: \n",
"08: int create_fractal(Img img, int iters);\n", "
09: int mandel(float real, float imag, int max_iters,\n", "
10: unsigned char * val);\n", "
11: \n",
"+12: def cython_create_fractal(pyimg, iters):\n", "
/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_1cython_create_fractal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_1cython_create_fractal = {\"cython_create_fractal\", (PyCFunction)__pyx_pw_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_1cython_create_fractal, METH_VARARGS|METH_KEYWORDS, 0};\n",
"static PyObject *__pyx_pw_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_1cython_create_fractal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" PyObject *__pyx_v_pyimg = 0;\n",
" PyObject *__pyx_v_iters = 0;\n",
" PyObject *__pyx_r = 0;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_create_fractal (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyimg,&__pyx_n_s_iters,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",
" 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_pyimg)) != 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_iters)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_create_fractal\", 1, 2, 2, 1); __PYX_ERR(0, 12, __pyx_L3_error)\n",
" }\n",
" }\n",
" if (unlikely(kw_args > 0)) {\n",
" if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"cython_create_fractal\") < 0)) __PYX_ERR(0, 12, __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_pyimg = values[0];\n",
" __pyx_v_iters = values[1];\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_create_fractal\", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 12, __pyx_L3_error)\n",
" __pyx_L3_error:;\n",
" __Pyx_AddTraceback(\"_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c.cython_create_fractal\", __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_95bdf0f67f7d980128cef3f0d2496e5c_cython_create_fractal(__pyx_self, __pyx_v_pyimg, __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_95bdf0f67f7d980128cef3f0d2496e5c_cython_create_fractal(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_pyimg, PyObject *__pyx_v_iters) {\n",
" Img __pyx_v_cimg;\n",
" int __pyx_v_citers;\n",
" __Pyx_memviewslice __pyx_v_tmp = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" PyObject *__pyx_r = NULL;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_create_fractal\", 0);\n",
"/* … */\n",
" /* function exit code */\n",
" __pyx_L1_error:;\n",
" __Pyx_XDECREF(__pyx_t_1);\n",
" __PYX_XDEC_MEMVIEW(&__pyx_t_2, 1);\n",
" __Pyx_AddTraceback(\"_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c.cython_create_fractal\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" __pyx_r = NULL;\n",
" __pyx_L0:;\n",
" __PYX_XDEC_MEMVIEW(&__pyx_v_tmp, 1);\n",
" __Pyx_XGIVEREF(__pyx_r);\n",
" __Pyx_RefNannyFinishContext();\n",
" return __pyx_r;\n",
"}\n",
"/* … */\n",
" __pyx_tuple__22 = PyTuple_Pack(5, __pyx_n_s_pyimg, __pyx_n_s_iters, __pyx_n_s_cimg, __pyx_n_s_citers, __pyx_n_s_tmp); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(0, 12, __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_95bdf0f67f7d980128cef3f0d2496e5c_1cython_create_fractal, NULL, __pyx_n_s_cython_magic_95bdf0f67f7d980128); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" __Pyx_GOTREF(__pyx_t_1);\n",
" if (PyDict_SetItem(__pyx_d, __pyx_n_s_cython_create_fractal, __pyx_t_1) < 0) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(2, 0, 5, 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_C_Users_Matti_ipython_cython__cy, __pyx_n_s_cython_create_fractal, 12, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
"13: cdef Img cimg\n", "
14: cdef int citers\n", "
+15: cdef unsigned char[::1] tmp = pyimg.data\n", "
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyimg, __pyx_n_s_data); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_t_2 = __Pyx_PyObject_to_MemoryviewSlice_dc_unsigned_char(__pyx_t_1, PyBUF_WRITABLE); if (unlikely(!__pyx_t_2.memview)) __PYX_ERR(0, 15, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_v_tmp = __pyx_t_2;\n", " __pyx_t_2.memview = NULL;\n", " __pyx_t_2.data = NULL;\n", "
16: \n",
"+17: citers = iters\n", "
__pyx_t_3 = __Pyx_PyInt_As_int(__pyx_v_iters); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L1_error)\n", " __pyx_v_citers = __pyx_t_3;\n", "
+18: cimg.width = pyimg.width\n", "
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyimg, __pyx_n_s_width); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 18, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_v_cimg.width = __pyx_t_3;\n", "
+19: cimg.height = pyimg.height\n", "
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_pyimg, __pyx_n_s_height); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 19, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_v_cimg.height = __pyx_t_3;\n", "
+20: cimg.data = &tmp[0]\n", "
__pyx_t_4 = 0;\n",
" __pyx_t_3 = -1;\n",
" if (__pyx_t_4 < 0) {\n",
" __pyx_t_4 += __pyx_v_tmp.shape[0];\n",
" if (unlikely(__pyx_t_4 < 0)) __pyx_t_3 = 0;\n",
" } else if (unlikely(__pyx_t_4 >= __pyx_v_tmp.shape[0])) __pyx_t_3 = 0;\n",
" if (unlikely(__pyx_t_3 != -1)) {\n",
" __Pyx_RaiseBufferIndexError(__pyx_t_3);\n",
" __PYX_ERR(0, 20, __pyx_L1_error)\n",
" }\n",
" __pyx_v_cimg.data = (&(*((unsigned char *) ( /* dim=0 */ ((char *) (((unsigned char *) __pyx_v_tmp.data) + __pyx_t_4)) ))));\n",
"+21: return create_fractal(cimg, citers)\n", "
__Pyx_XDECREF(__pyx_r);\n", " __pyx_t_1 = __Pyx_PyInt_From_int(create_fractal(__pyx_v_cimg, __pyx_v_citers)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_1);\n", " __pyx_r = __pyx_t_1;\n", " __pyx_t_1 = 0;\n", " goto __pyx_L0;\n", "
22: \n",
" 23: \n",
"+24: cpdef int cython_mandel(float real, float imag, int max_iters,\n", "
static PyObject *__pyx_pw_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_3cython_mandel(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static int __pyx_f_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_cython_mandel(float __pyx_v_real, float __pyx_v_imag, int __pyx_v_max_iters, __Pyx_memviewslice __pyx_v_val, CYTHON_UNUSED int __pyx_skip_dispatch) {\n",
" int __pyx_r;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_mandel\", 0);\n",
"/* … */\n",
" /* function exit code */\n",
" __pyx_L1_error:;\n",
" __Pyx_WriteUnraisable(\"_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c.cython_mandel\", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);\n",
" __pyx_r = 0;\n",
" __pyx_L0:;\n",
" __Pyx_RefNannyFinishContext();\n",
" return __pyx_r;\n",
"}\n",
"\n",
"/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_3cython_mandel(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyObject *__pyx_pw_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_3cython_mandel(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" float __pyx_v_real;\n",
" float __pyx_v_imag;\n",
" int __pyx_v_max_iters;\n",
" __Pyx_memviewslice __pyx_v_val = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" PyObject *__pyx_r = 0;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_mandel (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_real,&__pyx_n_s_imag,&__pyx_n_s_max_iters,&__pyx_n_s_val,0};\n",
" PyObject* values[4] = {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 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_real)) != 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_imag)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel\", 1, 4, 4, 1); __PYX_ERR(0, 24, __pyx_L3_error)\n",
" }\n",
" CYTHON_FALLTHROUGH;\n",
" case 2:\n",
" if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_max_iters)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel\", 1, 4, 4, 2); __PYX_ERR(0, 24, __pyx_L3_error)\n",
" }\n",
" CYTHON_FALLTHROUGH;\n",
" case 3:\n",
" if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_val)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel\", 1, 4, 4, 3); __PYX_ERR(0, 24, __pyx_L3_error)\n",
" }\n",
" }\n",
" if (unlikely(kw_args > 0)) {\n",
" if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"cython_mandel\") < 0)) __PYX_ERR(0, 24, __pyx_L3_error)\n",
" }\n",
" } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {\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",
" }\n",
" __pyx_v_real = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_real == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 24, __pyx_L3_error)\n",
" __pyx_v_imag = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_imag == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 24, __pyx_L3_error)\n",
" __pyx_v_max_iters = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_max_iters == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 24, __pyx_L3_error)\n",
" __pyx_v_val = __Pyx_PyObject_to_MemoryviewSlice_dc_unsigned_char(values[3], PyBUF_WRITABLE); if (unlikely(!__pyx_v_val.memview)) __PYX_ERR(0, 25, __pyx_L3_error)\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel\", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 24, __pyx_L3_error)\n",
" __pyx_L3_error:;\n",
" __Pyx_AddTraceback(\"_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c.cython_mandel\", __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_95bdf0f67f7d980128cef3f0d2496e5c_2cython_mandel(__pyx_self, __pyx_v_real, __pyx_v_imag, __pyx_v_max_iters, __pyx_v_val);\n",
"\n",
" /* function exit code */\n",
" __Pyx_RefNannyFinishContext();\n",
" return __pyx_r;\n",
"}\n",
"\n",
"static PyObject *__pyx_pf_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_2cython_mandel(CYTHON_UNUSED PyObject *__pyx_self, float __pyx_v_real, float __pyx_v_imag, int __pyx_v_max_iters, __Pyx_memviewslice __pyx_v_val) {\n",
" PyObject *__pyx_r = NULL;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_mandel\", 0);\n",
" __Pyx_XDECREF(__pyx_r);\n",
" if (unlikely(!__pyx_v_val.memview)) { __Pyx_RaiseUnboundLocalError(\"val\"); __PYX_ERR(0, 24, __pyx_L1_error) }\n",
" __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_f_46_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c_cython_mandel(__pyx_v_real, __pyx_v_imag, __pyx_v_max_iters, __pyx_v_val, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" __Pyx_GOTREF(__pyx_t_1);\n",
" __pyx_r = __pyx_t_1;\n",
" __pyx_t_1 = 0;\n",
" goto __pyx_L0;\n",
"\n",
" /* function exit code */\n",
" __pyx_L1_error:;\n",
" __Pyx_XDECREF(__pyx_t_1);\n",
" __Pyx_AddTraceback(\"_cython_magic_95bdf0f67f7d980128cef3f0d2496e5c.cython_mandel\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" __pyx_r = NULL;\n",
" __pyx_L0:;\n",
" __PYX_XDEC_MEMVIEW(&__pyx_v_val, 1);\n",
" __Pyx_XGIVEREF(__pyx_r);\n",
" __Pyx_RefNannyFinishContext();\n",
" return __pyx_r;\n",
"}\n",
"25: unsigned char[::1] val):\n", "
+26: return mandel(real, imag, max_iters, &val[0])\n", "
__pyx_t_1 = 0;\n",
" __pyx_t_2 = -1;\n",
" if (__pyx_t_1 < 0) {\n",
" __pyx_t_1 += __pyx_v_val.shape[0];\n",
" if (unlikely(__pyx_t_1 < 0)) __pyx_t_2 = 0;\n",
" } else if (unlikely(__pyx_t_1 >= __pyx_v_val.shape[0])) __pyx_t_2 = 0;\n",
" if (unlikely(__pyx_t_2 != -1)) {\n",
" __Pyx_RaiseBufferIndexError(__pyx_t_2);\n",
" __PYX_ERR(0, 26, __pyx_L1_error)\n",
" }\n",
" __pyx_r = mandel(__pyx_v_real, __pyx_v_imag, __pyx_v_max_iters, (&(*((unsigned char *) ( /* dim=0 */ ((char *) (((unsigned char *) __pyx_v_val.data) + __pyx_t_1)) )))));\n",
" goto __pyx_L0;\n",
"Generated by Cython 0.28.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: #cythonize the python code\n", "
+02: def cython_mandel2(x, y, max_iters, value):\n", "
/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_5992dda920094aacbe84c0095f6f022c_1cython_mandel2(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static char __pyx_doc_46_cython_magic_5992dda920094aacbe84c0095f6f022c_cython_mandel2[] = \"\\n Given the real and imaginary parts of a complex number,\\n determine if it is a candidate for membership in the Mandelbrot\\n set given a fixed number of iterations.\\n \";\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_5992dda920094aacbe84c0095f6f022c_1cython_mandel2 = {\"cython_mandel2\", (PyCFunction)__pyx_pw_46_cython_magic_5992dda920094aacbe84c0095f6f022c_1cython_mandel2, METH_VARARGS|METH_KEYWORDS, __pyx_doc_46_cython_magic_5992dda920094aacbe84c0095f6f022c_cython_mandel2};\n",
"static PyObject *__pyx_pw_46_cython_magic_5992dda920094aacbe84c0095f6f022c_1cython_mandel2(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" PyObject *__pyx_v_x = 0;\n",
" PyObject *__pyx_v_y = 0;\n",
" PyObject *__pyx_v_max_iters = 0;\n",
" PyObject *__pyx_v_value = 0;\n",
" PyObject *__pyx_r = 0;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_mandel2 (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_x,&__pyx_n_s_y,&__pyx_n_s_max_iters,&__pyx_n_s_value,0};\n",
" PyObject* values[4] = {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 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_x)) != 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_y)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel2\", 1, 4, 4, 1); __PYX_ERR(0, 2, __pyx_L3_error)\n",
" }\n",
" CYTHON_FALLTHROUGH;\n",
" case 2:\n",
" if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_max_iters)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel2\", 1, 4, 4, 2); __PYX_ERR(0, 2, __pyx_L3_error)\n",
" }\n",
" CYTHON_FALLTHROUGH;\n",
" case 3:\n",
" if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_value)) != 0)) kw_args--;\n",
" else {\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel2\", 1, 4, 4, 3); __PYX_ERR(0, 2, __pyx_L3_error)\n",
" }\n",
" }\n",
" if (unlikely(kw_args > 0)) {\n",
" if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"cython_mandel2\") < 0)) __PYX_ERR(0, 2, __pyx_L3_error)\n",
" }\n",
" } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {\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",
" }\n",
" __pyx_v_x = values[0];\n",
" __pyx_v_y = values[1];\n",
" __pyx_v_max_iters = values[2];\n",
" __pyx_v_value = values[3];\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" __Pyx_RaiseArgtupleInvalid(\"cython_mandel2\", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2, __pyx_L3_error)\n",
" __pyx_L3_error:;\n",
" __Pyx_AddTraceback(\"_cython_magic_5992dda920094aacbe84c0095f6f022c.cython_mandel2\", __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_5992dda920094aacbe84c0095f6f022c_cython_mandel2(__pyx_self, __pyx_v_x, __pyx_v_y, __pyx_v_max_iters, __pyx_v_value);\n",
"\n",
" /* function exit code */\n",
" __Pyx_RefNannyFinishContext();\n",
" return __pyx_r;\n",
"}\n",
"\n",
"static PyObject *__pyx_pf_46_cython_magic_5992dda920094aacbe84c0095f6f022c_cython_mandel2(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_x, PyObject *__pyx_v_y, PyObject *__pyx_v_max_iters, PyObject *__pyx_v_value) {\n",
" int __pyx_v_i;\n",
" __pyx_t_double_complex __pyx_v_c;\n",
" __pyx_t_double_complex __pyx_v_z;\n",
" PyObject *__pyx_r = NULL;\n",
" __Pyx_RefNannyDeclarations\n",
" __Pyx_RefNannySetupContext(\"cython_mandel2\", 0);\n",
"/* … */\n",
" /* function exit code */\n",
" __pyx_L1_error:;\n",
" __Pyx_XDECREF(__pyx_t_1);\n",
" __Pyx_XDECREF(__pyx_t_2);\n",
" __Pyx_AddTraceback(\"_cython_magic_5992dda920094aacbe84c0095f6f022c.cython_mandel2\", __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(7, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_max_iters, __pyx_n_s_value, __pyx_n_s_i, __pyx_n_s_c, __pyx_n_s_z); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 2, __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_5992dda920094aacbe84c0095f6f022c_1cython_mandel2, NULL, __pyx_n_s_cython_magic_5992dda920094aacbe); 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_cython_mandel2, __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: Given the real and imaginary parts of a complex number,\n", "
05: determine if it is a candidate for membership in the Mandelbrot\n", "
06: set given a fixed number of iterations.\n", "
07: """\n", "
+08: cdef int i = 0\n", "
__pyx_v_i = 0;\n",
"+09: cdef complex c = complex(x,y)\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_x);\n", " __Pyx_GIVEREF(__pyx_v_x);\n", " PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_x);\n", " __Pyx_INCREF(__pyx_v_y);\n", " __Pyx_GIVEREF(__pyx_v_y);\n", " PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_y);\n", " __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)(&PyComplex_Type)), __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n", " __pyx_t_3 = __Pyx_PyComplex_As___pyx_t_double_complex(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 9, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n", " __pyx_v_c = __pyx_t_3;\n", "
+10: cdef complex z = 0.0j\n", "
__pyx_v_z = __pyx_t_double_complex_from_parts(0, 0.0);\n",
"+11: for i in range(max_iters):\n", "
__pyx_t_4 = __Pyx_PyInt_As_long(__pyx_v_max_iters); if (unlikely((__pyx_t_4 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 11, __pyx_L1_error)\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_i = __pyx_t_6;\n", "
+12: 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",
"+13: if (z.real*z.real + z.imag*z.imag) >= 4:\n", "
__pyx_t_7 = ((((__Pyx_CREAL(__pyx_v_z) * __Pyx_CREAL(__pyx_v_z)) + (__Pyx_CIMAG(__pyx_v_z) * __Pyx_CIMAG(__pyx_v_z))) >= 4.0) != 0);\n", " if (__pyx_t_7) {\n", "/* … */\n", " }\n", " }\n", "
+14: value[0] = i\n", "
__pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n", " __Pyx_GOTREF(__pyx_t_2);\n", " if (unlikely(__Pyx_SetItemInt(__pyx_v_value, 0, __pyx_t_2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1) < 0)) __PYX_ERR(0, 14, __pyx_L1_error)\n", " __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n", "
+15: return 0\n", "
__Pyx_XDECREF(__pyx_r);\n", " __Pyx_INCREF(__pyx_int_0);\n", " __pyx_r = __pyx_int_0;\n", " goto __pyx_L0;\n", "
+16: value[0] = max_iters\n", "
if (unlikely(__Pyx_SetItemInt(__pyx_v_value, 0, __pyx_v_max_iters, long, 1, __Pyx_PyInt_From_long, 0, 0, 1) < 0)) __PYX_ERR(0, 16, __pyx_L1_error)\n", "
+17: return max_iters\n", "
__Pyx_XDECREF(__pyx_r);\n", " __Pyx_INCREF(__pyx_v_max_iters);\n", " __pyx_r = __pyx_v_max_iters;\n", " goto __pyx_L0;\n", "
| \n", " | time in ms | \n", "CreateFractal in Python | \n", "CreateFractal in C | \n", "
|---|---|---|---|
| 0 | \n", "Python | \n", "5361.09 millisecs | \n", "\n", " |
| 1 | \n", "C | \n", "\n", " | 82.00 millisecs | \n", "
| 2 | \n", "ctypes | \n", "2198.44 | \n", "144.21 | \n", "
| 3 | \n", "cffi - ABI | \n", "925.74 | \n", "139.34 | \n", "
| 4 | \n", "cffi - API | \n", "718.42 | \n", "38.27 | \n", "
| 5 | \n", "cython - c | \n", "916.12 | \n", "137.41 | \n", "
| 6 | \n", "cython - python | \n", "669.64 | \n", "137.41 | \n", "