<div dir="ltr">As discussed a long time ago, and as I raised here in an earlier reply in this thread, a total order over floating point values is almost never what you want. It distinguishes between +0.0 and -0.0, between +NaN and -NaN, between signaling NaN and quiet NaN, between different NaN payloads, and for IEEE Decimal (not yet implemented in Swift), between different representations of the same floating point value based on their exponent. Swift already exposes this function as `isTotallyOrdered` and it is, well, very niche.<div class="gmail_extra"><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 26, 2017 at 2:08 AM, Jaden Geller <span dir="ltr"><<a href="mailto:jaden.geller@gmail.com" target="_blank">jaden.geller@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span class=""><blockquote type="cite"><div>On Apr 25, 2017, at 11:50 PM, Jonathan Hull <<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>> wrote:</div><br class="m_1342665685428012218Apple-interchange-newline"><div><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On Apr 25, 2017, at 9:34 PM, Jaden Geller <<a href="mailto:jaden.geller@gmail.com" target="_blank">jaden.geller@gmail.com</a>> wrote:</div><br class="m_1342665685428012218Apple-interchange-newline"><div><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><br class="m_1342665685428012218Apple-interchange-newline">On Apr 25, 2017, at 8:28 PM, Jonathan Hull via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_1342665685428012218Apple-interchange-newline"><div><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On Apr 25, 2017, at 7:17 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><div><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div></div></blockquote><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>I'll refer you to Steve Canon's answer on StackOverflow: <a href="http://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values/1573715#1573715" target="_blank">http://<wbr>stackoverflow.com/questions/<wbr>1565164/what-is-the-rationale-<wbr>for-all-comparisons-returning-<wbr>false-for-ieee754-nan-values/<wbr>1573715#1573715</a></div></div></div></div></blockquote><div><br></div><div>I get what he is saying about not being able to suddenly change C’s definition to the opposite boolean value (even if they would have designed it differently for modern systems). We aren’t C though. And nil is a different name than NaN. This gives us a way to make a change without breaking conformance.</div></div></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">I really like this idea, but it’s not true to say this doesn’t break IEEE-compliance if what we expose as NaN no longer compares not equal to itself.</div></div></blockquote><div><br></div><div>I would argue that we aren’t actually exposing NaN, so much as we are exposing something which is different, but stays in sync with it. NaN is still there in the format under the surface, but you wouldn’t be able to access it directly (only indirectly).</div></div></div></div></blockquote><div><br></div></span><div>The problem is that the IEEE spec requires that certain operations return NaN. Either nil is NaN in this model, and we’re breaking the spec for equality, or nil is different from NaN in this model, and we’re breaking the spec for when NaN should be produced.</div><span class=""><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div>It is a bit of a magic trick. Whenever the value is NaN, we only let you access ‘.none’ instead of the value. So, if you were able to directly compare NaN with NaN, it would be false (or unordered), but you can’t get ahold of them to do that comparison.</div></div></div></div></blockquote><div><br></div></span><div>I don’t find this argument compelling. Again, if it doesn’t act like NaN, it isn’t following spec. It doesn’t matter that it has the same bit representation.</div><span class=""><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div>The important thing to me is binary compatibility. Algorithms need to be rewritten a bit anyway when moving them into swift, so that isn’t a big deal to write it for nil instead of NaN… especially when the compiler helps you due to the optional. But data, which might contain NaN, needs to be read/written in an interchangeable format. That is why I suggest having Optional do the lifting to match NaN. Anytime it crosses a boundary which strips the wrapper, it will just work (as long as we import as Double?).</div></div></div></div></blockquote><div><br></div></span><div>I think this would be a cool idea were it not that so many people are against breaking the spec. This trick did work well for UnsafePointer, but the circumstances were different.</div><div><br></div><div>Anyway, I would be partially in favor of this idea, but I don’t think there’s any way the community as a whole is going to be on-board.</div><span class=""><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><blockquote type="cite"><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><div style="word-wrap:break-word"><div><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>Bottom line is, whatever it's designed for, it's here to stay. I'm *not* on any IEEE committee; I'm not qualified to design an alternative universe of floating point types; and the Swift evolution mailing list (or even Swift itself) is not the place to design one. I and others rely on Swift floating point types to be IEEE-complaint, so that's where we start the discussion here about Comparable.</div></div></div></div></blockquote><div><br></div><div>It *is* IEEE compliant (or at least the same amount we currently are), what is different is the way we interface with that in code. You can think of Swift Double as a simple (runtime-cost-free) wrapper around the compiler’s double that limits how you can touch it (in order to provide additional safety guarantees). Sounds very swifty to me… we do similar things with other C constructs using various wrappers. We aren’t getting rid of NaN behind the scenes, just packaging it’s use in a way which aligns with Swift as a whole… What changes is the programer’s mental model. The bits are exactly the same.</div><div><br></div><div>If the naming is what bothers you, we could even just create a “new” Swift type that is this wrapper, and then discourage the use of Double outside of places where NaN is needed. I feel like NaN is actually needed in relatively few places though…</div><div><br></div><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div></div><div>The programmer (mental) model would be that Swift Double just doesn’t have NaN, and anywhere where you would normally return NaN, you return nil instead.</div></div></div></blockquote><div><br></div><div>Look, you can already use Double? today. There is no barrier to trying it out for yourself. However, `Double?.none` doesn't mean the same thing as `Double.nan`. The former indicates that _there is no value_; the latter indicates that there _is_ a value, it's just _not a number_. Suppose I parse a list of numbers into an array. If I ask for [Double].last and get nil, it's telling me that _there are no elements in the array_. If I get .nan, it's telling me that there *is* a value, it just wasn't a number. In the former case, I'd do nothing. In the latter case, I might prompt the user: this isn't a number!</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>However, the property of using NaN’s bits to represent nil let’s us inter-op seamlessly with C and ObjC (or any other language’s) code. They just treat it as a double with NaN as normal (including NaN != NaN) and we interface with it as ‘Double?'</div></div></div></blockquote><div><br></div><div>I'm going to sound like a broken record, now. Whether floating point types in Swift conform to IEEE standards is _not_ up for discussion, afaict; that's simply a given. Now, around that constraint, we're trying to design a revised Comparable protocol. Code written today for floating point work expects NaN != NaN. That is just something that is and will forever be. We break source compatibility if we change that.</div></div></div></div></blockquote><div><br></div><div>As I said above, they *do* conform to those standards… they just don’t expose the full capabilities directly to the end programmer. The capabilities are still there, you just have to be more explicit about their use. </div><div><br></div><div>I could be wrong, but I believe that in the current version of Swift, the result of doing comparisons with NaN is actually undefined at the moment… so it isn’t breaking source compatibility with the defined language. Just with code which is using implementation artifacts…</div></div></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">I think you’re incorrect. It says in the docs for NaN that it always compares false with itself.</div></blockquote><div><br></div><div>That’s too bad. I was looking in the language guide. I guess it would be a breaking change to change Float/Double. We could still use the idea though, we would just have to add the wrapper as a new type with a different name. </div></div></div></div></blockquote><div><br></div></span><div>I’d be a lot more in favor of this as compared to the Optional suggestion above, but I’m worried about the API surface impact. It also does not solve our `Equatable` and `Comparable` issues…</div><div><br></div><div>I guess we could just say `PotentiallyUnknown<Double>` doesn’t conform to either, and you need to unwrap if you’d like to compare. We could also add optional-returning comparison functions without creating a formal protocol. I think this would all be pretty reasonable.</div><span class=""><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div>I would be in favor of renaming Float/Double to something like CFloat/CDouble, and then reusing the names for the wrappers. Not sure if I could convince the powers that be of that though…</div></div></div></div></blockquote><div><br></div></span><div>We could also write `typealias CDouble = PartiallyUnknown<Double>` so it’s less painful to work with. I’d be very happy if `Double` trapped.</div><span class=""><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div>I am not sure how much code actually uses NaN in this way in the real world. </div><div><br></div><br><blockquote type="cite"><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><div style="word-wrap:break-word"><div><div>C code might require some simple changes to work in Swift, but as you argued passionately before, that is already to be expected. We shouldn’t have the expectation of copy/pasting C code without thinking through the differences in &+, etc...</div><br><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span class="m_1342665685428012218gmail-"><div></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>This did not always work correctly, if I recall, but it does now and it's an intentional part of the design. However, NaN must compare not equal to every NaN. These could not be more different properties. It seems quite absurd on its face that we might want NaN to compare equal to a value of type `Optional<UIViewController>`.<br></div></div></div></div></div></blockquote><div><br></div></span><div>Is there an algorithm that requires NaN != NaN that couldn’t be reasonably rewritten to handle nil/optionals instead? </div></div></div></blockquote><div><br></div><div>I don't need an algorithm to show you the problem. See this expression: `0 * Double.infinity == .infinity * 0` correctly evaluates to false. Zero times infinity is simply not equal to infinity times zero. You're suggesting a design where the result would be true, and that simply won't fly, because it's just not true.</div></div></div></div></blockquote><div><br></div><div>IEEE 754 says that the result of any comparison with NaN should be *undefined*. C’s implementation is the one who brings us this idea that NaN != NaN. The *correct* evaluation according to 754 would be ‘undefined’. We aren’t breaking 754, just breaking away from a C convention… in a way which is very much in line with how Swift breaks away from other C conventions.</div></div></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">I don’t think this is true. I got excited for a minute and looked it up. Where do you see that comparison behavior is undefined?</div></blockquote><div><br></div><div>Oh, sorry, I didn’t mean that the behavior is undefined… I used the wrong word (freudian slip). I meant to say that the correct evaluation is *unordered*. Four possibilities are defined in the spec: GreaterThan, LessThan, Equal, and Unordered. NaN is always unordered when compared with anything.</div></div></div></div></blockquote><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div>From the spec:</div><div><blockquote type="cite"><span style="font-size:10pt;font-family:TimesNewRomanPSMT">For every supported arithmetic format, it shall be possible to compare one floating-point datum to another
in that format (see </span><span style="font-size:10pt;font-family:TimesNewRomanPSMT;color:rgb(0,0,255)">5.6.1</span><span style="font-size:10pt;font-family:TimesNewRomanPSMT">). Additionally, floating-point data represented in different formats shall be
comparable as long as the operands’ formats have the same radix.</span></blockquote><blockquote type="cite">
        
                
                
        
        
                <div class="m_1342665685428012218page" title="Page 41">
                        <div class="m_1342665685428012218layoutArea">
                                <div class="m_1342665685428012218column"><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">Four mutually exclusive relations are possible: </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">less than</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">equal</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">greater than</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">unordered</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">. The last case
