Skip to content

Instantly share code, notes, and snippets.

@kvedala
Last active April 29, 2020 03:02
Show Gist options
  • Save kvedala/9713842d5e264c94e293a930b479f597 to your computer and use it in GitHub Desktop.
Save kvedala/9713842d5e264c94e293a930b479f597 to your computer and use it in GitHub Desktop.
Durand-Kerner Roots - Python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {
"toc": true
},
"cell_type": "markdown",
"source": "<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Fast-Numerical-algorithm-to-find-all-the-roots-of-an-n-th-degree-polynomial\" data-toc-modified-id=\"Fast-Numerical-algorithm-to-find-all-the-roots-of-an-n-th-degree-polynomial-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>Fast-Numerical algorithm to find all the roots of an n-th degree polynomial</a></span></li><li><span><a href=\"#Using-Numba\" data-toc-modified-id=\"Using-Numba-2\"><span class=\"toc-item-num\">2&nbsp;&nbsp;</span>Using Numba</a></span></li><li><span><a href=\"#Using-Cython\" data-toc-modified-id=\"Using-Cython-3\"><span class=\"toc-item-num\">3&nbsp;&nbsp;</span>Using Cython</a></span></li><li><span><a href=\"#Testing-&amp;-Benchmarking\" data-toc-modified-id=\"Testing-&amp;-Benchmarking-4\"><span class=\"toc-item-num\">4&nbsp;&nbsp;</span>Testing &amp; Benchmarking</a></span><ul class=\"toc-item\"><li><span><a href=\"#Known-bugs-in-Durand–Kerner-algorithm\" data-toc-modified-id=\"Known-bugs-in-Durand–Kerner-algorithm-4.1\"><span class=\"toc-item-num\">4.1&nbsp;&nbsp;</span>Known bugs in Durand–Kerner algorithm</a></span><ul class=\"toc-item\"><li><span><a href=\"#Fail-cases\" data-toc-modified-id=\"Fail-cases-4.1.1\"><span class=\"toc-item-num\">4.1.1&nbsp;&nbsp;</span>Fail cases</a></span></li><li><span><a href=\"#Fail-cases-resolved\" data-toc-modified-id=\"Fail-cases-resolved-4.1.2\"><span class=\"toc-item-num\">4.1.2&nbsp;&nbsp;</span>Fail cases resolved</a></span></li></ul></li></ul></li></ul></div>"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Fast-Numerical algorithm to find all the roots of an n-th degree polynomial\nThe algorithm is an implementation of [Durand–Kerner method](https://en.wikipedia.org/wiki/Durand–Kerner_method). The algorithm is implemented using the [numba](https://numba.pydata.org) optimizer and also using [cython](http://cython.readthedocs.io/). The two implementations are then compared with the implementation of numpy and we see that both usually perform better than `numpy.solve`. "
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-29T22:11:53.086454Z",
"start_time": "2020-02-29T22:11:50.238096Z"
},
"run_control": {
"marked": false
},
"trusted": true
},
"cell_type": "code",
"source": "import numpy as np\nimport numba\nfrom typing import Callable, List\nfrom math import sqrt\n%reload_ext cython",
"execution_count": 1,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Using Numba"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-29T22:11:53.120963Z",
"start_time": "2020-02-29T22:11:53.091450Z"
},
"trusted": true
},
"cell_type": "code",
"source": "@numba.njit(nogil=True, boundscheck=False, cache=True)\ndef f(poly, x: complex) -> complex:\n out = 0 + 0j\n L = len(poly)\n for i in range(L):\n k = L - i - 1\n if poly[k] != 0:\n out += poly[k] * pow(x, i)\n\n# if poly[i] != 0:\n# out += poly[i] * (x ** i)\n return out\n\n\n@numba.jit(parallel=True, \n nopython=True, boundscheck=False, nogil=True, cache=True)\ndef solve(poly: np.ndarray, max_iter: int = 50000):\n epsilon = 5e-16\n ii = 0\n scale = 500\n L = poly.shape[0] - 1\n roots = (np.random.random(L) + np.random.random(L) * 1j) - (0.5 + 0.5j)\n roots *= scale\n max_delta = 1\n\n while max_delta > epsilon and ii < max_iter:\n max_delta = 0\n ii += 1\n if L > 20:\n for i in numba.prange(L): # for ith root\n deno = 1 + 0j\n delta = f(poly, roots[i])\n for k in range(L):\n if k != i:\n delta /= (roots[i] - roots[k])\n roots[i] -= delta\n # print(ii, roots, delta)\n max_delta += ((delta.real * delta.real) +\n (delta.imag * delta.imag)) / L\n else:\n for i in range(L): # for ith root\n deno = 1 + 0j\n delta = f(poly, roots[i])\n for k in range(L):\n if k != i:\n delta /= (roots[i] - roots[k])\n roots[i] -= delta\n # print(ii, roots, delta)\n max_delta += ((delta.real * delta.real) +\n (delta.imag * delta.imag)) / L\n\n\n max_delta = np.sqrt(max_delta)\n return roots, max_delta\n\n\nsolve(np.array([1, 0, -1]))",
"execution_count": 4,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 4,
"data": {
"text/plain": "(array([-1.+0.j, 1.+0.j]), 1.123017639172393e-22)"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Using Cython"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-29T22:12:11.454576Z",
"start_time": "2020-02-29T22:11:53.126778Z"
},
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "%%cython -a -c=-Ofast -c=-flto=thin\n# cython: boundscheck=False, wraparound=False, cdivision=True\n\ncimport numpy as np\nimport numpy as np\n\ncimport cython\nfrom cython.parallel cimport prange\n\n# from libc.math cimport abs, sqrt, fmax\n# from libcpp.complex cimport pow as cpow, real, imag, abs\n\ncdef extern from \"complex.h\" nogil:\n np.complex128_t cpow(np.complex128_t, long)\n double cabs(np.complex128_t) \n double creal(np.complex128_t) \n double cimag(np.complex128_t) \n\ncdef extern from \"math.h\" nogil:\n long double sqrtl(long double)\n long double fabsl(long double)\n long double fmaxl(long double, long double)\n\n \ncdef np.complex128_t f_c(double[:] poly, np.complex128_t x) nogil:\n cdef:\n np.complex128_t out = 0 + 0j\n long i, k, L = poly.shape[0]\n \n for i in range(L):\n k = L - i - 1\n if poly[k] != 0:\n out += poly[k] * cpow(x, i)\n# if poly[i] != 0:\n# out += <np.complex128_t> poly[i] * (x ** i)\n return out \n\n\ndef solve_c(double[:] poly, long max_iter = 500000):\n cdef:\n double epsilon = 5e-10\n long ii = 0, i, k, L = poly.shape[0] - 1\n double scale = 500.0\n np.ndarray[np.complex128_t, ndim=1] roots = ((np.random.random(L) + np.random.random(L) * 1j) \\\n - (.5 + .5j)) * scale\n# np.complex128_t[:] roots = _roots\n np.complex128_t deno, delta\n long double max_delta = 1, d2, rd, id\n \n with nogil:\n while max_delta > epsilon and ii < max_iter:\n max_delta = 0\n ii += 1\n for i in range(L):\n# deno = 1 + 0j\n# delta = 0 + 0j\n delta = f_c(poly, roots[i])\n for k in range(L):\n if k != i:\n delta /= (roots[i] - roots[k])\n roots[i] -= delta\n rd = creal(delta)\n id = cimag(delta)\n max_delta += ((rd * rd) + (id * id)) / L\n# with gil:\n# print(ii, roots, delta)\n max_delta = sqrtl(max_delta)\n# print(\"max_delta = \", max_delta)\n return roots, max_delta",
"execution_count": 17,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 17,
"data": {
"text/plain": "<IPython.core.display.HTML object>",
"text/html": "<!DOCTYPE html>\n<!-- Generated by Cython 0.29.15 -->\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n <title>Cython: _cython_magic_7d2d8e83eb391e7da013a05885fe9a7f.pyx</title>\n <style type=\"text/css\">\n \nbody.cython { font-family: courier; font-size: 12; }\n\n.cython.tag { }\n.cython.line { margin: 0em }\n.cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n\n.cython.line .run { background-color: #B0FFB0; }\n.cython.line .mis { background-color: #FFB0B0; }\n.cython.code.run { border-left: 8px solid #B0FFB0; }\n.cython.code.mis { border-left: 8px solid #FFB0B0; }\n\n.cython.code .py_c_api { color: red; }\n.cython.code .py_macro_api { color: #FF7000; }\n.cython.code .pyx_c_api { color: #FF3000; }\n.cython.code .pyx_macro_api { color: #FF7000; }\n.cython.code .refnanny { color: #FFA000; }\n.cython.code .trace { color: #FFA000; }\n.cython.code .error_goto { color: #FFA000; }\n\n.cython.code .coerce { color: #008000; border: 1px dotted #008000 }\n.cython.code .py_attr { color: #FF0000; font-weight: bold; }\n.cython.code .c_attr { color: #0000FF; }\n.cython.code .py_call { color: #FF0000; font-weight: bold; }\n.cython.code .c_call { color: #0000FF; }\n\n.cython.score-0 {background-color: #FFFFff;}\n.cython.score-1 {background-color: #FFFFe7;}\n.cython.score-2 {background-color: #FFFFd4;}\n.cython.score-3 {background-color: #FFFFc4;}\n.cython.score-4 {background-color: #FFFFb6;}\n.cython.score-5 {background-color: #FFFFaa;}\n.cython.score-6 {background-color: #FFFF9f;}\n.cython.score-7 {background-color: #FFFF96;}\n.cython.score-8 {background-color: #FFFF8d;}\n.cython.score-9 {background-color: #FFFF86;}\n.cython.score-10 {background-color: #FFFF7f;}\n.cython.score-11 {background-color: #FFFF79;}\n.cython.score-12 {background-color: #FFFF73;}\n.cython.score-13 {background-color: #FFFF6e;}\n.cython.score-14 {background-color: #FFFF6a;}\n.cython.score-15 {background-color: #FFFF66;}\n.cython.score-16 {background-color: #FFFF62;}\n.cython.score-17 {background-color: #FFFF5e;}\n.cython.score-18 {background-color: #FFFF5b;}\n.cython.score-19 {background-color: #FFFF57;}\n.cython.score-20 {background-color: #FFFF55;}\n.cython.score-21 {background-color: #FFFF52;}\n.cython.score-22 {background-color: #FFFF4f;}\n.cython.score-23 {background-color: #FFFF4d;}\n.cython.score-24 {background-color: #FFFF4b;}\n.cython.score-25 {background-color: #FFFF48;}\n.cython.score-26 {background-color: #FFFF46;}\n.cython.score-27 {background-color: #FFFF44;}\n.cython.score-28 {background-color: #FFFF43;}\n.cython.score-29 {background-color: #FFFF41;}\n.cython.score-30 {background-color: #FFFF3f;}\n.cython.score-31 {background-color: #FFFF3e;}\n.cython.score-32 {background-color: #FFFF3c;}\n.cython.score-33 {background-color: #FFFF3b;}\n.cython.score-34 {background-color: #FFFF39;}\n.cython.score-35 {background-color: #FFFF38;}\n.cython.score-36 {background-color: #FFFF37;}\n.cython.score-37 {background-color: #FFFF36;}\n.cython.score-38 {background-color: #FFFF35;}\n.cython.score-39 {background-color: #FFFF34;}\n.cython.score-40 {background-color: #FFFF33;}\n.cython.score-41 {background-color: #FFFF32;}\n.cython.score-42 {background-color: #FFFF31;}\n.cython.score-43 {background-color: #FFFF30;}\n.cython.score-44 {background-color: #FFFF2f;}\n.cython.score-45 {background-color: #FFFF2e;}\n.cython.score-46 {background-color: #FFFF2d;}\n.cython.score-47 {background-color: #FFFF2c;}\n.cython.score-48 {background-color: #FFFF2b;}\n.cython.score-49 {background-color: #FFFF2b;}\n.cython.score-50 {background-color: #FFFF2a;}\n.cython.score-51 {background-color: #FFFF29;}\n.cython.score-52 {background-color: #FFFF29;}\n.cython.score-53 {background-color: #FFFF28;}\n.cython.score-54 {background-color: #FFFF27;}\n.cython.score-55 {background-color: #FFFF27;}\n.cython.score-56 {background-color: #FFFF26;}\n.cython.score-57 {background-color: #FFFF26;}\n.cython.score-58 {background-color: #FFFF25;}\n.cython.score-59 {background-color: #FFFF24;}\n.cython.score-60 {background-color: #FFFF24;}\n.cython.score-61 {background-color: #FFFF23;}\n.cython.score-62 {background-color: #FFFF23;}\n.cython.score-63 {background-color: #FFFF22;}\n.cython.score-64 {background-color: #FFFF22;}\n.cython.score-65 {background-color: #FFFF22;}\n.cython.score-66 {background-color: #FFFF21;}\n.cython.score-67 {background-color: #FFFF21;}\n.cython.score-68 {background-color: #FFFF20;}\n.cython.score-69 {background-color: #FFFF20;}\n.cython.score-70 {background-color: #FFFF1f;}\n.cython.score-71 {background-color: #FFFF1f;}\n.cython.score-72 {background-color: #FFFF1f;}\n.cython.score-73 {background-color: #FFFF1e;}\n.cython.score-74 {background-color: #FFFF1e;}\n.cython.score-75 {background-color: #FFFF1e;}\n.cython.score-76 {background-color: #FFFF1d;}\n.cython.score-77 {background-color: #FFFF1d;}\n.cython.score-78 {background-color: #FFFF1c;}\n.cython.score-79 {background-color: #FFFF1c;}\n.cython.score-80 {background-color: #FFFF1c;}\n.cython.score-81 {background-color: #FFFF1c;}\n.cython.score-82 {background-color: #FFFF1b;}\n.cython.score-83 {background-color: #FFFF1b;}\n.cython.score-84 {background-color: #FFFF1b;}\n.cython.score-85 {background-color: #FFFF1a;}\n.cython.score-86 {background-color: #FFFF1a;}\n.cython.score-87 {background-color: #FFFF1a;}\n.cython.score-88 {background-color: #FFFF1a;}\n.cython.score-89 {background-color: #FFFF19;}\n.cython.score-90 {background-color: #FFFF19;}\n.cython.score-91 {background-color: #FFFF19;}\n.cython.score-92 {background-color: #FFFF19;}\n.cython.score-93 {background-color: #FFFF18;}\n.cython.score-94 {background-color: #FFFF18;}\n.cython.score-95 {background-color: #FFFF18;}\n.cython.score-96 {background-color: #FFFF18;}\n.cython.score-97 {background-color: #FFFF17;}\n.cython.score-98 {background-color: #FFFF17;}\n.cython.score-99 {background-color: #FFFF17;}\n.cython.score-100 {background-color: #FFFF17;}\n.cython.score-101 {background-color: #FFFF16;}\n.cython.score-102 {background-color: #FFFF16;}\n.cython.score-103 {background-color: #FFFF16;}\n.cython.score-104 {background-color: #FFFF16;}\n.cython.score-105 {background-color: #FFFF16;}\n.cython.score-106 {background-color: #FFFF15;}\n.cython.score-107 {background-color: #FFFF15;}\n.cython.score-108 {background-color: #FFFF15;}\n.cython.score-109 {background-color: #FFFF15;}\n.cython.score-110 {background-color: #FFFF15;}\n.cython.score-111 {background-color: #FFFF15;}\n.cython.score-112 {background-color: #FFFF14;}\n.cython.score-113 {background-color: #FFFF14;}\n.cython.score-114 {background-color: #FFFF14;}\n.cython.score-115 {background-color: #FFFF14;}\n.cython.score-116 {background-color: #FFFF14;}\n.cython.score-117 {background-color: #FFFF14;}\n.cython.score-118 {background-color: #FFFF13;}\n.cython.score-119 {background-color: #FFFF13;}\n.cython.score-120 {background-color: #FFFF13;}\n.cython.score-121 {background-color: #FFFF13;}\n.cython.score-122 {background-color: #FFFF13;}\n.cython.score-123 {background-color: #FFFF13;}\n.cython.score-124 {background-color: #FFFF13;}\n.cython.score-125 {background-color: #FFFF12;}\n.cython.score-126 {background-color: #FFFF12;}\n.cython.score-127 {background-color: #FFFF12;}\n.cython.score-128 {background-color: #FFFF12;}\n.cython.score-129 {background-color: #FFFF12;}\n.cython.score-130 {background-color: #FFFF12;}\n.cython.score-131 {background-color: #FFFF12;}\n.cython.score-132 {background-color: #FFFF11;}\n.cython.score-133 {background-color: #FFFF11;}\n.cython.score-134 {background-color: #FFFF11;}\n.cython.score-135 {background-color: #FFFF11;}\n.cython.score-136 {background-color: #FFFF11;}\n.cython.score-137 {background-color: #FFFF11;}\n.cython.score-138 {background-color: #FFFF11;}\n.cython.score-139 {background-color: #FFFF11;}\n.cython.score-140 {background-color: #FFFF11;}\n.cython.score-141 {background-color: #FFFF10;}\n.cython.score-142 {background-color: #FFFF10;}\n.cython.score-143 {background-color: #FFFF10;}\n.cython.score-144 {background-color: #FFFF10;}\n.cython.score-145 {background-color: #FFFF10;}\n.cython.score-146 {background-color: #FFFF10;}\n.cython.score-147 {background-color: #FFFF10;}\n.cython.score-148 {background-color: #FFFF10;}\n.cython.score-149 {background-color: #FFFF10;}\n.cython.score-150 {background-color: #FFFF0f;}\n.cython.score-151 {background-color: #FFFF0f;}\n.cython.score-152 {background-color: #FFFF0f;}\n.cython.score-153 {background-color: #FFFF0f;}\n.cython.score-154 {background-color: #FFFF0f;}\n.cython.score-155 {background-color: #FFFF0f;}\n.cython.score-156 {background-color: #FFFF0f;}\n.cython.score-157 {background-color: #FFFF0f;}\n.cython.score-158 {background-color: #FFFF0f;}\n.cython.score-159 {background-color: #FFFF0f;}\n.cython.score-160 {background-color: #FFFF0f;}\n.cython.score-161 {background-color: #FFFF0e;}\n.cython.score-162 {background-color: #FFFF0e;}\n.cython.score-163 {background-color: #FFFF0e;}\n.cython.score-164 {background-color: #FFFF0e;}\n.cython.score-165 {background-color: #FFFF0e;}\n.cython.score-166 {background-color: #FFFF0e;}\n.cython.score-167 {background-color: #FFFF0e;}\n.cython.score-168 {background-color: #FFFF0e;}\n.cython.score-169 {background-color: #FFFF0e;}\n.cython.score-170 {background-color: #FFFF0e;}\n.cython.score-171 {background-color: #FFFF0e;}\n.cython.score-172 {background-color: #FFFF0e;}\n.cython.score-173 {background-color: #FFFF0d;}\n.cython.score-174 {background-color: #FFFF0d;}\n.cython.score-175 {background-color: #FFFF0d;}\n.cython.score-176 {background-color: #FFFF0d;}\n.cython.score-177 {background-color: #FFFF0d;}\n.cython.score-178 {background-color: #FFFF0d;}\n.cython.score-179 {background-color: #FFFF0d;}\n.cython.score-180 {background-color: #FFFF0d;}\n.cython.score-181 {background-color: #FFFF0d;}\n.cython.score-182 {background-color: #FFFF0d;}\n.cython.score-183 {background-color: #FFFF0d;}\n.cython.score-184 {background-color: #FFFF0d;}\n.cython.score-185 {background-color: #FFFF0d;}\n.cython.score-186 {background-color: #FFFF0d;}\n.cython.score-187 {background-color: #FFFF0c;}\n.cython.score-188 {background-color: #FFFF0c;}\n.cython.score-189 {background-color: #FFFF0c;}\n.cython.score-190 {background-color: #FFFF0c;}\n.cython.score-191 {background-color: #FFFF0c;}\n.cython.score-192 {background-color: #FFFF0c;}\n.cython.score-193 {background-color: #FFFF0c;}\n.cython.score-194 {background-color: #FFFF0c;}\n.cython.score-195 {background-color: #FFFF0c;}\n.cython.score-196 {background-color: #FFFF0c;}\n.cython.score-197 {background-color: #FFFF0c;}\n.cython.score-198 {background-color: #FFFF0c;}\n.cython.score-199 {background-color: #FFFF0c;}\n.cython.score-200 {background-color: #FFFF0c;}\n.cython.score-201 {background-color: #FFFF0c;}\n.cython.score-202 {background-color: #FFFF0c;}\n.cython.score-203 {background-color: #FFFF0b;}\n.cython.score-204 {background-color: #FFFF0b;}\n.cython.score-205 {background-color: #FFFF0b;}\n.cython.score-206 {background-color: #FFFF0b;}\n.cython.score-207 {background-color: #FFFF0b;}\n.cython.score-208 {background-color: #FFFF0b;}\n.cython.score-209 {background-color: #FFFF0b;}\n.cython.score-210 {background-color: #FFFF0b;}\n.cython.score-211 {background-color: #FFFF0b;}\n.cython.score-212 {background-color: #FFFF0b;}\n.cython.score-213 {background-color: #FFFF0b;}\n.cython.score-214 {background-color: #FFFF0b;}\n.cython.score-215 {background-color: #FFFF0b;}\n.cython.score-216 {background-color: #FFFF0b;}\n.cython.score-217 {background-color: #FFFF0b;}\n.cython.score-218 {background-color: #FFFF0b;}\n.cython.score-219 {background-color: #FFFF0b;}\n.cython.score-220 {background-color: #FFFF0b;}\n.cython.score-221 {background-color: #FFFF0b;}\n.cython.score-222 {background-color: #FFFF0a;}\n.cython.score-223 {background-color: #FFFF0a;}\n.cython.score-224 {background-color: #FFFF0a;}\n.cython.score-225 {background-color: #FFFF0a;}\n.cython.score-226 {background-color: #FFFF0a;}\n.cython.score-227 {background-color: #FFFF0a;}\n.cython.score-228 {background-color: #FFFF0a;}\n.cython.score-229 {background-color: #FFFF0a;}\n.cython.score-230 {background-color: #FFFF0a;}\n.cython.score-231 {background-color: #FFFF0a;}\n.cython.score-232 {background-color: #FFFF0a;}\n.cython.score-233 {background-color: #FFFF0a;}\n.cython.score-234 {background-color: #FFFF0a;}\n.cython.score-235 {background-color: #FFFF0a;}\n.cython.score-236 {background-color: #FFFF0a;}\n.cython.score-237 {background-color: #FFFF0a;}\n.cython.score-238 {background-color: #FFFF0a;}\n.cython.score-239 {background-color: #FFFF0a;}\n.cython.score-240 {background-color: #FFFF0a;}\n.cython.score-241 {background-color: #FFFF0a;}\n.cython.score-242 {background-color: #FFFF0a;}\n.cython.score-243 {background-color: #FFFF0a;}\n.cython.score-244 {background-color: #FFFF0a;}\n.cython.score-245 {background-color: #FFFF0a;}\n.cython.score-246 {background-color: #FFFF09;}\n.cython.score-247 {background-color: #FFFF09;}\n.cython.score-248 {background-color: #FFFF09;}\n.cython.score-249 {background-color: #FFFF09;}\n.cython.score-250 {background-color: #FFFF09;}\n.cython.score-251 {background-color: #FFFF09;}\n.cython.score-252 {background-color: #FFFF09;}\n.cython.score-253 {background-color: #FFFF09;}\n.cython.score-254 {background-color: #FFFF09;}\n.cython .hll { background-color: #ffffcc }\n.cython { background: #f8f8f8; }\n.cython .c { color: #408080; font-style: italic } /* Comment */\n.cython .err { border: 1px solid #FF0000 } /* Error */\n.cython .k { color: #008000; font-weight: bold } /* Keyword */\n.cython .o { color: #666666 } /* Operator */\n.cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n.cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n.cython .cp { color: #BC7A00 } /* Comment.Preproc */\n.cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n.cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n.cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n.cython .gd { color: #A00000 } /* Generic.Deleted */\n.cython .ge { font-style: italic } /* Generic.Emph */\n.cython .gr { color: #FF0000 } /* Generic.Error */\n.cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.cython .gi { color: #00A000 } /* Generic.Inserted */\n.cython .go { color: #888888 } /* Generic.Output */\n.cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.cython .gs { font-weight: bold } /* Generic.Strong */\n.cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.cython .gt { color: #0044DD } /* Generic.Traceback */\n.cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.cython .kp { color: #008000 } /* Keyword.Pseudo */\n.cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.cython .kt { color: #B00040 } /* Keyword.Type */\n.cython .m { color: #666666 } /* Literal.Number */\n.cython .s { color: #BA2121 } /* Literal.String */\n.cython .na { color: #7D9029 } /* Name.Attribute */\n.cython .nb { color: #008000 } /* Name.Builtin */\n.cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.cython .no { color: #880000 } /* Name.Constant */\n.cython .nd { color: #AA22FF } /* Name.Decorator */\n.cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n.cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n.cython .nf { color: #0000FF } /* Name.Function */\n.cython .nl { color: #A0A000 } /* Name.Label */\n.cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n.cython .nv { color: #19177C } /* Name.Variable */\n.cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.cython .w { color: #bbbbbb } /* Text.Whitespace */\n.cython .mb { color: #666666 } /* Literal.Number.Bin */\n.cython .mf { color: #666666 } /* Literal.Number.Float */\n.cython .mh { color: #666666 } /* Literal.Number.Hex */\n.cython .mi { color: #666666 } /* Literal.Number.Integer */\n.cython .mo { color: #666666 } /* Literal.Number.Oct */\n.cython .sa { color: #BA2121 } /* Literal.String.Affix */\n.cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n.cython .sc { color: #BA2121 } /* Literal.String.Char */\n.cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n.cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.cython .s2 { color: #BA2121 } /* Literal.String.Double */\n.cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n.cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n.cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n.cython .sx { color: #008000 } /* Literal.String.Other */\n.cython .sr { color: #BB6688 } /* Literal.String.Regex */\n.cython .s1 { color: #BA2121 } /* Literal.String.Single */\n.cython .ss { color: #19177C } /* Literal.String.Symbol */\n.cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n.cython .fm { color: #0000FF } /* Name.Function.Magic */\n.cython .vc { color: #19177C } /* Name.Variable.Class */\n.cython .vg { color: #19177C } /* Name.Variable.Global */\n.cython .vi { color: #19177C } /* Name.Variable.Instance */\n.cython .vm { color: #19177C } /* Name.Variable.Magic */\n.cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n </style>\n</head>\n<body class=\"cython\">\n<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.15</span></p>\n<p>\n <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n</p>\n<div class=\"cython\"><pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">01</span>: <span class=\"c\"># cython: boundscheck=False, wraparound=False, cdivision=True</span></pre>\n<pre class='cython code score-8 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 1, __pyx_L1_error)</span>\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">02</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">cimport</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">np</span></pre>\n<pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">04</span>: <span class=\"k\">import</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">np</span></pre>\n<pre class='cython code score-8 '> __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_numpy, 0, 0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_np, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L1_error)</span>\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">05</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">06</span>: <span class=\"k\">cimport</span> <span class=\"nn\">cython</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">07</span>: <span class=\"k\">from</span> <span class=\"nn\">cython.parallel</span> <span class=\"k\">cimport</span> <span class=\"n\">prange</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">08</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">09</span>: <span class=\"c\"># from libc.math cimport abs, sqrt, fmax</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">10</span>: <span class=\"c\"># from libcpp.complex cimport pow as cpow, real, imag, abs</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">11</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">12</span>: <span class=\"k\">cdef</span> <span class=\"kr\">extern</span> <span class=\"k\">from</span> <span class=\"s\">&quot;complex.h&quot;</span> <span class=\"k\">nogil</span><span class=\"p\">:</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">13</span>: <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span> <span class=\"n\">cpow</span><span class=\"p\">(</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span><span class=\"p\">,</span> <span class=\"nb\">long</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">14</span>: <span class=\"n\">double</span> <span class=\"n\">cabs</span><span class=\"p\">(</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">15</span>: <span class=\"n\">double</span> <span class=\"n\">creal</span><span class=\"p\">(</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">16</span>: <span class=\"n\">double</span> <span class=\"n\">cimag</span><span class=\"p\">(</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">17</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">18</span>: <span class=\"k\">cdef</span> <span class=\"kr\">extern</span> <span class=\"k\">from</span> <span class=\"s\">&quot;math.h&quot;</span> <span class=\"k\">nogil</span><span class=\"p\">:</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">19</span>: <span class=\"nb\">long</span> <span class=\"n\">double</span> <span class=\"n\">sqrtl</span><span class=\"p\">(</span><span class=\"nb\">long</span> <span class=\"n\">double</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">20</span>: <span class=\"nb\">long</span> <span class=\"n\">double</span> <span class=\"n\">fabsl</span><span class=\"p\">(</span><span class=\"nb\">long</span> <span class=\"n\">double</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">21</span>: <span class=\"nb\">long</span> <span class=\"n\">double</span> <span class=\"n\">fmaxl</span><span class=\"p\">(</span><span class=\"nb\">long</span> <span class=\"n\">double</span><span class=\"p\">,</span> <span class=\"nb\">long</span> <span class=\"n\">double</span><span class=\"p\">)</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">22</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">23</span>: </pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">24</span>: <span class=\"k\">cdef</span> <span class=\"kt\">np</span>.<span class=\"kt\">complex128_t</span> <span class=\"nf\">f_c</span><span class=\"p\">(</span><span class=\"n\">double</span><span class=\"p\">[:]</span> <span class=\"n\">poly</span><span class=\"p\">,</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span> <span class=\"n\">x</span><span class=\"p\">)</span> <span class=\"k\">nogil</span><span class=\"p\">:</span></pre>\n<pre class='cython code score-0 '>static __pyx_t_double_complex __pyx_f_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_f_c(__Pyx_memviewslice __pyx_v_poly, __pyx_t_double_complex __pyx_v_x) {\n __pyx_t_double_complex __pyx_v_out;\n long __pyx_v_i;\n long __pyx_v_k;\n long __pyx_v_L;\n __pyx_t_double_complex __pyx_r;\n/* … */\n /* function exit code */\n __pyx_L0:;\n return __pyx_r;\n}\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">25</span>: <span class=\"k\">cdef</span><span class=\"p\">:</span></pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">26</span>: <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span> <span class=\"n\">out</span> <span class=\"o\">=</span> <span class=\"mf\">0</span> <span class=\"o\">+</span> <span class=\"mf\">0</span><span class=\"n\">j</span></pre>\n<pre class='cython code score-0 '> __pyx_v_out = __Pyx_c_sum_double(__pyx_t_double_complex_from_parts(0, 0), __pyx_t_double_complex_from_parts(0, 0.0));\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">27</span>: <span class=\"nb\">long</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">k</span><span class=\"p\">,</span> <span class=\"n\">L</span> <span class=\"o\">=</span> <span class=\"n\">poly</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n<pre class='cython code score-0 '> __pyx_v_L = (__pyx_v_poly.shape[0]);\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">28</span>: </pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">29</span>: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n<pre class='cython code score-0 '> __pyx_t_1 = __pyx_v_L;\n __pyx_t_2 = __pyx_t_1;\n for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n __pyx_v_i = __pyx_t_3;\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">30</span>: <span class=\"n\">k</span> <span class=\"o\">=</span> <span class=\"n\">L</span> <span class=\"o\">-</span> <span class=\"n\">i</span> <span class=\"o\">-</span> <span class=\"mf\">1</span></pre>\n<pre class='cython code score-0 '> __pyx_v_k = ((__pyx_v_L - __pyx_v_i) - 1);\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">31</span>: <span class=\"k\">if</span> <span class=\"n\">poly</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">]</span> <span class=\"o\">!=</span> <span class=\"mf\">0</span><span class=\"p\">:</span></pre>\n<pre class='cython code score-0 '> __pyx_t_4 = __pyx_v_k;\n __pyx_t_5 = (((*((double *) ( /* dim=0 */ (__pyx_v_poly.data + __pyx_t_4 * __pyx_v_poly.strides[0]) ))) != 0.0) != 0);\n if (__pyx_t_5) {\n/* … */\n }\n }\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">32</span>: <span class=\"n\">out</span> <span class=\"o\">+=</span> <span class=\"n\">poly</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">cpow</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">i</span><span class=\"p\">)</span></pre>\n<pre class='cython code score-0 '> __pyx_t_6 = __pyx_v_k;\n __pyx_v_out = __Pyx_c_sum_double(__pyx_v_out, __Pyx_c_prod_double(__pyx_t_double_complex_from_parts((*((double *) ( /* dim=0 */ (__pyx_v_poly.data + __pyx_t_6 * __pyx_v_poly.strides[0]) ))), 0), cpow(__pyx_v_x, __pyx_v_i)));\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">33</span>: <span class=\"c\"># if poly[i] != 0:</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">34</span>: <span class=\"c\"># out += &lt;np.complex128_t&gt; poly[i] * (x ** i)</span></pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">35</span>: <span class=\"k\">return</span> <span class=\"n\">out</span></pre>\n<pre class='cython code score-0 '> __pyx_r = __pyx_v_out;\n goto __pyx_L0;\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">36</span>: </pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">37</span>: </pre>\n<pre class=\"cython line score-60\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">38</span>: <span class=\"k\">def</span> <span class=\"nf\">solve_c</span><span class=\"p\">(</span><span class=\"n\">double</span><span class=\"p\">[:]</span> <span class=\"n\">poly</span><span class=\"p\">,</span> <span class=\"nb\">long</span> <span class=\"n\">max_iter</span> <span class=\"o\">=</span> <span class=\"mf\">500000</span><span class=\"p\">):</span></pre>\n<pre class='cython code score-60 '>/* Python wrapper */\nstatic PyObject *__pyx_pw_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_1solve_c(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\nstatic PyMethodDef __pyx_mdef_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_1solve_c = {\"solve_c\", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_1solve_c, METH_VARARGS|METH_KEYWORDS, 0};\nstatic PyObject *__pyx_pw_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_1solve_c(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n __Pyx_memviewslice __pyx_v_poly = { 0, 0, { 0 }, { 0 }, { 0 } };\n long __pyx_v_max_iter;\n PyObject *__pyx_r = 0;\n <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"solve_c (wrapper)\", 0);\n {\n static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_poly,&amp;__pyx_n_s_max_iter,0};\n PyObject* values[2] = {0,0};\n if (unlikely(__pyx_kwds)) {\n Py_ssize_t kw_args;\n const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n switch (pos_args) {\n case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n CYTHON_FALLTHROUGH;\n case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n CYTHON_FALLTHROUGH;\n case 0: break;\n default: goto __pyx_L5_argtuple_error;\n }\n kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n switch (pos_args) {\n case 0:\n if (likely((values[0] = <span class='pyx_c_api'>__Pyx_PyDict_GetItemStr</span>(__pyx_kwds, __pyx_n_s_poly)) != 0)) kw_args--;\n else goto __pyx_L5_argtuple_error;\n CYTHON_FALLTHROUGH;\n case 1:\n if (kw_args &gt; 0) {\n PyObject* value = <span class='pyx_c_api'>__Pyx_PyDict_GetItemStr</span>(__pyx_kwds, __pyx_n_s_max_iter);\n if (value) { values[1] = value; kw_args--; }\n }\n }\n if (unlikely(kw_args &gt; 0)) {\n if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"solve_c\") &lt; 0)) <span class='error_goto'>__PYX_ERR(0, 38, __pyx_L3_error)</span>\n }\n } else {\n switch (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)) {\n case 2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n CYTHON_FALLTHROUGH;\n case 1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n break;\n default: goto __pyx_L5_argtuple_error;\n }\n }\n __pyx_v_poly = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_ds_double</span>(values[0], PyBUF_WRITABLE);<span class='error_goto'> if (unlikely(!__pyx_v_poly.memview)) __PYX_ERR(0, 38, __pyx_L3_error)</span>\n if (values[1]) {\n __pyx_v_max_iter = <span class='pyx_c_api'>__Pyx_PyInt_As_long</span>(values[1]); if (unlikely((__pyx_v_max_iter == (long)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 38, __pyx_L3_error)</span>\n } else {\n __pyx_v_max_iter = ((long)0x7A120);\n }\n }\n goto __pyx_L4_argument_unpacking_done;\n __pyx_L5_argtuple_error:;\n <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"solve_c\", 0, 1, 2, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); <span class='error_goto'>__PYX_ERR(0, 38, __pyx_L3_error)</span>\n __pyx_L3_error:;\n <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f.solve_c\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n return NULL;\n __pyx_L4_argument_unpacking_done:;\n __pyx_r = __pyx_pf_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_solve_c(__pyx_self, __pyx_v_poly, __pyx_v_max_iter);\n\n /* function exit code */\n <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n return __pyx_r;\n}\n\nstatic PyObject *__pyx_pf_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_solve_c(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_poly, long __pyx_v_max_iter) {\n double __pyx_v_epsilon;\n long __pyx_v_ii;\n long __pyx_v_i;\n long __pyx_v_k;\n long __pyx_v_L;\n double __pyx_v_scale;\n PyArrayObject *__pyx_v_roots = 0;\n __pyx_t_double_complex __pyx_v_delta;\n long double __pyx_v_max_delta;\n long double __pyx_v_rd;\n long double __pyx_v_id;\n __Pyx_LocalBuf_ND __pyx_pybuffernd_roots;\n __Pyx_Buffer __pyx_pybuffer_roots;\n PyObject *__pyx_r = NULL;\n <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"solve_c\", 0);\n __pyx_pybuffer_roots.pybuffer.buf = NULL;\n __pyx_pybuffer_roots.refcount = 0;\n __pyx_pybuffernd_roots.data = NULL;\n __pyx_pybuffernd_roots.rcbuffer = &amp;__pyx_pybuffer_roots;\n/* … */\n /* function exit code */\n __pyx_L1_error:;\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;\n __Pyx_PyThreadState_declare\n __Pyx_PyThreadState_assign\n <span class='pyx_c_api'>__Pyx_ErrFetch</span>(&amp;__pyx_type, &amp;__pyx_value, &amp;__pyx_tb);\n <span class='pyx_c_api'>__Pyx_SafeReleaseBuffer</span>(&amp;__pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer);\n <span class='pyx_c_api'>__Pyx_ErrRestore</span>(__pyx_type, __pyx_value, __pyx_tb);}\n <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f.solve_c\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n __pyx_r = NULL;\n goto __pyx_L2;\n __pyx_L0:;\n <span class='pyx_c_api'>__Pyx_SafeReleaseBuffer</span>(&amp;__pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer);\n __pyx_L2:;\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>((PyObject *)__pyx_v_roots);\n __PYX_XDEC_MEMVIEW(&amp;__pyx_v_poly, 1);\n <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n return __pyx_r;\n}\n/* … */\n __pyx_tuple__26 = <span class='py_c_api'>PyTuple_Pack</span>(15, __pyx_n_s_poly, __pyx_n_s_max_iter, __pyx_n_s_epsilon, __pyx_n_s_ii, __pyx_n_s_i, __pyx_n_s_k, __pyx_n_s_L, __pyx_n_s_scale, __pyx_n_s_roots, __pyx_n_s_deno, __pyx_n_s_delta, __pyx_n_s_max_delta, __pyx_n_s_d2, __pyx_n_s_rd, __pyx_n_s_id);<span class='error_goto'> if (unlikely(!__pyx_tuple__26)) __PYX_ERR(0, 38, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__26);\n <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__26);\n/* … */\n __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_1solve_c, NULL, __pyx_n_s_cython_magic_7d2d8e83eb391e7da0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 38, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_solve_c, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 38, __pyx_L1_error)</span>\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n __pyx_codeobj__27 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(2, 0, 15, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__26, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_kvedala_ipython_cython__c, __pyx_n_s_solve_c, 38, __pyx_empty_bytes);<span class='error_goto'> if (unlikely(!__pyx_codeobj__27)) __PYX_ERR(0, 38, __pyx_L1_error)</span>\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">39</span>: <span class=\"k\">cdef</span><span class=\"p\">:</span></pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">40</span>: <span class=\"n\">double</span> <span class=\"n\">epsilon</span> <span class=\"o\">=</span> <span class=\"mf\">5e-10</span></pre>\n<pre class='cython code score-0 '> __pyx_v_epsilon = 5e-10;\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">41</span>: <span class=\"nb\">long</span> <span class=\"n\">ii</span> <span class=\"o\">=</span> <span class=\"mf\">0</span><span class=\"p\">,</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">k</span><span class=\"p\">,</span> <span class=\"n\">L</span> <span class=\"o\">=</span> <span class=\"n\">poly</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"mf\">1</span></pre>\n<pre class='cython code score-0 '> __pyx_v_ii = 0;\n __pyx_v_L = ((__pyx_v_poly.shape[0]) - 1);\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">42</span>: <span class=\"n\">double</span> <span class=\"n\">scale</span> <span class=\"o\">=</span> <span class=\"mf\">500.0</span></pre>\n<pre class='cython code score-0 '> __pyx_v_scale = 500.0;\n</pre><pre class=\"cython line score-69\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">43</span>: <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">ndarray</span><span class=\"p\">[</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span><span class=\"p\">,</span> <span class=\"n\">ndim</span><span class=\"o\">=</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">roots</span> <span class=\"o\">=</span> <span class=\"p\">((</span><span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">random</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">)</span> <span class=\"o\">*</span> <span class=\"mf\">1</span><span class=\"n\">j</span><span class=\"p\">)</span> \\</pre>\n<pre class='cython code score-69 '> <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_2, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_2, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_3, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyInt_From_long</span>(__pyx_v_L);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n __pyx_t_4 = NULL;\n if (CYTHON_UNPACK_METHODS &amp;&amp; likely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_2))) {\n __pyx_t_4 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_2);\n if (likely(__pyx_t_4)) {\n PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_2);\n <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_4);\n <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_2, function);\n }\n }\n __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_2, __pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n if (unlikely(!__pyx_t_1)) <span class='error_goto'>__PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_3, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n __pyx_t_4 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_3, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_4, __pyx_n_s_random);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n __pyx_t_4 = <span class='pyx_c_api'>__Pyx_PyInt_From_long</span>(__pyx_v_L);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n __pyx_t_5 = NULL;\n if (CYTHON_UNPACK_METHODS &amp;&amp; likely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_3))) {\n __pyx_t_5 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_3);\n if (likely(__pyx_t_5)) {\n PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_5);\n <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_3, function);\n }\n }\n __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_3, __pyx_t_4);\n <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n if (unlikely(!__pyx_t_2)) <span class='error_goto'>__PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n __pyx_t_3 = <span class='py_c_api'>PyComplex_FromDoubles</span>(0.0, 1.0);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n __pyx_t_4 = <span class='py_c_api'>PyNumber_Multiply</span>(__pyx_t_2, __pyx_t_3);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n __pyx_t_3 = <span class='py_c_api'>PyNumber_Add</span>(__pyx_t_1, __pyx_t_4);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n</pre><pre class=\"cython line score-29\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">44</span>: <span class=\"o\">-</span> <span class=\"p\">(</span><span class=\"o\">.</span><span class=\"mf\">5</span> <span class=\"o\">+</span> <span class=\"o\">.</span><span class=\"mf\">5</span><span class=\"n\">j</span><span class=\"p\">))</span> <span class=\"o\">*</span> <span class=\"n\">scale</span></pre>\n<pre class='cython code score-29 '> __pyx_t_6 = __Pyx_c_sum_double(__pyx_t_double_complex_from_parts(.5, 0), __pyx_t_double_complex_from_parts(0, 0.5));\n __pyx_t_4 = __pyx_<span class='py_c_api'>PyComplex_FromComplex</span>(__pyx_t_6);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 44, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n __pyx_t_1 = <span class='py_c_api'>PyNumber_Subtract</span>(__pyx_t_3, __pyx_t_4);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 44, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n __pyx_t_4 = <span class='py_c_api'>PyFloat_FromDouble</span>(__pyx_v_scale);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 44, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n __pyx_t_3 = <span class='py_c_api'>PyNumber_Multiply</span>(__pyx_t_1, __pyx_t_4);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 44, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n if (!(likely(((__pyx_t_3) == Py_None) || likely(<span class='pyx_c_api'>__Pyx_TypeTest</span>(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) <span class='error_goto'>__PYX_ERR(0, 44, __pyx_L1_error)</span>\n __pyx_t_7 = ((PyArrayObject *)__pyx_t_3);\n {\n __Pyx_BufFmt_StackElem __pyx_stack[1];\n if (unlikely(<span class='pyx_c_api'>__Pyx_GetBufferAndValidate</span>(&amp;__pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer, (PyObject*)__pyx_t_7, &amp;__Pyx_TypeInfo___pyx_t_double_complex, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {\n __pyx_v_roots = ((PyArrayObject *)Py_None); <span class='pyx_macro_api'>__Pyx_INCREF</span>(Py_None); __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.buf = NULL;\n <span class='error_goto'>__PYX_ERR(0, 43, __pyx_L1_error)</span>\n } else {__pyx_pybuffernd_roots.diminfo[0].strides = __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.strides[0]; __pyx_pybuffernd_roots.diminfo[0].shape = __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.shape[0];\n }\n }\n __pyx_t_7 = 0;\n __pyx_v_roots = ((PyArrayObject *)__pyx_t_3);\n __pyx_t_3 = 0;\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">45</span>: <span class=\"c\"># np.complex128_t[:] roots = _roots</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">46</span>: <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">complex128_t</span> <span class=\"n\">deno</span><span class=\"p\">,</span> <span class=\"n\">delta</span></pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">47</span>: <span class=\"nb\">long</span> <span class=\"n\">double</span> <span class=\"n\">max_delta</span> <span class=\"o\">=</span> <span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"n\">d2</span><span class=\"p\">,</span> <span class=\"n\">rd</span><span class=\"p\">,</span> <span class=\"nb\">id</span></pre>\n<pre class='cython code score-0 '> __pyx_v_max_delta = 1.0;\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">48</span>: </pre>\n<pre class=\"cython line score-4\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">49</span>: <span class=\"k\">with</span> <span class=\"k\">nogil</span><span class=\"p\">:</span></pre>\n<pre class='cython code score-4 '> {\n #ifdef WITH_THREAD\n PyThreadState *_save;\n Py_UNBLOCK_THREADS\n <span class='pyx_c_api'>__Pyx_FastGIL_Remember</span>();\n #endif\n /*try:*/ {\n/* … */\n /*finally:*/ {\n /*normal exit:*/{\n #ifdef WITH_THREAD\n <span class='pyx_c_api'>__Pyx_FastGIL_Forget</span>();\n Py_BLOCK_THREADS\n #endif\n goto __pyx_L5;\n }\n __pyx_L5:;\n }\n }\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">50</span>: <span class=\"k\">while</span> <span class=\"n\">max_delta</span> <span class=\"o\">&gt;</span> <span class=\"n\">epsilon</span> <span class=\"ow\">and</span> <span class=\"n\">ii</span> <span class=\"o\">&lt;</span> <span class=\"n\">max_iter</span><span class=\"p\">:</span></pre>\n<pre class='cython code score-0 '> while (1) {\n __pyx_t_9 = ((__pyx_v_max_delta &gt; __pyx_v_epsilon) != 0);\n if (__pyx_t_9) {\n } else {\n __pyx_t_8 = __pyx_t_9;\n goto __pyx_L8_bool_binop_done;\n }\n __pyx_t_9 = ((__pyx_v_ii &lt; __pyx_v_max_iter) != 0);\n __pyx_t_8 = __pyx_t_9;\n __pyx_L8_bool_binop_done:;\n if (!__pyx_t_8) break;\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">51</span>: <span class=\"n\">max_delta</span> <span class=\"o\">=</span> <span class=\"mf\">0</span></pre>\n<pre class='cython code score-0 '> __pyx_v_max_delta = 0.0;\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">52</span>: <span class=\"n\">ii</span> <span class=\"o\">+=</span> <span class=\"mf\">1</span></pre>\n<pre class='cython code score-0 '> __pyx_v_ii = (__pyx_v_ii + 1);\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">53</span>: <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n<pre class='cython code score-0 '> __pyx_t_10 = __pyx_v_L;\n __pyx_t_11 = __pyx_t_10;\n for (__pyx_t_12 = 0; __pyx_t_12 &lt; __pyx_t_11; __pyx_t_12+=1) {\n __pyx_v_i = __pyx_t_12;\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">54</span>: <span class=\"c\"># deno = 1 + 0j</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">55</span>: <span class=\"c\"># delta = 0 + 0j</span></pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">56</span>: <span class=\"n\">delta</span> <span class=\"o\">=</span> <span class=\"n\">f_c</span><span class=\"p\">(</span><span class=\"n\">poly</span><span class=\"p\">,</span> <span class=\"n\">roots</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span></pre>\n<pre class='cython code score-0 '> __pyx_t_13 = __pyx_v_i;\n __pyx_v_delta = __pyx_f_46_cython_magic_7d2d8e83eb391e7da013a05885fe9a7f_f_c(__pyx_v_poly, (*__Pyx_BufPtrStrided1d(__pyx_t_double_complex *, __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.buf, __pyx_t_13, __pyx_pybuffernd_roots.diminfo[0].strides)));\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">57</span>: <span class=\"k\">for</span> <span class=\"n\">k</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">L</span><span class=\"p\">):</span></pre>\n<pre class='cython code score-0 '> __pyx_t_14 = __pyx_v_L;\n __pyx_t_15 = __pyx_t_14;\n for (__pyx_t_16 = 0; __pyx_t_16 &lt; __pyx_t_15; __pyx_t_16+=1) {\n __pyx_v_k = __pyx_t_16;\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">58</span>: <span class=\"k\">if</span> <span class=\"n\">k</span> <span class=\"o\">!=</span> <span class=\"n\">i</span><span class=\"p\">:</span></pre>\n<pre class='cython code score-0 '> __pyx_t_8 = ((__pyx_v_k != __pyx_v_i) != 0);\n if (__pyx_t_8) {\n/* … */\n }\n }\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">59</span>: <span class=\"n\">delta</span> <span class=\"o\">/=</span> <span class=\"p\">(</span><span class=\"n\">roots</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">-</span> <span class=\"n\">roots</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">])</span></pre>\n<pre class='cython code score-0 '> __pyx_t_17 = __pyx_v_i;\n __pyx_t_18 = __pyx_v_k;\n __pyx_v_delta = __Pyx_c_quot_double(__pyx_v_delta, __Pyx_c_diff_double((*__Pyx_BufPtrStrided1d(__pyx_t_double_complex *, __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_roots.diminfo[0].strides)), (*__Pyx_BufPtrStrided1d(__pyx_t_double_complex *, __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_roots.diminfo[0].strides))));\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">60</span>: <span class=\"n\">roots</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">-=</span> <span class=\"n\">delta</span></pre>\n<pre class='cython code score-0 '> __pyx_t_19 = __pyx_v_i;\n *__Pyx_BufPtrStrided1d(__pyx_t_double_complex *, __pyx_pybuffernd_roots.rcbuffer-&gt;pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_roots.diminfo[0].strides) -= __pyx_v_delta;\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">61</span>: <span class=\"n\">rd</span> <span class=\"o\">=</span> <span class=\"n\">creal</span><span class=\"p\">(</span><span class=\"n\">delta</span><span class=\"p\">)</span></pre>\n<pre class='cython code score-0 '> __pyx_v_rd = creal(__pyx_v_delta);\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">62</span>: <span class=\"nb\">id</span> <span class=\"o\">=</span> <span class=\"n\">cimag</span><span class=\"p\">(</span><span class=\"n\">delta</span><span class=\"p\">)</span></pre>\n<pre class='cython code score-0 '> __pyx_v_id = cimag(__pyx_v_delta);\n</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">63</span>: <span class=\"n\">max_delta</span> <span class=\"o\">+=</span> <span class=\"p\">((</span><span class=\"n\">rd</span> <span class=\"o\">*</span> <span class=\"n\">rd</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"p\">(</span><span class=\"nb\">id</span> <span class=\"o\">*</span> <span class=\"nb\">id</span><span class=\"p\">))</span> <span class=\"o\">/</span> <span class=\"n\">L</span></pre>\n<pre class='cython code score-0 '> __pyx_v_max_delta = (__pyx_v_max_delta + (((__pyx_v_rd * __pyx_v_rd) + (__pyx_v_id * __pyx_v_id)) / ((long double)__pyx_v_L)));\n }\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">64</span>: <span class=\"c\"># with gil:</span></pre>\n<pre class=\"cython line score-0\">&#xA0;<span class=\"\">65</span>: <span class=\"c\"># print(ii, roots, delta)</span></pre>\n<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">66</span>: <span class=\"n\">max_delta</span> <span class=\"o\">=</span> <span class=\"n\">sqrtl</span><span class=\"p\">(</span><span class=\"n\">max_delta</span><span class=\"p\">)</span></pre>\n<pre class='cython code score-0 '> __pyx_v_max_delta = sqrtl(__pyx_v_max_delta);\n }\n }\n</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">67</span>: <span class=\"c\"># print(&quot;max_delta = &quot;, max_delta)</span></pre>\n<pre class=\"cython line score-14\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">68</span>: <span class=\"k\">return</span> <span class=\"n\">roots</span><span class=\"p\">,</span> <span class=\"n\">max_delta</span></pre>\n<pre class='cython code score-14 '> <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n __pyx_t_3 = <span class='py_c_api'>PyFloat_FromDouble</span>(__pyx_v_max_delta);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 68, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n __pyx_t_4 = <span class='py_c_api'>PyTuple_New</span>(2);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error)</span>\n <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n <span class='pyx_macro_api'>__Pyx_INCREF</span>(((PyObject *)__pyx_v_roots));\n <span class='refnanny'>__Pyx_GIVEREF</span>(((PyObject *)__pyx_v_roots));\n <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 0, ((PyObject *)__pyx_v_roots));\n <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_t_3);\n <span class='py_macro_api'>PyTuple_SET_ITEM</span>(__pyx_t_4, 1, __pyx_t_3);\n __pyx_t_3 = 0;\n __pyx_r = __pyx_t_4;\n __pyx_t_4 = 0;\n goto __pyx_L0;\n</pre></div></body></html>"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Testing & Benchmarking"
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-29T22:12:11.494565Z",
"start_time": "2020-02-29T22:12:11.466458Z"
},
"trusted": true
},
"cell_type": "code",
"source": "def benchmark(polynom):\n L = len(polynom)\n msg = ''\n for i in range(L):\n if polynom[i] == 0:\n continue\n if i > 0:\n msg += '+ '\n msg += '({})x^{} '.format(polynom[i], L-i-1)\n print(msg)\n print('--------------')\n \n print(\"Using numpy.solve\")\n %timeit np.roots(polynom)\n roots1 = np.roots(polynom)\n print(roots1)\n print('--------------')\n print(\"Using numba implementation\")\n %timeit roots = solve(polynom)\n roots = solve(polynom)\n print(roots)\n print('--------------')\n print(\"Using cython implementation\")\n %timeit roots2, _ = solve_c(polynom)\n roots2, _ = solve_c(polynom)\n print(roots2)\n print('--------------')",
"execution_count": 10,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Known bugs in Durand–Kerner algorithm\n### Fail cases"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# 1 - fail example:\npolynom = np.array([4, 0, -1], dtype=float)\nbenchmark(polynom)\nprint('================')\n# 2 - fail example\npolynom = np.array([2, 13, -7], dtype=float)\nbenchmark(polynom)",
"execution_count": 14,
"outputs": [
{
"output_type": "stream",
"text": "(4.0)x^2 + (-1.0)x^0 \n--------------\nUsing numpy.solve\n76.2 µs ± 5.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[ 0.5 -0.5]\n--------------\nUsing numba implementation\n122 µs ± 39.5 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n(array([-inf+infj, nan+nanj]), nan)\n--------------\nUsing cython implementation\n65.7 µs ± 488 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[-90.81607955-24.37936125j inf +nanj]\n--------------\n(2.0)x^2 + (13.0)x^1 + (-7.0)x^0 \n--------------\nUsing numpy.solve\n74.1 µs ± 7.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[-7. 0.5]\n--------------\nUsing numba implementation\n11.1 ms ± 167 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n(array([ -10.15437377 -6.61299036j, 4040.40420859+4516.35012194j]), 8559.543666648191)\n--------------\nUsing cython implementation\n190 ms ± 1.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n[-6.11547323e+04-7.82040356e+04j 2.73825269e+01+3.89510547e+01j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Fail cases resolved"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# 1 - fail example - resolved:\npolynom = np.array([4, 0, -1])\npolynom = polynom / polynom[0]\nbenchmark(polynom)\n# 2 - fail example - resolved\npolynom = np.array([2, 13, -7])\npolynom = polynom / polynom[0]\nbenchmark(polynom)",
"execution_count": 18,
"outputs": [
{
"output_type": "stream",
"text": "(1.0)x^2 + (-0.25)x^0 \n--------------\nUsing numpy.solve\n98.8 µs ± 24.2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[ 0.5 -0.5]\n--------------\nUsing numba implementation\n71.7 µs ± 5.13 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n(array([ 0.5+0.j, -0.5+0.j]), 3.1526380599683343e-22)\n--------------\nUsing cython implementation\n13.9 µs ± 89.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n[ 0.5+0.00000000e+00j -0.5+6.34935309e-18j]\n--------------\n(1.0)x^2 + (6.5)x^1 + (-3.5)x^0 \n--------------\nUsing numpy.solve\n71.4 µs ± 3.71 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[-7. 0.5]\n--------------\nUsing numba implementation\n63.7 µs ± 4.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n(array([ 0.5+0.00000000e+00j, -7. +4.89163707e-16j]), 1.3882670517149822e-16)\n--------------\nUsing cython implementation\n15.4 µs ± 1.7 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n[-7. -4.62060783e-16j 0.5-3.85185989e-33j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2020-02-29T22:12:22.905023Z",
"start_time": "2020-02-29T22:12:11.526177Z"
},
"scrolled": false,
"trusted": false
},
"cell_type": "code",
"source": "polynom = np.array([1, 0, 0, 10, 0, 0, -27])\nbenchmark(polynom)",
"execution_count": 5,
"outputs": [
{
"output_type": "stream",
"text": "(1)x^6 + (10)x^3 + (-27)x^0 \n--------------\nUsing numpy.solve\n113 µs ± 27.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[-2.30277564+0.j 1.15138782+1.9942622j 1.15138782-1.9942622j\n -0.65138782+1.1282368j -0.65138782-1.1282368j 1.30277564+0.j ]\n--------------\nUsing numba implementation\nThe slowest run took 577.42 times longer than the fastest. This could mean that an intermediate result is being cached.\n20.7 ms ± 12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n(array([ 1.15138782-1.99426220e+00j, -0.65138782-1.12823680e+00j,\n -2.30277564-1.27822331e-16j, 1.30277564+1.02494282e-32j,\n -0.65138782+1.12823680e+00j, 1.15138782+1.99426220e+00j]), 2.2283351559332415e-16)\n--------------\nUsing cython implementation\n246 ms ± 83.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n[-0.65138782-1.12823680e+00j 1.30277564+5.02605867e-32j\n -0.65138782+1.12823680e+00j 1.15138782-1.99426220e+00j\n 1.15138782+1.99426220e+00j -2.30277564-7.30758745e-16j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-02-29T22:11:50.565Z"
},
"trusted": false
},
"cell_type": "code",
"source": "polynom = np.array([1,0,0,0,0,0,0,0,0,-1])\nbenchmark(polynom)",
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"text": "(1)x^9 + (-1)x^0 \n--------------\nUsing numpy.solve\n225 µs ± 89.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n[-0.93969262+0.34202014j -0.93969262-0.34202014j -0.5 +0.8660254j\n -0.5 -0.8660254j 0.17364818+0.98480775j 0.17364818-0.98480775j\n 1. +0.j 0.76604444+0.64278761j 0.76604444-0.64278761j]\n--------------\nUsing numba implementation\n91.3 µs ± 2.22 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n(array([ 1. +1.50463277e-36j, -0.5 -8.66025404e-01j,\n 0.17364818+9.84807753e-01j, 0.76604444-6.42787610e-01j,\n 0.76604444+6.42787610e-01j, -0.93969262-3.42020143e-01j,\n -0.93969262+3.42020143e-01j, -0.5 +8.66025404e-01j,\n 0.17364818-9.84807753e-01j]), 1.6244362503173417e-16)\n--------------\nUsing cython implementation\n88.8 µs ± 7.2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[-0.93969262+3.42020143e-01j -0.93969262-3.42020143e-01j\n 0.17364818-9.84807753e-01j 0.76604444-6.42787610e-01j\n 1. -2.61012179e-54j 0.17364818+9.84807753e-01j\n 0.76604444+6.42787610e-01j -0.5 -8.66025404e-01j\n -0.5 +8.66025404e-01j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-02-29T22:11:50.593Z"
},
"trusted": false
},
"cell_type": "code",
"source": "polynom = np.array([1, 0, 0, 0, -1, -1])\nbenchmark(polynom)",
"execution_count": 7,
"outputs": [
{
"output_type": "stream",
"text": "(1)x^5 + (-1)x^1 + (-1)x^0 \n--------------\nUsing numpy.solve\n79.6 µs ± 6.29 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[ 1.16730398+0.j 0.18123244+1.0839541j 0.18123244-1.0839541j\n -0.76488443+0.35247155j -0.76488443-0.35247155j]\n--------------\nUsing numba implementation\n44.7 µs ± 896 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n(array([-0.76488443+3.52471546e-01j, 1.16730398-7.24892101e-33j,\n -0.76488443-3.52471546e-01j, 0.18123244+1.08395410e+00j,\n 0.18123244-1.08395410e+00j]), 1.56743240643403e-16)\n--------------\nUsing cython implementation\n40.7 µs ± 286 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[ 1.16730398-3.65926689e-33j -0.76488443+3.52471546e-01j\n -0.76488443-3.52471546e-01j 0.18123244-1.08395410e+00j\n 0.18123244+1.08395410e+00j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-02-29T22:11:50.665Z"
},
"trusted": false
},
"cell_type": "code",
"source": "polynom = np.array([1,-3,3,-5])\nbenchmark(polynom)",
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"text": "(1)x^3 + (-3)x^2 + (3)x^1 + (-5)x^0 \n--------------\nUsing numpy.solve\n74 µs ± 4.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[2.58740105+0.j 0.20629947+1.37472964j 0.20629947-1.37472964j]\n--------------\nUsing numba implementation\n20 µs ± 1.84 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n(array([0.20629947-1.37472964e+00j, 0.20629947+1.37472964e+00j,\n 2.58740105+5.03794111e-32j]), 3.581396832712688e-16)\n--------------\nUsing cython implementation\n27 µs ± 1.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n[2.58740105+1.24235219e-32j 0.20629947-1.37472964e+00j\n 0.20629947+1.37472964e+00j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {
"scrolled": false,
"trusted": false
},
"cell_type": "code",
"source": "N = 61\npolynom = np.zeros(N, dtype=int)\npolynom[0] = 1\npolynom[N-1] = -1\nbenchmark(polynom)",
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"text": "(1)x^60 + (-1)x^0 \n--------------\nUsing numpy.solve\n951 µs ± 95.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n[-1.00000000e+00+0.j -9.94521895e-01+0.10452846j\n -9.94521895e-01-0.10452846j -9.78147601e-01+0.20791169j\n -9.78147601e-01-0.20791169j -9.51056516e-01+0.30901699j\n -9.51056516e-01-0.30901699j -9.13545458e-01+0.40673664j\n -9.13545458e-01-0.40673664j -8.66025404e-01+0.5j\n -8.66025404e-01-0.5j -8.09016994e-01+0.58778525j\n -8.09016994e-01-0.58778525j -7.43144825e-01+0.66913061j\n -7.43144825e-01-0.66913061j -6.69130606e-01+0.74314483j\n -6.69130606e-01-0.74314483j -5.87785252e-01+0.80901699j\n -5.87785252e-01-0.80901699j -5.00000000e-01+0.8660254j\n -5.00000000e-01-0.8660254j -4.06736643e-01+0.91354546j\n -4.06736643e-01-0.91354546j -3.09016994e-01+0.95105652j\n -3.09016994e-01-0.95105652j -2.07911691e-01+0.9781476j\n -2.07911691e-01-0.9781476j -1.04528463e-01+0.9945219j\n -1.04528463e-01-0.9945219j -5.68989300e-16+1.j\n -5.68989300e-16-1.j 1.04528463e-01+0.9945219j\n 1.04528463e-01-0.9945219j 2.07911691e-01+0.9781476j\n 2.07911691e-01-0.9781476j 3.09016994e-01+0.95105652j\n 3.09016994e-01-0.95105652j 4.06736643e-01+0.91354546j\n 4.06736643e-01-0.91354546j 5.00000000e-01+0.8660254j\n 5.00000000e-01-0.8660254j 5.87785252e-01+0.80901699j\n 5.87785252e-01-0.80901699j 6.69130606e-01+0.74314483j\n 6.69130606e-01-0.74314483j 7.43144825e-01+0.66913061j\n 7.43144825e-01-0.66913061j 8.09016994e-01+0.58778525j\n 8.09016994e-01-0.58778525j 1.00000000e+00+0.j\n 9.94521895e-01+0.10452846j 9.94521895e-01-0.10452846j\n 9.78147601e-01+0.20791169j 9.78147601e-01-0.20791169j\n 9.51056516e-01+0.30901699j 9.51056516e-01-0.30901699j\n 9.13545458e-01+0.40673664j 9.13545458e-01-0.40673664j\n 8.66025404e-01+0.5j 8.66025404e-01-0.5j ]\n--------------\nUsing numba implementation\n4.64 ms ± 330 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n(array([ 4.06736643e-01+9.13545458e-01j, 9.51056516e-01+3.09016994e-01j,\n 9.78147601e-01-2.07911691e-01j, -5.87785252e-01-8.09016994e-01j,\n 6.69130606e-01+7.43144825e-01j, 8.09016994e-01+5.87785252e-01j,\n 5.87785252e-01-8.09016994e-01j, -3.09016994e-01-9.51056516e-01j,\n -1.00000000e+00+1.19426323e-16j, 8.66025404e-01-5.00000000e-01j,\n -2.07911691e-01-9.78147601e-01j, 1.00000000e+00+1.06910588e-50j,\n 9.94521895e-01+1.04528463e-01j, -2.77756903e-16-1.00000000e+00j,\n -9.94521895e-01-1.04528463e-01j, -5.00000000e-01-8.66025404e-01j,\n -6.78056107e-17+1.00000000e+00j, 9.94521895e-01-1.04528463e-01j,\n -1.04528463e-01+9.94521895e-01j, 8.66025404e-01+5.00000000e-01j,\n 1.04528463e-01-9.94521895e-01j, 7.43144825e-01+6.69130606e-01j,\n -7.43144825e-01-6.69130606e-01j, 6.69130606e-01-7.43144825e-01j,\n -9.94521895e-01+1.04528463e-01j, 5.87785252e-01+8.09016994e-01j,\n -3.09016994e-01+9.51056516e-01j, -9.51056516e-01+3.09016994e-01j,\n 9.13545458e-01+4.06736643e-01j, 2.07911691e-01-9.78147601e-01j,\n -9.78147601e-01+2.07911691e-01j, 1.04528463e-01+9.94521895e-01j,\n -9.78147601e-01-2.07911691e-01j, 9.13545458e-01-4.06736643e-01j,\n -8.66025404e-01-5.00000000e-01j, -8.09016994e-01-5.87785252e-01j,\n -6.69130606e-01+7.43144825e-01j, -4.06736643e-01-9.13545458e-01j,\n -8.66025404e-01+5.00000000e-01j, -9.13545458e-01-4.06736643e-01j,\n 9.51056516e-01-3.09016994e-01j, -5.00000000e-01+8.66025404e-01j,\n -9.13545458e-01+4.06736643e-01j, -9.51056516e-01-3.09016994e-01j,\n 8.09016994e-01-5.87785252e-01j, 3.09016994e-01+9.51056516e-01j,\n 5.00000000e-01-8.66025404e-01j, -4.06736643e-01+9.13545458e-01j,\n 7.43144825e-01-6.69130606e-01j, -8.09016994e-01+5.87785252e-01j,\n -6.69130606e-01-7.43144825e-01j, 4.06736643e-01-9.13545458e-01j,\n 2.07911691e-01+9.78147601e-01j, 9.78147601e-01+2.07911691e-01j,\n -2.07911691e-01+9.78147601e-01j, -7.43144825e-01+6.69130606e-01j,\n -5.87785252e-01+8.09016994e-01j, -1.04528463e-01-9.94521895e-01j,\n 5.00000000e-01+8.66025404e-01j, 3.09016994e-01-9.51056516e-01j]), 1.5530898495486913e-16)\n--------------\nUsing cython implementation\n6.3 ms ± 352 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n[ 5.87785252e-01-8.09016994e-01j -5.00000000e-01+8.66025404e-01j\n -5.87785252e-01+8.09016994e-01j 7.43144825e-01-6.69130606e-01j\n 3.09016994e-01-9.51056516e-01j -3.09016994e-01+9.51056516e-01j\n -8.66025404e-01+5.00000000e-01j -2.07911691e-01-9.78147601e-01j\n 6.69130606e-01-7.43144825e-01j -5.00000000e-01-8.66025404e-01j\n -1.04528463e-01-9.94521895e-01j -8.66025404e-01-5.00000000e-01j\n -4.06736643e-01+9.13545458e-01j -1.04528463e-01+9.94521895e-01j\n 5.87785252e-01+8.09016994e-01j -8.09016994e-01+5.87785252e-01j\n 1.04528463e-01-9.94521895e-01j -1.26407118e-16+1.00000000e+00j\n -9.51056516e-01+3.09016994e-01j -8.09016994e-01-5.87785252e-01j\n 9.13545458e-01-4.06736643e-01j 1.00000000e+00-2.23032868e-57j\n 8.66025404e-01-5.00000000e-01j -6.69130606e-01+7.43144825e-01j\n 6.69130606e-01+7.43144825e-01j 1.04528463e-01+9.94521895e-01j\n 9.51056516e-01-3.09016994e-01j 9.78147601e-01+2.07911691e-01j\n 7.43144825e-01+6.69130606e-01j -6.69130606e-01-7.43144825e-01j\n 5.00000000e-01-8.66025404e-01j 3.09016994e-01+9.51056516e-01j\n -9.78147601e-01-2.07911691e-01j 8.66025404e-01+5.00000000e-01j\n -3.09016994e-01-9.51056516e-01j 4.06736643e-01-9.13545458e-01j\n -9.51263465e-17-1.00000000e+00j 2.07911691e-01-9.78147601e-01j\n -5.87785252e-01-8.09016994e-01j -4.06736643e-01-9.13545458e-01j\n -9.51056516e-01-3.09016994e-01j -9.78147601e-01+2.07911691e-01j\n 9.13545458e-01+4.06736643e-01j -9.13545458e-01+4.06736643e-01j\n -7.43144825e-01+6.69130606e-01j 9.94521895e-01+1.04528463e-01j\n 5.00000000e-01+8.66025404e-01j 8.09016994e-01+5.87785252e-01j\n -9.94521895e-01+1.04528463e-01j -1.00000000e+00-1.46665411e-16j\n 4.06736643e-01+9.13545458e-01j 9.94521895e-01-1.04528463e-01j\n 9.78147601e-01-2.07911691e-01j 8.09016994e-01-5.87785252e-01j\n -9.13545458e-01-4.06736643e-01j -9.94521895e-01-1.04528463e-01j\n -2.07911691e-01+9.78147601e-01j 2.07911691e-01+9.78147601e-01j\n -7.43144825e-01-6.69130606e-01j 9.51056516e-01+3.09016994e-01j]\n--------------\n",
"name": "stdout"
}
]
},
{
"metadata": {
"trusted": false
},
"cell_type": "code",
"source": "",
"execution_count": null,
"outputs": []
}
],
"metadata": {
"_draft": {
"nbviewer_url": "https://gist.github.com/9713842d5e264c94e293a930b479f597"
},
"gist": {
"id": "9713842d5e264c94e293a930b479f597",
"data": {
"description": "make the cofficient of x^n equal to 1. This improves the stability of the algorithm",
"public": true
}
},
"hide_input": false,
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"nbTranslate": {
"hotkey": "alt-t",
"sourceLang": "en",
"targetLang": "fr",
"displayLangs": [
"*"
],
"langInMainMenu": true,
"useGoogleTranslate": true
},
"toc": {
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"base_numbering": 1,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": true,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
},
"varInspector": {
"window_display": true,
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"library": "var_list.py",
"delete_cmd_prefix": "del ",
"delete_cmd_postfix": "",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"library": "var_list.r",
"delete_cmd_prefix": "rm(",
"delete_cmd_postfix": ") ",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"position": {
"left": "1228px",
"top": "197px",
"width": "312px",
"height": "384px",
"right": "20px"
}
},
"language_info": {
"name": "python",
"version": "3.7.7",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@kvedala
Copy link
Author

kvedala commented Apr 9, 2020

Performance improvement

Performing

polynom = polynom / polynom[0]

i.e., by ensuing the coefficient of the highest power of x to be 1 significantly improves the numerical stability.

For example, the above algorithm fails for:

# 1 - fail example:
polynom = np.array([4, 0, -1])
benchmark(polynom)
# 2 - fail example
polynom = np.array([2, 13, -7])
benchmark(polynom)

but the problem gets resolved when executing as such:

# 1 - fail example - resolved:
polynom = np.array([4, 0, -1])
polynom = polynom / polynom[0]
benchmark(polynom)
# 2 - fail example - resolved
polynom = np.array([2, 13, -7])
polynom = polynom / polynom[0]
benchmark(polynom)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment