[swift-dev] Rationalizing FloatingPoint conformance to Equatable

Xiaodi Wu xiaodi.wu at gmail.com
Fri Oct 20 12:16:49 CDT 2017

On Fri, Oct 20, 2017 at 10:05 Jonathan Hull <jhull at gbis.com> wrote:

> On Oct 20, 2017, at 7:36 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Fri, Oct 20, 2017 at 07:21 David Zarzycki <dave at znu.io> wrote:
>> On Oct 20, 2017, at 07:51, Xiaodi Wu via swift-dev <swift-dev at swift.org>
>> wrote:
>> On Fri, Oct 20, 2017 at 1:22 AM, Jonathan Hull <jhull at gbis.com> wrote:
>>> +1 for trapping unless using &==.  In the case of ‘Float?’ we could also
>>> map to nil.
>>> This is probably a more appropriate discussion for evolution though...
>>> On Oct 19, 2017, at 9:48 PM, Brent Royal-Gordon via swift-dev <
>>> swift-dev at swift.org> wrote:
>>> On Oct 19, 2017, at 4:29 PM, Xiaodi Wu via swift-dev <
>>> swift-dev at swift.org> wrote:
>>> D) Must floating-point IEEE-compliant equivalence be spelled `==`?
>>> In my view, this is something open for debate. I see no reason why it
>>> cannot be migrated to `&==` if it were felt that `==` *must* be a full
>>> equivalence relation. I believe this is controversial, however.
>>> I actually got partway through writing up a pitch on this yesterday, but
>>> my opinion is that NaNs are so exceptional, and so prone to misuse, that we
>>> ought to treat them like integer arithmetic overflows: trap when they're
>>> detected, unless you use an `&` variant operator which indicates you know
>>> what you're doing.
>>> I strongly suspect that, in practice, most float-manipulating code is
>>> not prepared to handle NaN and will not do anything sensible in its
>>> presence. For example, Apple platforms use floating-point types for
>>> geometry, color components, GPS locations, etc. Very little of this code
>>> will do anything sensible in the presence of a NaN. Arguably, it'd be
>>> better to exclude them through the type system, but I don't think that's a
>>> realistic possibility—we would need to have done that in a more
>>> source-break-friendly era. But that doesn't have to mean we're completely
>>> stuck.
>> Built-in floating point operators, as well as libc/libm math functions,
>> are designed to propagate NaN correctly. This is not meant to be a thread
>> about NaN, and we need to be cautious to define the scope of the problem to
>> be solved from the outset. The tendency of having ever-expanding discussion
>> where issues such as method names turn into discussions about the entire
>> standard library go nowhere.
>> The question here is about `==` specifically and how to accommodate
>> partial equivalence relations. For sanity, we start with the premise that
>> NaN will forever be as it is.
>> I support Jonathan’s argument. If Swift wants to trap on NaN to improve
>> self-consistency and simplicity, then the tradeoff might be worth it. The
>> alternative, teaching the Equality protocol about NaNs, feels like “the
>> tail wagging the dog".
>> In short: what IEEE requires of floating-point hardware is separable from
>> IEEE’s opinions about language/library design.
> IEEE 754 requires certain behaviors of conforming implementations and is
> meant to allow for portable use of floating point. Swift’s floating point
> facilities are conformant to that standard, and breaking IEEE 754
> conformance has been repeatedly stated to be a non-starter.
> The essential idea behind quiet NaN is that it can be used as input in
> operations that take floating point values without raising errors. Since
> breaking IEEE 754 conformance is a non-starter, trapping on NaN is outside
> the realm of available solutions.
> It has been pointed out, however, that IEEE does not require a specific
> syntax for floating point equivalence, hence the question of whether it can
> be spelled differently. However, trapping on NaN is emphatically not an
> option.
> But I really don’t want to discuss this at all here. The topic of this
> thread is about the semantics of Equatable.
> I don’t know about Brent, but I was only speaking about the
> semantics/behavior of == with respect to NaN.  Trap on NaN for ‘==‘, but
> restore full IEEE behavior by using ‘&==‘.  For ‘Float?’ we could treat NaN
> as nil for ‘==‘.  ‘&==‘ would still have the IEEE behavior.
> This restores reflexivity and we can count on == being a true equivalence
> relation in our generic algorithms.  Lack of proper handling of NaN is
> almost a stereotypical cause of bugs. Looking at code written for Floats,
> seeing &== will be a sign that the original programmer considered the
> possibility of NaN.

Ah, about == specifically. This is an interesting idea. However, trapping
on NaN doesn't meet the semantic guarantee for Equatable that for *any*
value a, a == a. This means that you continue to have issues with methods
like Array.== that rely on that guarantee, since it would compare equal
sometimes and trap sometimes.

(It’s also the case that this would go against the spirit and probably the
letter of IEEE 754, since you’re vending a comparison operation that traps
on a quiet NaN.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20171020/2773ab3a/attachment.html>

More information about the swift-dev mailing list