arises when at least one operand is NaN. Every NaN shall compare </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">unordered </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">with everything, including
itself. Comparisons shall ignore the sign of zero (so +0 = </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">0). Infinite operands of the same sign shall
compare </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">equal</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">.
</span></p></div></div></div></blockquote><div><br></div><div><br></div>And as I read further, It does appear I was wrong about NaN != NaN (when doing a partial order). I had somehow missed it in my first read-through In the 2008 version of the spec, it goes on to say:<br><blockquote type="cite"><div class="m_1342665685428012218page" title="Page 41"><div class="m_1342665685428012218layoutArea"><div class="m_1342665685428012218column"><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">Languages define how the result of a comparison shall be delivered, in one of two ways: either as a relation
identifying one of the four relations listed above, or as a true-false response to a predicate that names the
specific comparison desired.</span></p></div></div></div></blockquote><div>Which means that we should have 4 functions: ==, <, >, and isUnordered… where isUnordered is the only one which returns true for NaN</div></div></div></div></div></blockquote><div><br></div></span><div>That sounds a lot more like what I expected, cool.</div><span class=""><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><div>One loophole is that it gives alternate names for those functions which we could use for the official behavior (and still use < and == for our strict total order):</div><div>• compareQuietEqual</div><div>• compareQuietGreater</div><div>• compareQuietLess</div><div>• compareQuietUnordered</div></div></div></div></div></blockquote><div><br></div></span><div>Are you suggesting that `<` and friends trap? Is this still in the type-system aware NaN world, or is this an entirely different option you’re exploring?</div><span class=""><br><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><div>Also, we should all read section 5.10, as it seems to give a canonical answer of how to do a total order for 754:</div><div><blockquote type="cite">
        
                
                
        
        
                <div class="m_1342665685428012218page" title="Page 40">
                        <div class="m_1342665685428012218layoutArea">
                                <div class="m_1342665685428012218column"><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x, y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) imposes a total ordering on canonical members of the format of </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">:
