Skip to content

Instantly share code, notes, and snippets.

@ev-br
Created March 9, 2018 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ev-br/d876c35903877efcf8eda5247da99681 to your computer and use it in GitHub Desktop.
Save ev-br/d876c35903877efcf8eda5247da99681 to your computer and use it in GitHub Desktop.
cythonization example
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Spatial evolutionary game simulator\n",
"\n",
"S. Kolotev, A. Malyutin, E. Burovski, S. Krashakov and L. Shchur, *Dynamic fractals in spatial evolutionary games*, Physica A **499**, 142 (2018)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib as mpl\n",
"from matplotlib import animation\n",
"\n",
"%matplotlib notebook"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"('python ', '2.7.13 |Anaconda 4.4.0 (64-bit)| (default, Dec 20 2016, 23:09:15) \\n[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]')\n",
"('numpy', '1.12.1', ', matplotlib', '2.0.2', ', and Cython', '0.25.2')\n"
]
}
],
"source": [
"import sys\n",
"import cython\n",
"\n",
"print(\"python \", sys.version)\n",
"print(\"numpy\", np.__version__, \", matplotlib\", mpl.__version__, \", and Cython\", cython.__version__)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Main update function:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def evolve2(field, b, num_steps=1):\n",
" L = field.shape[0]\n",
" current = np.zeros((L, L), dtype=int)\n",
" scores = np.zeros((L, L), dtype=float)\n",
" \n",
" for step in range(num_steps):\n",
" current = field.copy()\n",
" scores = np.zeros((L, L), dtype=float)\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" scores[x, y] += (1 - field[ix, jy])\n",
" \n",
" if field[x, y] == 1:\n",
" scores[x, y] *= b\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" bestX = x\n",
" bestY = y\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" if (scores[bestX, bestY] < scores[ix, jy]):\n",
" bestX = ix\n",
" bestY = jy\n",
" \n",
" field[x, y] = current[bestX, bestY]\n",
" return field"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Run the simulation and animate"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" this.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" // select the cell after this one\n",
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
" IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"L = 75\n",
"field = np.zeros((L, L), dtype=int)\n",
"field[L//2, L//2] = 1\n",
"\n",
"# draw the initial field\n",
"fig = plt.figure()\n",
"im = plt.imshow(field, animated=True, cmap=plt.get_cmap('Paired'))\n",
"\n",
"# updater function\n",
"def updatefig(*args):\n",
" global field\n",
" field = evolve2(field, 1.81, 1)\n",
" im.set_array(field)\n",
" return im,\n",
"\n",
"# animate!\n",
"anim = animation.FuncAnimation(fig, updatefig, frames=200, interval=50, blit=True)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Timings"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 loop, best of 3: 345 ms per loop\n"
]
}
],
"source": [
"L = 44\n",
"field = np.zeros((L, L), dtype=int)\n",
"field[L//2, L//2] = 1\n",
"\n",
"%timeit evolve2(field, 1.81, 10)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# Enter Cython"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"In class, we started with the original code and did the conversion iteratively, removing yellow lines from the annotated output. Below is only the final result."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%load_ext cython"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!DOCTYPE html>\n",
"<!-- Generated by Cython 0.25.2 -->\n",
"<html>\n",
"<head>\n",
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
" <title>Cython: _cython_magic_4a51e9818ff378ac421ff64c016d5995.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.25.2</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\">&#xA0;<span class=\"\">01</span>: </pre>\n",
"<pre class=\"cython line score-19\" onclick='toggleDiv(this)'>+<span class=\"\">02</span>: <span class=\"k\">import</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">np</span></pre>\n",
"<pre class='cython code score-19 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __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_np, __pyx_t_1) &lt; 0) __PYX_ERR(0, 2, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"/* … */\n",
" __pyx_t_1 = <span class='py_c_api'>PyDict_New</span>(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __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_test, __pyx_t_1) &lt; 0) __PYX_ERR(0, 2, __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\">&#xA0;<span class=\"\">03</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">04</span>: <span class=\"k\">import</span> <span class=\"nn\">cython</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">05</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">06</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">cdivision</span><span class=\"p\">(</span><span class=\"bp\">True</span><span class=\"p\">)</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">07</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">boundscheck</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
"<pre class=\"cython line score-75\" onclick='toggleDiv(this)'>+<span class=\"\">08</span>: <span class=\"k\">def</span> <span class=\"nf\">evolve2_1</span><span class=\"p\">(</span><span class=\"nb\">long</span><span class=\"p\">[:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">field</span><span class=\"p\">,</span> <span class=\"n\">double</span> <span class=\"n\">b</span><span class=\"p\">,</span> <span class=\"nb\">int</span> <span class=\"n\">num_steps</span><span class=\"o\">=</span><span class=\"mf\">1</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-75 '>/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_4a51e9818ff378ac421ff64c016d5995_1evolve2_1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_4a51e9818ff378ac421ff64c016d5995_1evolve2_1 = {\"evolve2_1\", (PyCFunction)__pyx_pw_46_cython_magic_4a51e9818ff378ac421ff64c016d5995_1evolve2_1, METH_VARARGS|METH_KEYWORDS, 0};\n",
"static PyObject *__pyx_pw_46_cython_magic_4a51e9818ff378ac421ff64c016d5995_1evolve2_1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" __Pyx_memviewslice __pyx_v_field = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" double __pyx_v_b;\n",
" int __pyx_v_num_steps;\n",
" PyObject *__pyx_r = 0;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"evolve2_1 (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_field,&amp;__pyx_n_s_b,&amp;__pyx_n_s_num_steps,0};\n",
" PyObject* values[3] = {0,0,0};\n",
" if (unlikely(__pyx_kwds)) {\n",
" Py_ssize_t kw_args;\n",
" const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n",
" switch (pos_args) {\n",
" case 3: values[2] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 2);\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" case 0: break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n",
" switch (pos_args) {\n",
" case 0:\n",
" if (likely((values[0] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_field)) != 0)) kw_args--;\n",
" else goto __pyx_L5_argtuple_error;\n",
" case 1:\n",
" if (likely((values[1] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_b)) != 0)) kw_args--;\n",
" else {\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"evolve2_1\", 0, 2, 3, 1); __PYX_ERR(0, 8, __pyx_L3_error)\n",
" }\n",
" case 2:\n",
" if (kw_args &gt; 0) {\n",
" PyObject* value = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_num_steps);\n",
" if (value) { values[2] = value; kw_args--; }\n",
" }\n",
" }\n",
" if (unlikely(kw_args &gt; 0)) {\n",
" if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"evolve2_1\") &lt; 0)) __PYX_ERR(0, 8, __pyx_L3_error)\n",
" }\n",
" } else {\n",
" switch (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)) {\n",
" case 3: values[2] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 2);\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" }\n",
" __pyx_v_field = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_long</span>(values[0]); if (unlikely(!__pyx_v_field.memview)) __PYX_ERR(0, 8, __pyx_L3_error)\n",
" __pyx_v_b = __pyx_<span class='py_c_api'>PyFloat_AsDouble</span>(values[1]); if (unlikely((__pyx_v_b == (double)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) __PYX_ERR(0, 8, __pyx_L3_error)\n",
" if (values[2]) {\n",
" __pyx_v_num_steps = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(values[2]); if (unlikely((__pyx_v_num_steps == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) __PYX_ERR(0, 8, __pyx_L3_error)\n",
" } else {\n",
" __pyx_v_num_steps = ((int)1);\n",
" }\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"evolve2_1\", 0, 2, 3, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); __PYX_ERR(0, 8, __pyx_L3_error)\n",
" __pyx_L3_error:;\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_4a51e9818ff378ac421ff64c016d5995.evolve2_1\", __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_4a51e9818ff378ac421ff64c016d5995_evolve2_1(__pyx_self, __pyx_v_field, __pyx_v_b, __pyx_v_num_steps);\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_4a51e9818ff378ac421ff64c016d5995_evolve2_1(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_field, double __pyx_v_b, int __pyx_v_num_steps) {\n",
" int __pyx_v_x;\n",
" int __pyx_v_y;\n",
" int __pyx_v_L;\n",
" int __pyx_v_i;\n",
" int __pyx_v_j;\n",
" int __pyx_v_ix;\n",
" int __pyx_v_jy;\n",
" CYTHON_UNUSED int __pyx_v_step;\n",
" __Pyx_memviewslice __pyx_v_scores = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" __Pyx_memviewslice __pyx_v__zeros = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" __Pyx_memviewslice __pyx_v_current = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
" int __pyx_v_bestX;\n",
" int __pyx_v_bestY;\n",
" PyObject *__pyx_r = NULL;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"evolve2_1\", 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_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_5, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_6, 1);\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_4a51e9818ff378ac421ff64c016d5995.evolve2_1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" __pyx_r = NULL;\n",
" __pyx_L0:;\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_scores, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v__zeros, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_current, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_field, 1);\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__14 = <span class='py_c_api'>PyTuple_Pack</span>(16, __pyx_n_s_field, __pyx_n_s_b, __pyx_n_s_num_steps, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_L, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_ix, __pyx_n_s_jy, __pyx_n_s_step, __pyx_n_s_scores, __pyx_n_s_zeros_2, __pyx_n_s_current, __pyx_n_s_bestX, __pyx_n_s_bestY); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__14);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__14);\n",
"/* … */\n",
" __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_4a51e9818ff378ac421ff64c016d5995_1evolve2_1, NULL, __pyx_n_s_cython_magic_4a51e9818ff378ac42); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __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_evolve2_1, __pyx_t_1) &lt; 0) __PYX_ERR(0, 8, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_codeobj__15 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(3, 0, 16, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_br_cache_ipython_cython__c, __pyx_n_s_evolve2_1, 8, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">09</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">10</span>: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">x</span><span class=\"p\">,</span> <span class=\"nf\">y</span><span class=\"p\">,</span> <span class=\"nf\">L</span><span class=\"p\">,</span> <span class=\"nf\">i</span><span class=\"p\">,</span> <span class=\"nf\">j</span><span class=\"p\">,</span> <span class=\"nf\">ix</span><span class=\"p\">,</span> <span class=\"nf\">jy</span><span class=\"p\">,</span> <span class=\"nf\">step</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">11</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">12</span>: <span class=\"n\">L</span> <span class=\"o\">=</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_L = (__pyx_v_field.shape[0]);\n",
"</pre><pre class=\"cython line score-40\" onclick='toggleDiv(this)'>+<span class=\"\">13</span>: <span class=\"k\">cdef</span> <span class=\"kt\">double</span>[<span class=\"p\">:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">scores</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">zeros</span><span class=\"p\">((</span><span class=\"n\">L</span><span class=\"p\">,</span> <span class=\"n\">L</span><span class=\"p\">),</span> <span class=\"n\">dtype</span><span class=\"o\">=</span><span class=\"nb\">float</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-40 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_v_L); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_v_L); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" __pyx_t_4 = <span class='py_c_api'>PyTuple_New</span>(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_1);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0, __pyx_t_1);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_3);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 1, __pyx_t_3);\n",
" __pyx_t_1 = 0;\n",
" __pyx_t_3 = 0;\n",
" __pyx_t_3 = <span class='py_c_api'>PyTuple_New</span>(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_4);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 0, __pyx_t_4);\n",
" __pyx_t_4 = 0;\n",
" __pyx_t_4 = <span class='py_c_api'>PyDict_New</span>(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_t_4, __pyx_n_s_dtype, ((PyObject *)(&amp;PyFloat_Type))) &lt; 0) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_double</span>(__pyx_t_1);\n",
" if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_v_scores = __pyx_t_5;\n",
" __pyx_t_5.memview = NULL;\n",
" __pyx_t_5.data = NULL;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">14</span>: </pre>\n",
"<pre class=\"cython line score-40\" onclick='toggleDiv(this)'>+<span class=\"\">15</span>: <span class=\"k\">cdef</span> <span class=\"kt\">double</span>[<span class=\"p\">:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">_zeros</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">zeros</span><span class=\"p\">((</span><span class=\"n\">L</span><span class=\"p\">,</span> <span class=\"n\">L</span><span class=\"p\">),</span> <span class=\"n\">dtype</span><span class=\"o\">=</span><span class=\"nb\">float</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-40 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_4 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_v_L); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_v_L); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" __pyx_t_2 = <span class='py_c_api'>PyTuple_New</span>(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_1);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_2, 0, __pyx_t_1);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_3);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_2, 1, __pyx_t_3);\n",
" __pyx_t_1 = 0;\n",
" __pyx_t_3 = 0;\n",
" __pyx_t_3 = <span class='py_c_api'>PyTuple_New</span>(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_2);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 0, __pyx_t_2);\n",
" __pyx_t_2 = 0;\n",
" __pyx_t_2 = <span class='py_c_api'>PyDict_New</span>(); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_t_2, __pyx_n_s_dtype, ((PyObject *)(&amp;PyFloat_Type))) &lt; 0) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_4, __pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_double</span>(__pyx_t_1);\n",
" if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 15, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_v__zeros = __pyx_t_5;\n",
" __pyx_t_5.memview = NULL;\n",
" __pyx_t_5.data = NULL;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">16</span>: <span class=\"k\">cdef</span> <span class=\"kt\">long</span>[<span class=\"p\">:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">current</span> <span class=\"o\">=</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_6 = __pyx_memoryview_copy_slice_d_dc_long_c(__pyx_v_field); if (unlikely(!__pyx_t_6.memview)) __PYX_ERR(0, 16, __pyx_L1_error)\n",
" __pyx_v_current = __pyx_t_6;\n",
" __pyx_t_6.memview = NULL;\n",
" __pyx_t_6.data = NULL;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">17</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">18</span>: <span class=\"k\">for</span> <span class=\"n\">step</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">num_steps</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_7 = __pyx_v_num_steps;\n",
" for (__pyx_t_8 = 0; __pyx_t_8 &lt; __pyx_t_7; __pyx_t_8+=1) {\n",
" __pyx_v_step = __pyx_t_8;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">19</span>: <span class=\"n\">current</span> <span class=\"o\">=</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_6 = __pyx_memoryview_copy_slice_d_dc_long_c(__pyx_v_field); if (unlikely(!__pyx_t_6.memview)) __PYX_ERR(0, 19, __pyx_L1_error)\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_v_current, 1);\n",
" __pyx_v_current = __pyx_t_6;\n",
" __pyx_t_6.memview = NULL;\n",
" __pyx_t_6.data = NULL;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">20</span>: <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"o\">...</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">_zeros</span></pre>\n",
"<pre class='cython code score-0 '> if (unlikely(__pyx_memoryview_copy_contents(__pyx_v__zeros, __pyx_v_scores, 2, 2, 0) &lt; 0)) __PYX_ERR(0, 20, __pyx_L1_error)\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">21</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">22</span>: <span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_9 = __pyx_v_L;\n",
" for (__pyx_t_10 = 0; __pyx_t_10 &lt; __pyx_t_9; __pyx_t_10+=1) {\n",
" __pyx_v_x = __pyx_t_10;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">23</span>: <span class=\"k\">for</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_11 = __pyx_v_L;\n",
" for (__pyx_t_12 = 0; __pyx_t_12 &lt; __pyx_t_11; __pyx_t_12+=1) {\n",
" __pyx_v_y = __pyx_t_12;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">24</span>: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_13 = -1L; __pyx_t_13 &lt; 2; __pyx_t_13+=1) {\n",
" __pyx_v_i = __pyx_t_13;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">25</span>: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_14 = -1L; __pyx_t_14 &lt; 2; __pyx_t_14+=1) {\n",
" __pyx_v_j = __pyx_t_14;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">26</span>: <span class=\"n\">ix</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">i</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_ix = ((__pyx_v_x + __pyx_v_i) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">27</span>: <span class=\"n\">jy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">y</span> <span class=\"o\">+</span> <span class=\"n\">j</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_jy = ((__pyx_v_y + __pyx_v_j) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">28</span>: <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">+=</span> <span class=\"p\">(</span><span class=\"mf\">1</span> <span class=\"o\">-</span> <span class=\"n\">field</span><span class=\"p\">[</span><span class=\"n\">ix</span><span class=\"p\">,</span> <span class=\"n\">jy</span><span class=\"p\">])</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_15 = __pyx_v_ix;\n",
" __pyx_t_16 = __pyx_v_jy;\n",
" if (__pyx_t_15 &lt; 0) __pyx_t_15 += __pyx_v_field.shape[0];\n",
" if (__pyx_t_16 &lt; 0) __pyx_t_16 += __pyx_v_field.shape[1];\n",
" __pyx_t_17 = __pyx_v_x;\n",
" __pyx_t_18 = __pyx_v_y;\n",
" if (__pyx_t_17 &lt; 0) __pyx_t_17 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_18 &lt; 0) __pyx_t_18 += __pyx_v_scores.shape[1];\n",
" *((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_17 * __pyx_v_scores.strides[0]) )) + __pyx_t_18)) )) += (1 - (*((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_field.data + __pyx_t_15 * __pyx_v_field.strides[0]) )) + __pyx_t_16)) ))));\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">29</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">30</span>: <span class=\"k\">if</span> <span class=\"n\">field</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"mf\">1</span><span class=\"p\">:</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_19 = __pyx_v_x;\n",
" __pyx_t_20 = __pyx_v_y;\n",
" if (__pyx_t_19 &lt; 0) __pyx_t_19 += __pyx_v_field.shape[0];\n",
" if (__pyx_t_20 &lt; 0) __pyx_t_20 += __pyx_v_field.shape[1];\n",
" __pyx_t_21 = (((*((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_field.data + __pyx_t_19 * __pyx_v_field.strides[0]) )) + __pyx_t_20)) ))) == 1) != 0);\n",
" if (__pyx_t_21) {\n",
"/* … */\n",
" }\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">31</span>: <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">*=</span> <span class=\"n\">b</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_22 = __pyx_v_x;\n",
" __pyx_t_23 = __pyx_v_y;\n",
" if (__pyx_t_22 &lt; 0) __pyx_t_22 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_23 &lt; 0) __pyx_t_23 += __pyx_v_scores.shape[1];\n",
" *((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_22 * __pyx_v_scores.strides[0]) )) + __pyx_t_23)) )) *= __pyx_v_b;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">32</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">33</span>: <span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_9 = __pyx_v_L;\n",
" for (__pyx_t_10 = 0; __pyx_t_10 &lt; __pyx_t_9; __pyx_t_10+=1) {\n",
" __pyx_v_x = __pyx_t_10;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">34</span>: <span class=\"k\">for</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_11 = __pyx_v_L;\n",
" for (__pyx_t_12 = 0; __pyx_t_12 &lt; __pyx_t_11; __pyx_t_12+=1) {\n",
" __pyx_v_y = __pyx_t_12;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">35</span>: <span class=\"n\">bestX</span> <span class=\"o\">=</span> <span class=\"n\">x</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestX = __pyx_v_x;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">36</span>: <span class=\"n\">bestY</span> <span class=\"o\">=</span> <span class=\"n\">y</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestY = __pyx_v_y;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">37</span>: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_13 = -1L; __pyx_t_13 &lt; 2; __pyx_t_13+=1) {\n",
" __pyx_v_i = __pyx_t_13;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">38</span>: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_14 = -1L; __pyx_t_14 &lt; 2; __pyx_t_14+=1) {\n",
" __pyx_v_j = __pyx_t_14;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">39</span>: <span class=\"n\">ix</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">i</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_ix = ((__pyx_v_x + __pyx_v_i) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">40</span>: <span class=\"n\">jy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">y</span> <span class=\"o\">+</span> <span class=\"n\">j</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_jy = ((__pyx_v_y + __pyx_v_j) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">41</span>: <span class=\"k\">if</span> <span class=\"p\">(</span><span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">bestX</span><span class=\"p\">,</span> <span class=\"n\">bestY</span><span class=\"p\">]</span> <span class=\"o\">&lt;</span> <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">ix</span><span class=\"p\">,</span> <span class=\"n\">jy</span><span class=\"p\">]):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_24 = __pyx_v_bestX;\n",
" __pyx_t_25 = __pyx_v_bestY;\n",
" if (__pyx_t_24 &lt; 0) __pyx_t_24 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_25 &lt; 0) __pyx_t_25 += __pyx_v_scores.shape[1];\n",
" __pyx_t_26 = __pyx_v_ix;\n",
" __pyx_t_27 = __pyx_v_jy;\n",
" if (__pyx_t_26 &lt; 0) __pyx_t_26 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_27 &lt; 0) __pyx_t_27 += __pyx_v_scores.shape[1];\n",
" __pyx_t_21 = (((*((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_24 * __pyx_v_scores.strides[0]) )) + __pyx_t_25)) ))) &lt; (*((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_26 * __pyx_v_scores.strides[0]) )) + __pyx_t_27)) )))) != 0);\n",
" if (__pyx_t_21) {\n",
"/* … */\n",
" }\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">42</span>: <span class=\"n\">bestX</span> <span class=\"o\">=</span> <span class=\"n\">ix</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestX = __pyx_v_ix;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">43</span>: <span class=\"n\">bestY</span> <span class=\"o\">=</span> <span class=\"n\">jy</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestY = __pyx_v_jy;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">44</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">45</span>: <span class=\"n\">field</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">current</span><span class=\"p\">[</span><span class=\"n\">bestX</span><span class=\"p\">,</span> <span class=\"n\">bestY</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_28 = __pyx_v_bestX;\n",
" __pyx_t_29 = __pyx_v_bestY;\n",
" if (__pyx_t_28 &lt; 0) __pyx_t_28 += __pyx_v_current.shape[0];\n",
" if (__pyx_t_29 &lt; 0) __pyx_t_29 += __pyx_v_current.shape[1];\n",
" __pyx_t_30 = __pyx_v_x;\n",
" __pyx_t_31 = __pyx_v_y;\n",
" if (__pyx_t_30 &lt; 0) __pyx_t_30 += __pyx_v_field.shape[0];\n",
" if (__pyx_t_31 &lt; 0) __pyx_t_31 += __pyx_v_field.shape[1];\n",
" *((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_field.data + __pyx_t_30 * __pyx_v_field.strides[0]) )) + __pyx_t_31)) )) = (*((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_current.data + __pyx_t_28 * __pyx_v_current.strides[0]) )) + __pyx_t_29)) )));\n",
" }\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-1\" onclick='toggleDiv(this)'>+<span class=\"\">46</span>: <span class=\"k\">return</span> <span class=\"n\">field</span></pre>\n",
"<pre class='cython code score-1 '> <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
" __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_field, 2, (PyObject *(*)(char *)) __pyx_memview_get_long, (int (*)(char *, PyObject *)) __pyx_memview_set_long, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 46, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_r = __pyx_t_1;\n",
" __pyx_t_1 = 0;\n",
" goto __pyx_L0;\n",
"</pre></div></body></html>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%cython -a\n",
"\n",
"import numpy as np\n",
"\n",
"import cython\n",
"\n",
"@cython.cdivision(True)\n",
"@cython.boundscheck(False)\n",
"def evolve2_1(long[:, ::1] field, double b, int num_steps=1):\n",
" \n",
" cdef int x, y, L, i, j, ix, jy, step\n",
" \n",
" L = field.shape[0]\n",
" cdef double[:, ::1] scores = np.zeros((L, L), dtype=float)\n",
" \n",
" cdef double[:, ::1] _zeros = np.zeros((L, L), dtype=float)\n",
" cdef long[:, ::1] current = field.copy()\n",
" \n",
" for step in range(num_steps):\n",
" current = field.copy()\n",
" scores[...] = _zeros\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" scores[x, y] += (1 - field[ix, jy])\n",
" \n",
" if field[x, y] == 1:\n",
" scores[x, y] *= b\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" bestX = x\n",
" bestY = y\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" if (scores[bestX, bestY] < scores[ix, jy]):\n",
" bestX = ix\n",
" bestY = jy\n",
" \n",
" field[x, y] = current[bestX, bestY]\n",
" return field"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"100 loops, best of 3: 1.98 ms per loop\n"
]
}
],
"source": [
"L = 44\n",
"field = np.zeros((L, L), dtype=int)\n",
"field[L//2, L//2] = 1\n",
"\n",
"%timeit evolve2_1(field, 1.81, 10)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"174.24242424242425"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"345 / 1.98"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The recommended code structure is to have a python-facing `def` function which takes care of the input and output, allocated memory etc, and delegates all heavy lifting to an internal `cdef` function."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<!DOCTYPE html>\n",
"<!-- Generated by Cython 0.25.2 -->\n",
"<html>\n",
"<head>\n",
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
" <title>Cython: _cython_magic_451bc548913a9407f1c439613b3672aa.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.25.2</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\">&#xA0;<span class=\"\">01</span>: </pre>\n",
"<pre class=\"cython line score-19\" onclick='toggleDiv(this)'>+<span class=\"\">02</span>: <span class=\"k\">import</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">np</span></pre>\n",
"<pre class='cython code score-19 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __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_np, __pyx_t_1) &lt; 0) __PYX_ERR(0, 2, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
"/* … */\n",
" __pyx_t_1 = <span class='py_c_api'>PyDict_New</span>(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __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_test, __pyx_t_1) &lt; 0) __PYX_ERR(0, 2, __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\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">import</span> <span class=\"nn\">cython</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">04</span>: </pre>\n",
"<pre class=\"cython line score-62\" onclick='toggleDiv(this)'>+<span class=\"\">05</span>: <span class=\"k\">def</span> <span class=\"nf\">evolve2_2</span><span class=\"p\">(</span><span class=\"n\">field</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">,</span> <span class=\"n\">num_steps</span><span class=\"o\">=</span><span class=\"mf\">1</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-62 '>/* Python wrapper */\n",
"static PyObject *__pyx_pw_46_cython_magic_451bc548913a9407f1c439613b3672aa_1evolve2_2(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
"static PyMethodDef __pyx_mdef_46_cython_magic_451bc548913a9407f1c439613b3672aa_1evolve2_2 = {\"evolve2_2\", (PyCFunction)__pyx_pw_46_cython_magic_451bc548913a9407f1c439613b3672aa_1evolve2_2, METH_VARARGS|METH_KEYWORDS, 0};\n",
"static PyObject *__pyx_pw_46_cython_magic_451bc548913a9407f1c439613b3672aa_1evolve2_2(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
" PyObject *__pyx_v_field = 0;\n",
" PyObject *__pyx_v_b = 0;\n",
" PyObject *__pyx_v_num_steps = 0;\n",
" PyObject *__pyx_r = 0;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"evolve2_2 (wrapper)\", 0);\n",
" {\n",
" static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_field,&amp;__pyx_n_s_b,&amp;__pyx_n_s_num_steps,0};\n",
" PyObject* values[3] = {0,0,0};\n",
" values[2] = ((PyObject *)__pyx_int_1);\n",
" if (unlikely(__pyx_kwds)) {\n",
" Py_ssize_t kw_args;\n",
" const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n",
" switch (pos_args) {\n",
" case 3: values[2] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 2);\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" case 0: break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n",
" switch (pos_args) {\n",
" case 0:\n",
" if (likely((values[0] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_field)) != 0)) kw_args--;\n",
" else goto __pyx_L5_argtuple_error;\n",
" case 1:\n",
" if (likely((values[1] = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_b)) != 0)) kw_args--;\n",
" else {\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"evolve2_2\", 0, 2, 3, 1); __PYX_ERR(0, 5, __pyx_L3_error)\n",
" }\n",
" case 2:\n",
" if (kw_args &gt; 0) {\n",
" PyObject* value = <span class='py_c_api'>PyDict_GetItem</span>(__pyx_kwds, __pyx_n_s_num_steps);\n",
" if (value) { values[2] = value; kw_args--; }\n",
" }\n",
" }\n",
" if (unlikely(kw_args &gt; 0)) {\n",
" if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"evolve2_2\") &lt; 0)) __PYX_ERR(0, 5, __pyx_L3_error)\n",
" }\n",
" } else {\n",
" switch (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)) {\n",
" case 3: values[2] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 2);\n",
" case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
" values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
" break;\n",
" default: goto __pyx_L5_argtuple_error;\n",
" }\n",
" }\n",
" __pyx_v_field = values[0];\n",
" __pyx_v_b = values[1];\n",
" __pyx_v_num_steps = values[2];\n",
" }\n",
" goto __pyx_L4_argument_unpacking_done;\n",
" __pyx_L5_argtuple_error:;\n",
" <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"evolve2_2\", 0, 2, 3, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); __PYX_ERR(0, 5, __pyx_L3_error)\n",
" __pyx_L3_error:;\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_451bc548913a9407f1c439613b3672aa.evolve2_2\", __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_451bc548913a9407f1c439613b3672aa_evolve2_2(__pyx_self, __pyx_v_field, __pyx_v_b, __pyx_v_num_steps);\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_451bc548913a9407f1c439613b3672aa_evolve2_2(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_field, PyObject *__pyx_v_b, PyObject *__pyx_v_num_steps) {\n",
" PyObject *__pyx_v_L = NULL;\n",
" PyObject *__pyx_v_scores = NULL;\n",
" PyObject *__pyx_v_current = NULL;\n",
" PyObject *__pyx_v__zeros = NULL;\n",
" int __pyx_v__num_steps;\n",
" double __pyx_v__b;\n",
" PyObject *__pyx_r = NULL;\n",
" <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
" <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"evolve2_2\", 0);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_field);\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_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_7, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_8, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_9, 1);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_10, 1);\n",
" <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_451bc548913a9407f1c439613b3672aa.evolve2_2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
" __pyx_r = NULL;\n",
" __pyx_L0:;\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_L);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_scores);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_current);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v__zeros);\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_v_field);\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__14 = <span class='py_c_api'>PyTuple_Pack</span>(9, __pyx_n_s_field, __pyx_n_s_b, __pyx_n_s_num_steps, __pyx_n_s_L, __pyx_n_s_scores, __pyx_n_s_current, __pyx_n_s_zeros_2, __pyx_n_s_num_steps_2, __pyx_n_s_b_2); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(0, 5, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__14);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__14);\n",
"/* … */\n",
" __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_451bc548913a9407f1c439613b3672aa_1evolve2_2, NULL, __pyx_n_s_cython_magic_451bc548913a9407f1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __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_evolve2_2, __pyx_t_1) &lt; 0) __PYX_ERR(0, 5, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_codeobj__15 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(3, 0, 9, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_br_cache_ipython_cython__c, __pyx_n_s_evolve2_2, 5, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) __PYX_ERR(0, 5, __pyx_L1_error)\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">06</span>: <span class=\"c\"># validate input here</span></pre>\n",
"<pre class=\"cython line score-43\" onclick='toggleDiv(this)'>+<span class=\"\">07</span>: <span class=\"n\">field</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">atleast_2d</span><span class=\"p\">(</span><span class=\"n\">field</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-43 '> __pyx_t_2 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_2, __pyx_n_s_atleast_2d); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" __pyx_t_2 = NULL;\n",
" if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_3))) {\n",
" __pyx_t_2 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_3);\n",
" if (likely(__pyx_t_2)) {\n",
" PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_3, function);\n",
" }\n",
" }\n",
" if (!__pyx_t_2) {\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_3, __pyx_v_field); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" } else {\n",
" #if CYTHON_FAST_PYCALL\n",
" if (<span class='py_c_api'>PyFunction_Check</span>(__pyx_t_3)) {\n",
" PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_v_field};\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyFunction_FastCall</span>(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" } else\n",
" #endif\n",
" #if CYTHON_FAST_PYCCALL\n",
" if (<span class='pyx_c_api'>__Pyx_PyFastCFunction_Check</span>(__pyx_t_3)) {\n",
" PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_v_field};\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyCFunction_FastCall</span>(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" } else\n",
" #endif\n",
" {\n",
" __pyx_t_4 = <span class='py_c_api'>PyTuple_New</span>(1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_2); <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0, __pyx_t_2); __pyx_t_2 = NULL;\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_field);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_field);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0+1, __pyx_v_field);\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" }\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_v_field, __pyx_t_1);\n",
" __pyx_t_1 = 0;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">08</span>: <span class=\"c\"># XXX check that field is integer dtype etc</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">09</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">10</span>: <span class=\"c\"># allocate memory here</span></pre>\n",
"<pre class=\"cython line score-5\" onclick='toggleDiv(this)'>+<span class=\"\">11</span>: <span class=\"n\">L</span> <span class=\"o\">=</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-5 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_v_field, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" __pyx_t_3 = <span class='pyx_c_api'>__Pyx_GetItemInt</span>(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 11, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" __pyx_v_L = __pyx_t_3;\n",
" __pyx_t_3 = 0;\n",
"</pre><pre class=\"cython line score-35\" onclick='toggleDiv(this)'>+<span class=\"\">12</span>: <span class=\"n\">scores</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">zeros</span><span class=\"p\">((</span><span class=\"n\">L</span><span class=\"p\">,</span> <span class=\"n\">L</span><span class=\"p\">),</span> <span class=\"n\">dtype</span><span class=\"o\">=</span><span class=\"nb\">float</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-35 '> __pyx_t_3 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_3, __pyx_n_s_zeros); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" __pyx_t_3 = <span class='py_c_api'>PyTuple_New</span>(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_L);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_L);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 0, __pyx_v_L);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_L);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_L);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 1, __pyx_v_L);\n",
" __pyx_t_4 = <span class='py_c_api'>PyTuple_New</span>(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_3);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0, __pyx_t_3);\n",
" __pyx_t_3 = 0;\n",
" __pyx_t_3 = <span class='py_c_api'>PyDict_New</span>(); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_t_3, __pyx_n_s_dtype, ((PyObject *)(&amp;PyFloat_Type))) &lt; 0) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_1, __pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" __pyx_v_scores = __pyx_t_2;\n",
" __pyx_t_2 = 0;\n",
"</pre><pre class=\"cython line score-18\" onclick='toggleDiv(this)'>+<span class=\"\">13</span>: <span class=\"n\">current</span> <span class=\"o\">=</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span></pre>\n",
"<pre class='cython code score-18 '> __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_v_field, __pyx_n_s_copy); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" __pyx_t_4 = NULL;\n",
" if (CYTHON_UNPACK_METHODS &amp;&amp; likely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_3))) {\n",
" __pyx_t_4 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_3);\n",
" if (likely(__pyx_t_4)) {\n",
" PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_4);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_3, function);\n",
" }\n",
" }\n",
" if (__pyx_t_4) {\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" } else {\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_CallNoArg</span>(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
" }\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" __pyx_v_current = __pyx_t_2;\n",
" __pyx_t_2 = 0;\n",
"</pre><pre class=\"cython line score-35\" onclick='toggleDiv(this)'>+<span class=\"\">14</span>: <span class=\"n\">_zeros</span> <span class=\"o\">=</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">zeros</span><span class=\"p\">((</span><span class=\"n\">L</span><span class=\"p\">,</span> <span class=\"n\">L</span><span class=\"p\">),</span> <span class=\"n\">dtype</span><span class=\"o\">=</span><span class=\"nb\">float</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-35 '> __pyx_t_2 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_2, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" __pyx_t_2 = <span class='py_c_api'>PyTuple_New</span>(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_L);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_L);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_2, 0, __pyx_v_L);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_L);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_L);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_2, 1, __pyx_v_L);\n",
" __pyx_t_4 = <span class='py_c_api'>PyTuple_New</span>(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_2);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0, __pyx_t_2);\n",
" __pyx_t_2 = 0;\n",
" __pyx_t_2 = <span class='py_c_api'>PyDict_New</span>(); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_t_2, __pyx_n_s_dtype, ((PyObject *)(&amp;PyFloat_Type))) &lt; 0) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_3, __pyx_t_4, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" __pyx_v__zeros = __pyx_t_1;\n",
" __pyx_t_1 = 0;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">15</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">16</span>: <span class=\"k\">cdef</span><span class=\"p\">:</span></pre>\n",
"<pre class=\"cython line score-7\" onclick='toggleDiv(this)'>+<span class=\"\">17</span>: <span class=\"nb\">int</span> <span class=\"n\">_num_steps</span> <span class=\"o\">=</span> <span class=\"n\">num_steps</span></pre>\n",
"<pre class='cython code score-7 '> __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(__pyx_v_num_steps); if (unlikely((__pyx_t_5 == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) __PYX_ERR(0, 17, __pyx_L1_error)\n",
" __pyx_v__num_steps = __pyx_t_5;\n",
"</pre><pre class=\"cython line score-10\" onclick='toggleDiv(this)'>+<span class=\"\">18</span>: <span class=\"n\">double</span> <span class=\"n\">_b</span> <span class=\"o\">=</span> <span class=\"n\">b</span></pre>\n",
"<pre class='cython code score-10 '> __pyx_t_6 = __pyx_<span class='py_c_api'>PyFloat_AsDouble</span>(__pyx_v_b); if (unlikely((__pyx_t_6 == (double)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) __PYX_ERR(0, 18, __pyx_L1_error)\n",
" __pyx_v__b = __pyx_t_6;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">19</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">20</span>: <span class=\"c\"># do the work (`field` array is updated in-place)</span></pre>\n",
"<pre class=\"cython line score-8\" onclick='toggleDiv(this)'>+<span class=\"\">21</span>: <span class=\"n\">_evolve2_2_impl</span><span class=\"p\">(</span><span class=\"n\">field</span><span class=\"p\">,</span> <span class=\"n\">_b</span><span class=\"p\">,</span> <span class=\"n\">_num_steps</span><span class=\"p\">,</span> <span class=\"n\">scores</span><span class=\"p\">,</span> <span class=\"n\">_zeros</span><span class=\"p\">,</span> <span class=\"n\">current</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-8 '> __pyx_t_7 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_long</span>(__pyx_v_field);\n",
" if (unlikely(!__pyx_t_7.memview)) __PYX_ERR(0, 21, __pyx_L1_error)\n",
" __pyx_t_8 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_double</span>(__pyx_v_scores);\n",
" if (unlikely(!__pyx_t_8.memview)) __PYX_ERR(0, 21, __pyx_L1_error)\n",
" __pyx_t_9 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_double</span>(__pyx_v__zeros);\n",
" if (unlikely(!__pyx_t_9.memview)) __PYX_ERR(0, 21, __pyx_L1_error)\n",
" __pyx_t_10 = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_d_dc_long</span>(__pyx_v_current);\n",
" if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 21, __pyx_L1_error)\n",
" __pyx_f_46_cython_magic_451bc548913a9407f1c439613b3672aa__evolve2_2_impl(__pyx_t_7, __pyx_v__b, __pyx_v__num_steps, __pyx_t_8, __pyx_t_9, __pyx_t_10);\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_7, 1);\n",
" __pyx_t_7.memview = NULL;\n",
" __pyx_t_7.data = NULL;\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_8, 1);\n",
" __pyx_t_8.memview = NULL;\n",
" __pyx_t_8.data = NULL;\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_9, 1);\n",
" __pyx_t_9.memview = NULL;\n",
" __pyx_t_9.data = NULL;\n",
" __PYX_XDEC_MEMVIEW(&amp;__pyx_t_10, 1);\n",
" __pyx_t_10.memview = NULL;\n",
" __pyx_t_10.data = NULL;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">22</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">23</span>: <span class=\"c\"># convert memoryviews to numpy arrays</span></pre>\n",
"<pre class=\"cython line score-43\" onclick='toggleDiv(this)'>+<span class=\"\">24</span>: <span class=\"k\">return</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">asarray</span><span class=\"p\">(</span><span class=\"n\">field</span><span class=\"p\">)</span></pre>\n",
"<pre class='cython code score-43 '> <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
" __pyx_t_2 = <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
" __pyx_t_4 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_2, __pyx_n_s_asarray); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" __pyx_t_2 = NULL;\n",
" if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_4))) {\n",
" __pyx_t_2 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_4);\n",
" if (likely(__pyx_t_2)) {\n",
" PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_4);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2);\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_4, function);\n",
" }\n",
" }\n",
" if (!__pyx_t_2) {\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_4, __pyx_v_field); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" } else {\n",
" #if CYTHON_FAST_PYCALL\n",
" if (<span class='py_c_api'>PyFunction_Check</span>(__pyx_t_4)) {\n",
" PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_v_field};\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyFunction_FastCall</span>(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" } else\n",
" #endif\n",
" #if CYTHON_FAST_PYCCALL\n",
" if (<span class='pyx_c_api'>__Pyx_PyFastCFunction_Check</span>(__pyx_t_4)) {\n",
" PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_v_field};\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyCFunction_FastCall</span>(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" } else\n",
" #endif\n",
" {\n",
" __pyx_t_3 = <span class='py_c_api'>PyTuple_New</span>(1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_2); <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 0, __pyx_t_2); __pyx_t_2 = NULL;\n",
" <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_v_field);\n",
" <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_v_field);\n",
" <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_3, 0+1, __pyx_v_field);\n",
" __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyObject_Call</span>(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error)\n",
" <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
" }\n",
" }\n",
" <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
" __pyx_r = __pyx_t_1;\n",
" __pyx_t_1 = 0;\n",
" goto __pyx_L0;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">25</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">26</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">27</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">cdivision</span><span class=\"p\">(</span><span class=\"bp\">True</span><span class=\"p\">)</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">28</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">boundscheck</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
"<pre class=\"cython line score-2\" onclick='toggleDiv(this)'>+<span class=\"\">29</span>: <span class=\"k\">cdef</span> <span class=\"kt\">void</span> <span class=\"nf\">_evolve2_2_impl</span><span class=\"p\">(</span><span class=\"nb\">long</span><span class=\"p\">[:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">field</span><span class=\"p\">,</span> <span class=\"n\">double</span> <span class=\"n\">b</span><span class=\"p\">,</span> <span class=\"nb\">int</span> <span class=\"n\">num_steps</span><span class=\"p\">,</span></pre>\n",
"<pre class='cython code score-2 '>static void __pyx_f_46_cython_magic_451bc548913a9407f1c439613b3672aa__evolve2_2_impl(__Pyx_memviewslice __pyx_v_field, double __pyx_v_b, int __pyx_v_num_steps, __Pyx_memviewslice __pyx_v_scores, __Pyx_memviewslice __pyx_v__zeros, __Pyx_memviewslice __pyx_v_current) {\n",
" int __pyx_v_x;\n",
" int __pyx_v_y;\n",
" int __pyx_v_L;\n",
" int __pyx_v_i;\n",
" int __pyx_v_j;\n",
" int __pyx_v_ix;\n",
" int __pyx_v_jy;\n",
" CYTHON_UNUSED int __pyx_v_step;\n",
" int __pyx_v_bestX;\n",
" int __pyx_v_bestY;\n",
"/* … */\n",
" /* function exit code */\n",
" goto __pyx_L0;\n",
" __pyx_L1_error:;\n",
" <span class='pyx_c_api'>__Pyx_WriteUnraisable</span>(\"_cython_magic_451bc548913a9407f1c439613b3672aa._evolve2_2_impl\", __pyx_clineno, __pyx_lineno, __pyx_filename, 0, 1);\n",
" __pyx_L0:;\n",
"}\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">30</span>: <span class=\"n\">double</span><span class=\"p\">[:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">scores</span><span class=\"p\">,</span> <span class=\"n\">double</span><span class=\"p\">[:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">_zeros</span><span class=\"p\">,</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">31</span>: <span class=\"nb\">long</span><span class=\"p\">[:,</span> <span class=\"p\">::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">current</span><span class=\"p\">)</span> <span class=\"k\">nogil</span><span class=\"p\">:</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">32</span>: </pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">33</span>: <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">x</span><span class=\"p\">,</span> <span class=\"nf\">y</span><span class=\"p\">,</span> <span class=\"nf\">L</span><span class=\"p\">,</span> <span class=\"nf\">i</span><span class=\"p\">,</span> <span class=\"nf\">j</span><span class=\"p\">,</span> <span class=\"nf\">ix</span><span class=\"p\">,</span> <span class=\"nf\">jy</span><span class=\"p\">,</span> <span class=\"nf\">step</span></pre>\n",
"<pre class=\"cython line score-0\">&#xA0;<span class=\"\">34</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">35</span>: <span class=\"n\">L</span> <span class=\"o\">=</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_L = (__pyx_v_field.shape[0]);\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">36</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">37</span>: <span class=\"k\">for</span> <span class=\"n\">step</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">num_steps</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_1 = __pyx_v_num_steps;\n",
" for (__pyx_t_2 = 0; __pyx_t_2 &lt; __pyx_t_1; __pyx_t_2+=1) {\n",
" __pyx_v_step = __pyx_t_2;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">38</span>: <span class=\"n\">current</span><span class=\"p\">[</span><span class=\"o\">...</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">field</span></pre>\n",
"<pre class='cython code score-0 '> if (unlikely(__pyx_memoryview_copy_contents(__pyx_v_field, __pyx_v_current, 2, 2, 0) &lt; 0)) __PYX_ERR(0, 38, __pyx_L1_error)\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">39</span>: <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"o\">...</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">_zeros</span></pre>\n",
"<pre class='cython code score-0 '> if (unlikely(__pyx_memoryview_copy_contents(__pyx_v__zeros, __pyx_v_scores, 2, 2, 0) &lt; 0)) __PYX_ERR(0, 39, __pyx_L1_error)\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">40</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">41</span>: <span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_3 = __pyx_v_L;\n",
" for (__pyx_t_4 = 0; __pyx_t_4 &lt; __pyx_t_3; __pyx_t_4+=1) {\n",
" __pyx_v_x = __pyx_t_4;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">42</span>: <span class=\"k\">for</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_5 = __pyx_v_L;\n",
" for (__pyx_t_6 = 0; __pyx_t_6 &lt; __pyx_t_5; __pyx_t_6+=1) {\n",
" __pyx_v_y = __pyx_t_6;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">43</span>: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_7 = -1L; __pyx_t_7 &lt; 2; __pyx_t_7+=1) {\n",
" __pyx_v_i = __pyx_t_7;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">44</span>: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_8 = -1L; __pyx_t_8 &lt; 2; __pyx_t_8+=1) {\n",
" __pyx_v_j = __pyx_t_8;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">45</span>: <span class=\"n\">ix</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">i</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_ix = ((__pyx_v_x + __pyx_v_i) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">46</span>: <span class=\"n\">jy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">y</span> <span class=\"o\">+</span> <span class=\"n\">j</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_jy = ((__pyx_v_y + __pyx_v_j) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">47</span>: <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">+=</span> <span class=\"p\">(</span><span class=\"mf\">1</span> <span class=\"o\">-</span> <span class=\"n\">field</span><span class=\"p\">[</span><span class=\"n\">ix</span><span class=\"p\">,</span> <span class=\"n\">jy</span><span class=\"p\">])</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_9 = __pyx_v_ix;\n",
" __pyx_t_10 = __pyx_v_jy;\n",
" if (__pyx_t_9 &lt; 0) __pyx_t_9 += __pyx_v_field.shape[0];\n",
" if (__pyx_t_10 &lt; 0) __pyx_t_10 += __pyx_v_field.shape[1];\n",
" __pyx_t_11 = __pyx_v_x;\n",
" __pyx_t_12 = __pyx_v_y;\n",
" if (__pyx_t_11 &lt; 0) __pyx_t_11 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_12 &lt; 0) __pyx_t_12 += __pyx_v_scores.shape[1];\n",
" *((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_11 * __pyx_v_scores.strides[0]) )) + __pyx_t_12)) )) += (1 - (*((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_field.data + __pyx_t_9 * __pyx_v_field.strides[0]) )) + __pyx_t_10)) ))));\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">48</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">49</span>: <span class=\"k\">if</span> <span class=\"n\">field</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"mf\">1</span><span class=\"p\">:</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_13 = __pyx_v_x;\n",
" __pyx_t_14 = __pyx_v_y;\n",
" if (__pyx_t_13 &lt; 0) __pyx_t_13 += __pyx_v_field.shape[0];\n",
" if (__pyx_t_14 &lt; 0) __pyx_t_14 += __pyx_v_field.shape[1];\n",
" __pyx_t_15 = (((*((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_field.data + __pyx_t_13 * __pyx_v_field.strides[0]) )) + __pyx_t_14)) ))) == 1) != 0);\n",
" if (__pyx_t_15) {\n",
"/* … */\n",
" }\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">50</span>: <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">*=</span> <span class=\"n\">b</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_16 = __pyx_v_x;\n",
" __pyx_t_17 = __pyx_v_y;\n",
" if (__pyx_t_16 &lt; 0) __pyx_t_16 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_17 &lt; 0) __pyx_t_17 += __pyx_v_scores.shape[1];\n",
" *((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_16 * __pyx_v_scores.strides[0]) )) + __pyx_t_17)) )) *= __pyx_v_b;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">51</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">52</span>: <span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_3 = __pyx_v_L;\n",
" for (__pyx_t_4 = 0; __pyx_t_4 &lt; __pyx_t_3; __pyx_t_4+=1) {\n",
" __pyx_v_x = __pyx_t_4;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">53</span>: <span class=\"k\">for</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_5 = __pyx_v_L;\n",
" for (__pyx_t_6 = 0; __pyx_t_6 &lt; __pyx_t_5; __pyx_t_6+=1) {\n",
" __pyx_v_y = __pyx_t_6;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">54</span>: <span class=\"n\">bestX</span> <span class=\"o\">=</span> <span class=\"n\">x</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestX = __pyx_v_x;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">55</span>: <span class=\"n\">bestY</span> <span class=\"o\">=</span> <span class=\"n\">y</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestY = __pyx_v_y;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">56</span>: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_7 = -1L; __pyx_t_7 &lt; 2; __pyx_t_7+=1) {\n",
" __pyx_v_i = __pyx_t_7;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">57</span>: <span class=\"k\">for</span> <span class=\"n\">j</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"o\">-</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">):</span></pre>\n",
"<pre class='cython code score-0 '> for (__pyx_t_8 = -1L; __pyx_t_8 &lt; 2; __pyx_t_8+=1) {\n",
" __pyx_v_j = __pyx_t_8;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">58</span>: <span class=\"n\">ix</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">x</span> <span class=\"o\">+</span> <span class=\"n\">i</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_ix = ((__pyx_v_x + __pyx_v_i) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">59</span>: <span class=\"n\">jy</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">y</span> <span class=\"o\">+</span> <span class=\"n\">j</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"n\">L</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_jy = ((__pyx_v_y + __pyx_v_j) % __pyx_v_L);\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">60</span>: <span class=\"k\">if</span> <span class=\"p\">(</span><span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">bestX</span><span class=\"p\">,</span> <span class=\"n\">bestY</span><span class=\"p\">]</span> <span class=\"o\">&lt;</span> <span class=\"n\">scores</span><span class=\"p\">[</span><span class=\"n\">ix</span><span class=\"p\">,</span> <span class=\"n\">jy</span><span class=\"p\">]):</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_18 = __pyx_v_bestX;\n",
" __pyx_t_19 = __pyx_v_bestY;\n",
" if (__pyx_t_18 &lt; 0) __pyx_t_18 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_19 &lt; 0) __pyx_t_19 += __pyx_v_scores.shape[1];\n",
" __pyx_t_20 = __pyx_v_ix;\n",
" __pyx_t_21 = __pyx_v_jy;\n",
" if (__pyx_t_20 &lt; 0) __pyx_t_20 += __pyx_v_scores.shape[0];\n",
" if (__pyx_t_21 &lt; 0) __pyx_t_21 += __pyx_v_scores.shape[1];\n",
" __pyx_t_15 = (((*((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_18 * __pyx_v_scores.strides[0]) )) + __pyx_t_19)) ))) &lt; (*((double *) ( /* dim=1 */ ((char *) (((double *) ( /* dim=0 */ (__pyx_v_scores.data + __pyx_t_20 * __pyx_v_scores.strides[0]) )) + __pyx_t_21)) )))) != 0);\n",
" if (__pyx_t_15) {\n",
"/* … */\n",
" }\n",
" }\n",
" }\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">61</span>: <span class=\"n\">bestX</span> <span class=\"o\">=</span> <span class=\"n\">ix</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestX = __pyx_v_ix;\n",
"</pre><pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">62</span>: <span class=\"n\">bestY</span> <span class=\"o\">=</span> <span class=\"n\">jy</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_v_bestY = __pyx_v_jy;\n",
"</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">63</span>: </pre>\n",
"<pre class=\"cython line score-0\" onclick='toggleDiv(this)'>+<span class=\"\">64</span>: <span class=\"n\">field</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">current</span><span class=\"p\">[</span><span class=\"n\">bestX</span><span class=\"p\">,</span> <span class=\"n\">bestY</span><span class=\"p\">]</span></pre>\n",
"<pre class='cython code score-0 '> __pyx_t_22 = __pyx_v_bestX;\n",
" __pyx_t_23 = __pyx_v_bestY;\n",
" if (__pyx_t_22 &lt; 0) __pyx_t_22 += __pyx_v_current.shape[0];\n",
" if (__pyx_t_23 &lt; 0) __pyx_t_23 += __pyx_v_current.shape[1];\n",
" __pyx_t_24 = __pyx_v_x;\n",
" __pyx_t_25 = __pyx_v_y;\n",
" if (__pyx_t_24 &lt; 0) __pyx_t_24 += __pyx_v_field.shape[0];\n",
" if (__pyx_t_25 &lt; 0) __pyx_t_25 += __pyx_v_field.shape[1];\n",
" *((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_field.data + __pyx_t_24 * __pyx_v_field.strides[0]) )) + __pyx_t_25)) )) = (*((long *) ( /* dim=1 */ ((char *) (((long *) ( /* dim=0 */ (__pyx_v_current.data + __pyx_t_22 * __pyx_v_current.strides[0]) )) + __pyx_t_23)) )));\n",
" }\n",
" }\n",
" }\n",
"</pre></div></body></html>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%cython -a\n",
"\n",
"import numpy as np\n",
"import cython\n",
"\n",
"def evolve2_2(field, b, num_steps=1):\n",
" # validate input here\n",
" field = np.atleast_2d(field)\n",
" # XXX check that field is integer dtype etc\n",
" \n",
" # allocate memory here\n",
" L = field.shape[0]\n",
" scores = np.zeros((L, L), dtype=float)\n",
" current = field.copy()\n",
" _zeros = np.zeros((L, L), dtype=float)\n",
"\n",
" cdef:\n",
" int _num_steps = num_steps\n",
" double _b = b\n",
" \n",
" # do the work (`field` array is updated in-place)\n",
" _evolve2_2_impl(field, _b, _num_steps, scores, _zeros, current)\n",
" \n",
" # convert memoryviews to numpy arrays\n",
" return np.asarray(field)\n",
"\n",
"\n",
"@cython.cdivision(True)\n",
"@cython.boundscheck(False)\n",
"cdef void _evolve2_2_impl(long[:, ::1] field, double b, int num_steps,\n",
" double[:, ::1] scores, double[:, ::1] _zeros,\n",
" long[:, ::1] current) nogil:\n",
" \n",
" cdef int x, y, L, i, j, ix, jy, step\n",
" \n",
" L = field.shape[0]\n",
"\n",
" for step in range(num_steps):\n",
" current[...] = field\n",
" scores[...] = _zeros\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" scores[x, y] += (1 - field[ix, jy])\n",
" \n",
" if field[x, y] == 1:\n",
" scores[x, y] *= b\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" bestX = x\n",
" bestY = y\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" if (scores[bestX, bestY] < scores[ix, jy]):\n",
" bestX = ix\n",
" bestY = jy\n",
" \n",
" field[x, y] = current[bestX, bestY]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L = 44\n",
"field = np.zeros((L, L), dtype=int)\n",
"field[L//2, L//2] = 1\n",
"\n",
"%timeit evolve2_2(field, 1.81, 10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Now, for something completely different: `numba` just-in-time compilation"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numba"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def evolve3(field, b, num_steps=1):\n",
" L = field.shape[0]\n",
" _zeros = np.zeros((L, L), dtype=float)\n",
" _int_zeros = np.zeros((L, L), dtype=int)\n",
" current = _int_zeros.copy()\n",
" scores = _zeros.copy()\n",
" evolve3_impl(field, b, num_steps, _zeros, _int_zeros)\n",
" return field\n",
"\n",
"\n",
"# Note a single decorator: @jit\n",
"\n",
"\n",
"@numba.jit(nopython=True)\n",
"def evolve3_impl(field, b, num_steps, _zeros, _int_zeros):\n",
" L = field.shape[0]\n",
" current = _int_zeros.copy()\n",
" \n",
" for step in range(num_steps):\n",
" current = field.copy()\n",
" scores = _zeros.copy()\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" scores[x, y] += (1 - field[ix, jy])\n",
" \n",
" if field[x, y] == 1:\n",
" scores[x, y] *= b\n",
" \n",
" for x in range(L):\n",
" for y in range(L):\n",
" bestX = x\n",
" bestY = y\n",
" for i in range(-1, 2):\n",
" for j in range(-1, 2):\n",
" ix = (x + i) % L\n",
" jy = (y + j) % L\n",
" if (scores[bestX, bestY] < scores[ix, jy]):\n",
" bestX = ix\n",
" bestY = jy\n",
" \n",
" field[x, y] = current[bestX, bestY]\n",
" return field"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"100 loops, best of 3: 2.12 ms per loop\n"
]
}
],
"source": [
"L = 44\n",
"field = np.zeros((L, L), dtype=int)\n",
"field[L//2, L//2] = 1\n",
"\n",
"%timeit evolve3(field, 1.81, 10)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment