[issue35880] math.sin has no backward error; this isn't documented

New submission from Jurjen N.E. Bos <jneb@users.sourceforge.net>: The documentation of math.sin (and related trig functions) doesn't speak about backward error. In cPython, as far as I can see, there is no backward error at all, which is quite uncommon. This may vary between implementations; many math libraries of other languages have a backward error, resulting in large errors for large arguments. e.g. sin(1<<500) is correctly computed as 0.42925739234242827, where a backward error as small as 1e-150 can give a completely wrong result. Some text could be added (which I am happy to produce) that explains what backward error means, and under which circumstances you can expect an accurate result. ---------- assignee: docs@python components: Documentation messages: 334672 nosy: docs@python, jneb priority: normal severity: normal status: open title: math.sin has no backward error; this isn't documented versions: Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7, Python 3.8 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Mark Dickinson <dickinsm@gmail.com> added the comment: There's not a whole lot that we can usefully say about the accuracy of `math.sin`, since CPython just wraps C's sin function. So we just inherit the behaviour of the platform libm. I don't think I understand what you mean by "backward error" in this context. What do you mean by: "as far as I can see, there is no backward error at all"? It may indeed be the case that math.sin is correctly rounded, or at least close to correctly rounded (e.g., errors consistently within 0.503 ulp or some such) on some platforms, but that's entirely platform dependent. ---------- nosy: +mark.dickinson _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Steven D'Aprano <steve+python@pearwood.info> added the comment:
sin(1<<500) is correctly computed as 0.42925739234242827
py> math.sin(1<<500) 0.9996230490249484 Wolfram Alpha says it is 0.429257392342428277735329299112473759079115476327819897... https://www.wolframalpha.com/input/?i=sin%282^500%29&assumption=%22TrigRD%22+-%3E+%22R%22
Some text could be added (which I am happy to produce) that explains what backward error means
You could start by telling us here what you mean by backward error. Are you talking about this? https://en.wikipedia.org/wiki/Numerical_stability#Stability_in_numerical_lin... ---------- nosy: +steven.daprano _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Tim Peters <tim@python.org> added the comment: As Mark said, the behavior of Python's floating-point math functions (not just trig, but also log, pow, exp, ...) is inherited almost entirely from the platform C's math libraries. Python itself guarantees nothing about what `math.sin(x)` returns for any `x` - and it can, & does, vary across platforms. ---------- nosy: +tim.peters _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Change by Terry J. Reedy <tjreedy@udel.edu>: ---------- stage: -> needs patch versions: -Python 3.4, Python 3.5, Python 3.6 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Mark Dickinson <dickinsm@gmail.com> added the comment: @jneb: Please could you clarify what sort of addition to the documentation you're proposing? Again, it's not clear what you mean by "backward error" here, or what sort of addition would be useful given the divergence of math function behaviours across platforms. Any documentation addition should cover more than just sin here; sin isn't at all special. Setting to pending. ---------- status: open -> pending _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Jurjen N.E. Bos <jneb@users.sourceforge.net> added the comment: I stand corrected; more on that later. "backward error" is the mathematical term used for the accuracy of a function. (Forward error is in the result proper; backward error means that you calculate the correct result for a number that is very close to the input.) Since pi is not a machine representable number, it is pretty hard to implement the trig functions with a zero backward error, since you need to divide by 2*pi in any reasonable implementation. For some reason, I was in the impression that the backward error of the sine was zero. I wrote a program to demonstrate the matter, only to find out that I was wrong :P Maybe in the 32 bit version, but not in the 64 bits? Anyway, it is more implementation dependent than I though. Althougth the backward error of the builtin sine function isn't zero, it is still a cool 21 digits, as the program shows. - Jurjen ---------- resolution: -> rejected status: pending -> open Added file: https://bugs.python.org/file48199/sindemo.py _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________

Tim Peters <tim@python.org> added the comment: Jurjen, the errors you see in Python's sin() are _entirely_ due to your platform C's libm. Python just calls the platform C's sin. So nothing can be said about it in general. The better libm trig functions today do indeed perform trig argument reduction "as if" an infinite precision pi were used. In practice, even for IEEE double precision no more than a few thousand bits are ever needed in the worst case, and the better libm trig functions use something much cheaper than that for arguments in a "reasonably small" range. But, again, Python has nothing to do with that. The better libm implementations guarantee worst-case error strictly less than 1 ULP away from the infinitely precise result. But correctly rounded ("nearest-even") in all cases is still beyond what most of the better libms guarantee. ---------- stage: needs patch -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue35880> _______________________________________
participants (5)
-
Jurjen N.E. Bos
-
Mark Dickinson
-
Steven D'Aprano
-
Terry J. Reedy
-
Tim Peters