</span></p>
                                        <ol style="list-style-type:none">
                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">a) If </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">< </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x, y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) is true.
</span></p>
                                                </li>
                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">b) If </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">> </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x, y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) is false.
</span></p>
                                                </li>
                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">c) If</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">=</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">:
</span></p>
                                                        <ol style="list-style-type:none">
                                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">1) totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">0, +0) is true.
</span></p>
                                                                </li>
                                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">2) totalOrder(+0, </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">0) is false.
</span></p>
                                                                </li>
                                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">3) If </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">represent the same floating-point datum:
</span></p>
                                                                </li>
                                                        </ol>
                                                </li>
                                        </ol><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">i) If </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">have negative sign,<br>
totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) is true if and only if the exponent of </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">≥ </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">the exponent of </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y
</span></p><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">ii) otherwise<br>
totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) is true if and only if the exponent of </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">≤ </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">the exponent of </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y.
</span></p><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">d) If </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">are unordered numerically because </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">or </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">is NaN:
</span></p>
                                        <ol style="list-style-type:none">
                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">1) totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">NaN, </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) is true where </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">NaN represents a NaN with negative sign bit and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">is a
</span></p><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">floating-point number.
</span></p>
                                                </li>
                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">2) totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, +NaN) is true where +NaN represents a NaN with positive sign bit and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">is a
