<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 29, 2018 at 8:21 PM, Maxwell Aifer <span dir="ltr"><<a href="mailto:maifer@haverford.edu" target="_blank">maifer@haverford.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail-m_-6016144409142987216markdown-here-wrapper"><p style="margin:0px 0px 1.2em">Hi,<br>I noticed some frustrating inconsistencies in the various ways to evaluate polynomials using numpy. Numpy has three ways of evaluating polynomials (that I know of) and each of them has a different syntax:</p>
<ul style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px"><p style="margin:0.5em 0px"><a href="https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.polynomial.polynomial.Polynomial.html#numpy.polynomial.polynomial.Polynomial" target="_blank">numpy.polynomial.polynomial.<wbr>Polynomial</a>: You define a polynomial by a list of coefficients <strong>in order of increasing degree</strong>, and then use the class’s call() function.</p>
</li>
<li style="margin:0.5em 0px"><p style="margin:0.5em 0px"><a href="https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.polyval.html" target="_blank">np.polyval</a>: Evaluates a polynomial at a point. <em>First</em> argument is the polynomial, or list of coefficients <strong>in order of decreasing degree</strong>, and the <em>second</em> argument is the point to evaluate at.</p>
</li>
<li style="margin:0.5em 0px"><p style="margin:0.5em 0px"><a href="https://docs.scipy.org/doc/numpy-1.12.0/reference/generated/numpy.polynomial.polynomial.polyval.html" target="_blank">np.polynomial.polynomial.<wbr>polyval</a>: Also evaluates a polynomial at a point, but has more support for vectorization. <em>First</em> argument is the point to evaluate at, and <em>second</em> argument the list of coefficients <strong>in order of increasing degree</strong>.</p>
</li>
</ul>
<p style="margin:0px 0px 1.2em">Not only the order of arguments is changed between different methods, but the order of the coefficients is reversed as well, leading to puzzling bugs (in my experience). What could be the reason for this madness? As polyval is a shameless ripoff of <a href="https://www.mathworks.com/help/matlab/ref/polyval.html" target="_blank">Matlab’s function of the same name</a> anyway, why not just use matlab’s syntax (<code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">polyval([c0, c1, c2...], x)</code>) across the board?</p>
<div title="MDH:SGksPGRpdj5JIG5vdGljZWQgc29tZSBmcnVzdHJhdGluZyBpbmNvbnNpc3RlbmNpZXMgaW4gdGhl
IHZhcmlvdXMgd2F5cyB0byBldmFsdWF0ZSBwb2x5bm9taWFscyB1c2luZyA8ZyBjbGFzcz0iZ3Jf
IGdyXzE5NiBnci1hbGVydCBncl9zcGVsbCBncl9pbmxpbmVfY2FyZHMgZ3JfZGlzYWJsZV9hbmlt
X2FwcGVhciBDb250ZXh0dWFsU3BlbGxpbmciIGlkPSIxOTYiIGRhdGEtZ3ItaWQ9IjE5NiI+bnVt
cHk8L2c+LiBOdW1weSBoYXMgdGhyZWUgd2F5cyBvZiBldmFsdTxnIGNsYXNzPSJncl8gZ3JfMjM1
MSBnci1hbGVydCBncl9ncmFtbSBncl9pbmxpbmVfY2FyZHMgZ3JfZGlzYWJsZV9hbmltX2FwcGVh
ciBHcmFtbWFyIG9ubHktaW5zIHJlcGxhY2VXaXRob3V0U2VwIiBpZD0iMjM1MSIgZGF0YS1nci1p
ZD0iMjM1MSI+YXRpbmcgPC9nPnBvbHlub21pYWxzICh0aGF0IEkga25vdyBvZikgYW5kIGVhY2gg
b2YgdGhlbSBoYXMgYSBkaWZmZXJlbnQgc3ludGF4OjwvZGl2PjxkaXY+LSBbbnVtcHkucG9seW5v
bWlhbC5wb2x5bm9taWFsLlBvbHlub21pYWxdKGh0dHBzOi8vZG9jcy5zY2lweS5vcmcvZG9jL251
bXB5LTEuMTMuMC9yZWZlcmVuY2UvZ2VuZXJhdGVkL251bXB5LnBvbHlub21pYWwucG9seW5vbWlh
bC5Qb2x5bm9taWFsLmh0bWwjbnVtcHkucG9seW5vbWlhbC5wb2x5bm9taWFsLlBvbHlub21pYWwp
OiBZb3UgZGVmaW5lIGEgcG9seW5vbWlhbCBieSBhIGxpc3Qgb2YgY29lZmZpY2llbnRzICoqaW4g
b3JkZXIgb2YgaW5jcmVhc2luZyBkZWdyZWUqKiwgYW5kIHRoZW4gdXNlIHRoZSBjbGFzcydzIGNh
bGwoKSBmdW5jdGlvbi48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pi0gW25wLnBvbHl2YWxdKGh0
dHBzOi8vZG9jcy5zY2lweS5vcmcvZG9jL251bXB5LTEuMTMuMC9yZWZlcmVuY2UvZ2VuZXJhdGVk
L251bXB5LnBvbHl2YWwuaHRtbCk6IDxzcGFuIHN0eWxlPSJmb250LXNpemU6IHNtYWxsOyB0ZXh0
LWFsaWduOiBsZWZ0OyBiYWNrZ3JvdW5kLWNvbG9yOiByZ2IoMjU1LCAyNTUsIDI1NSk7IHRleHQt
ZGVjb3JhdGlvbi1zdHlsZTogaW5pdGlhbDsgdGV4dC1kZWNvcmF0aW9uLWNvbG9yOiBpbml0aWFs
OyBmbG9hdDogbm9uZTsgZGlzcGxheTogaW5saW5lOyI+RXZhbHVhdGVzIGEgcG9seW5vbWlhbCBh
dCBhIHBvaW50LjxzcGFuPiZuYnNwOyo8L3NwYW4+PC9zcGFuPjxzcGFuIGNsYXNzPSJnbWFpbC1n
cl8gZ21haWwtZ3JfMTQ1MiBnbWFpbC1nci1hbGVydCBnbWFpbC1ncl9ncmFtbSBnbWFpbC1ncl9p
bmxpbmVfY2FyZHMgZ21haWwtZ3JfcnVuX2FuaW0gZ21haWwtR3JhbW1hciBnbWFpbC1vbmx5LWlu
cyBnbWFpbC1yZXBsYWNlV2l0aG91dFNlcCIgaWQ9ImdtYWlsLTE0NTIiIHN0eWxlPSJkaXNwbGF5
OiBpbmxpbmU7IGZvbnQtc2l6ZTogc21hbGw7IGJvcmRlci1ib3R0b206IDJweCBzb2xpZCB0cmFu
c3BhcmVudDsgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsgYmFja2dyb3VuZC1wb3NpdGlv
bi14OiAtMXB4OyBhbmltYXRpb24tZHVyYXRpb246IDAuNHM7IGFuaW1hdGlvbi10aW1pbmctZnVu
Y3Rpb246IGVhc2U7IGFuaW1hdGlvbi1kZWxheTogaW5pdGlhbDsgYW5pbWF0aW9uLWl0ZXJhdGlv
bi1jb3VudDogaW5pdGlhbDsgYW5pbWF0aW9uLWRpcmVjdGlvbjogaW5pdGlhbDsgYW5pbWF0aW9u
LWZpbGwtbW9kZTogZm9yd2FyZHM7IGFuaW1hdGlvbi1wbGF5LXN0YXRlOiBpbml0aWFsOyBhbmlt
YXRpb24tbmFtZTogZ3JfX2FwcGVhcl9jcml0aWNhbDsgdGV4dC1hbGlnbjogbGVmdDsgYmFja2dy
b3VuZC1jb2xvcjogcmdiKDI1NSwgMjU1LCAyNTUpOyB0ZXh0LWRlY29yYXRpb24tc3R5bGU6IGlu
aXRpYWw7IHRleHQtZGVjb3JhdGlvbi1jb2xvcjogaW5pdGlhbDsiPkZpcnN0Kjwvc3Bhbj48c3Bh
biBzdHlsZT0iZm9udC1zaXplOiBzbWFsbDsgdGV4dC1hbGlnbjogbGVmdDsgYmFja2dyb3VuZC1j
b2xvcjogcmdiKDI1NSwgMjU1LCAyNTUpOyB0ZXh0LWRlY29yYXRpb24tc3R5bGU6IGluaXRpYWw7
IHRleHQtZGVjb3JhdGlvbi1jb2xvcjogaW5pdGlhbDsgZmxvYXQ6IG5vbmU7IGRpc3BsYXk6IGlu
bGluZTsiPjxzcGFuPiZuYnNwOzwvc3Bhbj5hcmd1bWVudCBpcyB0aGUgcG9seW5vbWlhbCwgb3Ig
bGlzdCBvZiBjb2VmZmljaWVudHMgKippbiBvcmRlciBvZiBkZWNyZWFzaW5nIGRlZ3JlZSoqLCBh
bmQgdGhlICpzZWNvbmQqIGFyZ3VtZW50IGlzIHRoZSBwb2ludCB0byBldmFsdWF0ZTxzcGFuPiZu
YnNwOzwvc3Bhbj48L3NwYW4+PHNwYW4gY2xhc3M9ImdtYWlsLWdyXyBnbWFpbC1ncl8yMDQyIGdt
YWlsLWdyLWFsZXJ0IGdtYWlsLWdyX3NwZWxsIGdtYWlsLWdyX2lubGluZV9jYXJkcyBnbWFpbC1n
cl9ydW5fYW5pbSBnbWFpbC1Db250ZXh0dWFsU3BlbGxpbmcgZ21haWwtaW5zLWRlbCIgaWQ9Imdt
YWlsLTIwNDIiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZvbnQtc2l6ZTogc21hbGw7IGJvcmRl
ci1ib3R0b206IDJweCBzb2xpZCB0cmFuc3BhcmVudDsgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJl
cGVhdDsgYmFja2dyb3VuZC1wb3NpdGlvbi14OiAtMXB4OyBhbmltYXRpb24tZHVyYXRpb246IDAu
NHM7IGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb246IGVhc2U7IGFuaW1hdGlvbi1kZWxheTogaW5p
dGlhbDsgYW5pbWF0aW9uLWl0ZXJhdGlvbi1jb3VudDogaW5pdGlhbDsgYW5pbWF0aW9uLWRpcmVj
dGlvbjogaW5pdGlhbDsgYW5pbWF0aW9uLWZpbGwtbW9kZTogZm9yd2FyZHM7IGFuaW1hdGlvbi1w
bGF5LXN0YXRlOiBpbml0aWFsOyBhbmltYXRpb24tbmFtZTogZ3JfX2FwcGVhcl9jcml0aWNhbDsg
dGV4dC1hbGlnbjogbGVmdDsgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI1NSwgMjU1LCAyNTUpOyB0
ZXh0LWRlY29yYXRpb24tc3R5bGU6IGluaXRpYWw7IHRleHQtZGVjb3JhdGlvbi1jb2xvcjogaW5p
dGlhbDsiPjxnIGNsYXNzPSJncl8gZ3JfMzQwNiBnci1hbGVydCBncl9zcGVsbCBncl9pbmxpbmVf
Y2FyZHMgZ3JfcnVuX2FuaW0gQ29udGV4dHVhbFNwZWxsaW5nIGlucy1kZWwiIGlkPSIzNDA2IiBk
YXRhLWdyLWlkPSIzNDA2Ij5hdDwvZz48L3NwYW4+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogc21h
bGw7IHRleHQtYWxpZ246IGxlZnQ7IGJhY2tncm91bmQtY29sb3I6IHJnYigyNTUsIDI1NSwgMjU1
KTsgdGV4dC1kZWNvcmF0aW9uLXN0eWxlOiBpbml0aWFsOyB0ZXh0LWRlY29yYXRpb24tY29sb3I6
IGluaXRpYWw7IGZsb2F0OiBub25lOyBkaXNwbGF5OiBpbmxpbmU7Ij4uPC9zcGFuPgoKPC9kaXY+
PGRpdj48c3BhbiBzdHlsZT0iZm9udC1zaXplOiBzbWFsbDsgdGV4dC1hbGlnbjogbGVmdDsgYmFj
a2dyb3VuZC1jb2xvcjogcmdiKDI1NSwgMjU1LCAyNTUpOyB0ZXh0LWRlY29yYXRpb24tc3R5bGU6
IGluaXRpYWw7IHRleHQtZGVjb3JhdGlvbi1jb2xvcjogaW5pdGlhbDsgZmxvYXQ6IG5vbmU7IGRp
c3BsYXk6IGlubGluZTsiPjxicj48L3NwYW4+PC9kaXY+PGRpdj48c3BhbiBzdHlsZT0iZm9udC1z
aXplOiBzbWFsbDsgdGV4dC1hbGlnbjogbGVmdDsgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI1NSwg
MjU1LCAyNTUpOyB0ZXh0LWRlY29yYXRpb24tc3R5bGU6IGluaXRpYWw7IHRleHQtZGVjb3JhdGlv
bi1jb2xvcjogaW5pdGlhbDsgZmxvYXQ6IG5vbmU7IGRpc3BsYXk6IGlubGluZTsiPi0gW25wLnBv
bHlub21pYWwucG9seW5vbWlhbC5wb2x5dmFsXShodHRwczovL2RvY3Muc2NpcHkub3JnL2RvYy9u
dW1weS0xLjEyLjAvcmVmZXJlbmNlL2dlbmVyYXRlZC9udW1weS5wb2x5bm9taWFsLnBvbHlub21p
YWwucG9seXZhbC5odG1sKTogQWxzbyBldmFsdWF0ZXMgYSBwb2x5bm9taWFsIGF0IGEgcG9pbnQs
IGJ1dCBoYXMgbW9yZSBzdXBwb3J0IGZvciB2ZWN0b3JpemF0aW9uLiAqRmlyc3QqIGFyZ3VtZW50
IGlzIHRoZSBwb2ludCB0byBldmFsdWF0ZSBhdCwgYW5kIDxnIGNsYXNzPSJncl8gZ3JfMzQxMiBn
ci1hbGVydCBncl90aW55IGdyX2dyYW1tIGdyX2lubGluZV9jYXJkcyBncl9ydW5fYW5pbSBHcmFt
bWFyIG9ubHktaW5zIHJlcGxhY2VXaXRob3V0U2VwIiBpZD0iMzQxMiIgZGF0YS1nci1pZD0iMzQx
MiI+KjwvZz5zZWNvbmQqIGFyZ3VtZW50IHRoZSBsaXN0IG9mIGNvZWZmaWNpZW50cyAqKmluIG9y
ZGVyIG9mIGluY3JlYXNpbmcgZGVncmVlKiouPC9zcGFuPjwvZGl2PjxkaXY+PHNwYW4gc3R5bGU9
ImZvbnQtc2l6ZTogc21hbGw7IHRleHQtYWxpZ246IGxlZnQ7IGJhY2tncm91bmQtY29sb3I6IHJn
YigyNTUsIDI1NSwgMjU1KTsgdGV4dC1kZWNvcmF0aW9uLXN0eWxlOiBpbml0aWFsOyB0ZXh0LWRl
Y29yYXRpb24tY29sb3I6IGluaXRpYWw7IGZsb2F0OiBub25lOyBkaXNwbGF5OiBpbmxpbmU7Ij48
YnI+PC9zcGFuPjwvZGl2PjxkaXY+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTogc21hbGw7IHRleHQt
YWxpZ246IGxlZnQ7IGJhY2tncm91bmQtY29sb3I6IHJnYigyNTUsIDI1NSwgMjU1KTsgdGV4dC1k
ZWNvcmF0aW9uLXN0eWxlOiBpbml0aWFsOyB0ZXh0LWRlY29yYXRpb24tY29sb3I6IGluaXRpYWw7
IGZsb2F0OiBub25lOyBkaXNwbGF5OiBpbmxpbmU7Ij5Ob3Qgb25seSB0aGUgb3JkZXIgb2YgYXJn
dW1lbnRzIGlzIGNoYW5nZWQgYmV0d2VlbiBkaWZmZXJlbnQgbWV0aG9kcywgYnV0IHRoZSBvcmRl
ciBvZiB0aGUgY29lZmZpY2llbnRzIGlzIHJldmVyc2VkIGFzIHdlbGwsIGxlYWRpbmcgdG8gcHV6
emxpbmcgYnVncyAoaW4gbXkgZXhwZXJpZW5jZSkuIFdoYXQgY291bGQgYmUgdGhlIHJlYXNvbiBm
b3IgdGhpcyBtYWRuZXNzPyBBcyA8ZyBjbGFzcz0iZ3JfIGdyXzM0MTQgZ3ItYWxlcnQgZ3Jfc3Bl
bGwgZ3JfaW5saW5lX2NhcmRzIGdyX3J1bl9hbmltIENvbnRleHR1YWxTcGVsbGluZyBpbnMtZGVs
IG11bHRpUmVwbGFjZSIgaWQ9IjM0MTQiIGRhdGEtZ3ItaWQ9IjM0MTQiPnBvbHl2YWw8L2c+IGlz
IGEgc2hhbWVsZXNzIHJpcG9mZiBvZiBbTWF0bGFiJ3MmbmJzcDtmdW5jdGlvbiBvZiB0aGUgc2Ft
ZSBuYW1lXShodHRwczovL3d3dy5tYXRod29ya3MuY29tL2hlbHAvbWF0bGFiL3JlZi9wb2x5dmFs
Lmh0bWwpIGFueXdheSwgd2h5IG5vdCBqdXN0IHVzZSA8ZyBjbGFzcz0iZ3JfIGdyXzM0MTMgZ3It
YWxlcnQgZ3Jfc3BlbGwgZ3JfaW5saW5lX2NhcmRzIGdyX3J1bl9hbmltIENvbnRleHR1YWxTcGVs
bGluZyBpbnMtZGVsIG11bHRpUmVwbGFjZSIgaWQ9IjM0MTMiIGRhdGEtZ3ItaWQ9IjM0MTMiPm1h
dGxhYidzPC9nPiBzeW50YXggKDxnIGNsYXNzPSJncl8gZ3JfMzQxNSBnci1hbGVydCBncl9zcGVs
bCBncl9pbmxpbmVfY2FyZHMgZ3JfcnVuX2FuaW0gQ29udGV4dHVhbFNwZWxsaW5nIiBpZD0iMzQx
NSIgZGF0YS1nci1pZD0iMzQxNSI+YGBgcG9seXZhbDwvZz4oW2MwLCBjMSwgYzIuLi5dLCB4KWBg
YCkgYWNyb3NzIHRoZSBib2FyZD88L3NwYW4+PC9kaXY+PGRpdj48YnI+PC9kaXY+" style="height:0px;width:0px;max-height:0px;max-width:0px;overflow:hidden;font-size:0em;padding:0px;margin:0px">​</div></div></div>
<br></blockquote><div><br></div><div>The polynomial package, with its various basis, deals with series, and especially with the truncated series approximations that are used in numerical work. Series are universally written in increasing order of the degree. The Polynomial class is efficient in a single variable, while the num<span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">py.polynomial.polynomial.polyval function is intended as a building block and can also deal with multivariate polynomials or multidimensional arrays of polynomials, or a mix. See the simple implementation of polyval3d for an example. If you are just dealing with a single variable, use Polynomial, which will also track scaling and offsets for numerical stability and is generally much superior to the simple polyval function from a numerical point of view.</span></div><div><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">As to the ordering of the degrees, learning that the degree matches the index is pretty easy and is a more natural fit for the implementation code, especially as the number of variables increases. I note that Matlab has ones based indexing, so that was really not an option for them.</span></div><div><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Chuck</span></div></div></div></div>