{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pystencils as ps\n",
    "from pystencils import plot as plt\n",
    "\n",
    "import numpy as np\n",
    "import sympy as sp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial 01: Getting Started\n",
    "\n",
    "\n",
    "## Overview\n",
    "\n",
    "*pystencils* is a package that can speed up computations on *numpy* arrays. All computations are carried out fully parallel on CPUs (single node with OpenMP, multiple nodes with MPI) or on GPUs.\n",
    "It is suited for applications that run the same operation on *numpy* arrays multiple times. It can be used to accelerate computations on images or voxel fields. Its main application, however, are numerical simulations using finite differences, finite volumes, or lattice Boltzmann methods. \n",
    "There already exist a variety of packages to speed up numeric Python code. One could use pure numpy or solutions that compile your code, like *Cython* and *numba*. See [this page](demo_benchmark.ipynb) for a comparison of these tools.\n",
    "\n",
    "![Stencil](../_static/img/pystencils_stencil_four_points_with_arrows.svg)\n",
    "\n",
    "As the name suggests, *pystencils* was developed for **stencil codes**, i.e. operations that update array elements using only a local neighborhood. \n",
    "It generates C code, compiles it behind the scenes, and lets you call the compiled C function as if it was a native Python function. \n",
    "But lets not dive too deep into the concepts of *pystencils* here, they are covered in detail in the following tutorials. Let's instead look at a simple example, that computes the average neighbor values of a *numpy* array. Therefor we first create two rather large arrays for input and output:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_arr = np.random.rand(1024, 1024)\n",
    "output_arr = np.zeros_like(input_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We first implement a version of this algorithm using pure numpy and benchmark it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def numpy_kernel():\n",
    "    output_arr[1:-1, 1:-1] = input_arr[2:, 1:-1] + input_arr[:-2, 1:-1] + \\\n",
    "                             input_arr[1:-1, 2:] + input_arr[1:-1, :-2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.85 ms ± 169 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit \n",
    "numpy_kernel()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets see how to run the same algorithm with *pystencils*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle {dst}_{(0,0)} \\leftarrow_{} \\frac{{src}_{(1,0)}}{4} + \\frac{{src}_{(0,1)}}{4} + \\frac{{src}_{(0,-1)}}{4} + \\frac{{src}_{(-1,0)}}{4}$"
      ],
      "text/plain": [
       "Assignment(dst_C, src_E/4 + src_N/4 + src_S/4 + src_W/4)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "src, dst = ps.fields(src=input_arr, dst=output_arr)\n",
    "\n",
    "symbolic_description = ps.Assignment(dst[0,0], \n",
    "                                     (src[1, 0] + src[-1, 0] + src[0, 1] + src[0, -1]) / 4)\n",
    "symbolic_description"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAARUAAAEgCAYAAACaWef8AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjExLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvctoD+AAAAAlwSFlzAAAPYQAAD2EBqD+naQAAEPVJREFUeJzt3X+Q1PV9x/HXd3dv7yd3B96t8kPgsCUkGg3EiBqVtJUcARSwmY6jdVLxqiSaMaOx7dhpmxgm2I6atFMrFGhaNbSd6SQaryqMWlEbK0EQ5IdDCgQ4wON+cMcdt7/32z/oHYf76/buLbvLPh8zzrg/7rPvmdt98v1+93u7juu6rgDAiCffAwC4sBAVAKaICgBTvnwPgMIQS7h6szuqjZ1RHQnFFUmM7OcqPI5mVXv1tcYyfam+7NMdEkXB4UAtIglX39rdr7dPxsa0TsuUcj0yo8poKhQrdn+g1YdDYw6KJK1rC+uNrojBRChmRAX6zw67ELzcETVbC8WJYyolrj/m6jfB9AdQgru2KH7qpCTJP7lJ/mkzM673Yd/Yt3hQ3IhKiQvGMx9S6//lq4oc2KPw/36ocfP/QI33/VXG+w9kWQ8XPqJS4rIloPHev5QkHV95n8l6uPBxTAWAKaICwBRRAWCKqAAwRVQAmOLdH2QUPrhX0eOHFes4LjcSVv8vN8o/bab8k5vyPRoKFFsqyCi483/U+4ufyFNZJTcSUu8vfqLwr3fmeywUMP6gsMSdCCd043u9Zus1+h29c2292XooPuz+IK198yakvW3m5u7zOAmKCVFBWsPDkQie1okfPaLymVdp/NdHdnYtShPHVDAinet/qNPvb1Zo95Z8j4ICR1SQVWjfDgU/fE+1N38936OgCBAVZOTG42p/8mEFHnxc8vB0QXY8S5BRz8/+URW//XlVfu7qfI+CIsGBWqQVPdGmk/+xRtPW/le+R0ERISpIq++1n8nx+nTiR9+VJIX371YiNKD2Jx/SxQ8/lefpUKiICtKqvr5ZvosnD11OhEOK93Sqeu7NeZwKhY6oIK3y6Z9R+fTPKBGPa//+/XLq3lG1v0I1NyzM92goYEQFWZ3q65PrunKvvllV42vzPQ4KHFEpcWXZ3v9zXfWcPPNp+pryWwrW1aku03qOYzUaihRvKZe4Wp+jam/620OhkCKRs98L1HfqlBLxeNr7TyrnKVXqeAaUOK/j6HcmpP8O5J7ec/+C2XVdnerrS3v/+Q18n3KpIypQy6UVqvUl77Yk4nH1nTqVdH1Pz0kpxSdmNFV6tPRi/6cyI4oHUYE+W+PTP3++RjeN92l4WwYP0H5SJBxRKBwaulztlW4J+PX8VeNUn/UgDS50fEgTztEfc3U8nFA4ntDSZcu0f//+pK0Sr9erW5cs0Q8ee0yVXkdTKjzyezhAizOIClLasmWL5s6dm/b2iooKtbe3q7aWt5hxLrZVkdKaNWvk9aZ/WygUCmnDhg3ncSIUC6KClD744APFM7x1LEk7d/IB2EjG7g9SOnTokHbt2jV0efHixZKk1tbWoetuuOEG1dVlOhUOpYioYESc/z9TlqcLsmH3B4ApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmfOluiCRcvXQioo2dER0YSCiUcEe0YIXH0Ywqj5ob/Lol4Jff45gNC8BGTzShn7dH9FpnVMfCCUXd7K9vR1Klx9GVtT4tbCzT717kT30/101eLZJwdf/ufr11MjamwW8a79PTl9cQlguA45z5HaZ4uqDIdEYS+sMdfToYTIxpnZYp5XpkRlXS9Sl3fzYcC485KJL01smYNhwLj3kdAHYePxAcc1AkaV1bWL/qiSZdnzIqr3RExvyAg17ttFsLwNhEEq7e6LJ8fSdHJeUxlY9Ox9MuMrD9HUWPHpAklU2eoarZN2R80I/6068F4Pw6Ekwow8tbfW++qER/rySp4vIvqbzpsxnXS/X6ThmVUIYto+ixgwru2arQR9tVPuNzWaNisJUFwEi2N1zC+3cp1tWu0++9rgm3P5A1KsEU66V99yedukV3qW7RXepY833FOo7l+uMACljDPX8uSWp7aNmo1+A8FQCmiAoAU0QFgKmCiMqhQ4c4qQoYo1gspra2tnyPkb+o9Pf3a+3atZo9e7amT5+uVatW5WsU4IKwbNkyTZ06Vc3NzXrxxRcVi439BNbRyPndn/D+3QrtfV/h/buV6OtRb+uz8k+fpcorrhnRz2/fvl1r1qzRc889p4GBATmOI4/Ho8OHD+c8PICzjhw5Itd19frrr2vTpk0KBAK699571dLSomnTpo1ojYH3Nyt6/JBinccV2rNVva3PqvILX5Z/ymUjniPnLZVYxzEF92yVr+ES+ZtmKbhnq6LHMwehv79f69at0+zZszVnzhytX79eAwMDks78LYnX6811DABpxONnTkg7ceKEVq1apaamprNbL/HMJ6NG2g4ouGerKq64Rk5ltYJ7tire05nT4+e8pVJ97XxVXzt/RPcNh0Lq6e3RxRdfPbRVIilps8x1XR09elTbt2/PdRycZ/yOCldPT0/SdYOBGdx6mfCF66S/+Bc1NDSkXKN+yd2S7h7THDlFZd+8CWlvm7m5O+m6o0ePngnIsK2SVGKxmFpbW9Xa2prLOMiDOXPm5HsEjMJgXLq7u6WurpRRyfX1nU5OURm+cCIS1vHvt6iscZIC3/nrlPdvaGzUye5uhSX5fL60B468Xq8cx1FLS0su4+A8Wr16tSRpxYoVeZ4E6Qz+jtLxer2KO46qqqtT3j789R39+Ig+fvwB1dy0WONv++Oc5sh592dQ9/NPKXJwj+K96fe3amtrVVtbq3/btu2cg7Mej0eJxNk/CvJ4PFq+fLmeeeaZ0Y6DT9ngE5bfUeF69913tWPHjnOu83q9isfjCgQCuu+++3TjnS16oH1c1rVO/PgRxdqPDP3xcC5G9ZZy5NA+9b/zsuqXLB/R/WfPnq3Vq1ervb1da9eu1VVXXSXpzNaLpHMCA2DsBrf+58+frxdeeEFHjx7VY489pkmTJmX92b43fi6nokqVV143qsfOOSqu66r9yYcUuH+lVJb64+TSqampUUtLi7Zt26Zt27bpnnvuUVVVleLxuMrLy3MdBcAwg6+hQCCgRx99VAcPHtQrr7yiJUuWDP0Dnk28/5Q61/9QjfevHPUcOe/+nHr5efkuukRVX5yn8KF9o37gwa2XJ554Qps2bdLChQtHvRYA6aWXXtKWLVu0YMGCEUfkkzrXfF91t35DZY3Zt2jSyemRYyc71PXsE5r69KujfsBPqqmp0W233Wa2HlCqAoGAFi9ePOqfD+56T8HdWxR4MPUbLyOVU1QGtr4pNxTU8R/cK0mKdRxXvKdDRx68RVOeekEOJ7EBRavvzRflBk+r7eEzn6USOfxrOV6vEsHTuuRP/m7E6+QUlaovztPE7/3T0OX+t1s1sO1tXfRHfyp5CuJvEwGMUv3SFtV8+exhiO4NP5anslr1t+Z2MlxOUfFNCMg3ITB0OXxwrzz7dmT9SEkAhc8/ZYb8U2YMXT716r/KU1Orilmzc1pn1OepSFLNjYtUecXcsSwBoEBNuONByZt7IlL+RJkjRUfw8SZljZOyHiX28z1iQMHI5Yv9/NNmjmC95OtSHgiZWml3fORSw7UAjM3Eco98hv/QX1qR/OZMyld8c0NuJ7VlYrkWgLGp8Tm6vn5MRz3O0dxQlnRdyqjcOalcTQZbGE2VHt05iTNlgULynemVqjXYXLlxvE9fmZAclZRf0C5JHeGEnjkc0sbOiDpHcoBlmIYyR80Nfn1zaoUay9n9uRDwBe0Xlr39Ma1vC+uNrkjGbyxMpanSo4WNfq2YWpHyGE3aqAxyXVd9MTfjtxYOV+GRxvmcoSchLgxE5cIUd12dirmKjuD17Uiq8jqqzrKVkzUqgERUMHLsmwAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApogLAFFEBYIqoADBFVACYIioATBEVAKaICgBTRAWAKaICwBRRAWCKqAAwRVQAmCIqAEwRFQCmiAoAU0QFgCmiAsAUUQFgiqgAMEVUAJgiKgBMERUApogKAFNEBYApX74HQGEKBoPq7e1Nuv7jjz8e+v+Ghgb5fDyFcC62VJDS0qVLNXHixKH/Bg2/buXKlXmcEIWKqCAlv98vx3Ey3sfr9Z6naVBMiApSWrFihVzXTXu7x+PR8uXLz+NEKBZEBSktWLDgnN2e4bxerxYtWqTJkyef56lQDBw30z9HKBmdkYR+eiysjZ0RHQ4mFHWlrs5OdXV1pbz/5MmTVV1TowqPNKvaq681+nXHpHL5PZl3mXDhIypQRzihu3b26WAwcc71sWhUBw4cSLq/1+fTZTNmSJ845nLTeJ+evryGsJQ4dn+gfzgcSgqKJPnKylRdXZ10fX19fVJQJOmtkzG1noh8GiOiiBCVEue6rjZ1pg9BfX190nV1tbVp77+xM2oxFooYZy6VuL6Yq85o+j3g+H+3ytm7U24iIV12paqvnidfWVna++8fiH8aY6KIsKVS4kLJez3ncGNRVXgd6VevSXveU319XZb1OERX6thSQUZ1i+5SdTSqA0cOyHEcVVclH2MBhiMqyMpXVqZxtbXyjR+f8gAtMBy7PwBMERUApogKAFNEBYApDtQio9NbXlfoo+2KHNyrWHubup59QlVzblTlFXPzPRoKFFFBRm4sJjcSVvV1zWcuR8Jy41lObkFJIyrIqOb6ZtVc35zvMVBEiArS2jdvQtrbZm7uPo+ToJgQFaQ1PBzRjmM6+t3fV9XVX1Hg26vyOBUKHe/+YEQ6/vbP5PjKFO8+ke9RUOCICrLqf+dluW5CVdf8Xr5HQREgKsgoMdCvjtXfY5cHI0ZUkFHnupWqbb5dZZdcmu9RUCQ4UIu0Qh9t18D7mzVt3eZ8j4IiQlSQ1sD7mxXratdvvnGdJCne2y03Htfhb35VU5/ZlOfpUKiICtKqu/Vu1cy7dejyyX//e8U6jinw4N/kcSoUOqKCtLzj6uQdd/bjIz01dfL096ps4tQ8ToVCR1QwYhNu/7bceCzfY6DAEZUSV5HD+3/euvSn7Z9dj4+bLHW8pVzixvkcNZTZheCyKq/ZWihORKXEOY6jrzb4zdZrbkj/nUAoDUQF+tbUCjVVjv2pcNN4nxYH7AKF4sQXtEOS1BlJ6KfHwtrYGdGRYEKRET4rKj3SrBqvFjT4dcekcr6cHUQFgC12fwCYIioATBEVAKaICgBT/wc2maAGYPNmUQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 300x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(3,3))\n",
    "ps.stencil.plot_expression(symbolic_description.rhs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we first have created a symbolic notation of the stencil itself. This representation is built on top of *sympy* and is explained in detail in the next section. \n",
    "This description is then compiled and loaded as a Python function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "kernel = ps.create_kernel(symbolic_description).compile()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This whole process might seem overly complicated. We have already spent more lines of code than we needed for the *numpy* implementation and don't have anything running yet! However, this multi-stage process of formulating the algorithm symbolically, and just in the end actually running it, is what makes *pystencils* faster and more flexible than other approaches.\n",
    "\n",
    "Now finally lets benchmark the *pystencils* kernel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pystencils_kernel():\n",
    "    kernel(src=input_arr, dst=output_arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "863 μs ± 30.7 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "pystencils_kernel()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This benchmark shows that *pystencils* is a lot faster than pure *numpy*, especially for large arrays. \n",
    "If you are interested in performance details and comparison to other packages like Cython, have a look at [this page](demo_benchmark.ipynb).\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Short *sympy* introduction\n",
    "\n",
    "In this tutorial we continue with a short *sympy* introduction, since the symbolic kernel definition is built on top of this package. If you already know *sympy* you can skip this section. \n",
    "You can also read the full [sympy documentation here](http://docs.sympy.org/latest/index.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sympy as sp\n",
    "sp.init_printing()  # enable nice LaTeX output"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*sympy* is a package for symbolic calculation. So first we need some symbols:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "sympy.core.symbol.Symbol"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = sp.Symbol(\"x\")\n",
    "y = sp.Symbol(\"y\")\n",
    "type(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The usual mathematical operations are defined for symbols:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle x^{2} \\left(x + y + 5\\right) + x^{2}$"
      ],
      "text/plain": [
       " 2                2\n",
       "x ⋅(x + y + 5) + x "
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr = x**2 * ( y + x + 5) + x**2\n",
    "expr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can do all sorts of operations on these expressions: expand them, factor them, substitute variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle x^{3} + x^{2} y + 6 x^{2}$"
      ],
      "text/plain": [
       " 3    2        2\n",
       "x  + x ⋅y + 6⋅x "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.expand()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle x^{2} \\left(x + y + 6\\right)$"
      ],
      "text/plain": [
       " 2            \n",
       "x ⋅(x + y + 6)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.factor()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle x^{2} \\left(x + \\cos{\\left(x \\right)} + 5\\right) + x^{2}$"
      ],
      "text/plain": [
       " 2                     2\n",
       "x ⋅(x + cos(x) + 5) + x "
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.subs(y, sp.cos(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also built equations and solve them"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle x^{2} \\left(x + y + 5\\right) + x^{2} = 1$"
      ],
      "text/plain": [
       " 2                2    \n",
       "x ⋅(x + y + 5) + x  = 1"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq = sp.Eq(expr, 1)\n",
    "eq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHsAAAAcCAYAAABBNsCdAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjExLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvctoD+AAAAAlwSFlzAAASdAAAEnQB3mYfeAAABRFJREFUeJztm3uIVVUUxn/mVIPSmD2UyjBTU4MgEdOKrL9MLe1BkUZZIj5KiSIjSOrzK7UpekhUloVoD7OaIk0UDaJEwspHhSUqhWSmVGI1PvBR0x97j16vd+49d7yPibkfDGf2Xmev/d27zlp77bXPbdPQ0ACA7QHAcuAtAmZI2kEFZYPtjsDdwC3ABkkTctzfB5gUmxOBrpK2N8qrUu5tA+yRNLmgjCtoFmyfDmwA6oB6oFeuMZI2ApPj+EkEmx5BVaZBrQkxok0C+gPVwEZgHlAn6d8yUqsHekjab/t1oMeJKmzVxrb9CDCdYz3gAmAocBfwRhloASDpH2B/IXWeVEhl/yfYHgXMiM3ZQD/gPOAaYCHQUB5mxUOr9GzbpwDPx+YTkpQi/hX43Hab40cm0r0VWClp9ImxLDxKYmzbg4APgbWSrk2T9QaWAgeBIZK2loDSMKAz8BswM9MNkprr2WcBNc0cW1SUJIxLWgl8Awy2fV1jv+3zgRXA2cDoEhka4Kp4XSTpQInmLDtKGcYfAtYC020vBc4kGLoTMEzSVyXkcmG8fm37CuBR4BLgb2AV8IykzSXkUxKULEGTtB54G7gUGEsI3T2BkZI+LRWPiNPitRfwGTCEkJz1AcYB6+LSU1bYXmx7DXAD0M/2mthuFnJ6tu0ewOo89U6UVJehfyqhGvQaIdsdI+mjBBzmAiPymH+LpMuzyBtD9/2Eh64W2Ebw+GmEjHye7Z5xC5SJ0x3ArAyi9sBQ239kkPWVtC0B/0ZMBU7N4/6sSBLGqwghNx9UN9H/J7Ad6A68I2l+Qn01eXLI9EVnkm8GbpZ0OLa32b4+9ncD+gJNeVJ1Fk6nNCFr2xQh24kTQtvH9UnKuXtIEsa3EBKofP7ez0CwGlhM8J56YLjtTgnmBxiT5/wDc+j7IV6/TDE0AJL2Autj89wsOt5sYu69wLImZD/n4FVU5PTsGMZyeUpW2K4C3gOuBqYQKkMvAeJo4T4bh3rCA1IofEII3Rdn4NqWo3Xo37NwOsDR5SB1PMBBSXl9Z0k880RR9AQtFifmAsOBmZKeJazZPwHjbV9UbA7pkLSOkIdcZvs522dErp2Bxjr0DpoO4WWD7S62X7a9zPbD8eFMhFJk47OAO4E5kqYCSDoEPEaILLUl4JAJ44C/gAeAXbb3ADsJR4qHgQmRZ0vDQuA7QmQcRUgyE6GoxrYt4D7CGn5PmngB8C1wk+0ri8kjEyRtAAYAiwjhuH28rgAGSfq41JwSYrCkVyQtIRzUJM17il5UeZHwBO5OPy6U1BALGu2AfUXmkRGSNgE3xqWmhnCen3GrlQe6Ekq/RYGkfQC2zwFuA25NOraoxpa0K4d8H2UydBqPBkJIL4SurJ+5ELDdnXDmPlZS4gy/VZ56tVTYbgdsAmZLmhn7+hN2D/dKWhBftngBuF3Sj/nob7Xn2S0RMdLVAlNs10QPXgI8KWlBvG050AGYb3uV7WlJ9Vc8u+VhDvAg4Q2aIcC7kp5KkQ/jWCdtshaQjoqxWxgkHbI9g7DfryNtayXpi+bqroTxFoa4bo8n7PV3FvKlx4qxWxBSysoHgZGECmO3QumvGLtl4VXCQdEISR8QDmSOP+JqJtLX7A62Z8X/ayXtLNREFWSH7ccJrzAPlLQ7dgtYavvpWPHLpaM34ZcgGXHEsyWtBjoSTqWmVAxdchjoklokkbSc8PLC9wl1bCLaDzhZ0i+pwv8ANk23Rc86Lx4AAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle \\left[ - x - 6 + \\frac{1}{x^{2}}\\right]$"
      ],
      "text/plain": [
       "⎡         1 ⎤\n",
       "⎢-x - 6 + ──⎥\n",
       "⎢          2⎥\n",
       "⎣         x ⎦"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sp.solve(sp.Eq(expr, 1), y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A *sympy* expression is represented by an abstract syntax tree (AST), which can be inspected and modified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle x^{2} \\left(x + y + 5\\right) + x^{2}$"
      ],
      "text/plain": [
       " 2                2\n",
       "x ⋅(x + y + 5) + x "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"425pt\" height=\"260pt\"\n",
       " viewBox=\"0.00 0.00 425.00 260.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 256)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-256 421,-256 421,4 -4,4\"/>\n",
       "<!-- Add(Pow(Symbol(&#39;x&#39;), Integer(2)), Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))))_() -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>Add(Pow(Symbol(&#39;x&#39;), Integer(2)), Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))))_()</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"136\" cy=\"-234\" rx=\"28.7\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"136\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\">Add</text>\n",
       "</g>\n",
       "<!-- Pow(Symbol(&#39;x&#39;), Integer(2))_(0,) -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>Pow(Symbol(&#39;x&#39;), Integer(2))_(0,)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"98\" cy=\"-162\" rx=\"29.8\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"98\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">Pow</text>\n",
       "</g>\n",
       "<!-- Add(Pow(Symbol(&#39;x&#39;), Integer(2)), Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))))_()&#45;&gt;Pow(Symbol(&#39;x&#39;), Integer(2))_(0,) -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>Add(Pow(Symbol(&#39;x&#39;), Integer(2)), Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))))_()&#45;&gt;Pow(Symbol(&#39;x&#39;), Integer(2))_(0,)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M127.19,-216.76C122.65,-208.4 117.01,-198.02 111.9,-188.61\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"114.88,-186.75 107.03,-179.63 108.72,-190.09 114.88,-186.75\"/>\n",
       "</g>\n",
       "<!-- Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,) -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"174\" cy=\"-162\" rx=\"28.7\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"174\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">Mul</text>\n",
       "</g>\n",
       "<!-- Add(Pow(Symbol(&#39;x&#39;), Integer(2)), Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))))_()&#45;&gt;Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,) -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>Add(Pow(Symbol(&#39;x&#39;), Integer(2)), Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))))_()&#45;&gt;Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M144.81,-216.76C149.42,-208.28 155.16,-197.71 160.32,-188.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"163.54,-189.61 165.23,-179.15 157.39,-186.27 163.54,-189.61\"/>\n",
       "</g>\n",
       "<!-- Symbol(&#39;x&#39;)_(0, 0) -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>Symbol(&#39;x&#39;)_(0, 0)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">x</text>\n",
       "</g>\n",
       "<!-- Pow(Symbol(&#39;x&#39;), Integer(2))_(0,)&#45;&gt;Symbol(&#39;x&#39;)_(0, 0) -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>Pow(Symbol(&#39;x&#39;), Integer(2))_(0,)&#45;&gt;Symbol(&#39;x&#39;)_(0, 0)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M82.94,-146.15C73.02,-136.37 59.87,-123.4 48.81,-112.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"51.13,-109.87 41.55,-105.35 46.21,-114.86 51.13,-109.87\"/>\n",
       "</g>\n",
       "<!-- Integer(2)_(0, 1) -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>Integer(2)_(0, 1)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n",
       "</g>\n",
       "<!-- Pow(Symbol(&#39;x&#39;), Integer(2))_(0,)&#45;&gt;Integer(2)_(0, 1) -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>Pow(Symbol(&#39;x&#39;), Integer(2))_(0,)&#45;&gt;Integer(2)_(0, 1)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M98.25,-143.7C98.36,-135.98 98.49,-126.71 98.61,-118.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"102.11,-118.15 98.76,-108.1 95.11,-118.05 102.11,-118.15\"/>\n",
       "</g>\n",
       "<!-- Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0) -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"174\" cy=\"-90\" rx=\"29.8\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"174\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">Pow</text>\n",
       "</g>\n",
       "<!-- Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,)&#45;&gt;Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0) -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,)&#45;&gt;Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M174,-143.7C174,-135.98 174,-126.71 174,-118.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"177.5,-118.1 174,-108.1 170.5,-118.1 177.5,-118.1\"/>\n",
       "</g>\n",
       "<!-- Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1) -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"284\" cy=\"-90\" rx=\"28.7\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"284\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">Add</text>\n",
       "</g>\n",
       "<!-- Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,)&#45;&gt;Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1) -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>Mul(Pow(Symbol(&#39;x&#39;), Integer(2)), Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;)))_(1,)&#45;&gt;Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M193.41,-148.65C210.74,-137.62 236.33,-121.33 255.9,-108.88\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"257.85,-111.79 264.41,-103.47 254.1,-105.88 257.85,-111.79\"/>\n",
       "</g>\n",
       "<!-- Symbol(&#39;x&#39;)_(1, 0, 0) -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>Symbol(&#39;x&#39;)_(1, 0, 0)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"102\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"102\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">x</text>\n",
       "</g>\n",
       "<!-- Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0)&#45;&gt;Symbol(&#39;x&#39;)_(1, 0, 0) -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0)&#45;&gt;Symbol(&#39;x&#39;)_(1, 0, 0)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M158.73,-74.15C148.67,-64.37 135.33,-51.4 124.11,-40.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"126.36,-37.81 116.75,-33.35 121.49,-42.83 126.36,-37.81\"/>\n",
       "</g>\n",
       "<!-- Integer(2)_(1, 0, 1) -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>Integer(2)_(1, 0, 1)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"174\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"174\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n",
       "</g>\n",
       "<!-- Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0)&#45;&gt;Integer(2)_(1, 0, 1) -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>Pow(Symbol(&#39;x&#39;), Integer(2))_(1, 0)&#45;&gt;Integer(2)_(1, 0, 1)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M174,-71.7C174,-63.98 174,-54.71 174,-46.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"177.5,-46.1 174,-36.1 170.5,-46.1 177.5,-46.1\"/>\n",
       "</g>\n",
       "<!-- Integer(5)_(1, 1, 0) -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>Integer(5)_(1, 1, 0)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"246\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"246\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">5</text>\n",
       "</g>\n",
       "<!-- Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)&#45;&gt;Integer(5)_(1, 1, 0) -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)&#45;&gt;Integer(5)_(1, 1, 0)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M275.19,-72.76C270.58,-64.28 264.84,-53.71 259.68,-44.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"262.61,-42.27 254.77,-35.15 256.46,-45.61 262.61,-42.27\"/>\n",
       "</g>\n",
       "<!-- Symbol(&#39;x&#39;)_(1, 1, 1) -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>Symbol(&#39;x&#39;)_(1, 1, 1)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"318\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"318\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">x</text>\n",
       "</g>\n",
       "<!-- Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)&#45;&gt;Symbol(&#39;x&#39;)_(1, 1, 1) -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)&#45;&gt;Symbol(&#39;x&#39;)_(1, 1, 1)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M292.06,-72.41C296.08,-64.13 301.04,-53.92 305.54,-44.66\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"308.78,-45.99 310,-35.47 302.48,-42.94 308.78,-45.99\"/>\n",
       "</g>\n",
       "<!-- Symbol(&#39;y&#39;)_(1, 1, 2) -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>Symbol(&#39;y&#39;)_(1, 1, 2)</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"390\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"390\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">y</text>\n",
       "</g>\n",
       "<!-- Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)&#45;&gt;Symbol(&#39;y&#39;)_(1, 1, 2) -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>Add(Integer(5), Symbol(&#39;x&#39;), Symbol(&#39;y&#39;))_(1, 1)&#45;&gt;Symbol(&#39;y&#39;)_(1, 1, 2)</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M302.95,-76.49C319.71,-65.42 344.35,-49.15 363.14,-36.74\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"365.15,-39.6 371.57,-31.17 361.29,-33.76 365.15,-39.6\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.sources.Source at 0x7f49dd6262d0>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ps.to_dot(expr, graph_style={'size': \"9.5,12.5\"} )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Programatically the children node type is acessible as ``expr.func`` and its children as ``expr.args``.\n",
    "With these members a tree can be traversed and modified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "sympy.core.add.Add"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.func"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left( x^{2}, \\  x^{2} \\left(x + y + 5\\right)\\right)$"
      ],
      "text/plain": [
       "⎛ 2   2            ⎞\n",
       "⎝x , x ⋅(x + y + 5)⎠"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr.args"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using *pystencils* \n",
    "\n",
    "\n",
    "### Fields\n",
    "\n",
    "*pystencils* is a module to generate code for stencil operations. \n",
    "One has to specify an update rule for each element of an array, with optional dependencies to neighbors.\n",
    "This is done use pure *sympy* with one addition: **Fields**.\n",
    "\n",
    "Fields represent a multidimensional array, where some dimensions are considered *spatial*, and some as *index* dimensions. Spatial coordinates are given relative (i.e. one can specify \"the current cell\" and \"the left neighbor\") whereas index dimensions are used to index multiple values per cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_field = ps.fields(\"f(3) : double[2D]\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Neighbors are labeled according to points on a compass where the first coordinate is west/east, second coordinate north/south and third coordinate top/bottom. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAC0AAAAeCAYAAAC49JeZAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjExLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvctoD+AAAAAlwSFlzAAASdAAAEnQB3mYfeAAAA0ZJREFUeJzVmE+IVVUcxz+OOqbWuJgczBF0Rl2ISoiaIKSIKGIo/RENFCJwIe5q08b48oUQFBepOEJgCm4sWwSi1EqTNqkUQYSpGJZKME5Ig+no6LQ4576Ob+6bd5/63ozfzbv39+983rn3nN+9d9TAwADPm8YUDbQ9AXgX2ALclfRG3aiqqKmG2J+A14HrwKv1wSmmWqAXSXof+LVeMEU15O1huxloBu5L6m0MUnUNgrbdAuwC3gEmR/PHwCcN5BpSeTN9BHgrHt8DHgIXGwVURI9B2+4kAF8CVku6NixUVTQGwHYTMAFYG+2fAT22XwT+lfRomPhyle0e64BeYH883xPPe4G5w8A1pLLbox24A4wn/JE70T4AXAWwfQBYAkwB2mxfiDFvSrreMGIitKQuoMv2DaBJ0is5sXuBlhx7dx35clVaiLanAlOBE3mBki41Cqqa0o64OP5eyAscScqDPj8cILWo8Ezb7rA9qf5IpfFabHfk+VLohcA1SYMWVkz+gfAcUu6bYXv2U8C1256e4xoLnLM9s9yRNZdOoBU4U6H2TuBQ+odsbwa2AwuAm8CsGmFnAMeBOUC/7ZvARkm/AEjqsX0ojr0pzc1muuL9bLsd2AB8XuZaAXwE7K4FNtEXwN+EyWoFfga+tj02iTkMvB0ZBkHPJzSUcznF1wN/SLqcGiVtlfT9k9DaXgC8FsqoT9JDwpPkTGBlMsZvhKu4Ps3PmssOYEeFMZYQZuFZaiGh25aurKQrtruj75sk9kdgKXAwMxR5c5kC3HomqP+rFbgdZzhVD/Byma07MpRUBPo+ObvGU6q/Qs1xwIMcW19qKAL9OzDtidAq609gou2XMoPt0UBb9KVqjwwlFYH+Dlgcn7lrku05tifnuM4S3ojWJrblwETgdJLfRNjZTqfJRb57nCRcnlXAt0nBjjhIG9Bse150XZTUH4/PE/bZnWlBSX/Z7gL22n4Q6+8Dvsz26ahVhNvzVJpfdfYk9QGfEhpJKgPHgGXAP/H4GGGRZQ2rGfiqQukPCC8bHxK2u6PAe2Ux24B9ku6lxlFFPovZfoGwDW2VdKVqQsjZAMyXpCLxOfmdhOayRtLd1FcIeqSp5sU1EvQfViD8QbCuyrsAAAAASUVORK5CYII=",
      "text/latex": [
       "$\\displaystyle {f}_{(1,0)}^{1}$"
      ],
      "text/plain": [
       "f_E__1"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "field_access = my_field[1, 0](1)\n",
    "field_access"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The result of indexing a field is an instance of ``Field.Access``. This class is a subclass of a *sympy* Symbol and thus can be used whereever normal symbols can be used. It is just like a normal symbol with some additional information attached to it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance(field_access, sp.Symbol)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Building our first stencil kernel\n",
    "\n",
    "Lets start by building a simple filter kernel. We create a field representing an image, then define a edge detection filter on the third pixel component which is blue for an RGB image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "img_field = ps.fields(\"img(4): [2D]\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left({img}_{(1,0)}^{2} w_{2} - {img}_{(1,1)}^{2} w_{1} - {img}_{(-1,1)}^{2} w_{1} + {img}_{(1,-1)}^{2} w_{1} - {img}_{(-1,-1)}^{2} w_{1} - {img}_{(-1,0)}^{2} w_{2}\\right)^{2}$"
      ],
      "text/plain": [
       "                                                                               ↪\n",
       "(img_E__2⋅w₂ - img_NE__2⋅w₁ - img_NW__2⋅w₁ + img_SE__2⋅w₁ - img_SW__2⋅w₁ - img ↪\n",
       "\n",
       "↪          2\n",
       "↪ _W__2⋅w₂) "
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w1, w2 = sp.symbols(\"w_1 w_2\")\n",
    "color = 2\n",
    "sobel_x = (-w2 * img_field[-1,0](color) - w1 * img_field[-1,-1](color) - w1 * img_field[-1, +1](color) \\\n",
    "           +w2 * img_field[+1,0](color) + w1 * img_field[+1,-1](color) - w1 * img_field[+1, +1](color))**2\n",
    "sobel_x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have mixed some standard *sympy* symbols into this expression to possibly give the different directions different weights. The complete expression is still a valid *sympy* expression, so all features of *sympy* work on it. Lets for example now fix one weight by substituting it with a constant."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle \\left({img}_{(1,0)}^{2} w_{2} - 0.5 {img}_{(1,1)}^{2} - 0.5 {img}_{(-1,1)}^{2} + 0.5 {img}_{(1,-1)}^{2} - 0.5 {img}_{(-1,-1)}^{2} - {img}_{(-1,0)}^{2} w_{2}\\right)^{2}$"
      ],
      "text/plain": [
       "                                                                               ↪\n",
       "(img_E__2⋅w₂ - 0.5⋅img_NE__2 - 0.5⋅img_NW__2 + 0.5⋅img_SE__2 - 0.5⋅img_SW__2 - ↪\n",
       "\n",
       "↪              2\n",
       "↪  img_W__2⋅w₂) "
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sobel_x = sobel_x.subs(w1, 0.5)\n",
    "sobel_x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets built an executable kernel out of it, which writes the result to a second field. Assignments are created using *pystencils* `Assignment` class, that gets the left- and right hand side of the assignment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/latex": [
       "$\\displaystyle {dst}_{(0,0)} \\leftarrow_{} \\left({img}_{(1,0)}^{2} w_{2} - 0.5 {img}_{(1,1)}^{2} - 0.5 {img}_{(-1,1)}^{2} + 0.5 {img}_{(1,-1)}^{2} - 0.5 {img}_{(-1,-1)}^{2} - {img}_{(-1,0)}^{2} w_{2}\\right)^{2}$"
      ],
      "text/plain": [
       "                                                                               ↪\n",
       "dst_C := (img_E__2⋅w₂ - 0.5⋅img_NE__2 - 0.5⋅img_NW__2 + 0.5⋅img_SE__2 - 0.5⋅im ↪\n",
       "\n",
       "↪                       2\n",
       "↪ g_SW__2 - img_W__2⋅w₂) "
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dst_field = ps.fields('dst: [2D]' )\n",
    "update_rule = ps.Assignment(dst_field[0,0], sobel_x)\n",
    "update_rule"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we can see *pystencils* in action which creates a kernel for us."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pystencils import create_kernel\n",
    "ast = create_kernel(update_rule)\n",
    "compiled_kernel = ast.compile()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This compiled kernel is now just an ordinary Python function. \n",
    "Now lets grab an image to apply this filter to:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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gjNnzuCLL77Az3/+c8GG7smx6ezsBAC88847uOOOO/Daa6/hzjvvxNKlS9HT0wMguvfklBI1er0edrsdDodDkj40NKQ4I4Xwj16vx9DQkCSNP+avZTA204UjR47g3nvvxd///d/jiSeeENL5pb6VrpP4Oo5lM11444038P777+Py5cvo7OzEN77xDeEc3ZNj85vf/AYjIyMwGo14++238fbbb8PpdOLkyZPYuXMnALong6WwsBDz588XjmfOnIlvfetbwnUE6J4MBv4ztra24ty5c/jrX/+K+vp6dHd34/nnnwcQ3XtySoka/pdJc3OzkOZyudDS0oIbbrhhspo1JSkuLvZx11+9ehXx8fHIysoK2mY6cPToUdx22214+umn8U//9E+Sc/w9Kb9OTU1Nwj0ZjM10w2Aw4IEHHsCBAweENH/3m1qtRlFRUdA2sUxhYSGqqqqwY8cO4c/lcqGmpgZ79uwB4P9+u3r16pj3pNhmOpKUlISuri7h2N/9BkByLceyiWWKioqgVquxadMmaLVaAEBiYiLWr1+PEydOAPBeh0D3WzA2QRF09M11wMjICEtOTmYvvPCCkPbBBx8wjuPYuXPnJrFl1y/+AoV//etfs5SUFGY2mxljnpk9y5cvZ5s3bw7JJtY5duwYM5lM7Cc/+YnieYfDwbKystjzzz8vpO3bt48BYF999VXQNrGO0iyvb37zm2zWrFnC8auvvsoMBgPr6uoS0jZs2MDWrl0bks10Q2n2U0lJCXvmmWeE41OnTjEAbO/evSHZxDLye9LlcrGqqirJ5Iht27YxlUolWXrgoYceYkuWLAnJJta57bbb2OOPPy5JW7VqFbvvvvuE48rKSvb1r39dOL58+TJTqVTsz3/+c0g2YzGlRA1j3qjy559/nv36179mGRkZ7Pvf//5kN+u6wmKxsLfeeou99dZbLDc3l917773srbfekjyshoaG2Lx589jSpUvZb3/7W7Z582ZmMpkk4jAYm1jm0qVLLDk5mZWXlwvXk/8TTwP9r//6L6bRaNhPfvIT9r//9/9mubm57Jvf/KakrGBsYpknn3ySbdmyhb300kvs97//PduyZQvT6/WSKfM2m41VVVWxxYsXs5dffpk99thjLC4uTiL8grGZbiiJmp07dzKNRsN+8IMfsH/7t39jM2fOZHfffXfINrHMT37yE7Zp0yb2r//6r+zll19my5cvZ+np6ay6ulqwcblcbPXq1Wzu3LnspZdeYk899RTT6XTsiy++CMkm1jl9+jRLTk5m3//+99lrr73GHn30URYXFye5lvv27WM6nY79zd/8DXvppZfYnDlz2OrVqyWzFoOxGYspuUv3Z599hj//+c+w2WxYu3YtHnrooWm3ym0gent78fTTT/ukz5kzB//jf/wP4dhsNuO3v/2tsFrwU089hZkzZ0ryBGMTq9TU1GDr1q2K51588UXJcMeXX36Jt99+GxaLBbfccgsee+wxn1Vug7GJZXbt2oVPPvkEIyMjuOGGG/DYY4/5rGBrsVjwu9/9DjU1NcjMzMR3vvMdzJ49O2Sb6cTjjz+ORx55BOvXr5ekHz9+HG+++SbMZjOWLVuGb33rWz6zpYKxiWX27t2L3bt3Y3h4GHPmzMETTzwBk8kksbHZbHj11Vfx1VdfITU1FY8//jgWLlwYsk2s09jYiFdffRVtbW1CfFJ+fr7E5vTp03jjjTfQ29uLJUuW4MknnxRiaUKxCcSUFDUEQRAEQRByps/PRIIgCIIgYhoSNQRBEARBxAQkagiCIAiCiAlI1BAEQRAEEROQqCEIgiAIIiYgUUMQBEEQRExAooYgCIIgiJiARA1BEARBEDEBiRqCIAiCIGICEjUEQRAEQcQEJGoIgiAIgogJSNQQBEEQBBET/P8Jccsh39uQ7wAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "try:\n",
    "    import requests\n",
    "    import imageio.v2 as imageio\n",
    "    from io import BytesIO\n",
    "\n",
    "    response = requests.get(\"https://www.python.org/static/community_logos/python-logo-master-v3-TM.png\")\n",
    "    img = imageio.imread(BytesIO(response.content)).astype(np.double)\n",
    "    img /= img.max()\n",
    "    plt.imshow(img);\n",
    "except ImportError:\n",
    "    print(\"No requests or imageio installed\")\n",
    "    img = np.random.random((82, 290, 4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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MzP43ve+h56eHtx6661rPmFUq9Xw//7f/8Pc3BxuuOEGjIyMrJFBKaOFd4Xh6aef9rZs2eIdOHDAe/nLX+61t7d7X/jCFy63Wi8qnDlzxvvJn/xJb9u2bV57e7v3gQ98QFruPe95j9fe3u699rWv9QYHB7277rrLW15eti6zUTE5Oen92I/9mDcyMuK9/vWv96699lpv69at3r/8y780lTt27Ji3bds275prrvFe+cpXevl83vvrv/5r6zIbGYcOHfJuvvlm74YbbvB+7Md+zNu6dat37bXXeqOjo03lPvCBD3j5fN675557vK1bt3q33HKLNzc3Z13mpYCFhQVvz549Xjwe9z760Y82nTtz5oy3Z88eb8+ePd5dd93l5XI578///M+ty2xkfP/73/cAeG9+85u9Bx54wP/3/PPPN5X7yEc+4uVyOe/uu+/2tm/f7l133XXexMSEdZmNjg996ENePp/37r77bu+ee+7xXv7ylzety4mJCe+6667zduzY4d19991eLpfzPvKRjzTJoJQx4YojNdddd533wAMP+L9///d/3+vs7PRmZ2cvo1YvLjzzzDPe5z73Oa9arXr79u2TkpovfvGLXjKZ9J566inP8zxvenraGx4e9n7nd37HqsxGxunTp70vf/nL/u9Go+H98i//srdly5amcrfddpt33333efV63fM8z/uTP/kTL5fLeePj41ZlNjKeeOIJ78SJE/7vUqnkHThwwPv5n/95/9g///M/ewB80ri4uOhdddVV3q/+6q9alXmp4Kd/+qe93/u93/Pa2trWkJrXve513l133eVVq1XP8zzvv//3/+4lk8mmDZtSZiODkZr5+XllmSeffNKLxWLeo48+6nme562urno33HCD95a3vMWqzEbHI4884mUyGe873/mOf+z73/++NzY25v9+4IEHvJtuuskrFoue513aX2KxmL+/UMuYcEWRmqefftoD4H33u9/1jy0sLHjpdNr79Kc/fRk1e/FCRWp+8id/0nvta1/bdOzf/tt/6w0PD1uVeanhq1/9qgfAm5yc9DzP855//nkPgPeP//iPfpnV1VWvra3N+9jHPkYu81LEfffd573pTW/yf//SL/2Sd8sttzSV+Y//8T96nZ2dPhmklHkp4OMf/7h3++23e9VqdQ2pmZyc9GKxWFMGu1areQMDA96HPvQhcpmNDkZqvvzlL3uPPvqolMy9973v9fbs2dN07BOf+ISXTqe9lZUVcpmNjt27d3vvete7lOdXVla8dDrtPfLII03Hd+3a5f3Wb/0WuQwFV9SFaPZ5huuuu84/1tXVhW3btq35dEMEPY4cOdI0jgBw4MABXLhwAQsLC+QyLzV84xvfwKZNm/z7YWQ2mcvlsGfPHv8cpcxLBV/4whfwl3/5l/j1X/91PPvss/jgBz/on1PZ29LSEs6dO0cus9Hx7LPP4nd/93fx13/919L7Np599ll4ntc0TolEAvv37/ftjVLmpYBkMokPf/jD+NM//VMcPHgQ999/P1ZXV/3zR44cWXM/4oEDB1CpVPDcc8+Ry2xkjI+P49SpU7j33nvx3HPP4ctf/jKeeuopeNwr8E6ePIlKpSJdu8zeKGUouKJIzeLiItLpNPL5fNPxvr6+l+wm64rFxUX/S+cM7OY4NpaUMi8l/OM//iM++tGP4sMf/rB/bHFxEQCk48SPo6nMSwWPPvoovvCFL+CLX/wibrjhhqabpSObNKNYLOKBBx7Ahz/8YezevVtaJrJJGjZt2oRnnnkG3/nOd/AP//APOHr0KL71rW/hd3/3d/0ykU2aMTU1BQD47Gc/i9e//vV45JFH8IY3vAG33347ZmdnAayvTV5RpCaTyaBSqaBarTYdX15elj6REkGNTCaD5eXlpmPsNxtLSpmXCp544gm86U1vwm//9m/jF3/xF/3j7FXfsnHix9FU5qWCT3/60/jyl7+M06dPY2pqCj//8z/vn4ts0ow//uM/RrFYRC6Xw9/+7d/ib//2b1Gr1fDUU0/h0UcfBRDZJBUjIyO49tpr/d87d+7EO97xDn8cgcgmKWB9HB8fx/Hjx/F3f/d3eO655zAzM4OHHnoIwPra5BVFalhkcv78ef9YvV7H2NgYdu3adbnUuiKxe/fuNen60dFRtLW1YXBwkFzmpYDvfve7eN3rXod3v/vd+IM/+IOmc8wmxXE6d+6cb5OUMi81ZLNZ/NRP/RQee+wx/5jK3hKJBLZv304us5ExMjKCW265BV/60pf8f/V6HYcOHcLf//3fA1Db2+joqNEm+TIvRXR2dmJ6etr/rbI3AE1jaSqzkbF9+3YkEgncd999SKVSAICOjg7ce++9ePLJJwH8cBx09kYpQwL57psXAYrFotfd3e19+MMf9o995Stf8WKxmHf8+PHLqNmLF6obhf/oj/7I6+np8ZaWljzPu/Rkz5133undf//9VmU2Or73ve95XV1d3vve9z7p+Wq16g0ODnoPPfSQf+yb3/ymB8D7wQ9+QC6z0SF7yusXfuEXvKuuusr//clPftLLZrPe9PS0f+xHfuRHvHvuuceqzEsNsqef9uzZ473nPe/xfz/zzDMeAO8b3/iGVZmNDNEm6/W6d8sttzQ9HPG5z33Oi8fjTa8eeMtb3uLdfPPNVmU2Ol73utd5b3/725uO3XXXXd6b3/xm//dNN93k/dzP/Zz/+/Tp0148Hvc+//nPW5Ux4YoiNZ73w7vKH3roIe+P/uiPvIGBAe/Xf/3XL7daLyqsrq56n/nMZ7zPfOYz3tDQkPemN73J+8xnPtPkrJaXl739+/d7t99+u/dnf/Zn3v333+91dXU1kUNKmY2MF154wevu7vZuuOEGfzzZP/4x0P/5P/+nl0wmvfe9733ef/pP/8kbGhryfuEXfqFJFqXMRsY73/lO74EHHvA++tGPeh//+Me9Bx54wMtkMk2PzJfLZe+WW27xrr/+eu9jH/uY97a3vc3L5/NNxI9S5qUGGal59NFHvWQy6f3Gb/yG96d/+qfezp07vR//8R+3LrOR8b73vc+77777vP/8n/+z97GPfcy78847vf7+fu/pp5/2y9Trde/Vr361d80113gf/ehHvXe9611eOp32vvWtb1mV2eg4fPiw193d7f36r/+698gjj3g/+7M/6+Xz+aax/OY3v+ml02nvV37lV7yPfvSj3tVXX+29+tWvbnpqkVLGhCvyK93/9E//hM9//vMol8u455578Ja3vOUl95ZbHebm5vDud797zfGrr74a//7f/3v/99LSEv7sz/7Mf1vwu971LuzcubOpDqXMRsWhQ4fw8MMPS8995CMfabrc8e1vfxt/+7d/i9XVVbzqVa/C2972tjVvuaWU2cj46le/in/4h39AsVjErl278La3vW3NG2xXV1fxF3/xFzh06BA2bdqEX/7lX8a+ffusy7yU8Pa3vx1vfetbce+99zYd//73v4+//uu/xtLSEu644w684x3vWPO0FKXMRsY3vvENfP3rX8fKygquvvpq/OIv/iK6urqaypTLZXzyk5/ED37wA/T29uLtb387Xvayl1mX2eg4c+YMPvnJT2JiYsK/P2l4eLipzOHDh/HpT38ac3NzuPnmm/HOd77Tv5fGpowOVySpiRAhQoQIESJEEPHSCRMjRIgQIUKECBsaEamJECFChAgRImwIRKQmQoQIESJEiLAhEJGaCBEiRIgQIcKGQERqIkSIECFChAgbAhGpiRAhQoQIESJsCESkJkKECBEiRIiwIRCRmggRIkSIECHChkBEaiJEiBAhQoQIGwIRqYkQIUKECBEibAhEpCZChAgRIkSIsCEQkZoIESJEiBAhwobA/wfUqWwT+2Y9+QAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "filtered_image = np.zeros_like(img[..., 0])\n",
    "# here we call the compiled stencil function\n",
    "compiled_kernel(img=img, dst=filtered_image, w_2=0.5)\n",
    "plt.imshow(filtered_image, cmap='gray');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Digging into *pystencils*\n",
    "\n",
    "On our way we have created an ``ast``-object. We can inspect this, to see what *pystencils* actually does."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "#   TODO nbackend\n",
    "# ps.to_dot(ast, graph_style={'size': \"9.5,12.5\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*pystencils* also builds a tree structure of the program, where each `Assignment` node internally again has a *sympy* AST which is not printed here. Out of this representation *C* code can be generated:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>pre { line-height: 125%; }\n",
       "td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".output_html .hll { background-color: #ffffcc }\n",
       ".output_html { background: #f8f8f8; }\n",
       ".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n",
       ".output_html .err { border: 1px solid #F00 } /* Error */\n",
       ".output_html .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".output_html .o { color: #666 } /* Operator */\n",
       ".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n",
       ".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n",
       ".output_html .cp { color: #9C6500 } /* Comment.Preproc */\n",
       ".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n",
       ".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n",
       ".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n",
       ".output_html .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".output_html .ge { font-style: italic } /* Generic.Emph */\n",
       ".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n",
       ".output_html .gr { color: #E40000 } /* Generic.Error */\n",
       ".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".output_html .gi { color: #008400 } /* Generic.Inserted */\n",
       ".output_html .go { color: #717171 } /* Generic.Output */\n",
       ".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".output_html .gs { font-weight: bold } /* Generic.Strong */\n",
       ".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".output_html .gt { color: #04D } /* Generic.Traceback */\n",
       ".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".output_html .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".output_html .kt { color: #B00040 } /* Keyword.Type */\n",
       ".output_html .m { color: #666 } /* Literal.Number */\n",
       ".output_html .s { color: #BA2121 } /* Literal.String */\n",
       ".output_html .na { color: #687822 } /* Name.Attribute */\n",
       ".output_html .nb { color: #008000 } /* Name.Builtin */\n",
       ".output_html .nc { color: #00F; font-weight: bold } /* Name.Class */\n",
       ".output_html .no { color: #800 } /* Name.Constant */\n",
       ".output_html .nd { color: #A2F } /* Name.Decorator */\n",
       ".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n",
       ".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n",
       ".output_html .nf { color: #00F } /* Name.Function */\n",
       ".output_html .nl { color: #767600 } /* Name.Label */\n",
       ".output_html .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n",
       ".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".output_html .nv { color: #19177C } /* Name.Variable */\n",
       ".output_html .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n",
       ".output_html .w { color: #BBB } /* Text.Whitespace */\n",
       ".output_html .mb { color: #666 } /* Literal.Number.Bin */\n",
       ".output_html .mf { color: #666 } /* Literal.Number.Float */\n",
       ".output_html .mh { color: #666 } /* Literal.Number.Hex */\n",
       ".output_html .mi { color: #666 } /* Literal.Number.Integer */\n",
       ".output_html .mo { color: #666 } /* Literal.Number.Oct */\n",
       ".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".output_html .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n",
       ".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n",
       ".output_html .sx { color: #008000 } /* Literal.String.Other */\n",
       ".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n",
       ".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".output_html .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".output_html .fm { color: #00F } /* Name.Function.Magic */\n",
       ".output_html .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".output_html .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".output_html .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".output_html .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".output_html .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"kt\">void</span><span class=\"w\"> </span><span class=\"nf\">kernel</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"kt\">double</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">RESTRICT</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">_data_dst</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"kt\">double</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">RESTRICT</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_size_dst_0</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_size_dst_1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_0</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"p\">)</span>\n",
       "<span class=\"p\">{</span>\n",
       "<span class=\"w\">   </span><span class=\"k\">for</span><span class=\"p\">(</span><span class=\"n\">ctr_0</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"n\">_size_dst_0</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span>\n",
       "<span class=\"w\">   </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">      </span><span class=\"k\">for</span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"n\">_size_dst_1</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span>\n",
       "<span class=\"w\">      </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">         </span><span class=\"n\">_data_dst</span><span class=\"p\">[</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_1</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">([</span><span class=\"mf\">0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">([</span><span class=\"mf\">0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]);</span>\n",
       "<span class=\"w\">      </span><span class=\"p\">}</span>\n",
       "<span class=\"w\">   </span><span class=\"p\">}</span>\n",
       "<span class=\"p\">}</span>\n",
       "</pre></div>\n"
      ],
      "text/latex": [
       "\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n",
       "\\PY{k+kt}{void}\\PY{+w}{ }\\PY{n+nf}{kernel}\\PY{+w}{ }\\PY{p}{(}\\PY{k+kt}{double}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{RESTRICT}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}dst}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{k+kt}{double}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{RESTRICT}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}0}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}1}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}0}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}1}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{float64}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{p}{)}\n",
       "\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{   }\\PY{k}{for}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{\\PYZlt{}}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}0}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\n",
       "\\PY{+w}{   }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{      }\\PY{k}{for}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{\\PYZlt{}}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}1}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\n",
       "\\PY{+w}{      }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{         }\\PY{n}{\\PYZus{}data\\PYZus{}dst}\\PY{p}{[}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}1}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{(}\\PY{p}{[}\\PY{l+m+mf}{0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{(}\\PY{p}{[}\\PY{l+m+mf}{0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{p}{)}\\PY{p}{;}\n",
       "\\PY{+w}{      }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{+w}{   }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{p}{\\PYZcb{}}\n",
       "\\end{Verbatim}\n"
      ],
      "text/plain": [
       "void kernel (double * RESTRICT const _data_dst, const double * RESTRICT const _data_img, const int64 _size_dst_0, const int64 _size_dst_1, const int64 _stride_dst_0, const int64 _stride_dst_1, const int64 _stride_img_0, const int64 _stride_img_1, const int64 _stride_img_2, const float64 w_2)\n",
       "{\n",
       "   for(ctr_0: int64 = [1: int64]; ctr_0 < _size_dst_0 - [1: int64]; ctr_0 += [1: int64])\n",
       "   {\n",
       "      for(ctr_1: int64 = [1: int64]; ctr_1 < _size_dst_1 - [1: int64]; ctr_1 += [1: int64])\n",
       "      {\n",
       "         _data_dst[ctr_0 * _stride_dst_0 + ctr_1 * _stride_dst_1] = ([0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + w_2 * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2] - w_2 * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2]) * ([0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + w_2 * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2] - w_2 * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2]);\n",
       "      }\n",
       "   }\n",
       "}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ps.inspect(ast)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Behind the scenes this code is compiled into a shared library and made available as a Python function. Before compiling this function we can modify the AST object, for example to parallelize it with OpenMP."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>pre { line-height: 125%; }\n",
       "td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".output_html .hll { background-color: #ffffcc }\n",
       ".output_html { background: #f8f8f8; }\n",
       ".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n",
       ".output_html .err { border: 1px solid #F00 } /* Error */\n",
       ".output_html .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".output_html .o { color: #666 } /* Operator */\n",
       ".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n",
       ".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n",
       ".output_html .cp { color: #9C6500 } /* Comment.Preproc */\n",
       ".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n",
       ".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n",
       ".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n",
       ".output_html .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".output_html .ge { font-style: italic } /* Generic.Emph */\n",
       ".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n",
       ".output_html .gr { color: #E40000 } /* Generic.Error */\n",
       ".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".output_html .gi { color: #008400 } /* Generic.Inserted */\n",
       ".output_html .go { color: #717171 } /* Generic.Output */\n",
       ".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".output_html .gs { font-weight: bold } /* Generic.Strong */\n",
       ".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".output_html .gt { color: #04D } /* Generic.Traceback */\n",
       ".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".output_html .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".output_html .kt { color: #B00040 } /* Keyword.Type */\n",
       ".output_html .m { color: #666 } /* Literal.Number */\n",
       ".output_html .s { color: #BA2121 } /* Literal.String */\n",
       ".output_html .na { color: #687822 } /* Name.Attribute */\n",
       ".output_html .nb { color: #008000 } /* Name.Builtin */\n",
       ".output_html .nc { color: #00F; font-weight: bold } /* Name.Class */\n",
       ".output_html .no { color: #800 } /* Name.Constant */\n",
       ".output_html .nd { color: #A2F } /* Name.Decorator */\n",
       ".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n",
       ".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n",
       ".output_html .nf { color: #00F } /* Name.Function */\n",
       ".output_html .nl { color: #767600 } /* Name.Label */\n",
       ".output_html .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n",
       ".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".output_html .nv { color: #19177C } /* Name.Variable */\n",
       ".output_html .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n",
       ".output_html .w { color: #BBB } /* Text.Whitespace */\n",
       ".output_html .mb { color: #666 } /* Literal.Number.Bin */\n",
       ".output_html .mf { color: #666 } /* Literal.Number.Float */\n",
       ".output_html .mh { color: #666 } /* Literal.Number.Hex */\n",
       ".output_html .mi { color: #666 } /* Literal.Number.Integer */\n",
       ".output_html .mo { color: #666 } /* Literal.Number.Oct */\n",
       ".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".output_html .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n",
       ".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n",
       ".output_html .sx { color: #008000 } /* Literal.String.Other */\n",
       ".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n",
       ".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".output_html .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".output_html .fm { color: #00F } /* Name.Function.Magic */\n",
       ".output_html .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".output_html .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".output_html .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".output_html .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".output_html .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"kt\">void</span><span class=\"w\"> </span><span class=\"nf\">kernel</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"kt\">double</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">RESTRICT</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">_data_dst</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"kt\">double</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">RESTRICT</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_size_dst_0</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_size_dst_1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_0</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"p\">)</span>\n",
       "<span class=\"p\">{</span>\n",
       "<span class=\"w\">   </span><span class=\"cp\">#pragma omp parallel num_threads(2)</span>\n",
       "<span class=\"w\">   </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">      </span><span class=\"cp\">#pragma omp for schedule(static)</span>\n",
       "<span class=\"w\">      </span><span class=\"k\">for</span><span class=\"p\">(</span><span class=\"n\">ctr_0</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"n\">_size_dst_0</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span>\n",
       "<span class=\"w\">      </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">         </span><span class=\"k\">for</span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"n\">_size_dst_1</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span>\n",
       "<span class=\"w\">         </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">            </span><span class=\"n\">_data_dst</span><span class=\"p\">[</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_dst_1</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">([</span><span class=\"mf\">0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">([</span><span class=\"mf\">0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-0.5</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"n\">w_2</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_img</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_stride_img_2</span><span class=\"p\">]);</span>\n",
       "<span class=\"w\">         </span><span class=\"p\">}</span>\n",
       "<span class=\"w\">      </span><span class=\"p\">}</span>\n",
       "<span class=\"w\">   </span><span class=\"p\">}</span>\n",
       "<span class=\"p\">}</span>\n",
       "</pre></div>\n"
      ],
      "text/latex": [
       "\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n",
       "\\PY{k+kt}{void}\\PY{+w}{ }\\PY{n+nf}{kernel}\\PY{+w}{ }\\PY{p}{(}\\PY{k+kt}{double}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{RESTRICT}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}dst}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{k+kt}{double}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{RESTRICT}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}0}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}1}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}0}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}1}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{,}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{float64}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{p}{)}\n",
       "\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{   }\\PY{c+cp}{\\PYZsh{}}\\PY{c+cp}{pragma omp parallel num\\PYZus{}threads(2)}\n",
       "\\PY{+w}{   }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{      }\\PY{c+cp}{\\PYZsh{}}\\PY{c+cp}{pragma omp for schedule(static)}\n",
       "\\PY{+w}{      }\\PY{k}{for}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{\\PYZlt{}}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}0}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\n",
       "\\PY{+w}{      }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{         }\\PY{k}{for}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{\\PYZlt{}}\\PY{+w}{ }\\PY{n}{\\PYZus{}size\\PYZus{}dst\\PYZus{}1}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\n",
       "\\PY{+w}{         }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{            }\\PY{n}{\\PYZus{}data\\PYZus{}dst}\\PY{p}{[}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}dst\\PYZus{}1}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{(}\\PY{p}{[}\\PY{l+m+mf}{0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{(}\\PY{p}{[}\\PY{l+m+mf}{0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}0.5}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{n}{w\\PYZus{}2}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}img}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}stride\\PYZus{}img\\PYZus{}2}\\PY{p}{]}\\PY{p}{)}\\PY{p}{;}\n",
       "\\PY{+w}{         }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{+w}{      }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{+w}{   }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{p}{\\PYZcb{}}\n",
       "\\end{Verbatim}\n"
      ],
      "text/plain": [
       "void kernel (double * RESTRICT const _data_dst, const double * RESTRICT const _data_img, const int64 _size_dst_0, const int64 _size_dst_1, const int64 _stride_dst_0, const int64 _stride_dst_1, const int64 _stride_img_0, const int64 _stride_img_1, const int64 _stride_img_2, const float64 w_2)\n",
       "{\n",
       "   #pragma omp parallel num_threads(2)\n",
       "   {\n",
       "      #pragma omp for schedule(static)\n",
       "      for(ctr_0: int64 = [1: int64]; ctr_0 < _size_dst_0 - [1: int64]; ctr_0 += [1: int64])\n",
       "      {\n",
       "         for(ctr_1: int64 = [1: int64]; ctr_1 < _size_dst_1 - [1: int64]; ctr_1 += [1: int64])\n",
       "         {\n",
       "            _data_dst[ctr_0 * _stride_dst_0 + ctr_1 * _stride_dst_1] = ([0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + w_2 * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2] - w_2 * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2]) * ([0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + [-0.5: float64] * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + (ctr_1 + [-1: int64]) * _stride_img_1 + [2: int64] * _stride_img_2] + w_2 * _data_img[(ctr_0 + [1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2] - w_2 * _data_img[(ctr_0 + [-1: int64]) * _stride_img_0 + ctr_1 * _stride_img_1 + [2: int64] * _stride_img_2]);\n",
       "         }\n",
       "      }\n",
       "   }\n",
       "}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "cfg = ps.CreateKernelConfig()\n",
    "cfg.cpu.openmp.enable = True\n",
    "cfg.cpu.openmp.num_threads = 2\n",
    "ast = ps.create_kernel(\n",
    "    update_rule,\n",
    "    cfg\n",
    ")\n",
    "\n",
    "ps.inspect(ast)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fixed array sizes\n",
    "\n",
    "Since we already know the arrays to which the kernel should be applied, we can \n",
    "create *Field* objects with fixed size, based on a numpy array:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>pre { line-height: 125%; }\n",
       "td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".output_html .hll { background-color: #ffffcc }\n",
       ".output_html { background: #f8f8f8; }\n",
       ".output_html .c { color: #3D7B7B; font-style: italic } /* Comment */\n",
       ".output_html .err { border: 1px solid #F00 } /* Error */\n",
       ".output_html .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".output_html .o { color: #666 } /* Operator */\n",
       ".output_html .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\n",
       ".output_html .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\n",
       ".output_html .cp { color: #9C6500 } /* Comment.Preproc */\n",
       ".output_html .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\n",
       ".output_html .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\n",
       ".output_html .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\n",
       ".output_html .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".output_html .ge { font-style: italic } /* Generic.Emph */\n",
       ".output_html .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n",
       ".output_html .gr { color: #E40000 } /* Generic.Error */\n",
       ".output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".output_html .gi { color: #008400 } /* Generic.Inserted */\n",
       ".output_html .go { color: #717171 } /* Generic.Output */\n",
       ".output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".output_html .gs { font-weight: bold } /* Generic.Strong */\n",
       ".output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".output_html .gt { color: #04D } /* Generic.Traceback */\n",
       ".output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".output_html .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".output_html .kt { color: #B00040 } /* Keyword.Type */\n",
       ".output_html .m { color: #666 } /* Literal.Number */\n",
       ".output_html .s { color: #BA2121 } /* Literal.String */\n",
       ".output_html .na { color: #687822 } /* Name.Attribute */\n",
       ".output_html .nb { color: #008000 } /* Name.Builtin */\n",
       ".output_html .nc { color: #00F; font-weight: bold } /* Name.Class */\n",
       ".output_html .no { color: #800 } /* Name.Constant */\n",
       ".output_html .nd { color: #A2F } /* Name.Decorator */\n",
       ".output_html .ni { color: #717171; font-weight: bold } /* Name.Entity */\n",
       ".output_html .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\n",
       ".output_html .nf { color: #00F } /* Name.Function */\n",
       ".output_html .nl { color: #767600 } /* Name.Label */\n",
       ".output_html .nn { color: #00F; font-weight: bold } /* Name.Namespace */\n",
       ".output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".output_html .nv { color: #19177C } /* Name.Variable */\n",
       ".output_html .ow { color: #A2F; font-weight: bold } /* Operator.Word */\n",
       ".output_html .w { color: #BBB } /* Text.Whitespace */\n",
       ".output_html .mb { color: #666 } /* Literal.Number.Bin */\n",
       ".output_html .mf { color: #666 } /* Literal.Number.Float */\n",
       ".output_html .mh { color: #666 } /* Literal.Number.Hex */\n",
       ".output_html .mi { color: #666 } /* Literal.Number.Integer */\n",
       ".output_html .mo { color: #666 } /* Literal.Number.Oct */\n",
       ".output_html .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".output_html .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".output_html .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".output_html .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".output_html .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\n",
       ".output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".output_html .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\n",
       ".output_html .sx { color: #008000 } /* Literal.String.Other */\n",
       ".output_html .sr { color: #A45A77 } /* Literal.String.Regex */\n",
       ".output_html .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".output_html .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".output_html .fm { color: #00F } /* Name.Function.Magic */\n",
       ".output_html .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".output_html .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".output_html .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".output_html .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".output_html .il { color: #666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"kt\">void</span><span class=\"w\"> </span><span class=\"nf\">kernel</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"kt\">double</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">RESTRICT</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"kt\">double</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">RESTRICT</span><span class=\"w\"> </span><span class=\"k\">const</span><span class=\"w\"> </span><span class=\"n\">_data_dst</span><span class=\"p\">)</span>\n",
       "<span class=\"p\">{</span>\n",
       "<span class=\"w\">   </span><span class=\"k\">for</span><span class=\"p\">(</span><span class=\"n\">ctr_0</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">202</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span>\n",
       "<span class=\"w\">   </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">      </span><span class=\"k\">for</span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">600</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">];</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span>\n",
       "<span class=\"w\">      </span><span class=\"p\">{</span>\n",
       "<span class=\"w\">         </span><span class=\"n\">_data_dst</span><span class=\"p\">[</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">601</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-1.0</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2404</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">4</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]]</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2404</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">4</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]]</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2404</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">4</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">-2.0</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2404</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">4</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mf\">2.0</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">float64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2404</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">4</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"n\">_data_I</span><span class=\"p\">[(</span><span class=\"n\">ctr_0</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">2404</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"n\">ctr_1</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">-1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">])</span><span class=\"w\"> </span><span class=\"o\">*</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">4</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"o\">:</span><span class=\"w\"> </span><span class=\"n\">int64</span><span class=\"p\">]];</span>\n",
       "<span class=\"w\">      </span><span class=\"p\">}</span>\n",
       "<span class=\"w\">   </span><span class=\"p\">}</span>\n",
       "<span class=\"p\">}</span>\n",
       "</pre></div>\n"
      ],
      "text/latex": [
       "\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n",
       "\\PY{k+kt}{void}\\PY{+w}{ }\\PY{n+nf}{kernel}\\PY{+w}{ }\\PY{p}{(}\\PY{k}{const}\\PY{+w}{ }\\PY{k+kt}{double}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{RESTRICT}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{,}\\PY{+w}{ }\\PY{k+kt}{double}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{RESTRICT}\\PY{+w}{ }\\PY{k}{const}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}dst}\\PY{p}{)}\n",
       "\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{   }\\PY{k}{for}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{\\PYZlt{}}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{202}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\n",
       "\\PY{+w}{   }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{      }\\PY{k}{for}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{\\PYZlt{}}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{600}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{;}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\n",
       "\\PY{+w}{      }\\PY{p}{\\PYZob{}}\n",
       "\\PY{+w}{         }\\PY{n}{\\PYZus{}data\\PYZus{}dst}\\PY{p}{[}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{601}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{=}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}1.0}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2404}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{4}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2404}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{4}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{\\PYZhy{}}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2404}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{4}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{\\PYZhy{}2.0}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2404}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{4}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mf}{2.0}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{float64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2404}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{4}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{n}{\\PYZus{}data\\PYZus{}I}\\PY{p}{[}\\PY{p}{(}\\PY{n}{ctr\\PYZus{}0}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{2404}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{(}\\PY{n}{ctr\\PYZus{}1}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{\\PYZhy{}1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{)}\\PY{+w}{ }\\PY{o}{*}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{4}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{+w}{ }\\PY{o}{+}\\PY{+w}{ }\\PY{p}{[}\\PY{l+m+mi}{1}\\PY{o}{:}\\PY{+w}{ }\\PY{n}{int64}\\PY{p}{]}\\PY{p}{]}\\PY{p}{;}\n",
       "\\PY{+w}{      }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{+w}{   }\\PY{p}{\\PYZcb{}}\n",
       "\\PY{p}{\\PYZcb{}}\n",
       "\\end{Verbatim}\n"
      ],
      "text/plain": [
       "void kernel (const double * RESTRICT const _data_I, double * RESTRICT const _data_dst)\n",
       "{\n",
       "   for(ctr_0: int64 = [1: int64]; ctr_0 < [202: int64]; ctr_0 += [1: int64])\n",
       "   {\n",
       "      for(ctr_1: int64 = [1: int64]; ctr_1 < [600: int64]; ctr_1 += [1: int64])\n",
       "      {\n",
       "         _data_dst[ctr_0 * [601: int64] + ctr_1] = [-1.0: float64] * _data_I[(ctr_0 + [1: int64]) * [2404: int64] + (ctr_1 + [1: int64]) * [4: int64] + [1: int64]] - _data_I[(ctr_0 + [-1: int64]) * [2404: int64] + (ctr_1 + [1: int64]) * [4: int64] + [1: int64]] - _data_I[(ctr_0 + [-1: int64]) * [2404: int64] + (ctr_1 + [-1: int64]) * [4: int64] + [1: int64]] + [-2.0: float64] * _data_I[(ctr_0 + [-1: int64]) * [2404: int64] + ctr_1 * [4: int64] + [1: int64]] + [2.0: float64] * _data_I[(ctr_0 + [1: int64]) * [2404: int64] + ctr_1 * [4: int64] + [1: int64]] + _data_I[(ctr_0 + [1: int64]) * [2404: int64] + (ctr_1 + [-1: int64]) * [4: int64] + [1: int64]];\n",
       "      }\n",
       "   }\n",
       "}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "img_field, dst_field = ps.fields(\"I(4), dst : [2D]\", I=img.astype(np.double), dst=filtered_image)\n",
    "\n",
    "sobel_x = -2 * img_field[-1,0](1) - img_field[-1,-1](1) - img_field[-1, +1](1) \\\n",
    "         +2 * img_field[+1,0](1) + img_field[+1,-1](1) - img_field[+1, +1](1)\n",
    "update_rule = ps.Assignment(dst_field[0,0], sobel_x)\n",
    "\n",
    "ast = create_kernel(update_rule)\n",
    "ps.inspect(ast)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Compare this code to the version above. In this code the loop bounds and array offsets are constants, which usually leads to faster kernels."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Running on GPU\n",
    "\n",
    "If you have a GPU and [cupy](https://cupy.dev/) installed, *pystencils* can run your kernel on the GPU as well. You can find more details about this in the GPU tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Please install cupy for GPU support\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    import cupy\n",
    "    from pystencils.gpu import BlockIndexing\n",
    "\n",
    "    gpu_ast = create_kernel(update_rule, target=ps.Target.GPU,\n",
    "                            gpu_indexing=BlockIndexing,\n",
    "                            gpu_indexing_params={'blockSize': (64, 1, 1)})\n",
    "\n",
    "    ps.inspect(gpu_ast)\n",
    "except ImportError:\n",
    "    print(\"Please install cupy for GPU support\")"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
