>> On Mon, Jun 6, 2011 at 8:54 AM, Chris Torek <nos...@torek.net> wrote: >>> A signalling NaN traps at (more or less -- details vary depending on >>> FPU architecture) load time.
>On Mon, 06 Jun 2011 09:13:25 +1000, Chris Angelico wrote: >> Load. By this you mean the operation of taking a bit-pattern in RAM and >> putting it into a register? So, you can calculate 0/0, get a signalling >> NaN, and then save that into a memory variable, all without it trapping; >> and then it traps when you next perform an operation on that number? I mean, if you think of the FPU as working (in principle) with either just one or two registers and a load/store architecture, or a tiny little FPU-stack (the latter is in fact the case for Intel FPUs), with no optimization, you get a trap when you attempted to load-up the sNaN value in order to do some operation on it. For instance, if x is an sNaN, "y = x + 1" turns into "load x; load 1.0; add; store y" and the trap occurs when you do "load x". In article <4dec2ba6$0$29996$c3e8da3$54964...@news.astraweb.com>, Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote: >The intended behaviour is operations on "quiet NANs" should return NANs, >but operations on "signalling NANs" should cause a trap, which can either >be ignored, and converted into a quiet NAN, or treated as an exception. > >E.g. in Decimal: > >>>> import decimal >>>> qnan = decimal.Decimal('nan') # quiet NAN >>>> snan = decimal.Decimal('snan') # signalling NAN >>>> 1 + qnan >Decimal('NaN') >>>> 1 + snan >Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "/usr/local/lib/python3.1/decimal.py", line 1108, in __add__ > ans = self._check_nans(other, context) > File "/usr/local/lib/python3.1/decimal.py", line 746, in _check_nans > self) > File "/usr/local/lib/python3.1/decimal.py", line 3812, in _raise_error > raise error(explanation) >decimal.InvalidOperation: sNaN Moreover: >>> cx = decimal.getcontext() >>> cx Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[DivisionByZero, Overflow, InvalidOperation]) >>> cx.traps[decimal.InvalidOperation] = False >>> snan Decimal("sNaN") >>> 1 + snan Decimal("NaN") so as you can see, by ignoring the InvalidOperation exception, we had our sNaN converted to a (regular, non-signal-ing, "quiet") NaN, and 1 + NaN is still NaN. (I admit that my mental model using "loads" can mislead a bit since: >>> cx.traps[decimal.InvalidOperation] = True # restore trapping >>> also_snan = snan >>> A simple copy operation is not a "load" in this particular sense, and on most real hardware, one just uses an ordinary 64-bit integer memory-copying operation to copy FP bit patterns from one place to another.) There is some good information on wikipedia: http://en.wikipedia.org/wiki/NaN (Until I read this, I was not aware that IEEE now recommends that the quiet-vs-signal bit be 1-for-quiet 0-for-signal. I prefer the other way around since you can then set memory to all-1-bits if it contains floating point numbers, and get exceptions if you refer to a value before seting it.) -- In-Real-Life: Chris Torek, Wind River Systems Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603 email: gmail (figure it out) http://web.torek.net/torek/index.html
-- http://mail.python.org/mailman/listinfo/python-list