floating-point number.
</span></p>
                                                </li>
                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">3) If </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">are both NaNs, then totalOrder reflects a total ordering based on:
</span></p>
                                                        <ol style="list-style-type:none">
                                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">i) negative sign orders below positive sign
</span></p></li></ol></li></ol></div></div></div></blockquote></div></div></div></div></div></blockquote></span><div>Oh god, I didn’t realize that NaN could be signed…</div><span class=""><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div class="m_1342665685428012218page" title="Page 40"><div class="m_1342665685428012218layoutArea"><div class="m_1342665685428012218column"><ol style="list-style-type:none" start="3"><li><ol style="list-style-type:none" start="1"><li>
                                                                </li>
                                                                <li><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">ii) signaling orders below quiet for +NaN, reverse for </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">NaN
</span></p>
                                                                </li>
                                                        </ol><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">iii) lesser payload, when regarded as an integer, orders below greater payload for +NaN,
reverse for </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">−</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">NaN.
</span></p>
                                                </li>
                                        </ol><p><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">Neither signaling NaNs nor quiet NaNs signal an exception. For canonical </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">, totalOrder(</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x, y</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) and
totalOrder( </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y, x</span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">) are both true if </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">x </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">and </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPS';font-style:italic">y </span><span style="font-size:10.000000pt;font-family:'TimesNewRomanPSMT'">are bitwise identical. </span></p>
                                </div>
                        </div>
                </div></blockquote></div><div>Here we see NaN == NaN when doing a total order (as long as the payloads are the same).</div><div><br></div><div>Thanks,</div><div>Jon</div><div><br></div></div></div></div></div></blockquote><br></span></div><div>Cheers,</div><div>Jaden Geller</div><div><br></div></div></blockquote></div><br></div></div>