[swift-dev] Rationalizing FloatingPoint conformance to Equatable

Xiaodi Wu xiaodi.wu at gmail.com
Thu Oct 26 01:22:54 CDT 2017


On Wed, Oct 25, 2017 at 11:46 PM, Jonathan Hull <jhull at gbis.com> wrote:

> As someone mentioned earlier, we are trying to square a circle here. We
> can’t have everything at once… we will have to prioritize.  I feel like the
> precedent in Swift is to prioritize safety/correctness with an option
> ignore safety and regain speed.
>
> I think the 3 point solution I proposed is a good compromise that follows
> that precedent.  It does mean that there is, by default, a small
> performance hit for floats in generic contexts, but in exchange for that,
> we get increased correctness and safety.  This is the exact same tradeoff
> that Swift makes for optionals!  Any speed lost can be regained by
> providing a specific override for FloatingPoint that uses ‘&==‘.
>

My point is not about performance. My point is that `Numeric.==` must
continue to have IEEE floating-point semantics for floating-point types and
integer semantics for integer types, or else existing uses of `Numeric.==`
will break without any way to fix them. The whole point of *having*
`Numeric` is to permit such generic algorithms to be written. But since
`Numeric.==` *is* `Equatable.==`, we have a large constraint on how the
semantics of `==` can be changed.


> For example, if someone wants to write a generic function that works both
> on Integer and FloatingPoint, then they would have to use the new protocol
> which would force them to correctly handle cases involving NaN.
>

What "new protocol" are you referring to, and what do you mean about
"correctly handling cases involving NaN"? The existing API of `Numeric`
makes it possible to write generic algorithms that accommodate both integer
and floating-point types--yes, even if the value is NaN. If you change the
definition of `==` or `<`, currently correct generic algorithms that use
`Numeric` will start to _incorrectly_ handle NaN.

If speed is super important in that particular case, then they can write
> overrides for the FloatingPoint case which uses &==, and for Equatable
> which uses ==.
>
> Because Float’s Equatable conformance is just being depreciated (with a
> warning/fixit), authors have at least a version to decide whether speed or
> correctness (or hopefully both) is most important to them.
>

My point here is not about generic algorithms written to take any Equatable
value; it's about protocol-based numeric algorithms, which we in SE-0104
devoted much time and energy to support in the first place.


> Thanks,
> Jon
>
> P.S. We really should not be comparing against the speed of algorithms
> which don’t correctly handle NaN. Let’s compare Apples to Apples.
>

Again, what do you mean about "correctly handle NaN"? Most algorithms today
*do* correctly handle NaN, in that they are concordant with the
IEEE-specified behavior. Set *not* deduplicating NaN *is* correct handling
of NaN, for instance, for as long as NaN != NaN.

On Oct 25, 2017, at 6:36 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Wed, Oct 25, 2017 at 8:26 PM, Jonathan Hull <jhull at gbis.com> wrote:
>
>> > On Oct 25, 2017, at 9:01 AM, David Sweeris via swift-dev <
>> swift-dev at swift.org> wrote:
>> >
>> > That said, I fully acknowledge that this is all above my pay grade
>> (also I hadn't realized that the issue was as settled as it apparently is).
>> If splitting the protocols is a no-go from the get go, I'll go back to
>> trying to figure out a better way to handle it without doing that.
>>
>>
>> I don’t think it is settled.  The issue that Xiaodi mentioned was a
>> PartiallyEq protocol which still had a signature of (T,T)->Bool.  People
>> just used that protocol instead of Equatable without taking into account
>> the difference in behavior.  The signature of (T,T)->Bool? changes things
>> because people are forced to deal with the optional.
>>
>> Currently, I think we should do 3 things:
>>
>> 1) Create a new protocol with a partial equivalence relation with
>> signature of (T, T)->Bool? and automatically conform Equatable things to it
>> 2) Depreciate Float, etc’s… Equatable conformance with a warning that it
>> will eventually be removed (and conform Float, etc… to the partial
>> equivalence protocol)
>> 3) Provide an '&==‘ relation on Float, etc… (without a protocol) with the
>> native Float IEEE comparison
>>
>> I think this provides several benefits.  #3 allows pure speed when
>> needed, but not in a generic context (and is appropriately scary to cause
>> some thought).  #1 forces correct handling in generic contexts.  #2 gives
>> people time to make the adjustment, but also eventually requires them to
>> switch to using #1 or #3.
>>
>> I think it will cause A LOT of currently incorrect code to be fixed.
>>
>
> One issue which occurred to me only recently, which I hadn't considered,
> renders my `&==` idea and all similar schemes untenable:
>
> Useful algorithms can and are written which operate on both floating-point
> and integer numeric types. In fact, the whole point of laboriously
> designing `Numeric` as part of SE-0104 was to make it possible to do so. If
> IEEE comparison is relegated to `FloatingPoint` and the only operator
> remaining on `Numeric` is `==`, then not only will there be a mandatory
> performance hit, but currently correct algorithms can be broken with
> absolutely no way to express a fix.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20171026/a7bf7833/attachment.html>


More information about the swift-dev mailing list