In the IEEE total order, +0 and 0 are distinct, which your order doesn't handle, For NaNs, the issue is that NaN is NOT a single representation, but each combination of the sign bit and the 52 mantissa bits (except all zeros which signify infinity) when the exponent field is all ones is a different NaN (and the MSB of the mantissa indicates quiet or signalling). you code makes all these values unordered with respect to each other as opposed to having a distinct strict order. That probably isn't that important of a distinction.
Ok. Fair enough. My 3line version puts all the NaNs in whatever order they started out in in the list. Well, positive and negative get separated properly. I could add one more line to deal with the +/ zeros, but it's the same idea of making a tuple where the first element sorts first (maybe 0.5 / 0.5, or make the NaNs +/2, whatever).
The thing is that there's no *Python* way (other than the struct module) to get NaNs with any particular bits. I have no control over which bits I'll get with `float('nan')` or `math.nan` or `1e10001e999`. But if we actually want those bits I don't control ordered, we have to do it Tim's way... I get it now.
Has anyone actually ever used those available bits for the zillions of NaNs for anything good?
IEEE total_order puts NaN as bigger than infinity, and NaN as
less than inf.
You mean like this?
def total_order(x):
... if math.isnan(x): ... return (math.copysign(1, x), x) ... return (0, x) ... ...
nums = [1, 2, float('inf'), float('nan'), float('inf'),
float('nan')]
nums
[1, 2, inf, nan, inf, nan]
sorted(nums, key=total_order)
[nan, inf, 1, 2, inf, nan]
[David]
Has anyone actually ever used those available bits for the zillions of NaNs for anything good?
Yes: in Python, many sample programs I've posted cleverly use NaN bits to hide ASCII encodings of delightful puns ;)
Seriously? Not that I've seen. The _intent_ was that, e.g., quiet NaNs could encode diagnostic information, such as the source code line number of the operation that produced a qNaN. But I don't know that anyone ever exploited that.
Signaling NaNs were even more quixotic. For example, in theory, an implementation _could_ reserve some range of sNaN bit patterns to mean "the lower 20 bits are an index into a table of extended precision values", and a trap handler could catch the signal when the sNaN was used, and do extendedprecision calculation in software, store the result in the table, and return an sNaN containing the result's index (or a regular double if the result fit in the format).
In short, the kinds of things hardware designers think software would love ;)
What is it, 2**482 signaling NaNs and 2**48 quiet NaNs? Is my quick count correct (in 64bit)? Great opportunity for steganography, I reckon.
On Sun, Dec 29, 2019 at 11:51 PM Tim Peters tim.peters@gmail.com wrote:
[David]
Has anyone actually ever used those available bits for the zillions of
NaNs for
anything good?
Yes: in Python, many sample programs I've posted cleverly use NaN bits to hide ASCII encodings of delightful puns ;)
Seriously? Not that I've seen. The _intent_ was that, e.g., quiet NaNs could encode diagnostic information, such as the source code line number of the operation that produced a qNaN. But I don't know that anyone ever exploited that.
Signaling NaNs were even more quixotic. For example, in theory, an implementation _could_ reserve some range of sNaN bit patterns to mean "the lower 20 bits are an index into a table of extended precision values", and a trap handler could catch the signal when the sNaN was used, and do extendedprecision calculation in software, store the result in the table, and return an sNaN containing the result's index (or a regular double if the result fit in the format).
In short, the kinds of things hardware designers think software would love ;)
[David]
What is it, 2**482 signaling NaNs and 2**48 quiet NaNs? Is my quick count correct (in 64bit)?
Any bit pattern where the exponent is all ones (there are 11 exponent bits, giving 2**(6411) = 2**53 bit patterns with an allones exponent), _and_ the significand isn't all 0 (it's an infinity if they're all 0). So that's 2**53  2 NaN bit patterns in all. The original standard didn't define the encoding difference between signaling and quiet, so all that can be said is that there are 2**52  2 of one and 2**52 of the other. But in real life, almost all implementations take the mostsignificant bit of the significand to mean "quiet", so in almost all implementations there are 2 more qNaNs than sNaNs.
Great opportunity for steganography, I reckon.
Too easy ;) When I send messages to my Russian handlers, I send a long list of floatingpoint +  * / and sqrt examples. The CIA hasn't yet figured out the secret: an example means "1" if the 56th most significant bit of the infinitely precise result is 1, else 0. Staring at the actual double precision results is useless :)
64 bit binary floating point (what Python uses as Float) as 1 sign bit, 11 exponent bits, as 52 mantissa bits.
NaNs are numbers with the exponent bits being all ones, with the exception that exponent bits all ones and mantissa bits all zeros is infinity. Within NaNs, the MSB of the mantissa indicates if the NaN is signalling or quiet, so we have 51 mantissa bits, and the sign bit (52 total) to make different NaNs with.
On 12/30/19 12:09 AM, David Mertz wrote:
What is it, 2**482 signaling NaNs and 2**48 quiet NaNs? Is my quick count correct (in 64bit)? Great opportunity for steganography, I reckon.
On Sun, Dec 29, 2019 at 11:51 PM Tim Peters <tim.peters@gmail.com mailto:tim.peters@gmail.com> wrote:
[David] > Has anyone actually ever used those available bits for the zillions of NaNs for > anything good? Yes: in Python, many sample programs I've posted cleverly use NaN bits to hide ASCII encodings of delightful puns ;) Seriously? Not that I've seen. The _intent_ was that, e.g., quiet NaNs could encode diagnostic information, such as the source code line number of the operation that produced a qNaN. But I don't know that anyone ever exploited that. Signaling NaNs were even more quixotic. For example, in theory, an implementation _could_ reserve some range of sNaN bit patterns to mean "the lower 20 bits are an index into a table of extended precision values", and a trap handler could catch the signal when the sNaN was used, and do extendedprecision calculation in software, store the result in the table, and return an sNaN containing the result's index (or a regular double if the result fit in the format). In short, the kinds of things hardware designers think software would love ;)
On 30 Dec 2019, at 05:55, Tim Peters tim.peters@gmail.com wrote:
[David]
Has anyone actually ever used those available bits for the zillions of NaNs for anything good?
Yes: in Python, many sample programs I've posted cleverly use NaN bits to hide ASCII encodings of delightful puns ;)
Seriously? Not that I've seen. The _intent_ was that, e.g., quiet NaNs could encode diagnostic information, such as the source code line number of the operation that produced a qNaN. But I don't know that anyone ever exploited that.
That sounds amazing! If python was the first to do this with the data then displayed in error messages it could really force other languages to play catch up.
On Dec 29, 2019, at 20:22, David Mertz mertz@gnosis.cx wrote:
Has anyone actually ever used those available bits for the zillions of NaNs for anything good?
Good? No. But I have used qNaN payloads for smuggling tagged values through a JS bridge or AppleEvents. It turns out that it’s a lot harder to debug your code when you can’t inspect the values, but on the plus side you do feel really clever for a few seconds when you first get it working. :)
On Sun, Dec 29, 2019 at 11:21:51PM 0500, David Mertz wrote:
Has anyone actually ever used those available bits for the zillions of NaNs for anything good?
Absolutely.
Back in the 1980s, Apple released one of the first (if not the first) IEEE754 compliant maths library: SANE, the Standard Apple Numerics Environment.
SANE used the NAN payload to encode diagnostic information on the kind of failure. For example, a payload of 1 was an invalid sqrt; a payload of 17 was an invalid string to float conversion; a payload of 34 was an invalid argument to an inverse trig function. I can tell you from personal experience that this was quite useful although not a panacea.
For 64bit floats, there are 51 bits available for the NAN payload. That's enough for a seven ASCII character message, or to encode (say) a 7 bit error code and 44 bits for a line number, or whatever information you need to allow the compiler to identify the source of the error.
Javascript does a horrible/awesome (choose one) hack called "NAN boxing":
https://anniecherkaev.com/thesecretlifeofnan
There's at least one Ada project that encodes tagged data in NANs:
http://dan.corlan.net/software/nan_payload/
Unfortunately, indifferent support for NAN payloads by many compilers and languages has lead to developers neglecting NAN payloads, and lack of developer use for payloads leads to poor compiler support.
participants (6)

Anders Hovmöller

Andrew Barnert

David Mertz

Richard Damon

Steven D'Aprano

Tim Peters