From a9179378e589ccd4612ba3fe3f043c0b38f1f9b7 Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <MichielCottaar@gmail.com> Date: Fri, 16 Feb 2018 11:47:35 +0000 Subject: [PATCH] Added packages/speed talks --- talks/packages/packages.ipynb | 870 ++++++++++++++ talks/packages/packages.md | 579 +++++++++ talks/speed/speed.ipynb | 2060 +++++++++++++++++++++++++++++++++ 3 files changed, 3509 insertions(+) create mode 100644 talks/packages/packages.ipynb create mode 100644 talks/packages/packages.md create mode 100644 talks/speed/speed.ipynb diff --git a/talks/packages/packages.ipynb b/talks/packages/packages.ipynb new file mode 100644 index 0000000..0c2b66f --- /dev/null +++ b/talks/packages/packages.ipynb @@ -0,0 +1,870 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Main scientific python libraries\n", + "See https://scipy.org/\n", + "\n", + "Most of these packages have or are in thr progress of dropping support for python2.\n", + "So use python3!\n", + "\n", + "## [Numpy](http://www.numpy.org/): arrays\n", + "This is the main library underlying (nearly) all of the scientific python ecosystem.\n", + "See the tutorial in the beginner session or [the official numpy tutorial](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html) for usage details.\n", + "\n", + "The usual nickname of numpy is np:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Numpy includes support for:\n", + "- N-dimensional arrays with various datatypes\n", + "- basic functions (e.g., polynomials)\n", + "- basic linear algebra\n", + "- random number generation\n", + "\n", + "## [Scipy](https://scipy.org/scipylib/index.html): most general scientific tools\n", + "At the top level this module includes all of the basic functionality from numpy.\n", + "You could import this as, but you might as well import numpy directly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import scipy as sp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main strength in scipy lies in its sub-packages:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy import optimize\n", + "def costfunc(params):\n", + " return params[0] ** 2 * (params[1] - 3) ** 2 + (params[0] - 2) ** 2\n", + "optimize.minimize(costfunc, x0=[0, 0], method='l-bfgs-b')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Tutorials for all sub-packages can be found [here](https://docs.scipy.org/doc/scipy-1.0.0/reference/).\n", + "\n", + "## [Matplotlib](https://matplotlib.org/): Main plotting library" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib as mpl\n", + "mpl.use('nbagg')\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The matplotlib tutorials are [here](https://matplotlib.org/tutorials/index.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(0, 2, 100)\n", + "\n", + "plt.plot(x, x, label='linear')\n", + "plt.plot(x, x**2, label='quadratic')\n", + "plt.plot(x, x**3, label='cubic')\n", + "\n", + "plt.xlabel('x label')\n", + "plt.ylabel('y label')\n", + "\n", + "plt.title(\"Simple Plot\")\n", + "\n", + "plt.legend()\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatives:\n", + "- [Mayavi](http://docs.enthought.com/mayavi/mayavi/): 3D plotting (hard to install)\n", + "- [Bokeh](https://bokeh.pydata.org/en/latest/) among many others: interactive plots in the browser (i.e., in javascript)\n", + "\n", + "## [Ipython](http://ipython.org/)/[Jupyter](https://jupyter.org/) notebook: interactive python environments\n", + "There are many [useful extensions available](https://github.com/ipython-contrib/jupyter_contrib_nbextensions).\n", + "\n", + "## [Pandas](https://pandas.pydata.org/): Analyzing \"clean\" data\n", + "Once your data is in tabular form (e.g. Biobank IDP's), you want to use pandas dataframes to analyze them.\n", + "This brings most of the functionality of R into python.\n", + "Pandas has excellent support for:\n", + "- fast IO to many tabular formats\n", + "- accurate handling of missing data\n", + "- Many, many routines to handle data\n", + " - group by categorical data (i.e., male/female, or age groups)\n", + " - joining/merging data\n", + " - time series support\n", + "- statistical models through [statsmodels](http://www.statsmodels.org/stable/index.html)\n", + "- plotting though seaborn [seaborn](https://seaborn.pydata.org/)\n", + "- Use [dask](https://dask.pydata.org/en/latest/) if your data is too big for memory (or if you want to run in parallel)\n", + "\n", + "You should also install `numexpr` and `bottleneck` for optimal performance.\n", + "\n", + "For the documentation check [here](http://pandas.pydata.org/pandas-docs/stable/index.html)\n", + "\n", + "### Adjusted example from statsmodels tutorial" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import statsmodels.api as sm\n", + "import statsmodels.formula.api as smf\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = sm.datasets.get_rdataset(\"Guerry\", \"HistData\").data\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.describe()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.groupby('Region').mean()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results = smf.ols('Lottery ~ Literacy + np.log(Pop1831)', data=df).fit()\n", + "results.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df['log_pop'] = np.log(df.Pop1831)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results = smf.ols('Lottery ~ Literacy + log_pop', data=df).fit()\n", + "results.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results = smf.ols('Lottery ~ Literacy + np.log(Pop1831) + Region', data=df).fit()\n", + "results.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results = smf.ols('Lottery ~ Literacy + np.log(Pop1831) + Region + Region * Literacy', data=df).fit()\n", + "results.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib nbagg\n", + "import seaborn as sns\n", + "sns.pairplot(df, hue=\"Region\", vars=('Lottery', 'Literacy', 'log_pop'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## [Sympy](http://www.sympy.org/en/index.html): Symbolic programming" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sympy as sym # no standard nickname" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x, a, b, c = sym.symbols('x, a, b, c')\n", + "sym.solve(a * x ** 2 + b * x + c, x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sym.integrate(x/(x**2+a*x+2), x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "f = sym.utilities.lambdify((x, a), sym.integrate((x**2+a*x+2), x))\n", + "f(np.random.rand(10), np.random.rand(10))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Other topics\n", + "## [Argparse](https://docs.python.org/3.6/howto/argparse.html): Command line arguments" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%writefile test_argparse.py\n", + "import argparse\n", + "\n", + "def main():\n", + " parser = argparse.ArgumentParser(description=\"calculate X to the power of Y\")\n", + " parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\")\n", + " parser.add_argument(\"x\", type=int, help=\"the base\")\n", + " parser.add_argument(\"y\", type=int, help=\"the exponent\")\n", + " args = parser.parse_args()\n", + " answer = args.x**args.y\n", + "\n", + " if args.verbose:\n", + " print(\"{} to the power {} equals {}\".format(args.x, args.y, answer))\n", + " else:\n", + " print(\"{}^{} == {}\".format(args.x, args.y, answer))\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run test_argparse.py 3 8 -v" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run test_argparse.py -h" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run test_argparse.py 3 8.5 -q" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### [Gooey](https://github.com/chriskiehl/Gooey): GUI from command line tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%writefile test_gooey.py\n", + "import argparse\n", + "from gooey import Gooey\n", + "\n", + "@Gooey\n", + "def main():\n", + " parser = argparse.ArgumentParser(description=\"calculate X to the power of Y\")\n", + " parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\")\n", + " parser.add_argument(\"x\", type=int, help=\"the base\")\n", + " parser.add_argument(\"y\", type=int, help=\"the exponent\")\n", + " args = parser.parse_args()\n", + " answer = args.x**args.y\n", + "\n", + " if args.verbose:\n", + " print(\"{} to the power {} equals {}\".format(args.x, args.y, answer))\n", + " else:\n", + " print(\"{}^{} == {}\".format(args.x, args.y, answer))\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run test_gooey.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gcoord_gui" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## [Jinja2](http://jinja.pocoo.org/docs/2.10/): HTML generation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%writefile image_list.jinja2\n", + "<!DOCTYPE html>\n", + "<html lang=\"en\">\n", + "<head>\n", + " {% block head %}\n", + " <title>{{ title }}</title>\n", + " {% endblock %}\n", + "</head>\n", + "<body>\n", + " <div id=\"content\">\n", + " {% block content %}\n", + " {% for description, filenames in images %}\n", + " <p>\n", + " {{ description }}\n", + " </p>\n", + " {% for filename in filenames %}\n", + " <a href=\"{{ filename }}\">\n", + " <img src=\"{{ filename }}\">\n", + " </a>\n", + " {% endfor %}\n", + " {% endfor %}\n", + " {% endblock %}\n", + " </div>\n", + " <footer>\n", + " Created on {{ time }}\n", + " </footer>\n", + "</body>\n", + "</html>" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_sine(amplitude, frequency):\n", + " x = np.linspace(0, 2 * np.pi, 100)\n", + " y = amplitude * np.sin(frequency * x)\n", + " plt.plot(x, y)\n", + " plt.xticks([0, np.pi, 2 * np.pi], ['0', '$\\pi$', '$2 \\pi$'])\n", + " plt.ylim(-1.1, 1.1)\n", + " filename = 'plots/A{:.2f}_F{:.2f}.png'.format(amplitude, frequency)\n", + " plt.title('A={:.2f}, F={:.2f}'.format(amplitude, frequency))\n", + " plt.savefig(filename)\n", + " plt.close(plt.gcf())\n", + " return filename\n", + "\n", + "!mkdir plots\n", + "amplitudes = [plot_sine(A, 1.) for A in [0.1, 0.3, 0.7, 1.0]]\n", + "frequencies = [plot_sine(1., F) for F in [1, 2, 3, 4, 5, 6]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from jinja2 import Environment, FileSystemLoader\n", + "from datetime import datetime\n", + "loader = FileSystemLoader('.')\n", + "env = Environment(loader=loader)\n", + "template = env.get_template('image_list.jinja2')\n", + "\n", + "images = [\n", + " ('Varying the amplitude', amplitudes),\n", + " ('Varying the frequency', frequencies),\n", + "]\n", + "\n", + "with open('image_list.html', 'w') as f:\n", + " f.write(template.render(title='Lots of sines',\n", + " images=images, time=datetime.now()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!open image_list.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Neuroimage packages\n", + "The [nipy](http://nipy.org/) ecosystem covers most of these.\n", + "\n", + "### [CIFTI](https://github.com/MichielCottaar/cifti): easy creation/manipulation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import nibabel\n", + "thickness = nibabel.load('100307/fsaverage_LR32k/100307.L.thickness.32k_fs_LR.shape.gii').darrays[0].data\n", + "thickness" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import cifti\n", + "ctx = thickness != 0\n", + "arr = np.random.rand(ctx.sum())\n", + "\n", + "bm_ctx = cifti.BrainModel.from_mask(ctx, name='CortexLeft')\n", + "sc = cifti.Scalar.from_names(['random'])\n", + "cifti.write('random_ctx.dscalar.nii', arr[None, :], (sc, bm_ctx))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!wb_view 100307/fsaverage_LR32k/100307.*.32k_fs_LR.surf.gii random_ctx.dscalar.nii" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "img = nibabel.load('100307/aparc+aseg.nii.gz')\n", + "cerebellum = img.get_data() == 8\n", + "\n", + "bm = bm_ctx + cifti.BrainModel.from_mask(cerebellum, name='CerebellumLeft', affine=img.affine)\n", + "sc = cifti.Scalar.from_names(['random'])\n", + "arr = np.random.rand(len(bm))\n", + "cifti.write('random_ctx_cerebellum.dscalar.nii', arr[None, :], (sc, bm))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!wb_view 100307/fsaverage_LR32k/100307.*.32k_fs_LR.surf.gii 100307/aparc+aseg.nii.gz random_ctx_cerebellum.dscalar.nii" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "arr = abs(thickness[ctx, None] - thickness[None, ctx])\n", + "cifti.write('diff_thickness.dconn.nii', arr, (bm_ctx, bm_ctx))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!wb_view 100307/fsaverage_LR32k/100307.*.32k_fs_LR.surf.gii diff_thickness.dconn.nii" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## [networkx](https://networkx.github.io/): graph theory\n", + "\n", + "## GUI\n", + "- [tkinter](https://docs.python.org/3.6/library/tkinter.html): thin wrapper around Tcl/Tk; included in python\n", + "- [wxpython](https://www.wxpython.org/): Wrapper around the C++ wxWidgets library" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%writefile wx_hello_world.py\n", + "#!/usr/bin/env python\n", + "\"\"\"\n", + "Hello World, but with more meat.\n", + "\"\"\"\n", + "\n", + "import wx\n", + "\n", + "class HelloFrame(wx.Frame):\n", + " \"\"\"\n", + " A Frame that says Hello World\n", + " \"\"\"\n", + "\n", + " def __init__(self, *args, **kw):\n", + " # ensure the parent's __init__ is called\n", + " super(HelloFrame, self).__init__(*args, **kw)\n", + "\n", + " # create a panel in the frame\n", + " pnl = wx.Panel(self)\n", + "\n", + " # and put some text with a larger bold font on it\n", + " st = wx.StaticText(pnl, label=\"Hello World!\", pos=(25,25))\n", + " font = st.GetFont()\n", + " font.PointSize += 10\n", + " font = font.Bold()\n", + " st.SetFont(font)\n", + "\n", + " # create a menu bar\n", + " self.makeMenuBar()\n", + "\n", + " # and a status bar\n", + " self.CreateStatusBar()\n", + " self.SetStatusText(\"Welcome to wxPython!\")\n", + "\n", + "\n", + " def makeMenuBar(self):\n", + " \"\"\"\n", + " A menu bar is composed of menus, which are composed of menu items.\n", + " This method builds a set of menus and binds handlers to be called\n", + " when the menu item is selected.\n", + " \"\"\"\n", + "\n", + " # Make a file menu with Hello and Exit items\n", + " fileMenu = wx.Menu()\n", + " # The \"\\t...\" syntax defines an accelerator key that also triggers\n", + " # the same event\n", + " helloItem = fileMenu.Append(-1, \"&Hello...\\tCtrl-H\",\n", + " \"Help string shown in status bar for this menu item\")\n", + " fileMenu.AppendSeparator()\n", + " # When using a stock ID we don't need to specify the menu item's\n", + " # label\n", + " exitItem = fileMenu.Append(wx.ID_EXIT)\n", + "\n", + " # Now a help menu for the about item\n", + " helpMenu = wx.Menu()\n", + " aboutItem = helpMenu.Append(wx.ID_ABOUT)\n", + "\n", + " # Make the menu bar and add the two menus to it. The '&' defines\n", + " # that the next letter is the \"mnemonic\" for the menu item. On the\n", + " # platforms that support it those letters are underlined and can be\n", + " # triggered from the keyboard.\n", + " menuBar = wx.MenuBar()\n", + " menuBar.Append(fileMenu, \"&File\")\n", + " menuBar.Append(helpMenu, \"&Help\")\n", + "\n", + " # Give the menu bar to the frame\n", + " self.SetMenuBar(menuBar)\n", + "\n", + " # Finally, associate a handler function with the EVT_MENU event for\n", + " # each of the menu items. That means that when that menu item is\n", + " # activated then the associated handler function will be called.\n", + " self.Bind(wx.EVT_MENU, self.OnHello, helloItem)\n", + " self.Bind(wx.EVT_MENU, self.OnExit, exitItem)\n", + " self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)\n", + "\n", + "\n", + " def OnExit(self, event):\n", + " \"\"\"Close the frame, terminating the application.\"\"\"\n", + " self.Close(True)\n", + "\n", + "\n", + " def OnHello(self, event):\n", + " \"\"\"Say hello to the user.\"\"\"\n", + " wx.MessageBox(\"Hello again from wxPython\")\n", + "\n", + "\n", + " def OnAbout(self, event):\n", + " \"\"\"Display an About Dialog\"\"\"\n", + " wx.MessageBox(\"This is a wxPython Hello World sample\",\n", + " \"About Hello World 2\",\n", + " wx.OK|wx.ICON_INFORMATION)\n", + "\n", + "\n", + "if __name__ == '__main__':\n", + " # When this module is run (not imported) then create the app, the\n", + " # frame, show it, and start the event loop.\n", + " app = wx.App()\n", + " frm = HelloFrame(None, title='Hello World 2')\n", + " frm.Show()\n", + " app.MainLoop()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run wx_hello_world.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Machine learning\n", + "- scikit-learn\n", + "- theano/tensorflow/pytorch\n", + " - keras\n", + "\n", + "## [Pycuda](https://documen.tician.de/pycuda/): Programming the GPU" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pycuda.autoinit\n", + "import pycuda.driver as drv\n", + "\n", + "from pycuda.compiler import SourceModule\n", + "mod = SourceModule(\"\"\"\n", + "__global__ void multiply_them(double *dest, double *a, double *b)\n", + "{\n", + " const int i = threadIdx.x;\n", + " dest[i] = a[i] * b[i];\n", + "}\n", + "\"\"\")\n", + "\n", + "multiply_them = mod.get_function(\"multiply_them\")\n", + "\n", + "a = np.random.randn(400)\n", + "b = np.random.randn(400)\n", + "\n", + "dest = np.zeros_like(a)\n", + "multiply_them(\n", + " drv.Out(dest), drv.In(a), drv.In(b),\n", + " block=(400,1,1), grid=(1,1))\n", + "\n", + "print(dest-a*b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing\n", + "- [unittest](https://docs.python.org/3.6/library/unittest.html): python built-in testing\n", + "> ```\n", + "> import unittest\n", + ">\n", + "> class TestStringMethods(unittest.TestCase):\n", + ">\n", + "> def test_upper(self):\n", + "> self.assertEqual('foo'.upper(), 'FOO')\n", + ">\n", + "> def test_isupper(self):\n", + "> self.assertTrue('FOO'.isupper())\n", + "> self.assertFalse('Foo'.isupper())\n", + ">\n", + "> def test_split(self):\n", + "> s = 'hello world'\n", + "> self.assertEqual(s.split(), ['hello', 'world'])\n", + "> # check that s.split fails when the separator is not a string\n", + "> with self.assertRaises(TypeError):\n", + "> s.split(2)\n", + ">\n", + "> if __name__ == '__main__':\n", + "> unittest.main()\n", + "> ```\n", + "- [doctest](https://docs.python.org/3.6/library/doctest.html): checks the example usage in the documentation\n", + "> ```\n", + "> def factorial(n):\n", + "> \"\"\"Return the factorial of n, an exact integer >= 0.\n", + ">\n", + "> >>> [factorial(n) for n in range(6)]\n", + "> [1, 1, 2, 6, 24, 120]\n", + "> >>> factorial(30)\n", + "> 265252859812191058636308480000000\n", + "> >>> factorial(-1)\n", + "> Traceback (most recent call last):\n", + "> ...\n", + "> ValueError: n must be >= 0\n", + ">\n", + "> Factorials of floats are OK, but the float must be an exact integer:\n", + "> >>> factorial(30.1)\n", + "> Traceback (most recent call last):\n", + "> ...\n", + "> ValueError: n must be exact integer\n", + "> >>> factorial(30.0)\n", + "> 265252859812191058636308480000000\n", + ">\n", + "> It must also not be ridiculously large:\n", + "> >>> factorial(1e100)\n", + "> Traceback (most recent call last):\n", + "> ...\n", + "> OverflowError: n too large\n", + "> \"\"\"\n", + ">\n", + "> import math\n", + "> if not n >= 0:\n", + "> raise ValueError(\"n must be >= 0\")\n", + "> if math.floor(n) != n:\n", + "> raise ValueError(\"n must be exact integer\")\n", + "> if n+1 == n: # catch a value like 1e300\n", + "> raise OverflowError(\"n too large\")\n", + "> result = 1\n", + "> factor = 2\n", + "> while factor <= n:\n", + "> result *= factor\n", + "> factor += 1\n", + "> return result\n", + ">\n", + ">\n", + "> if __name__ == \"__main__\":\n", + "> import doctest\n", + "> doctest.testmod()\n", + "> ```\n", + "Two external packages provide more convenient unit tests:\n", + "- [py.test](https://docs.pytest.org/en/latest/)\n", + "- [nose2](http://nose2.readthedocs.io/en/latest/usage.html)\n", + "> ```\n", + "> # content of test_sample.py\n", + "> def inc(x):\n", + "> return x + 1\n", + ">\n", + "> def test_answer():\n", + "> assert inc(3) == 5\n", + "> ```\n", + "\n", + "- [coverage](https://coverage.readthedocs.io/en/coverage-4.5.1/): measures which part of the code is covered by the tests\n", + "\n", + "## Linters\n", + "Linters check the code for any syntax errors, [style errors](https://www.python.org/dev/peps/pep-0008/), unused variables, unreachable code, etc.\n", + "- [pylint](https://pypi.python.org/pypi/pylint): most extensive linter\n", + "- [pyflake](https://pypi.python.org/pypi/pyflakes): if you think pylint is too strict\n", + "- [pep8](https://pypi.python.org/pypi/pep8): just checks for style errors\n", + "- [mypy](http://mypy-lang.org/): adding explicit typing to python" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/talks/packages/packages.md b/talks/packages/packages.md new file mode 100644 index 0000000..8da72e4 --- /dev/null +++ b/talks/packages/packages.md @@ -0,0 +1,579 @@ +# Main scientific python libraries +See https://scipy.org/ + +Most of these packages have or are in thr progress of dropping support for python2. +So use python3! + +## [Numpy](http://www.numpy.org/): arrays +This is the main library underlying (nearly) all of the scientific python ecosystem. +See the tutorial in the beginner session or [the official numpy tutorial](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html) for usage details. + +The usual nickname of numpy is np: +``` +import numpy as np +``` + +Numpy includes support for: +- N-dimensional arrays with various datatypes +- basic functions (e.g., polynomials) +- basic linear algebra +- random number generation + +## [Scipy](https://scipy.org/scipylib/index.html): most general scientific tools +At the top level this module includes all of the basic functionality from numpy. +You could import this as, but you might as well import numpy directly. +``` +import scipy as sp +``` + +The main strength in scipy lies in its sub-packages: +``` +from scipy import optimize +def costfunc(params): + return params[0] ** 2 * (params[1] - 3) ** 2 + (params[0] - 2) ** 2 +optimize.minimize(costfunc, x0=[0, 0], method='l-bfgs-b') +``` + +Tutorials for all sub-packages can be found [here](https://docs.scipy.org/doc/scipy-1.0.0/reference/). + +## [Matplotlib](https://matplotlib.org/): Main plotting library +``` +import matplotlib as mpl +mpl.use('nbagg') +import matplotlib.pyplot as plt +``` +The matplotlib tutorials are [here](https://matplotlib.org/tutorials/index.html) + +``` +x = np.linspace(0, 2, 100) + +plt.plot(x, x, label='linear') +plt.plot(x, x**2, label='quadratic') +plt.plot(x, x**3, label='cubic') + +plt.xlabel('x label') +plt.ylabel('y label') + +plt.title("Simple Plot") + +plt.legend() + +plt.show() +``` + +Alternatives: +- [Mayavi](http://docs.enthought.com/mayavi/mayavi/): 3D plotting (hard to install) +- [Bokeh](https://bokeh.pydata.org/en/latest/) among many others: interactive plots in the browser (i.e., in javascript) + +## [Ipython](http://ipython.org/)/[Jupyter](https://jupyter.org/) notebook: interactive python environments +There are many [useful extensions available](https://github.com/ipython-contrib/jupyter_contrib_nbextensions). + +## [Pandas](https://pandas.pydata.org/): Analyzing "clean" data +Once your data is in tabular form (e.g. Biobank IDP's), you want to use pandas dataframes to analyze them. +This brings most of the functionality of R into python. +Pandas has excellent support for: +- fast IO to many tabular formats +- accurate handling of missing data +- Many, many routines to handle data + - group by categorical data (i.e., male/female, or age groups) + - joining/merging data + - time series support +- statistical models through [statsmodels](http://www.statsmodels.org/stable/index.html) +- plotting though seaborn [seaborn](https://seaborn.pydata.org/) +- Use [dask](https://dask.pydata.org/en/latest/) if your data is too big for memory (or if you want to run in parallel) + +You should also install `numexpr` and `bottleneck` for optimal performance. + +For the documentation check [here](http://pandas.pydata.org/pandas-docs/stable/index.html) + +### Adjusted example from statsmodels tutorial +``` +import statsmodels.api as sm +import statsmodels.formula.api as smf +import numpy as np +``` + +``` +df = sm.datasets.get_rdataset("Guerry", "HistData").data +df +``` + +``` +df.describe() +``` + +``` +df.groupby('Region').mean() +``` + +``` +results = smf.ols('Lottery ~ Literacy + np.log(Pop1831)', data=df).fit() +results.summary() +``` + +``` +df['log_pop'] = np.log(df.Pop1831) +df +``` + +``` +results = smf.ols('Lottery ~ Literacy + log_pop', data=df).fit() +results.summary() +``` + +``` +results = smf.ols('Lottery ~ Literacy + np.log(Pop1831) + Region', data=df).fit() +results.summary() +``` + +``` +results = smf.ols('Lottery ~ Literacy + np.log(Pop1831) + Region + Region * Literacy', data=df).fit() +results.summary() +``` + +``` +%matplotlib nbagg +import seaborn as sns +sns.pairplot(df, hue="Region", vars=('Lottery', 'Literacy', 'log_pop')) +``` + +## [Sympy](http://www.sympy.org/en/index.html): Symbolic programming +``` +import sympy as sym # no standard nickname +``` + +``` +x, a, b, c = sym.symbols('x, a, b, c') +sym.solve(a * x ** 2 + b * x + c, x) +``` + +``` +sym.integrate(x/(x**2+a*x+2), x) +``` + +``` +f = sym.utilities.lambdify((x, a), sym.integrate((x**2+a*x+2), x)) +f(np.random.rand(10), np.random.rand(10)) +``` + +# Other topics +## [Argparse](https://docs.python.org/3.6/howto/argparse.html): Command line arguments +``` +%%writefile test_argparse.py +import argparse + +def main(): + parser = argparse.ArgumentParser(description="calculate X to the power of Y") + parser.add_argument("-v", "--verbose", action="store_true") + parser.add_argument("x", type=int, help="the base") + parser.add_argument("y", type=int, help="the exponent") + args = parser.parse_args() + answer = args.x**args.y + + if args.verbose: + print("{} to the power {} equals {}".format(args.x, args.y, answer)) + else: + print("{}^{} == {}".format(args.x, args.y, answer)) + +if __name__ == '__main__': + main() +``` + +``` +%run test_argparse.py 3 8 -v +``` + +``` +%run test_argparse.py -h +``` + +``` +%run test_argparse.py 3 8.5 -q +``` + +### [Gooey](https://github.com/chriskiehl/Gooey): GUI from command line tool +``` +%%writefile test_gooey.py +import argparse +from gooey import Gooey + +@Gooey +def main(): + parser = argparse.ArgumentParser(description="calculate X to the power of Y") + parser.add_argument("-v", "--verbose", action="store_true") + parser.add_argument("x", type=int, help="the base") + parser.add_argument("y", type=int, help="the exponent") + args = parser.parse_args() + answer = args.x**args.y + + if args.verbose: + print("{} to the power {} equals {}".format(args.x, args.y, answer)) + else: + print("{}^{} == {}".format(args.x, args.y, answer)) + +if __name__ == '__main__': + main() +``` + +``` +%run test_gooey.py +``` + +``` +!gcoord_gui +``` + +## [Jinja2](http://jinja.pocoo.org/docs/2.10/): HTML generation +``` +%%writefile image_list.jinja2 +<!DOCTYPE html> +<html lang="en"> +<head> + {% block head %} + <title>{{ title }}</title> + {% endblock %} +</head> +<body> + <div id="content"> + {% block content %} + {% for description, filenames in images %} + <p> + {{ description }} + </p> + {% for filename in filenames %} + <a href="{{ filename }}"> + <img src="{{ filename }}"> + </a> + {% endfor %} + {% endfor %} + {% endblock %} + </div> + <footer> + Created on {{ time }} + </footer> +</body> +</html> +``` + +``` +def plot_sine(amplitude, frequency): + x = np.linspace(0, 2 * np.pi, 100) + y = amplitude * np.sin(frequency * x) + plt.plot(x, y) + plt.xticks([0, np.pi, 2 * np.pi], ['0', '$\pi$', '$2 \pi$']) + plt.ylim(-1.1, 1.1) + filename = 'plots/A{:.2f}_F{:.2f}.png'.format(amplitude, frequency) + plt.title('A={:.2f}, F={:.2f}'.format(amplitude, frequency)) + plt.savefig(filename) + plt.close(plt.gcf()) + return filename + +!mkdir plots +amplitudes = [plot_sine(A, 1.) for A in [0.1, 0.3, 0.7, 1.0]] +frequencies = [plot_sine(1., F) for F in [1, 2, 3, 4, 5, 6]] +``` + +``` +from jinja2 import Environment, FileSystemLoader +from datetime import datetime +loader = FileSystemLoader('.') +env = Environment(loader=loader) +template = env.get_template('image_list.jinja2') + +images = [ + ('Varying the amplitude', amplitudes), + ('Varying the frequency', frequencies), +] + +with open('image_list.html', 'w') as f: + f.write(template.render(title='Lots of sines', + images=images, time=datetime.now())) +``` + +``` +!open image_list.html +``` + +## Neuroimage packages +The [nipy](http://nipy.org/) ecosystem covers most of these. + +### [CIFTI](https://github.com/MichielCottaar/cifti): easy creation/manipulation +``` +import nibabel +thickness = nibabel.load('100307/fsaverage_LR32k/100307.L.thickness.32k_fs_LR.shape.gii').darrays[0].data +thickness +``` + +``` +import cifti +ctx = thickness != 0 +arr = np.random.rand(ctx.sum()) + +bm_ctx = cifti.BrainModel.from_mask(ctx, name='CortexLeft') +sc = cifti.Scalar.from_names(['random']) +cifti.write('random_ctx.dscalar.nii', arr[None, :], (sc, bm_ctx)) +``` + +``` +!wb_view 100307/fsaverage_LR32k/100307.*.32k_fs_LR.surf.gii random_ctx.dscalar.nii +``` + +``` +img = nibabel.load('100307/aparc+aseg.nii.gz') +cerebellum = img.get_data() == 8 + +bm = bm_ctx + cifti.BrainModel.from_mask(cerebellum, name='CerebellumLeft', affine=img.affine) +sc = cifti.Scalar.from_names(['random']) +arr = np.random.rand(len(bm)) +cifti.write('random_ctx_cerebellum.dscalar.nii', arr[None, :], (sc, bm)) +``` + +``` +!wb_view 100307/fsaverage_LR32k/100307.*.32k_fs_LR.surf.gii 100307/aparc+aseg.nii.gz random_ctx_cerebellum.dscalar.nii +``` + +``` +arr = abs(thickness[ctx, None] - thickness[None, ctx]) +cifti.write('diff_thickness.dconn.nii', arr, (bm_ctx, bm_ctx)) +``` + +``` +!wb_view 100307/fsaverage_LR32k/100307.*.32k_fs_LR.surf.gii diff_thickness.dconn.nii +``` + +## [networkx](https://networkx.github.io/): graph theory + +## GUI +- [tkinter](https://docs.python.org/3.6/library/tkinter.html): thin wrapper around Tcl/Tk; included in python +- [wxpython](https://www.wxpython.org/): Wrapper around the C++ wxWidgets library +``` +%%writefile wx_hello_world.py +#!/usr/bin/env python +""" +Hello World, but with more meat. +""" + +import wx + +class HelloFrame(wx.Frame): + """ + A Frame that says Hello World + """ + + def __init__(self, *args, **kw): + # ensure the parent's __init__ is called + super(HelloFrame, self).__init__(*args, **kw) + + # create a panel in the frame + pnl = wx.Panel(self) + + # and put some text with a larger bold font on it + st = wx.StaticText(pnl, label="Hello World!", pos=(25,25)) + font = st.GetFont() + font.PointSize += 10 + font = font.Bold() + st.SetFont(font) + + # create a menu bar + self.makeMenuBar() + + # and a status bar + self.CreateStatusBar() + self.SetStatusText("Welcome to wxPython!") + + + def makeMenuBar(self): + """ + A menu bar is composed of menus, which are composed of menu items. + This method builds a set of menus and binds handlers to be called + when the menu item is selected. + """ + + # Make a file menu with Hello and Exit items + fileMenu = wx.Menu() + # The "\t..." syntax defines an accelerator key that also triggers + # the same event + helloItem = fileMenu.Append(-1, "&Hello...\tCtrl-H", + "Help string shown in status bar for this menu item") + fileMenu.AppendSeparator() + # When using a stock ID we don't need to specify the menu item's + # label + exitItem = fileMenu.Append(wx.ID_EXIT) + + # Now a help menu for the about item + helpMenu = wx.Menu() + aboutItem = helpMenu.Append(wx.ID_ABOUT) + + # Make the menu bar and add the two menus to it. The '&' defines + # that the next letter is the "mnemonic" for the menu item. On the + # platforms that support it those letters are underlined and can be + # triggered from the keyboard. + menuBar = wx.MenuBar() + menuBar.Append(fileMenu, "&File") + menuBar.Append(helpMenu, "&Help") + + # Give the menu bar to the frame + self.SetMenuBar(menuBar) + + # Finally, associate a handler function with the EVT_MENU event for + # each of the menu items. That means that when that menu item is + # activated then the associated handler function will be called. + self.Bind(wx.EVT_MENU, self.OnHello, helloItem) + self.Bind(wx.EVT_MENU, self.OnExit, exitItem) + self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem) + + + def OnExit(self, event): + """Close the frame, terminating the application.""" + self.Close(True) + + + def OnHello(self, event): + """Say hello to the user.""" + wx.MessageBox("Hello again from wxPython") + + + def OnAbout(self, event): + """Display an About Dialog""" + wx.MessageBox("This is a wxPython Hello World sample", + "About Hello World 2", + wx.OK|wx.ICON_INFORMATION) + + +if __name__ == '__main__': + # When this module is run (not imported) then create the app, the + # frame, show it, and start the event loop. + app = wx.App() + frm = HelloFrame(None, title='Hello World 2') + frm.Show() + app.MainLoop() +``` + +``` +%run wx_hello_world.py +``` + +## Machine learning +- scikit-learn +- theano/tensorflow/pytorch + - keras + +## [Pycuda](https://documen.tician.de/pycuda/): Programming the GPU +``` +import pycuda.autoinit +import pycuda.driver as drv + +from pycuda.compiler import SourceModule +mod = SourceModule(""" +__global__ void multiply_them(double *dest, double *a, double *b) +{ + const int i = threadIdx.x; + dest[i] = a[i] * b[i]; +} +""") + +multiply_them = mod.get_function("multiply_them") + +a = np.random.randn(400) +b = np.random.randn(400) + +dest = np.zeros_like(a) +multiply_them( + drv.Out(dest), drv.In(a), drv.In(b), + block=(400,1,1), grid=(1,1)) + +print(dest-a*b) +``` + +## Testing +- [unittest](https://docs.python.org/3.6/library/unittest.html): python built-in testing +> ``` +> import unittest +> +> class TestStringMethods(unittest.TestCase): +> +> def test_upper(self): +> self.assertEqual('foo'.upper(), 'FOO') +> +> def test_isupper(self): +> self.assertTrue('FOO'.isupper()) +> self.assertFalse('Foo'.isupper()) +> +> def test_split(self): +> s = 'hello world' +> self.assertEqual(s.split(), ['hello', 'world']) +> # check that s.split fails when the separator is not a string +> with self.assertRaises(TypeError): +> s.split(2) +> +> if __name__ == '__main__': +> unittest.main() +> ``` +- [doctest](https://docs.python.org/3.6/library/doctest.html): checks the example usage in the documentation +> ``` +> def factorial(n): +> """Return the factorial of n, an exact integer >= 0. +> +> >>> [factorial(n) for n in range(6)] +> [1, 1, 2, 6, 24, 120] +> >>> factorial(30) +> 265252859812191058636308480000000 +> >>> factorial(-1) +> Traceback (most recent call last): +> ... +> ValueError: n must be >= 0 +> +> Factorials of floats are OK, but the float must be an exact integer: +> >>> factorial(30.1) +> Traceback (most recent call last): +> ... +> ValueError: n must be exact integer +> >>> factorial(30.0) +> 265252859812191058636308480000000 +> +> It must also not be ridiculously large: +> >>> factorial(1e100) +> Traceback (most recent call last): +> ... +> OverflowError: n too large +> """ +> +> import math +> if not n >= 0: +> raise ValueError("n must be >= 0") +> if math.floor(n) != n: +> raise ValueError("n must be exact integer") +> if n+1 == n: # catch a value like 1e300 +> raise OverflowError("n too large") +> result = 1 +> factor = 2 +> while factor <= n: +> result *= factor +> factor += 1 +> return result +> +> +> if __name__ == "__main__": +> import doctest +> doctest.testmod() +> ``` +Two external packages provide more convenient unit tests: +- [py.test](https://docs.pytest.org/en/latest/) +- [nose2](http://nose2.readthedocs.io/en/latest/usage.html) +> ``` +> # content of test_sample.py +> def inc(x): +> return x + 1 +> +> def test_answer(): +> assert inc(3) == 5 +> ``` + +- [coverage](https://coverage.readthedocs.io/en/coverage-4.5.1/): measures which part of the code is covered by the tests + +## Linters +Linters check the code for any syntax errors, [style errors](https://www.python.org/dev/peps/pep-0008/), unused variables, unreachable code, etc. +- [pylint](https://pypi.python.org/pypi/pylint): most extensive linter +- [pyflake](https://pypi.python.org/pypi/pyflakes): if you think pylint is too strict +- [pep8](https://pypi.python.org/pypi/pep8): just checks for style errors +- [mypy](http://mypy-lang.org/): adding explicit typing to python \ No newline at end of file diff --git a/talks/speed/speed.ipynb b/talks/speed/speed.ipynb new file mode 100644 index 0000000..c8c9cde --- /dev/null +++ b/talks/speed/speed.ipynb @@ -0,0 +1,2060 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Numpy vectorizing" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((nan, nan), (-1.0, 4.0), (0.0, 0.0))" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def root(a, b, c):\n", + " D = b ** 2 - 4 * a * c\n", + " if D < 0:\n", + " return np.nan, np.nan\n", + " x1 = (-b + np.sqrt(D)) / (2 * a)\n", + " x2 = (-b - np.sqrt(D)) / (2 * a)\n", + " return x1, x2\n", + "root(1, 3, 4), root(-1, 3, 4), root(1, 0, 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-19-5d1fed3ed2df>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1e6\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1e6\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mroot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m<ipython-input-18-54b500cd66b1>\u001b[0m in \u001b[0;36mroot\u001b[0;34m(a, b, c)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mroot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mD\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m**\u001b[0m \u001b[0;36m2\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m4\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mD\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnan\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnan\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mx1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mb\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msqrt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mD\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" + ] + } + ], + "source": [ + "a = np.random.randn(int(1e6))\n", + "b = np.random.randn(int(1e6))\n", + "c = np.random.randn(int(1e6))\n", + "root(a, b, c)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 3.64 s, sys: 65.9 ms, total: 3.71 s\n", + "Wall time: 3.71 s\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[-0.55797188, 1.11121928],\n", + " [ nan, nan],\n", + " [ 0.76166857, -1.70637551],\n", + " ...,\n", + " [-0.56859783, 0.98659831],\n", + " [ nan, nan],\n", + " [-0.53531175, 0.18339357]])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "np.array([root(av, bv, cv) for av, bv, cv in zip(a, b, c)])" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "root_vec = np.vectorize(root)\n", + "np.vectorize?" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.85 s, sys: 71.9 ms, total: 1.92 s\n", + "Wall time: 1.92 s\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([-0.55797188, nan, 0.76166857, ..., -0.56859783,\n", + " nan, -0.53531175]),\n", + " array([ 1.11121928, nan, -1.70637551, ..., 0.98659831,\n", + " nan, 0.18339357]))" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "root_vec(a, b, c)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.66 s, sys: 62.7 ms, total: 1.73 s\n", + "Wall time: 1.73 s\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([-1.72246968, -2.63787563, nan, ..., -2.20722406,\n", + " nan, -1.84415698]),\n", + " array([2.27571708, 2.04353033, nan, ..., 2.62522454, nan,\n", + " 1.4922388 ]))" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "root_vec(a, b, 7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Numba" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numba" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "root_jit = numba.jit(root)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.08 µs ± 192 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" + ] + } + ], + "source": [ + "%timeit root(23, 78, 19.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The slowest run took 11.09 times longer than the fastest. This could mean that an intermediate result is being cached.\n", + "786 ns ± 1.08 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit root_jit(23, 78, 19.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "ename": "SystemError", + "evalue": "CPUDispatcher(<function root at 0x114035620>) returned a result with an error set", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mSystemError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<timed eval>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mSystemError\u001b[0m: CPUDispatcher(<function root at 0x114035620>) returned a result with an error set" + ] + } + ], + "source": [ + "%%time\n", + "root_jit(a, b, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 406 ms, sys: 57.2 ms, total: 464 ms\n", + "Wall time: 464 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([-1.72246968, -2.63787563, nan, ..., -2.20722406,\n", + " nan, -1.84415698]),\n", + " array([2.27571708, 2.04353033, nan, ..., 2.62522454, nan,\n", + " 1.4922388 ]))" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "root_jit_vec = np.vectorize(root_jit)\n", + "%time root_jit_vec(a, b, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 391 ms, sys: 58.2 ms, total: 449 ms\n", + "Wall time: 448 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([-1.72246968, -2.63787563, nan, ..., -2.20722406,\n", + " nan, -1.84415698]),\n", + " array([2.27571708, 2.04353033, nan, ..., 2.62522454, nan,\n", + " 1.4922388 ]))" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@np.vectorize\n", + "@numba.jit\n", + "def fast_root(a, b, c):\n", + " D = b ** 2 - 4 * a * c\n", + " if D < 0:\n", + " return np.nan, np.nan\n", + " x1 = (-b + np.sqrt(D)) / (2 * a)\n", + " x2 = (-b - np.sqrt(D)) / (2 * a)\n", + " return x1, x2\n", + "%time fast_root(a, b, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "ename": "NotImplementedError", + "evalue": "(float64 x 2) cannot be represented as a Numpy dtype", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNotImplementedError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<timed eval>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m~/miniconda3/lib/python3.6/site-packages/numba/npyufunc/dufunc.py\u001b[0m in \u001b[0;36m_compile_for_args\u001b[0;34m(self, *args, **kws)\u001b[0m\n\u001b[1;32m 166\u001b[0m \u001b[0margty\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 167\u001b[0m \u001b[0margtys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margty\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 168\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compile_for_argtys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margtys\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 169\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 170\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_compile_for_argtys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margtys\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreturn_type\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/lib/python3.6/site-packages/numba/npyufunc/dufunc.py\u001b[0m in \u001b[0;36m_compile_for_argtys\u001b[0;34m(self, argtys, return_type)\u001b[0m\n\u001b[1;32m 188\u001b[0m cres, argtys, return_type)\n\u001b[1;32m 189\u001b[0m dtypenums, ptr, env = ufuncbuilder._build_element_wise_ufunc_wrapper(\n\u001b[0;32m--> 190\u001b[0;31m cres, actual_sig)\n\u001b[0m\u001b[1;32m 191\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_add_loop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlongint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mptr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtypenums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_keepalive\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mptr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcres\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlibrary\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0menv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/lib/python3.6/site-packages/numba/npyufunc/ufuncbuilder.py\u001b[0m in \u001b[0;36m_build_element_wise_ufunc_wrapper\u001b[0;34m(cres, signature)\u001b[0m\n\u001b[1;32m 163\u001b[0m \u001b[0;31m# Get dtypes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 164\u001b[0m \u001b[0mdtypenums\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mas_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 165\u001b[0;31m \u001b[0mdtypenums\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mas_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msignature\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_type\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 166\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdtypenums\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mptr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0menv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 167\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/lib/python3.6/site-packages/numba/numpy_support.py\u001b[0m in \u001b[0;36mas_dtype\u001b[0;34m(nbtype)\u001b[0m\n\u001b[1;32m 134\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mas_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnbtype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 135\u001b[0m raise NotImplementedError(\"%r cannot be represented as a Numpy dtype\"\n\u001b[0;32m--> 136\u001b[0;31m % (nbtype,))\n\u001b[0m\u001b[1;32m 137\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 138\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNotImplementedError\u001b[0m: (float64 x 2) cannot be represented as a Numpy dtype" + ] + } + ], + "source": [ + "@numba.vectorize\n", + "def fast_root(a, b, c):\n", + " D = b ** 2 - 4 * a * c\n", + " if D < 0:\n", + " return np.nan, np.nan\n", + " x1 = (-b + np.sqrt(D)) / (2 * a)\n", + " x2 = (-b - np.sqrt(D)) / (2 * a)\n", + " return x1, x2\n", + "%time fast_root(a, b, 7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# But run the profiler first" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.56 s, sys: 3.5 ms, total: 1.56 s\n", + "Wall time: 1.56 s\n" + ] + }, + { + "data": { + "text/plain": [ + "5702887" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def fib(n):\n", + " if n <= 1:\n", + " return 1\n", + " else:\n", + " return fib(n-2) + fib(n-1)\n", + "%time fib(33)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 63.4 ms, sys: 1.79 ms, total: 65.2 ms\n", + "Wall time: 64.2 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "5702887" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@numba.jit\n", + "def fib_jit(n):\n", + " if n <= 1:\n", + " return 1\n", + " else:\n", + " return fib_jit(n-2) + fib_jit(n-1)\n", + "%time fib_jit(33)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.28 s, sys: 5.26 ms, total: 1.28 s\n", + "Wall time: 1.28 s\n" + ] + }, + { + "data": { + "text/plain": [ + "267914296" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time fib_jit(41)" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + } + ], + "source": [ + "%prun fib(33)" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + } + ], + "source": [ + "%prun fib_jit(41)" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 20 µs, sys: 1 µs, total: 21 µs\n", + "Wall time: 24.1 µs\n" + ] + } + ], + "source": [ + "from functools import lru_cache\n", + "@lru_cache(None)\n", + "def fib_cache(n):\n", + " if n <= 1:\n", + " return 1\n", + " else:\n", + " return fib_cache(n-2) + fib_cache(n-1)\n", + "%time fib_cache(33)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "lru_cache?" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 261 µs, sys: 1e+03 ns, total: 262 µs\n", + "Wall time: 267 µs\n" + ] + }, + { + "data": { + "text/plain": [ + "225591516161936330872512695036072072046011324913758190588638866418474627738686883405015987052796968498626" + ] + }, + "execution_count": 111, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time fib_cache(500)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Optimizing numpy algebra" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Multiplying/adding arrays incurs a lot of overhead, because lots of intermediate arrays get created and discarded again" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "139 ms ± 1.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "a = np.random.randn(int(1e7))\n", + "b = np.random.randn(int(1e7))\n", + "%timeit a * b + 4.1 * a < 3 * b" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "11.4 ms ± 484 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "import numexpr as ne\n", + "%timeit ne.evaluate('a * b + 4.1 * a < 3 * b')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Efficiency gain reduces once the operations become more complex" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "141 ms ± 1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%timeit a * np.sqrt(abs(b)) < 3 * b" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "12.6 ms ± 986 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "%timeit ne.evaluate('a * sqrt(abs(b)) < 3 * b')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Cython" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "http://docs.cython.org/en/latest/\n", + "\n", + "Compiles most python programs to C code for extra speed (but less introspection). Also allows direct calling of C library code.\n", + "\n", + "Can include python classes and much more." + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The cython extension is already loaded. To reload it, use:\n", + " %reload_ext cython\n" + ] + } + ], + "source": [ + "%load_ext cython" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]\n", + "CPU times: user 67.4 ms, sys: 1.22 ms, total: 68.6 ms\n", + "Wall time: 68 ms\n" + ] + } + ], + "source": [ + "def primes(kmax):\n", + " p = {}\n", + " result = []\n", + " if kmax > 1000:\n", + " kmax = 1000\n", + " k = 0\n", + " n = 2\n", + " while k < kmax:\n", + " i = 0\n", + " while i < k and n % p[i] != 0:\n", + " i = i + 1\n", + " if i == k:\n", + " p[k] = n\n", + " k = k + 1\n", + " result.append(n)\n", + " n = n + 1\n", + " return result" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<!DOCTYPE html>\n", + "<!-- Generated by Cython 0.26 -->\n", + "<html>\n", + "<head>\n", + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n", + " <title>Cython: _cython_magic_52e640a266384bf0478136fe7ab4a75d.pyx</title>\n", + " <style type=\"text/css\">\n", + " \n", + "body.cython { font-family: courier; font-size: 12; }\n", + "\n", + ".cython.tag { }\n", + ".cython.line { margin: 0em }\n", + ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n", + "\n", + ".cython.line .run { background-color: #B0FFB0; }\n", + ".cython.line .mis { background-color: #FFB0B0; }\n", + ".cython.code.run { border-left: 8px solid #B0FFB0; }\n", + ".cython.code.mis { border-left: 8px solid #FFB0B0; }\n", + "\n", + ".cython.code .py_c_api { color: red; }\n", + ".cython.code .py_macro_api { color: #FF7000; }\n", + ".cython.code .pyx_c_api { color: #FF3000; }\n", + ".cython.code .pyx_macro_api { color: #FF7000; }\n", + ".cython.code .refnanny { color: #FFA000; }\n", + ".cython.code .trace { color: #FFA000; }\n", + ".cython.code .error_goto { color: #FFA000; }\n", + "\n", + ".cython.code .coerce { color: #008000; border: 1px dotted #008000 }\n", + ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n", + ".cython.code .c_attr { color: #0000FF; }\n", + ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n", + ".cython.code .c_call { color: #0000FF; }\n", + "\n", + ".cython.score-0 {background-color: #FFFFff;}\n", + ".cython.score-1 {background-color: #FFFFe7;}\n", + ".cython.score-2 {background-color: #FFFFd4;}\n", + ".cython.score-3 {background-color: #FFFFc4;}\n", + ".cython.score-4 {background-color: #FFFFb6;}\n", + ".cython.score-5 {background-color: #FFFFaa;}\n", + ".cython.score-6 {background-color: #FFFF9f;}\n", + ".cython.score-7 {background-color: #FFFF96;}\n", + ".cython.score-8 {background-color: #FFFF8d;}\n", + ".cython.score-9 {background-color: #FFFF86;}\n", + ".cython.score-10 {background-color: #FFFF7f;}\n", + ".cython.score-11 {background-color: #FFFF79;}\n", + ".cython.score-12 {background-color: #FFFF73;}\n", + ".cython.score-13 {background-color: #FFFF6e;}\n", + ".cython.score-14 {background-color: #FFFF6a;}\n", + ".cython.score-15 {background-color: #FFFF66;}\n", + ".cython.score-16 {background-color: #FFFF62;}\n", + ".cython.score-17 {background-color: #FFFF5e;}\n", + ".cython.score-18 {background-color: #FFFF5b;}\n", + ".cython.score-19 {background-color: #FFFF57;}\n", + ".cython.score-20 {background-color: #FFFF55;}\n", + ".cython.score-21 {background-color: #FFFF52;}\n", + ".cython.score-22 {background-color: #FFFF4f;}\n", + ".cython.score-23 {background-color: #FFFF4d;}\n", + ".cython.score-24 {background-color: #FFFF4b;}\n", + ".cython.score-25 {background-color: #FFFF48;}\n", + ".cython.score-26 {background-color: #FFFF46;}\n", + ".cython.score-27 {background-color: #FFFF44;}\n", + ".cython.score-28 {background-color: #FFFF43;}\n", + ".cython.score-29 {background-color: #FFFF41;}\n", + ".cython.score-30 {background-color: #FFFF3f;}\n", + ".cython.score-31 {background-color: #FFFF3e;}\n", + ".cython.score-32 {background-color: #FFFF3c;}\n", + ".cython.score-33 {background-color: #FFFF3b;}\n", + ".cython.score-34 {background-color: #FFFF39;}\n", + ".cython.score-35 {background-color: #FFFF38;}\n", + ".cython.score-36 {background-color: #FFFF37;}\n", + ".cython.score-37 {background-color: #FFFF36;}\n", + ".cython.score-38 {background-color: #FFFF35;}\n", + ".cython.score-39 {background-color: #FFFF34;}\n", + ".cython.score-40 {background-color: #FFFF33;}\n", + ".cython.score-41 {background-color: #FFFF32;}\n", + ".cython.score-42 {background-color: #FFFF31;}\n", + ".cython.score-43 {background-color: #FFFF30;}\n", + ".cython.score-44 {background-color: #FFFF2f;}\n", + ".cython.score-45 {background-color: #FFFF2e;}\n", + ".cython.score-46 {background-color: #FFFF2d;}\n", + ".cython.score-47 {background-color: #FFFF2c;}\n", + ".cython.score-48 {background-color: #FFFF2b;}\n", + ".cython.score-49 {background-color: #FFFF2b;}\n", + ".cython.score-50 {background-color: #FFFF2a;}\n", + ".cython.score-51 {background-color: #FFFF29;}\n", + ".cython.score-52 {background-color: #FFFF29;}\n", + ".cython.score-53 {background-color: #FFFF28;}\n", + ".cython.score-54 {background-color: #FFFF27;}\n", + ".cython.score-55 {background-color: #FFFF27;}\n", + ".cython.score-56 {background-color: #FFFF26;}\n", + ".cython.score-57 {background-color: #FFFF26;}\n", + ".cython.score-58 {background-color: #FFFF25;}\n", + ".cython.score-59 {background-color: #FFFF24;}\n", + ".cython.score-60 {background-color: #FFFF24;}\n", + ".cython.score-61 {background-color: #FFFF23;}\n", + ".cython.score-62 {background-color: #FFFF23;}\n", + ".cython.score-63 {background-color: #FFFF22;}\n", + ".cython.score-64 {background-color: #FFFF22;}\n", + ".cython.score-65 {background-color: #FFFF22;}\n", + ".cython.score-66 {background-color: #FFFF21;}\n", + ".cython.score-67 {background-color: #FFFF21;}\n", + ".cython.score-68 {background-color: #FFFF20;}\n", + ".cython.score-69 {background-color: #FFFF20;}\n", + ".cython.score-70 {background-color: #FFFF1f;}\n", + ".cython.score-71 {background-color: #FFFF1f;}\n", + ".cython.score-72 {background-color: #FFFF1f;}\n", + ".cython.score-73 {background-color: #FFFF1e;}\n", + ".cython.score-74 {background-color: #FFFF1e;}\n", + ".cython.score-75 {background-color: #FFFF1e;}\n", + ".cython.score-76 {background-color: #FFFF1d;}\n", + ".cython.score-77 {background-color: #FFFF1d;}\n", + ".cython.score-78 {background-color: #FFFF1c;}\n", + ".cython.score-79 {background-color: #FFFF1c;}\n", + ".cython.score-80 {background-color: #FFFF1c;}\n", + ".cython.score-81 {background-color: #FFFF1c;}\n", + ".cython.score-82 {background-color: #FFFF1b;}\n", + ".cython.score-83 {background-color: #FFFF1b;}\n", + ".cython.score-84 {background-color: #FFFF1b;}\n", + ".cython.score-85 {background-color: #FFFF1a;}\n", + ".cython.score-86 {background-color: #FFFF1a;}\n", + ".cython.score-87 {background-color: #FFFF1a;}\n", + ".cython.score-88 {background-color: #FFFF1a;}\n", + ".cython.score-89 {background-color: #FFFF19;}\n", + ".cython.score-90 {background-color: #FFFF19;}\n", + ".cython.score-91 {background-color: #FFFF19;}\n", + ".cython.score-92 {background-color: #FFFF19;}\n", + ".cython.score-93 {background-color: #FFFF18;}\n", + ".cython.score-94 {background-color: #FFFF18;}\n", + ".cython.score-95 {background-color: #FFFF18;}\n", + ".cython.score-96 {background-color: #FFFF18;}\n", + ".cython.score-97 {background-color: #FFFF17;}\n", + ".cython.score-98 {background-color: #FFFF17;}\n", + ".cython.score-99 {background-color: #FFFF17;}\n", + ".cython.score-100 {background-color: #FFFF17;}\n", + ".cython.score-101 {background-color: #FFFF16;}\n", + ".cython.score-102 {background-color: #FFFF16;}\n", + ".cython.score-103 {background-color: #FFFF16;}\n", + ".cython.score-104 {background-color: #FFFF16;}\n", + ".cython.score-105 {background-color: #FFFF16;}\n", + ".cython.score-106 {background-color: #FFFF15;}\n", + ".cython.score-107 {background-color: #FFFF15;}\n", + ".cython.score-108 {background-color: #FFFF15;}\n", + ".cython.score-109 {background-color: #FFFF15;}\n", + ".cython.score-110 {background-color: #FFFF15;}\n", + ".cython.score-111 {background-color: #FFFF15;}\n", + ".cython.score-112 {background-color: #FFFF14;}\n", + ".cython.score-113 {background-color: #FFFF14;}\n", + ".cython.score-114 {background-color: #FFFF14;}\n", + ".cython.score-115 {background-color: #FFFF14;}\n", + ".cython.score-116 {background-color: #FFFF14;}\n", + ".cython.score-117 {background-color: #FFFF14;}\n", + ".cython.score-118 {background-color: #FFFF13;}\n", + ".cython.score-119 {background-color: #FFFF13;}\n", + ".cython.score-120 {background-color: #FFFF13;}\n", + ".cython.score-121 {background-color: #FFFF13;}\n", + ".cython.score-122 {background-color: #FFFF13;}\n", + ".cython.score-123 {background-color: #FFFF13;}\n", + ".cython.score-124 {background-color: #FFFF13;}\n", + ".cython.score-125 {background-color: #FFFF12;}\n", + ".cython.score-126 {background-color: #FFFF12;}\n", + ".cython.score-127 {background-color: #FFFF12;}\n", + ".cython.score-128 {background-color: #FFFF12;}\n", + ".cython.score-129 {background-color: #FFFF12;}\n", + ".cython.score-130 {background-color: #FFFF12;}\n", + ".cython.score-131 {background-color: #FFFF12;}\n", + ".cython.score-132 {background-color: #FFFF11;}\n", + ".cython.score-133 {background-color: #FFFF11;}\n", + ".cython.score-134 {background-color: #FFFF11;}\n", + ".cython.score-135 {background-color: #FFFF11;}\n", + ".cython.score-136 {background-color: #FFFF11;}\n", + ".cython.score-137 {background-color: #FFFF11;}\n", + ".cython.score-138 {background-color: #FFFF11;}\n", + ".cython.score-139 {background-color: #FFFF11;}\n", + ".cython.score-140 {background-color: #FFFF11;}\n", + ".cython.score-141 {background-color: #FFFF10;}\n", + ".cython.score-142 {background-color: #FFFF10;}\n", + ".cython.score-143 {background-color: #FFFF10;}\n", + ".cython.score-144 {background-color: #FFFF10;}\n", + ".cython.score-145 {background-color: #FFFF10;}\n", + ".cython.score-146 {background-color: #FFFF10;}\n", + ".cython.score-147 {background-color: #FFFF10;}\n", + ".cython.score-148 {background-color: #FFFF10;}\n", + ".cython.score-149 {background-color: #FFFF10;}\n", + ".cython.score-150 {background-color: #FFFF0f;}\n", + ".cython.score-151 {background-color: #FFFF0f;}\n", + ".cython.score-152 {background-color: #FFFF0f;}\n", + ".cython.score-153 {background-color: #FFFF0f;}\n", + ".cython.score-154 {background-color: #FFFF0f;}\n", + ".cython.score-155 {background-color: #FFFF0f;}\n", + ".cython.score-156 {background-color: #FFFF0f;}\n", + ".cython.score-157 {background-color: #FFFF0f;}\n", + ".cython.score-158 {background-color: #FFFF0f;}\n", + ".cython.score-159 {background-color: #FFFF0f;}\n", + ".cython.score-160 {background-color: #FFFF0f;}\n", + ".cython.score-161 {background-color: #FFFF0e;}\n", + ".cython.score-162 {background-color: #FFFF0e;}\n", + ".cython.score-163 {background-color: #FFFF0e;}\n", + ".cython.score-164 {background-color: #FFFF0e;}\n", + ".cython.score-165 {background-color: #FFFF0e;}\n", + ".cython.score-166 {background-color: #FFFF0e;}\n", + ".cython.score-167 {background-color: #FFFF0e;}\n", + ".cython.score-168 {background-color: #FFFF0e;}\n", + ".cython.score-169 {background-color: #FFFF0e;}\n", + ".cython.score-170 {background-color: #FFFF0e;}\n", + ".cython.score-171 {background-color: #FFFF0e;}\n", + ".cython.score-172 {background-color: #FFFF0e;}\n", + ".cython.score-173 {background-color: #FFFF0d;}\n", + ".cython.score-174 {background-color: #FFFF0d;}\n", + ".cython.score-175 {background-color: #FFFF0d;}\n", + ".cython.score-176 {background-color: #FFFF0d;}\n", + ".cython.score-177 {background-color: #FFFF0d;}\n", + ".cython.score-178 {background-color: #FFFF0d;}\n", + ".cython.score-179 {background-color: #FFFF0d;}\n", + ".cython.score-180 {background-color: #FFFF0d;}\n", + ".cython.score-181 {background-color: #FFFF0d;}\n", + ".cython.score-182 {background-color: #FFFF0d;}\n", + ".cython.score-183 {background-color: #FFFF0d;}\n", + ".cython.score-184 {background-color: #FFFF0d;}\n", + ".cython.score-185 {background-color: #FFFF0d;}\n", + ".cython.score-186 {background-color: #FFFF0d;}\n", + ".cython.score-187 {background-color: #FFFF0c;}\n", + ".cython.score-188 {background-color: #FFFF0c;}\n", + ".cython.score-189 {background-color: #FFFF0c;}\n", + ".cython.score-190 {background-color: #FFFF0c;}\n", + ".cython.score-191 {background-color: #FFFF0c;}\n", + ".cython.score-192 {background-color: #FFFF0c;}\n", + ".cython.score-193 {background-color: #FFFF0c;}\n", + ".cython.score-194 {background-color: #FFFF0c;}\n", + ".cython.score-195 {background-color: #FFFF0c;}\n", + ".cython.score-196 {background-color: #FFFF0c;}\n", + ".cython.score-197 {background-color: #FFFF0c;}\n", + ".cython.score-198 {background-color: #FFFF0c;}\n", + ".cython.score-199 {background-color: #FFFF0c;}\n", + ".cython.score-200 {background-color: #FFFF0c;}\n", + ".cython.score-201 {background-color: #FFFF0c;}\n", + ".cython.score-202 {background-color: #FFFF0c;}\n", + ".cython.score-203 {background-color: #FFFF0b;}\n", + ".cython.score-204 {background-color: #FFFF0b;}\n", + ".cython.score-205 {background-color: #FFFF0b;}\n", + ".cython.score-206 {background-color: #FFFF0b;}\n", + ".cython.score-207 {background-color: #FFFF0b;}\n", + ".cython.score-208 {background-color: #FFFF0b;}\n", + ".cython.score-209 {background-color: #FFFF0b;}\n", + ".cython.score-210 {background-color: #FFFF0b;}\n", + ".cython.score-211 {background-color: #FFFF0b;}\n", + ".cython.score-212 {background-color: #FFFF0b;}\n", + ".cython.score-213 {background-color: #FFFF0b;}\n", + ".cython.score-214 {background-color: #FFFF0b;}\n", + ".cython.score-215 {background-color: #FFFF0b;}\n", + ".cython.score-216 {background-color: #FFFF0b;}\n", + ".cython.score-217 {background-color: #FFFF0b;}\n", + ".cython.score-218 {background-color: #FFFF0b;}\n", + ".cython.score-219 {background-color: #FFFF0b;}\n", + ".cython.score-220 {background-color: #FFFF0b;}\n", + ".cython.score-221 {background-color: #FFFF0b;}\n", + ".cython.score-222 {background-color: #FFFF0a;}\n", + ".cython.score-223 {background-color: #FFFF0a;}\n", + ".cython.score-224 {background-color: #FFFF0a;}\n", + ".cython.score-225 {background-color: #FFFF0a;}\n", + ".cython.score-226 {background-color: #FFFF0a;}\n", + ".cython.score-227 {background-color: #FFFF0a;}\n", + ".cython.score-228 {background-color: #FFFF0a;}\n", + ".cython.score-229 {background-color: #FFFF0a;}\n", + ".cython.score-230 {background-color: #FFFF0a;}\n", + ".cython.score-231 {background-color: #FFFF0a;}\n", + ".cython.score-232 {background-color: #FFFF0a;}\n", + ".cython.score-233 {background-color: #FFFF0a;}\n", + ".cython.score-234 {background-color: #FFFF0a;}\n", + ".cython.score-235 {background-color: #FFFF0a;}\n", + ".cython.score-236 {background-color: #FFFF0a;}\n", + ".cython.score-237 {background-color: #FFFF0a;}\n", + ".cython.score-238 {background-color: #FFFF0a;}\n", + ".cython.score-239 {background-color: #FFFF0a;}\n", + ".cython.score-240 {background-color: #FFFF0a;}\n", + ".cython.score-241 {background-color: #FFFF0a;}\n", + ".cython.score-242 {background-color: #FFFF0a;}\n", + ".cython.score-243 {background-color: #FFFF0a;}\n", + ".cython.score-244 {background-color: #FFFF0a;}\n", + ".cython.score-245 {background-color: #FFFF0a;}\n", + ".cython.score-246 {background-color: #FFFF09;}\n", + ".cython.score-247 {background-color: #FFFF09;}\n", + ".cython.score-248 {background-color: #FFFF09;}\n", + ".cython.score-249 {background-color: #FFFF09;}\n", + ".cython.score-250 {background-color: #FFFF09;}\n", + ".cython.score-251 {background-color: #FFFF09;}\n", + ".cython.score-252 {background-color: #FFFF09;}\n", + ".cython.score-253 {background-color: #FFFF09;}\n", + ".cython.score-254 {background-color: #FFFF09;}\n", + ".cython .hll { background-color: #ffffcc }\n", + ".cython { background: #f8f8f8; }\n", + ".cython .c { color: #408080; font-style: italic } /* Comment */\n", + ".cython .err { border: 1px solid #FF0000 } /* Error */\n", + ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n", + ".cython .o { color: #666666 } /* Operator */\n", + ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n", + ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n", + ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n", + ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n", + ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n", + ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n", + ".cython .gd { color: #A00000 } /* Generic.Deleted */\n", + ".cython .ge { font-style: italic } /* Generic.Emph */\n", + ".cython .gr { color: #FF0000 } /* Generic.Error */\n", + ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n", + ".cython .gi { color: #00A000 } /* Generic.Inserted */\n", + ".cython .go { color: #888888 } /* Generic.Output */\n", + ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n", + ".cython .gs { font-weight: bold } /* Generic.Strong */\n", + ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n", + ".cython .gt { color: #0044DD } /* Generic.Traceback */\n", + ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n", + ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n", + ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n", + ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n", + ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n", + ".cython .kt { color: #B00040 } /* Keyword.Type */\n", + ".cython .m { color: #666666 } /* Literal.Number */\n", + ".cython .s { color: #BA2121 } /* Literal.String */\n", + ".cython .na { color: #7D9029 } /* Name.Attribute */\n", + ".cython .nb { color: #008000 } /* Name.Builtin */\n", + ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n", + ".cython .no { color: #880000 } /* Name.Constant */\n", + ".cython .nd { color: #AA22FF } /* Name.Decorator */\n", + ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n", + ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n", + ".cython .nf { color: #0000FF } /* Name.Function */\n", + ".cython .nl { color: #A0A000 } /* Name.Label */\n", + ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n", + ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n", + ".cython .nv { color: #19177C } /* Name.Variable */\n", + ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n", + ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n", + ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n", + ".cython .mf { color: #666666 } /* Literal.Number.Float */\n", + ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n", + ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n", + ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n", + ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n", + ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n", + ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n", + ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n", + ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n", + ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n", + ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n", + ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n", + ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n", + ".cython .sx { color: #008000 } /* Literal.String.Other */\n", + ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n", + ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n", + ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n", + ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n", + ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n", + ".cython .vc { color: #19177C } /* Name.Variable.Class */\n", + ".cython .vg { color: #19177C } /* Name.Variable.Global */\n", + ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n", + ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n", + ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n", + " </style>\n", + " <script>\n", + " function toggleDiv(id) {\n", + " theDiv = id.nextElementSibling\n", + " if (theDiv.style.display != 'block') theDiv.style.display = 'block';\n", + " else theDiv.style.display = 'none';\n", + " }\n", + " </script>\n", + "</head>\n", + "<body class=\"cython\">\n", + "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.26</span></p>\n", + "<p>\n", + " <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n", + " Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n", + "</p>\n", + "<div class=\"cython\"><pre class=\"cython line score-24\" onclick='toggleDiv(this)'>+<span class=\"\">01</span>: <span class=\"k\">def</span> <span class=\"nf\">cprimes</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">kmax</span><span class=\"p\">):</span></pre>\n", + "<pre class='cython code score-24 '>/* Python wrapper */\n", + "static PyObject *__pyx_pw_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_1cprimes(PyObject *__pyx_self, PyObject *__pyx_arg_kmax); /*proto*/\n", + "static PyMethodDef __pyx_mdef_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_1cprimes = {\"cprimes\", (PyCFunction)__pyx_pw_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_1cprimes, METH_O, 0};\n", + "static PyObject *__pyx_pw_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_1cprimes(PyObject *__pyx_self, PyObject *__pyx_arg_kmax) {\n", + " int __pyx_v_kmax;\n", + " PyObject *__pyx_r = 0;\n", + " <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n", + " <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"cprimes (wrapper)\", 0);\n", + " assert(__pyx_arg_kmax); {\n", + " __pyx_v_kmax = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_arg_kmax); if (unlikely((__pyx_v_kmax == (int)-1) && <span class='py_c_api'>PyErr_Occurred</span>())) __PYX_ERR(0, 1, __pyx_L3_error)\n", + " }\n", + " goto __pyx_L4_argument_unpacking_done;\n", + " __pyx_L3_error:;\n", + " <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_52e640a266384bf0478136fe7ab4a75d.cprimes\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", + " <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n", + " return NULL;\n", + " __pyx_L4_argument_unpacking_done:;\n", + " __pyx_r = __pyx_pf_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_cprimes(__pyx_self, ((int)__pyx_v_kmax));\n", + "\n", + " /* function exit code */\n", + " <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n", + " return __pyx_r;\n", + "}\n", + "\n", + "static PyObject *__pyx_pf_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_cprimes(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_kmax) {\n", + " int __pyx_v_p[0x3E8];\n", + " PyObject *__pyx_v_result = NULL;\n", + " int __pyx_v_k;\n", + " int __pyx_v_n;\n", + " int __pyx_v_i;\n", + " PyObject *__pyx_r = NULL;\n", + " <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n", + " <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"cprimes\", 0);\n", + "/* … */\n", + " /* function exit code */\n", + " __pyx_L1_error:;\n", + " <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n", + " <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_52e640a266384bf0478136fe7ab4a75d.cprimes\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", + " __pyx_r = NULL;\n", + " __pyx_L0:;\n", + " <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_result);\n", + " <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n", + " <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n", + " return __pyx_r;\n", + "}\n", + "/* … */\n", + " __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(7, __pyx_n_s_kmax, __pyx_n_s_kmax, __pyx_n_s_p, __pyx_n_s_result, __pyx_n_s_k, __pyx_n_s_n, __pyx_n_s_i); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 1, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n", + " <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n", + "/* … */\n", + " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_52e640a266384bf0478136fe7ab4a75d_1cprimes, NULL, __pyx_n_s_cython_magic_52e640a266384bf047); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n", + " if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_cprimes, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n", + " <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n", + "</pre><pre class=\"cython line score-0\"> <span class=\"\">02</span>: <span class=\"k\">cdef</span> <span class=\"kt\">int</span>[1000] <span class=\"nf\">p</span></pre>\n", + "<pre class=\"cython line score-5\" onclick='toggleDiv(this)'>+<span class=\"\">03</span>: <span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"p\">[]</span></pre>\n", + "<pre class='cython code score-5 '> __pyx_t_1 = <span class='py_c_api'>PyList_New</span>(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n", + " __pyx_v_result = ((PyObject*)__pyx_t_1);\n", + " __pyx_t_1 = 0;\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">04</span>: <span class=\"k\">if</span> <span class=\"n\">kmax</span> <span class=\"o\">></span> <span class=\"mf\">1000</span><span class=\"p\">:</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_t_2 = ((__pyx_v_kmax > 0x3E8) != 0);\n", + " if (__pyx_t_2) {\n", + "/* … */\n", + " }\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">05</span>: <span class=\"n\">kmax</span> <span class=\"o\">=</span> <span class=\"mf\">1000</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_kmax = 0x3E8;\n", + "</pre><pre class=\"cython line score-0\"> <span class=\"\">06</span>: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">k</span><span class=\"p\">,</span> <span class=\"nf\">n</span><span class=\"p\">,</span> <span class=\"nf\">i</span></pre>\n", + "<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">07</span>: <span class=\"n\">k</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_k = 0;\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">08</span>: <span class=\"n\">n</span> <span class=\"o\">=</span> <span class=\"mf\">2</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_n = 2;\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">09</span>: <span class=\"k\">while</span> <span class=\"n\">k</span> <span class=\"o\"><</span> <span class=\"n\">kmax</span><span class=\"p\">:</span></pre>\n", + "<pre class='cython code score-0 '> while (1) {\n", + " __pyx_t_2 = ((__pyx_v_k < __pyx_v_kmax) != 0);\n", + " if (!__pyx_t_2) break;\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">10</span>: <span class=\"n\">i</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_i = 0;\n", + "</pre><pre class=\"cython line score-5\" onclick='toggleDiv(this)'>+<span class=\"\">11</span>: <span class=\"k\">while</span> <span class=\"n\">i</span> <span class=\"o\"><</span> <span class=\"n\">k</span> <span class=\"ow\">and</span> <span class=\"n\">n</span> <span class=\"o\">%</span> <span class=\"n\">p</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">!=</span> <span class=\"mf\">0</span><span class=\"p\">:</span></pre>\n", + "<pre class='cython code score-5 '> 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", + " <span class='py_c_api'>PyErr_SetString</span>(PyExc_ZeroDivisionError, \"integer division or modulo by zero\");\n", + " __PYX_ERR(0, 11, __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", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">12</span>: <span class=\"n\">i</span> <span class=\"o\">=</span> <span class=\"n\">i</span> <span class=\"o\">+</span> <span class=\"mf\">1</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_i = (__pyx_v_i + 1);\n", + " }\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">13</span>: <span class=\"k\">if</span> <span class=\"n\">i</span> <span class=\"o\">==</span> <span class=\"n\">k</span><span class=\"p\">:</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_t_2 = ((__pyx_v_i == __pyx_v_k) != 0);\n", + " if (__pyx_t_2) {\n", + "/* … */\n", + " }\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">14</span>: <span class=\"n\">p</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">n</span></pre>\n", + "<pre class='cython code score-0 '> (__pyx_v_p[__pyx_v_k]) = __pyx_v_n;\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">15</span>: <span class=\"n\">k</span> <span class=\"o\">=</span> <span class=\"n\">k</span> <span class=\"o\">+</span> <span class=\"mf\">1</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_k = (__pyx_v_k + 1);\n", + "</pre><pre class=\"cython line score-5\" onclick='toggleDiv(this)'>+<span class=\"\">16</span>: <span class=\"n\">result</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">)</span></pre>\n", + "<pre class='cython code score-5 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_v_n); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n", + " __pyx_t_4 = <span class='pyx_c_api'>__Pyx_PyList_Append</span>(__pyx_v_result, __pyx_t_1); if (unlikely(__pyx_t_4 == -1)) __PYX_ERR(0, 16, __pyx_L1_error)\n", + " <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">17</span>: <span class=\"n\">n</span> <span class=\"o\">=</span> <span class=\"n\">n</span> <span class=\"o\">+</span> <span class=\"mf\">1</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_v_n = (__pyx_v_n + 1);\n", + " }\n", + "</pre><pre class=\"cython line score-2\" onclick='toggleDiv(this)'>+<span class=\"\">18</span>: <span class=\"k\">return</span> <span class=\"n\">result</span></pre>\n", + "<pre class='cython code score-2 '> <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n", + " <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_result);\n", + " __pyx_r = __pyx_v_result;\n", + " goto __pyx_L0;\n", + "</pre></div></body></html>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%cython -a\n", + "def cprimes(int kmax):\n", + " cdef int[1000] p\n", + " result = []\n", + " if kmax > 1000:\n", + " kmax = 1000\n", + " cdef int k, n, i\n", + " k = 0\n", + " n = 2\n", + " while k < kmax:\n", + " i = 0\n", + " while i < k and n % p[i] != 0:\n", + " i = i + 1\n", + " if i == k:\n", + " p[k] = n\n", + " k = k + 1\n", + " result.append(n)\n", + " n = n + 1\n", + " return result" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]\n", + "CPU times: user 2.2 ms, sys: 10 µs, total: 2.21 ms\n", + "Wall time: 2.22 ms\n" + ] + } + ], + "source": [ + "print(cprimes(10))\n", + "%time _ = cprimes(10000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Defining C-style function" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "#%%cython -a\n", + "def fib(n):\n", + " if n <= 1:\n", + " return 1\n", + " else:\n", + " return fib(n-2) + fib(n-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.48 s, sys: 1.79 ms, total: 1.48 s\n", + "Wall time: 1.48 s\n" + ] + }, + { + "data": { + "text/plain": [ + "5702887" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time fib(33)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 27.5 ms, sys: 73 µs, total: 27.5 ms\n", + "Wall time: 27.5 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "5702887" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time fib_jit(33)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<!DOCTYPE html>\n", + "<!-- Generated by Cython 0.26 -->\n", + "<html>\n", + "<head>\n", + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n", + " <title>Cython: _cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b.pyx</title>\n", + " <style type=\"text/css\">\n", + " \n", + "body.cython { font-family: courier; font-size: 12; }\n", + "\n", + ".cython.tag { }\n", + ".cython.line { margin: 0em }\n", + ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n", + "\n", + ".cython.line .run { background-color: #B0FFB0; }\n", + ".cython.line .mis { background-color: #FFB0B0; }\n", + ".cython.code.run { border-left: 8px solid #B0FFB0; }\n", + ".cython.code.mis { border-left: 8px solid #FFB0B0; }\n", + "\n", + ".cython.code .py_c_api { color: red; }\n", + ".cython.code .py_macro_api { color: #FF7000; }\n", + ".cython.code .pyx_c_api { color: #FF3000; }\n", + ".cython.code .pyx_macro_api { color: #FF7000; }\n", + ".cython.code .refnanny { color: #FFA000; }\n", + ".cython.code .trace { color: #FFA000; }\n", + ".cython.code .error_goto { color: #FFA000; }\n", + "\n", + ".cython.code .coerce { color: #008000; border: 1px dotted #008000 }\n", + ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n", + ".cython.code .c_attr { color: #0000FF; }\n", + ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n", + ".cython.code .c_call { color: #0000FF; }\n", + "\n", + ".cython.score-0 {background-color: #FFFFff;}\n", + ".cython.score-1 {background-color: #FFFFe7;}\n", + ".cython.score-2 {background-color: #FFFFd4;}\n", + ".cython.score-3 {background-color: #FFFFc4;}\n", + ".cython.score-4 {background-color: #FFFFb6;}\n", + ".cython.score-5 {background-color: #FFFFaa;}\n", + ".cython.score-6 {background-color: #FFFF9f;}\n", + ".cython.score-7 {background-color: #FFFF96;}\n", + ".cython.score-8 {background-color: #FFFF8d;}\n", + ".cython.score-9 {background-color: #FFFF86;}\n", + ".cython.score-10 {background-color: #FFFF7f;}\n", + ".cython.score-11 {background-color: #FFFF79;}\n", + ".cython.score-12 {background-color: #FFFF73;}\n", + ".cython.score-13 {background-color: #FFFF6e;}\n", + ".cython.score-14 {background-color: #FFFF6a;}\n", + ".cython.score-15 {background-color: #FFFF66;}\n", + ".cython.score-16 {background-color: #FFFF62;}\n", + ".cython.score-17 {background-color: #FFFF5e;}\n", + ".cython.score-18 {background-color: #FFFF5b;}\n", + ".cython.score-19 {background-color: #FFFF57;}\n", + ".cython.score-20 {background-color: #FFFF55;}\n", + ".cython.score-21 {background-color: #FFFF52;}\n", + ".cython.score-22 {background-color: #FFFF4f;}\n", + ".cython.score-23 {background-color: #FFFF4d;}\n", + ".cython.score-24 {background-color: #FFFF4b;}\n", + ".cython.score-25 {background-color: #FFFF48;}\n", + ".cython.score-26 {background-color: #FFFF46;}\n", + ".cython.score-27 {background-color: #FFFF44;}\n", + ".cython.score-28 {background-color: #FFFF43;}\n", + ".cython.score-29 {background-color: #FFFF41;}\n", + ".cython.score-30 {background-color: #FFFF3f;}\n", + ".cython.score-31 {background-color: #FFFF3e;}\n", + ".cython.score-32 {background-color: #FFFF3c;}\n", + ".cython.score-33 {background-color: #FFFF3b;}\n", + ".cython.score-34 {background-color: #FFFF39;}\n", + ".cython.score-35 {background-color: #FFFF38;}\n", + ".cython.score-36 {background-color: #FFFF37;}\n", + ".cython.score-37 {background-color: #FFFF36;}\n", + ".cython.score-38 {background-color: #FFFF35;}\n", + ".cython.score-39 {background-color: #FFFF34;}\n", + ".cython.score-40 {background-color: #FFFF33;}\n", + ".cython.score-41 {background-color: #FFFF32;}\n", + ".cython.score-42 {background-color: #FFFF31;}\n", + ".cython.score-43 {background-color: #FFFF30;}\n", + ".cython.score-44 {background-color: #FFFF2f;}\n", + ".cython.score-45 {background-color: #FFFF2e;}\n", + ".cython.score-46 {background-color: #FFFF2d;}\n", + ".cython.score-47 {background-color: #FFFF2c;}\n", + ".cython.score-48 {background-color: #FFFF2b;}\n", + ".cython.score-49 {background-color: #FFFF2b;}\n", + ".cython.score-50 {background-color: #FFFF2a;}\n", + ".cython.score-51 {background-color: #FFFF29;}\n", + ".cython.score-52 {background-color: #FFFF29;}\n", + ".cython.score-53 {background-color: #FFFF28;}\n", + ".cython.score-54 {background-color: #FFFF27;}\n", + ".cython.score-55 {background-color: #FFFF27;}\n", + ".cython.score-56 {background-color: #FFFF26;}\n", + ".cython.score-57 {background-color: #FFFF26;}\n", + ".cython.score-58 {background-color: #FFFF25;}\n", + ".cython.score-59 {background-color: #FFFF24;}\n", + ".cython.score-60 {background-color: #FFFF24;}\n", + ".cython.score-61 {background-color: #FFFF23;}\n", + ".cython.score-62 {background-color: #FFFF23;}\n", + ".cython.score-63 {background-color: #FFFF22;}\n", + ".cython.score-64 {background-color: #FFFF22;}\n", + ".cython.score-65 {background-color: #FFFF22;}\n", + ".cython.score-66 {background-color: #FFFF21;}\n", + ".cython.score-67 {background-color: #FFFF21;}\n", + ".cython.score-68 {background-color: #FFFF20;}\n", + ".cython.score-69 {background-color: #FFFF20;}\n", + ".cython.score-70 {background-color: #FFFF1f;}\n", + ".cython.score-71 {background-color: #FFFF1f;}\n", + ".cython.score-72 {background-color: #FFFF1f;}\n", + ".cython.score-73 {background-color: #FFFF1e;}\n", + ".cython.score-74 {background-color: #FFFF1e;}\n", + ".cython.score-75 {background-color: #FFFF1e;}\n", + ".cython.score-76 {background-color: #FFFF1d;}\n", + ".cython.score-77 {background-color: #FFFF1d;}\n", + ".cython.score-78 {background-color: #FFFF1c;}\n", + ".cython.score-79 {background-color: #FFFF1c;}\n", + ".cython.score-80 {background-color: #FFFF1c;}\n", + ".cython.score-81 {background-color: #FFFF1c;}\n", + ".cython.score-82 {background-color: #FFFF1b;}\n", + ".cython.score-83 {background-color: #FFFF1b;}\n", + ".cython.score-84 {background-color: #FFFF1b;}\n", + ".cython.score-85 {background-color: #FFFF1a;}\n", + ".cython.score-86 {background-color: #FFFF1a;}\n", + ".cython.score-87 {background-color: #FFFF1a;}\n", + ".cython.score-88 {background-color: #FFFF1a;}\n", + ".cython.score-89 {background-color: #FFFF19;}\n", + ".cython.score-90 {background-color: #FFFF19;}\n", + ".cython.score-91 {background-color: #FFFF19;}\n", + ".cython.score-92 {background-color: #FFFF19;}\n", + ".cython.score-93 {background-color: #FFFF18;}\n", + ".cython.score-94 {background-color: #FFFF18;}\n", + ".cython.score-95 {background-color: #FFFF18;}\n", + ".cython.score-96 {background-color: #FFFF18;}\n", + ".cython.score-97 {background-color: #FFFF17;}\n", + ".cython.score-98 {background-color: #FFFF17;}\n", + ".cython.score-99 {background-color: #FFFF17;}\n", + ".cython.score-100 {background-color: #FFFF17;}\n", + ".cython.score-101 {background-color: #FFFF16;}\n", + ".cython.score-102 {background-color: #FFFF16;}\n", + ".cython.score-103 {background-color: #FFFF16;}\n", + ".cython.score-104 {background-color: #FFFF16;}\n", + ".cython.score-105 {background-color: #FFFF16;}\n", + ".cython.score-106 {background-color: #FFFF15;}\n", + ".cython.score-107 {background-color: #FFFF15;}\n", + ".cython.score-108 {background-color: #FFFF15;}\n", + ".cython.score-109 {background-color: #FFFF15;}\n", + ".cython.score-110 {background-color: #FFFF15;}\n", + ".cython.score-111 {background-color: #FFFF15;}\n", + ".cython.score-112 {background-color: #FFFF14;}\n", + ".cython.score-113 {background-color: #FFFF14;}\n", + ".cython.score-114 {background-color: #FFFF14;}\n", + ".cython.score-115 {background-color: #FFFF14;}\n", + ".cython.score-116 {background-color: #FFFF14;}\n", + ".cython.score-117 {background-color: #FFFF14;}\n", + ".cython.score-118 {background-color: #FFFF13;}\n", + ".cython.score-119 {background-color: #FFFF13;}\n", + ".cython.score-120 {background-color: #FFFF13;}\n", + ".cython.score-121 {background-color: #FFFF13;}\n", + ".cython.score-122 {background-color: #FFFF13;}\n", + ".cython.score-123 {background-color: #FFFF13;}\n", + ".cython.score-124 {background-color: #FFFF13;}\n", + ".cython.score-125 {background-color: #FFFF12;}\n", + ".cython.score-126 {background-color: #FFFF12;}\n", + ".cython.score-127 {background-color: #FFFF12;}\n", + ".cython.score-128 {background-color: #FFFF12;}\n", + ".cython.score-129 {background-color: #FFFF12;}\n", + ".cython.score-130 {background-color: #FFFF12;}\n", + ".cython.score-131 {background-color: #FFFF12;}\n", + ".cython.score-132 {background-color: #FFFF11;}\n", + ".cython.score-133 {background-color: #FFFF11;}\n", + ".cython.score-134 {background-color: #FFFF11;}\n", + ".cython.score-135 {background-color: #FFFF11;}\n", + ".cython.score-136 {background-color: #FFFF11;}\n", + ".cython.score-137 {background-color: #FFFF11;}\n", + ".cython.score-138 {background-color: #FFFF11;}\n", + ".cython.score-139 {background-color: #FFFF11;}\n", + ".cython.score-140 {background-color: #FFFF11;}\n", + ".cython.score-141 {background-color: #FFFF10;}\n", + ".cython.score-142 {background-color: #FFFF10;}\n", + ".cython.score-143 {background-color: #FFFF10;}\n", + ".cython.score-144 {background-color: #FFFF10;}\n", + ".cython.score-145 {background-color: #FFFF10;}\n", + ".cython.score-146 {background-color: #FFFF10;}\n", + ".cython.score-147 {background-color: #FFFF10;}\n", + ".cython.score-148 {background-color: #FFFF10;}\n", + ".cython.score-149 {background-color: #FFFF10;}\n", + ".cython.score-150 {background-color: #FFFF0f;}\n", + ".cython.score-151 {background-color: #FFFF0f;}\n", + ".cython.score-152 {background-color: #FFFF0f;}\n", + ".cython.score-153 {background-color: #FFFF0f;}\n", + ".cython.score-154 {background-color: #FFFF0f;}\n", + ".cython.score-155 {background-color: #FFFF0f;}\n", + ".cython.score-156 {background-color: #FFFF0f;}\n", + ".cython.score-157 {background-color: #FFFF0f;}\n", + ".cython.score-158 {background-color: #FFFF0f;}\n", + ".cython.score-159 {background-color: #FFFF0f;}\n", + ".cython.score-160 {background-color: #FFFF0f;}\n", + ".cython.score-161 {background-color: #FFFF0e;}\n", + ".cython.score-162 {background-color: #FFFF0e;}\n", + ".cython.score-163 {background-color: #FFFF0e;}\n", + ".cython.score-164 {background-color: #FFFF0e;}\n", + ".cython.score-165 {background-color: #FFFF0e;}\n", + ".cython.score-166 {background-color: #FFFF0e;}\n", + ".cython.score-167 {background-color: #FFFF0e;}\n", + ".cython.score-168 {background-color: #FFFF0e;}\n", + ".cython.score-169 {background-color: #FFFF0e;}\n", + ".cython.score-170 {background-color: #FFFF0e;}\n", + ".cython.score-171 {background-color: #FFFF0e;}\n", + ".cython.score-172 {background-color: #FFFF0e;}\n", + ".cython.score-173 {background-color: #FFFF0d;}\n", + ".cython.score-174 {background-color: #FFFF0d;}\n", + ".cython.score-175 {background-color: #FFFF0d;}\n", + ".cython.score-176 {background-color: #FFFF0d;}\n", + ".cython.score-177 {background-color: #FFFF0d;}\n", + ".cython.score-178 {background-color: #FFFF0d;}\n", + ".cython.score-179 {background-color: #FFFF0d;}\n", + ".cython.score-180 {background-color: #FFFF0d;}\n", + ".cython.score-181 {background-color: #FFFF0d;}\n", + ".cython.score-182 {background-color: #FFFF0d;}\n", + ".cython.score-183 {background-color: #FFFF0d;}\n", + ".cython.score-184 {background-color: #FFFF0d;}\n", + ".cython.score-185 {background-color: #FFFF0d;}\n", + ".cython.score-186 {background-color: #FFFF0d;}\n", + ".cython.score-187 {background-color: #FFFF0c;}\n", + ".cython.score-188 {background-color: #FFFF0c;}\n", + ".cython.score-189 {background-color: #FFFF0c;}\n", + ".cython.score-190 {background-color: #FFFF0c;}\n", + ".cython.score-191 {background-color: #FFFF0c;}\n", + ".cython.score-192 {background-color: #FFFF0c;}\n", + ".cython.score-193 {background-color: #FFFF0c;}\n", + ".cython.score-194 {background-color: #FFFF0c;}\n", + ".cython.score-195 {background-color: #FFFF0c;}\n", + ".cython.score-196 {background-color: #FFFF0c;}\n", + ".cython.score-197 {background-color: #FFFF0c;}\n", + ".cython.score-198 {background-color: #FFFF0c;}\n", + ".cython.score-199 {background-color: #FFFF0c;}\n", + ".cython.score-200 {background-color: #FFFF0c;}\n", + ".cython.score-201 {background-color: #FFFF0c;}\n", + ".cython.score-202 {background-color: #FFFF0c;}\n", + ".cython.score-203 {background-color: #FFFF0b;}\n", + ".cython.score-204 {background-color: #FFFF0b;}\n", + ".cython.score-205 {background-color: #FFFF0b;}\n", + ".cython.score-206 {background-color: #FFFF0b;}\n", + ".cython.score-207 {background-color: #FFFF0b;}\n", + ".cython.score-208 {background-color: #FFFF0b;}\n", + ".cython.score-209 {background-color: #FFFF0b;}\n", + ".cython.score-210 {background-color: #FFFF0b;}\n", + ".cython.score-211 {background-color: #FFFF0b;}\n", + ".cython.score-212 {background-color: #FFFF0b;}\n", + ".cython.score-213 {background-color: #FFFF0b;}\n", + ".cython.score-214 {background-color: #FFFF0b;}\n", + ".cython.score-215 {background-color: #FFFF0b;}\n", + ".cython.score-216 {background-color: #FFFF0b;}\n", + ".cython.score-217 {background-color: #FFFF0b;}\n", + ".cython.score-218 {background-color: #FFFF0b;}\n", + ".cython.score-219 {background-color: #FFFF0b;}\n", + ".cython.score-220 {background-color: #FFFF0b;}\n", + ".cython.score-221 {background-color: #FFFF0b;}\n", + ".cython.score-222 {background-color: #FFFF0a;}\n", + ".cython.score-223 {background-color: #FFFF0a;}\n", + ".cython.score-224 {background-color: #FFFF0a;}\n", + ".cython.score-225 {background-color: #FFFF0a;}\n", + ".cython.score-226 {background-color: #FFFF0a;}\n", + ".cython.score-227 {background-color: #FFFF0a;}\n", + ".cython.score-228 {background-color: #FFFF0a;}\n", + ".cython.score-229 {background-color: #FFFF0a;}\n", + ".cython.score-230 {background-color: #FFFF0a;}\n", + ".cython.score-231 {background-color: #FFFF0a;}\n", + ".cython.score-232 {background-color: #FFFF0a;}\n", + ".cython.score-233 {background-color: #FFFF0a;}\n", + ".cython.score-234 {background-color: #FFFF0a;}\n", + ".cython.score-235 {background-color: #FFFF0a;}\n", + ".cython.score-236 {background-color: #FFFF0a;}\n", + ".cython.score-237 {background-color: #FFFF0a;}\n", + ".cython.score-238 {background-color: #FFFF0a;}\n", + ".cython.score-239 {background-color: #FFFF0a;}\n", + ".cython.score-240 {background-color: #FFFF0a;}\n", + ".cython.score-241 {background-color: #FFFF0a;}\n", + ".cython.score-242 {background-color: #FFFF0a;}\n", + ".cython.score-243 {background-color: #FFFF0a;}\n", + ".cython.score-244 {background-color: #FFFF0a;}\n", + ".cython.score-245 {background-color: #FFFF0a;}\n", + ".cython.score-246 {background-color: #FFFF09;}\n", + ".cython.score-247 {background-color: #FFFF09;}\n", + ".cython.score-248 {background-color: #FFFF09;}\n", + ".cython.score-249 {background-color: #FFFF09;}\n", + ".cython.score-250 {background-color: #FFFF09;}\n", + ".cython.score-251 {background-color: #FFFF09;}\n", + ".cython.score-252 {background-color: #FFFF09;}\n", + ".cython.score-253 {background-color: #FFFF09;}\n", + ".cython.score-254 {background-color: #FFFF09;}\n", + ".cython .hll { background-color: #ffffcc }\n", + ".cython { background: #f8f8f8; }\n", + ".cython .c { color: #408080; font-style: italic } /* Comment */\n", + ".cython .err { border: 1px solid #FF0000 } /* Error */\n", + ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n", + ".cython .o { color: #666666 } /* Operator */\n", + ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n", + ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n", + ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n", + ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n", + ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n", + ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n", + ".cython .gd { color: #A00000 } /* Generic.Deleted */\n", + ".cython .ge { font-style: italic } /* Generic.Emph */\n", + ".cython .gr { color: #FF0000 } /* Generic.Error */\n", + ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n", + ".cython .gi { color: #00A000 } /* Generic.Inserted */\n", + ".cython .go { color: #888888 } /* Generic.Output */\n", + ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n", + ".cython .gs { font-weight: bold } /* Generic.Strong */\n", + ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n", + ".cython .gt { color: #0044DD } /* Generic.Traceback */\n", + ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n", + ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n", + ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n", + ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n", + ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n", + ".cython .kt { color: #B00040 } /* Keyword.Type */\n", + ".cython .m { color: #666666 } /* Literal.Number */\n", + ".cython .s { color: #BA2121 } /* Literal.String */\n", + ".cython .na { color: #7D9029 } /* Name.Attribute */\n", + ".cython .nb { color: #008000 } /* Name.Builtin */\n", + ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n", + ".cython .no { color: #880000 } /* Name.Constant */\n", + ".cython .nd { color: #AA22FF } /* Name.Decorator */\n", + ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n", + ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n", + ".cython .nf { color: #0000FF } /* Name.Function */\n", + ".cython .nl { color: #A0A000 } /* Name.Label */\n", + ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n", + ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n", + ".cython .nv { color: #19177C } /* Name.Variable */\n", + ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n", + ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n", + ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n", + ".cython .mf { color: #666666 } /* Literal.Number.Float */\n", + ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n", + ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n", + ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n", + ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n", + ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n", + ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n", + ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n", + ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n", + ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n", + ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n", + ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n", + ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n", + ".cython .sx { color: #008000 } /* Literal.String.Other */\n", + ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n", + ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n", + ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n", + ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n", + ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n", + ".cython .vc { color: #19177C } /* Name.Variable.Class */\n", + ".cython .vg { color: #19177C } /* Name.Variable.Global */\n", + ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n", + ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n", + ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n", + " </style>\n", + " <script>\n", + " function toggleDiv(id) {\n", + " theDiv = id.nextElementSibling\n", + " if (theDiv.style.display != 'block') theDiv.style.display = 'block';\n", + " else theDiv.style.display = 'none';\n", + " }\n", + " </script>\n", + "</head>\n", + "<body class=\"cython\">\n", + "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.26</span></p>\n", + "<p>\n", + " <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n", + " Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n", + "</p>\n", + "<div class=\"cython\"><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">1</span>: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">cfib</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">n</span><span class=\"p\">)</span> <span class=\"k\">nogil</span><span class=\"p\">:</span></pre>\n", + "<pre class='cython code score-0 '>static int __pyx_f_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_cfib(int __pyx_v_n) {\n", + " int __pyx_r;\n", + "/* … */\n", + " /* function exit code */\n", + " __pyx_L0:;\n", + " return __pyx_r;\n", + "}\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">2</span>: <span class=\"k\">if</span> <span class=\"n\">n</span> <span class=\"o\"><=</span> <span class=\"mf\">1</span><span class=\"p\">:</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_t_1 = ((__pyx_v_n <= 1) != 0);\n", + " if (__pyx_t_1) {\n", + "/* … */\n", + " }\n", + "</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">3</span>: <span class=\"k\">return</span> <span class=\"mf\">1</span></pre>\n", + "<pre class='cython code score-0 '> __pyx_r = 1;\n", + " goto __pyx_L0;\n", + "</pre><pre class=\"cython line score-0\"> <span class=\"\">4</span>: <span class=\"k\">else</span><span class=\"p\">:</span></pre>\n", + "<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">5</span>: <span class=\"k\">return</span> <span class=\"n\">cfib</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"o\">-</span><span class=\"mf\">2</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"n\">cfib</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">)</span></pre>\n", + "<pre class='cython code score-0 '> /*else*/ {\n", + " __pyx_r = (__pyx_f_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_cfib((__pyx_v_n - 2)) + __pyx_f_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_cfib((__pyx_v_n - 1)));\n", + " goto __pyx_L0;\n", + " }\n", + "</pre><pre class=\"cython line score-0\"> <span class=\"\">6</span>: </pre>\n", + "<pre class=\"cython line score-14\" onclick='toggleDiv(this)'>+<span class=\"\">7</span>: <span class=\"k\">def</span> <span class=\"nf\">fib</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n", + "<pre class='cython code score-14 '>/* Python wrapper */\n", + "static PyObject *__pyx_pw_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_1fib(PyObject *__pyx_self, PyObject *__pyx_v_n); /*proto*/\n", + "static PyMethodDef __pyx_mdef_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_1fib = {\"fib\", (PyCFunction)__pyx_pw_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_1fib, METH_O, 0};\n", + "static PyObject *__pyx_pw_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_1fib(PyObject *__pyx_self, PyObject *__pyx_v_n) {\n", + " PyObject *__pyx_r = 0;\n", + " <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n", + " <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"fib (wrapper)\", 0);\n", + " __pyx_r = __pyx_pf_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_fib(__pyx_self, ((PyObject *)__pyx_v_n));\n", + "\n", + " /* function exit code */\n", + " <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n", + " return __pyx_r;\n", + "}\n", + "\n", + "static PyObject *__pyx_pf_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_fib(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_n) {\n", + " PyObject *__pyx_r = NULL;\n", + " <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n", + " <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"fib\", 0);\n", + "/* … */\n", + " /* function exit code */\n", + " __pyx_L1_error:;\n", + " <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n", + " <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b.fib\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n", + " __pyx_r = NULL;\n", + " __pyx_L0:;\n", + " <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n", + " <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n", + " return __pyx_r;\n", + "}\n", + "/* … */\n", + " __pyx_tuple_ = <span class='py_c_api'>PyTuple_Pack</span>(1, __pyx_n_s_n); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 7, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple_);\n", + " <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple_);\n", + "/* … */\n", + " __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_1fib, NULL, __pyx_n_s_cython_magic_ed1fcd3356d03e7c12); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n", + " if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_fib, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error)\n", + " <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n", + "</pre><pre class=\"cython line score-10\" onclick='toggleDiv(this)'>+<span class=\"\">8</span>: <span class=\"k\">return</span> <span class=\"n\">cfib</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">)</span></pre>\n", + "<pre class='cython code score-10 '> <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n", + " __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_v_n); if (unlikely((__pyx_t_1 == (int)-1) && <span class='py_c_api'>PyErr_Occurred</span>())) __PYX_ERR(0, 8, __pyx_L1_error)\n", + " __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_f_46_cython_magic_ed1fcd3356d03e7c12842ade7d34bd4b_cfib(__pyx_t_1)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error)\n", + " <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n", + " __pyx_r = __pyx_t_2;\n", + " __pyx_t_2 = 0;\n", + " goto __pyx_L0;\n", + "</pre></div></body></html>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%cython -a\n", + "cdef int cfib(int n) nogil:\n", + " if n <= 1:\n", + " return 1\n", + " else:\n", + " return cfib(n-2) + cfib(n-1)\n", + "\n", + "def fib(n):\n", + " return cfib(n)" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 10.2 ms, sys: 138 µs, total: 10.4 ms\n", + "Wall time: 10.4 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "5702887" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time fib(33)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cython in production code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def root(a, b, c):\n", + " D = b ** 2 - 4 * a * c\n", + " if D < 0:\n", + " return NAN, NAN\n", + " x1 = (-b + sqrt(D)) / (2 * a)\n", + " x2 = (-b - sqrt(D)) / (2 * a)\n", + " return x1, x2" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 236 ms, sys: 53.7 ms, total: 290 ms\n", + "Wall time: 288 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([-1.72246969, -2.6378758 , nan, ..., -2.20722389,\n", + " nan, -1.84415698]),\n", + " array([2.27571702, 2.04353046, nan, ..., 2.62522459, nan,\n", + " 1.49223876]))" + ] + }, + "execution_count": 68, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time np.vectorize(root)(a, b, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 353 ms, sys: 57.8 ms, total: 411 ms\n", + "Wall time: 410 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([-1.72246968, -2.63787563, nan, ..., -2.20722406,\n", + " nan, -1.84415698]),\n", + " array([2.27571708, 2.04353033, nan, ..., 2.62522454, nan,\n", + " 1.4922388 ]))" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time root_jit_vec(a, b, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%%cython -a\n", + "from libc.math cimport sqrt, NAN\n", + "\n", + "def root(float a, float b, float c):\n", + " cdef float D, x1, x2\n", + " D = b ** 2 - 4 * a * c\n", + " if D < 0:\n", + " return NAN, NAN\n", + " x1 = (-b + sqrt(D)) / (2 * a)\n", + " x2 = (-b - sqrt(D)) / (2 * a)\n", + " return x1, x2\n", + "print(root(1, 3, 4), root(-1, 3, 4), root(1, 0, 0))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cython in production code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "http://docs.cython.org/en/latest/src/tutorial/cython_tutorial.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Steps to optimizing code:\n", + "- Profile where the bottleneck is (%prun)\n", + "- Is there a faster algorithm for the bottleneck?\n", + "- If the bottleneck is vectorized: can we optimize with numexpr?\n", + "- If the internal part of the loop can not be vectorized:\n", + " - numba jit if simple enough otherwise cython\n", + " - the loop itself can be sped up with numpy.vectorize\n", + "- If the bottleneck gets called too often: cache the result\n", + "- If even that fails: pycuda\n", + "- If that is too slow: learn to optimize cuda code or find an easier problem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.2" + }, + "toc": { + "colors": { + "hover_highlight": "#DAA520", + "running_highlight": "#FF0000", + "selected_highlight": "#FFD700" + }, + "moveMenuLeft": true, + "nav_menu": { + "height": "179px", + "width": "252px" + }, + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "threshold": 4, + "toc_cell": false, + "toc_section_display": "block", + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- GitLab