Apologies for the bad formatting. &nbsp;Here&#39;s a repost with shorter lines.<div><br class="webkit-block-placeholder"></div><div><br class="webkit-block-placeholder"></div><div>Dear all,</div><div><br class="webkit-block-placeholder">
</div><div>I&#39;d like to draw your attention to some of the work that&#39;s been going on in</div><div>the trunk-math branch. &nbsp;Christian Heimes and I have been working on various</div><div>aspects of Python mathematics, and we&#39;re hoping to get at least some of this</div>
<div>work into Python 2.6/3.0. &nbsp;Most of the changes are completed or nearly</div><div>complete, and 2.6/3.0 isn&#39;t very far away, so it seems like a good time to</div><div>try to get some feedback from python-dev.</div>
<div><div class="gmail_quote"><div>&nbsp;</div><div>Here&#39;s an overview of the changes (overview originally written by Christian,</div><div>edited and augmented by me. &nbsp;I hope Christian will step in and correct me if</div><div>
I misrepresent him or his work here.) &nbsp;Many of the changes were motivated by</div><div>Christian&#39;s work (already in the trunk) in making infinities and nans more</div><div>accessible and portable for Python users. (See issue #1640.)</div>
<div>&nbsp;</div><div>* Structural reorganization: there are new files Include/pymath.h and</div><div>Objects/pymath.c with math-related definitions and replacement functions for</div><div>platforms without copysign, log1p, hypot and inverse hyperbolic functions.</div>
<div><br class="webkit-block-placeholder"></div><div>* New math functions: inverse hyperbolic functions (acosh, asinh, atanh).</div><div>&nbsp;</div><div>* New float methods: is_finite, is_inf, is_integer and is_nan.</div><div>
<br class="webkit-block-placeholder"></div><div>* New cmath functions: phase, polar and rect, isinf and isnan.</div><div><br class="webkit-block-placeholder"></div><div>* New complex method: is_finite.</div><div><br class="webkit-block-placeholder">
</div><div>* Work on math and cmath functions to make them handle special values</div><div>(infinities and nans) and floating-point exceptions according to the C99</div><div>standard. &nbsp; The general philosophy follows the ideas put forth by Tim Peters</div>
<div>and co. many moons ago. and repeated in the issue #1640 thread more</div><div>recently: &nbsp;where the C99 standard (or IEEE 754) specifies raising &#39;invalid&#39;</div><div>or &#39;divide-by-zero&#39; Python should raise a ValueError. &nbsp;Where the C99</div>
<div>standard specifies raising &#39;overflow&#39; Python should raise OverflowError.</div><div>&#39;underflow&#39; and &#39;inexact&#39; flags are ignored. &nbsp;From a user&#39;s perspective,</div><div>this means that infinities and nans are never produced by math or cmath</div>
<div>operations on finite values (but see below). &nbsp;sqrt(-1) will always raise</div><div>ValueError, instead of returning a NaN. &nbsp;See issue #711019 and the resulting</div><div>warning at the bottom of the math module documentation. &nbsp; Although</div>
<div>complex_abs doesn&#39;t live in cmathmodule.c, it was also fixed up this way.</div><div><br class="webkit-block-placeholder"></div><div>* The cmath module has been rescued: &nbsp;it&#39;s no longer numerically unsound</div>
<div>(see issue #1381). &nbsp;For the majority of functions (sin, cos, tan, sinh,</div><div>cosh, tanh, asin, acos, atan, asinh, acosh, atanh, exp, sqrt) the real and</div><div>imaginary parts of the results are always within a few ulps of the true</div>
<div>values. &nbsp;(In extensive but non-exhaustive testing I haven&#39;t found errors of</div><div>more than 5 ulps in either the real or imaginary parts for these functions.)</div><div>For log and log10 the errors can be larger when the argument has absolute</div>
<div>value close to 1; this seems pretty much unavoidable without using</div><div>multiple-precision arithmetic. &nbsp;pow and two-argument log are less accurate;</div><div>again, this is essentially unavoidable without adding hundreds of extra</div>
<div>lines of code.</div><div><br class="webkit-block-placeholder"></div><div>* Many more tests. In addition to a handful of extra test_* methods in</div><div>test_math and test_cmath, there are over 1700 testcases (in a badly-named</div>
<div>file Lib/test/cmath.ctest) for the cmath and math functions, with a testcase</div><div>format inspired in no small part by the decimal .decTest file format. &nbsp;Most</div><div>of the testcase values were produced independently of Python using MPFR and</div>
<div>interval arithmetic (C code available on request); &nbsp;some were created by</div><div>hand.</div><div>&nbsp;</div><div>* There&#39;s a per-thread state for division operator. In IEEE 754 mode 1./0.</div><div>and 1.%0. return INF and 0./0. NAN. The contextlib has a new context</div>
<div>&quot;ieee754&quot; and the math lib set_ieee754/get_ieee754 (XXX better place for the</div><div>functions?)</div><div><br class="webkit-block-placeholder"></div><div>Some notes:<br></div><div><br class="webkit-block-placeholder">
</div><div>* We&#39;ve used the C99 standard (especially Annex F and Annex G) as a</div><div>reference for deciding what the math and cmath functions should do, wherever</div><div>possible. It seems to make sense to choose to follow some standard,</div>
<div>essentially so that all the hard decisions have been thought through</div><div>thoroughly by a group of experts. &nbsp;Two obvious choices are the C99 standard</div><div>and IEEE 754(r); for almost all math issues the two say essentially the same</div>
<div>thing. &nbsp;C99 has the advantage that it includes specifications for complex</div><div>math, while IEEE 754(r) does not. &nbsp;(Actually, I&#39;ve been using draft version</div><div>N1124 of the C99 standard, not the standard itself, since I&#39;m too cheap to</div>
<div>pay up for a genuine version. Google &#39;N1124&#39; for a copy.)</div><div>&nbsp;</div><div>* I&#39;m offering to act as long-term maintainer for the cmath module, if</div><div>that&#39;s useful.</div><div>&nbsp;</div><div>* The most interesting and exciting feature, by far (in my opinion) is the</div>
<div>last one. &nbsp;By way of introduction, here&#39;s a snippet from Tim Peters, in a</div><div>comp.lang.python posting</div><div>(<a href="http://mail.python.org/pipermail/python-list/2005-July/330745.html" target="_blank">http://mail.python.org/pipermail/python-list/2005-July/330745.html</a>),</div>
<div>answering a question from Michael Hudson about 1e300*1e300 and inf/inf.</div><div>&nbsp;</div><div>&quot;I believe Python should raise exceptions in these cases by default,</div><div>because, as above, they correspond to the overflow and invalid-operation</div>
<div>signals respectively, and Python should raise exceptions on the overflow,</div><div>invalid-operation, and divide-by-0 signals by default. But I also believe</div><div>Python _dare not_ do so unless it also supplies sane machinery for disabling</div>
<div>traps on specific signals (along the lines of the relevant standards here).</div><div>Many serious numeric programmers would be livid, and justifiably so, if they</div><div>couldn&#39;t get non-stop mode back. The most likely x-platfrom accident so far</div>
<div>is that they&#39;ve been getting non-stop mode in Python since its beginning.&quot;</div><div>&nbsp;</div><div>Christian has found a simple, elegant and practical way to make it possible</div><div>for Python to raise these exceptions by default, while also allowing serious</div>
<div>numeric users access to non-stop mode---i.e., a mode that generates inf from</div><div>1/0 instead of raising a Python exception. &nbsp;(I had a much more elaborate</div><div>plan in mind, involving a thread-local context similar to Decimal&#39;s, with</div>
<div>control over individual traps and flags. &nbsp;Christian&#39;s solution is far more</div><div>practical.) &nbsp;The idea is that any arithmetic operating under a &quot;with</div><div>ieee754:&quot; acts like arithmetic on an IEEE 754 platform with no traps</div>
<div>enabled: &nbsp;invalid operations like sqrt(-1) produce a nan, division by zero</div><div>produces an infinity, etc. &nbsp;No Python exceptions related to floating-point</div><div>are raised.</div><div>&nbsp;</div><div>See the thread started by Neal Becker at<a href="http://mail.python.org/pipermail/python-list/2008-February/477064.html" target="_blank"></a></div>
<div><a href="http://mail.python.org/pipermail/python-list/2008-February/477064.html" target="_blank">http://mail.python.org/pipermail/python-list/2008-February/477064.html</a></div><div>entitled &quot;Turn off ZeroDivisionError?&quot; for a recent discussion of these</div>
<div>issues.</div><div>&nbsp;</div><div>I fear that the per-thread state change seems like something where a PEP</div><div>might be necessary; it&#39;s also not clear right now that Christian and I have</div><div>exactly the same goals here (discussion is ongoing). &nbsp;But I hope that the</div>
<div>rest of the changes are uncontroversial enough to merit consideration for</div><div>possible inclusion in 2.6/3.0.</div><div>&nbsp;</div><div>Thoughts?</div><div>&nbsp;</div><div>Mark</div><div><br></div></div></div>