[Review #2] SE-0067: Enhanced Floating Point Protocols


(Chris Lattner) #1

Hello Swift community,

Steve opted to revise his original proposal in order to incorporate great feedback from the original review period. As such, we’re extending the review period in order to get adequate consideration of his new changes. The extended review of "SE-0067: Enhanced Floating Point Protocols" runs through April 29. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0067-floating-point-protocols.md

His previous revision is available here:

  https://github.com/apple/swift-evolution/blob/fb1368a6a5474f57aa8f1846b5355d18753098f3/proposals/0067-floating-point-protocols.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at:

  https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  * What is your evaluation of the proposal?
  * Is the problem being addressed significant enough to warrant a change to Swift?
  * Does this proposal fit well with the feel and direction of Swift?
  * If you have you used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

  https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager


(Jacob Bandes-Storch) #2

The diff might be helpful as well:

https://github.com/apple/swift-evolution/commit/5015578c019818234f1b33d82ad96b94cb444b1b?short_path=3a8f57a#diff-3a8f57ac6db03a3be35cb05972e95d69

···

On Mon, Apr 25, 2016 at 4:35 PM, Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

Hello Swift community,

Steve opted to revise his original proposal in order to incorporate great
feedback from the original review period. As such, we’re extending the
review period in order to get adequate consideration of his new changes.
The extended review of "SE-0067: Enhanced Floating Point Protocols" runs
through April 29. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0067-floating-point-protocols.md

His previous revision is available here:

https://github.com/apple/swift-evolution/blob/fb1368a6a5474f57aa8f1846b5355d18753098f3/proposals/0067-floating-point-protocols.md

Reviews are an important part of the Swift evolution process. All reviews
should be sent to the swift-evolution mailing list at:

        https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the
review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift. When writing your review, here are some questions you might want to
answer in your review:

        * What is your evaluation of the proposal?
        * Is the problem being addressed significant enough to warrant a
change to Swift?
        * Does this proposal fit well with the feel and direction of Swift?
        * If you have you used other languages or libraries with a similar
feature, how do you feel that this proposal compares to those?
        * How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?

More information about the Swift evolution process is available at

        https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #3

        * What is your evaluation of the proposal?

Improved.

Suggestions re naming of `isLessThanOrEqualTo(_:)`:
"Less-than" can be regarded as a unit. Thus, `isLessThan(_:)` is
reasonable. However, `isEqualTo(_:)` is kind of a stretch, but it could
just be `equals(_:)`. Thus, you could have:

equals(_:)
isLessThan(_:)
isLessThanOrEquals(_:)
isGreaterThan(_:)
isGreaterThanOrEquals(_:)
isTotallyOrdered(below:)

Typos in comments (not exhaustive):
* Above `init(signOf:magnitudeOf:)`, comment should read "...exponent and
significand are taken from `magnitudeOf`" instead of "...taken from
`magnitude`"
* Above `isTotallyOrdered(below:)`, "preceeds" [sic] should be "precedes"

Other thoughts:
* I finally see why IEEE 754 calls it "minNum"--namely, "Num" implies
strongly how NaNs are handled. (What's the minimum of 0 and NaN? I dunno,
they're unordered. What's the minimum *number* given 0 and NaN? Well, it
has to be 0, because NaN isn't a number.) I wonder if this is a useful
thing to include in the Swift name (i.e. `minimumNumber`)
* Still not sure about ulpOfOne; if the point is to encourage people who
incorrectly reach for DBL_EPSILON to understand what's going on, then by
the time they learn what ULP is they should know that `(1.0).ulp ==
Double.ulpOfOne`

        * Is the problem being addressed significant enough to warrant a

change to Swift?

Yes, as mentioned previously.

        * Does this proposal fit well with the feel and direction of Swift?

Yes, fits much better with these revisions.

        * If you have you used other languages or libraries with a similar
feature, how do you feel that this proposal compares to those?

Compares favorably.

        * How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?

Quick reading of revised proposal; in-depth study of earlier iterations.


(Brent Royal-Gordon) #4

isLessThanOrEqual(to:) --> isLessThanOrEqualTo(_:). I'm still not totally convinced that this is an improvement, so I'd love to hear further suggestions on how to handle this case.

One possibility would be `isNoGreater(than:)`, which neatly sidesteps the problem. However, given the bizarreness of NaNs, you could argue whether it's actually accurate. (I would say it is, while `isNotGreater(than:)` would not be correct name, but admittedly that's a slight stretch.)

I'll comment on the rest another time.

···

--
Brent Royal-Gordon
Architechies


(Nicola Salmoria) #5

Forgive me if this has been answered already, but is

func isLessThanOrEqualTo(_ other: Self) -> Bool

really needed?

I understand the lack of trichotomy. But can’t this simply be implemented using the other existing methods?

Consider that the consumers of the types will normally use the global operators instead of the protocol methods. So instead of

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
  return lhs.isLessThanOrEqualTo(rhs)
}

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
  return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x == y) are both false?

Thanks,
Nicola

···

Hello Swift community,

Steve opted to revise his original proposal in order to incorporate great feedback from the original review period. As such, we’re extending the review period in order to get adequate consideration of his new changes. The extended review of "SE-0067: Enhanced Floating Point Protocols" runs through April 29. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0067-floating-point-protocols.md

His previous revision is available here:

https://github.com/apple/swift-evolution/blob/fb1368a6a5474f57aa8f1846b5355d18753098f3/proposals/0067-floating-point-protocols.md

Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at:

https://lists.swift.org/mailman/listinfo/swift-evolution

or, if you would like to keep your feedback private, directly to the review manager.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

* What is your evaluation of the proposal?
* Is the problem being addressed significant enough to warrant a change to Swift?
* Does this proposal fit well with the feel and direction of Swift?
* If you have you used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
* How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

-Chris Lattner
Review Manager


(Stephen Canon) #6

The other thing that comes to mind is:

  isEqual(comparedWith: )
  isLess(comparedWith: )
  isLessOrEqual(comparedWith: )

  isTotallyOrdered(below: )

I don’t love these either, but something in this direction may be workable.
– Steve

···

On Apr 25, 2016, at 8:45 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Suggestions re naming of `isLessThanOrEqualTo(_:)`:
"Less-than" can be regarded as a unit. Thus, `isLessThan(_:)` is reasonable. However, `isEqualTo(_:)` is kind of a stretch, but it could just be `equals(_:)`. Thus, you could have:
```
equals(_:slight_smile:
isLessThan(_:slight_smile:
isLessThanOrEquals(_:slight_smile:
isGreaterThan(_:slight_smile:
isGreaterThanOrEquals(_:slight_smile:
isTotallyOrdered(below:)


(Stephen Canon) #7

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows about the built-in floating-point types (Float, Double, Float80) and their aliases (CGFloat, etc) and can fuse the two comparisons into a single hardware operation. However, for soft-float types, without a lessThanOrEqual method, there is no single comparison that the compiler could fuse these to.

In some cases, if they are simple enough, the compiler may be able to actually fuse the bodies of the two comparison operations, but we can’t reasonably depend on that happening or even being possible in all cases. So for performance, it’s important that there be an actual less than or equal to method.

– Steve

···

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution <swift-evolution@swift.org> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
  return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x == y) are both false?


(Nicola Salmoria) #8

If performance is the only reasons to have a separate method, perhaps it
might make sense to have a note about this in the isLessThanOrEqualTo
description, and provide a default implementation that calls down on isLess
and isEqual.

Nicola

···

On Tue, Apr 26, 2016 at 4:59 PM, Stephen Canon <scanon@apple.com> wrote:

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution < > swift-evolution@swift.org> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x ==
y) are both false?

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows about
the built-in floating-point types (Float, Double, Float80) and their
aliases (CGFloat, etc) and can fuse the two comparisons into a single
hardware operation. However, for soft-float types, without a
lessThanOrEqual method, there is no single comparison that the compiler
could fuse these to.

In some cases, if they are simple enough, the compiler may be able to
actually fuse the bodies of the two comparison operations, but we can’t
reasonably depend on that happening or even being possible in all cases.
So for performance, it’s important that there be an actual less than or
equal to method.

– Steve


(Xiaodi Wu) #9

Unrelated to this discussion about comparison operators, please remember to
put back .abs() or .absoluteValue() somewhere in FloatingPoint. Thanks!

···

On Tue, Apr 26, 2016 at 12:07 PM, Nicola Salmoria via swift-evolution < swift-evolution@swift.org> wrote:

If performance is the only reasons to have a separate method, perhaps it
might make sense to have a note about this in the isLessThanOrEqualTo
description, and provide a default implementation that calls down on isLess
and isEqual.

Nicola

On Tue, Apr 26, 2016 at 4:59 PM, Stephen Canon <scanon@apple.com> wrote:

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution < >> swift-evolution@swift.org> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x
== y) are both false?

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows about
the built-in floating-point types (Float, Double, Float80) and their
aliases (CGFloat, etc) and can fuse the two comparisons into a single
hardware operation. However, for soft-float types, without a
lessThanOrEqual method, there is no single comparison that the compiler
could fuse these to.

In some cases, if they are simple enough, the compiler may be able to
actually fuse the bodies of the two comparison operations, but we can’t
reasonably depend on that happening or even being possible in all cases.
So for performance, it’s important that there be an actual less than or
equal to method.

– Steve

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Stephen Canon) #10

Do you actually want a method added, or just conformance to AbsoluteValuable?

– Steve

···

On Apr 26, 2016, at 7:41 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Unrelated to this discussion about comparison operators, please remember to put back .abs() or .absoluteValue() somewhere in FloatingPoint. Thanks!

On Tue, Apr 26, 2016 at 12:07 PM, Nicola Salmoria via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
If performance is the only reasons to have a separate method, perhaps it might make sense to have a note about this in the isLessThanOrEqualTo description, and provide a default implementation that calls down on isLess and isEqual.

Nicola

On Tue, Apr 26, 2016 at 4:59 PM, Stephen Canon <scanon@apple.com <mailto:scanon@apple.com>> wrote:

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
  return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x == y) are both false?

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows about the built-in floating-point types (Float, Double, Float80) and their aliases (CGFloat, etc) and can fuse the two comparisons into a single hardware operation. However, for soft-float types, without a lessThanOrEqual method, there is no single comparison that the compiler could fuse these to.

In some cases, if they are simple enough, the compiler may be able to actually fuse the bodies of the two comparison operations, but we can’t reasonably depend on that happening or even being possible in all cases. So for performance, it’s important that there be an actual less than or equal to method.

– Steve

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #11

I thought you'd mentioned that AbsoluteValuable conformance was removed for
a reason and that the method would be added to FloatingPoint? Otherwise, it
seems like conformance to AbsoluteValuable would be much the same...

···

On Tue, Apr 26, 2016 at 6:54 PM, Stephen Canon <scanon@apple.com> wrote:

Do you actually want a method added, or just conformance to
AbsoluteValuable?

– Steve

On Apr 26, 2016, at 7:41 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Unrelated to this discussion about comparison operators, please remember
to put back .abs() or .absoluteValue() somewhere in FloatingPoint. Thanks!

On Tue, Apr 26, 2016 at 12:07 PM, Nicola Salmoria via swift-evolution < > swift-evolution@swift.org> wrote:

If performance is the only reasons to have a separate method, perhaps it
might make sense to have a note about this in the isLessThanOrEqualTo
description, and provide a default implementation that calls down on isLess
and isEqual.

Nicola

On Tue, Apr 26, 2016 at 4:59 PM, Stephen Canon <scanon@apple.com> wrote:

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution < >>> swift-evolution@swift.org> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x
== y) are both false?

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows about
the built-in floating-point types (Float, Double, Float80) and their
aliases (CGFloat, etc) and can fuse the two comparisons into a single
hardware operation. However, for soft-float types, without a
lessThanOrEqual method, there is no single comparison that the compiler
could fuse these to.

In some cases, if they are simple enough, the compiler may be able to
actually fuse the bodies of the two comparison operations, but we can’t
reasonably depend on that happening or even being possible in all cases.
So for performance, it’s important that there be an actual less than or
equal to method.

– Steve

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Patrick Pijnappel) #12

Am I correct in assuming that this would also eliminate the hidden
associatedtype
_BitsType currently preventing non-stdlib conformances?

···

On Wed, Apr 27, 2016 at 2:04 AM, Xiaodi Wu via swift-evolution < swift-evolution@swift.org> wrote:

I thought you'd mentioned that AbsoluteValuable conformance was removed
for a reason and that the method would be added to FloatingPoint?
Otherwise, it seems like conformance to AbsoluteValuable would be much the
same...

On Tue, Apr 26, 2016 at 6:54 PM, Stephen Canon <scanon@apple.com> wrote:

Do you actually want a method added, or just conformance to
AbsoluteValuable?

– Steve

On Apr 26, 2016, at 7:41 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Unrelated to this discussion about comparison operators, please remember
to put back .abs() or .absoluteValue() somewhere in FloatingPoint. Thanks!

On Tue, Apr 26, 2016 at 12:07 PM, Nicola Salmoria via swift-evolution < >> swift-evolution@swift.org> wrote:

If performance is the only reasons to have a separate method, perhaps it
might make sense to have a note about this in the isLessThanOrEqualTo
description, and provide a default implementation that calls down on isLess
and isEqual.

Nicola

On Tue, Apr 26, 2016 at 4:59 PM, Stephen Canon <scanon@apple.com> wrote:

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution < >>>> swift-evolution@swift.org> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x
== y) are both false?

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows
about the built-in floating-point types (Float, Double, Float80) and their
aliases (CGFloat, etc) and can fuse the two comparisons into a single
hardware operation. However, for soft-float types, without a
lessThanOrEqual method, there is no single comparison that the compiler
could fuse these to.

In some cases, if they are simple enough, the compiler may be able to
actually fuse the bodies of the two comparison operations, but we can’t
reasonably depend on that happening or even being possible in all cases.
So for performance, it’s important that there be an actual less than or
equal to method.

– Steve

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Patrick Pijnappel) #13

Also, maximum() should probably return y if x == y to be consistent with
max()
<https://github.com/apple/swift/blob/master/stdlib/public/core/Algorithm.swift#L38>,
preserving stable ordering for (x, y) = (min(x, y), max(x, y)). I think
IEEE 754 leaves the x == y case unspecified. Currently we have the
guarantee below.

/// (…) Returns `x` if `x >= y`, `y` if `y > x` (…)static func
maximum(x: Self, _ y: Self) -> Self

Patrick

···

On Sun, May 1, 2016 at 9:03 AM, Patrick Pijnappel < patrickpijnappel@gmail.com> wrote:

Am I correct in assuming that this would also eliminate the hidden associatedtype
_BitsType currently preventing non-stdlib conformances?

On Wed, Apr 27, 2016 at 2:04 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

I thought you'd mentioned that AbsoluteValuable conformance was removed
for a reason and that the method would be added to FloatingPoint?
Otherwise, it seems like conformance to AbsoluteValuable would be much the
same...

On Tue, Apr 26, 2016 at 6:54 PM, Stephen Canon <scanon@apple.com> wrote:

Do you actually want a method added, or just conformance to
AbsoluteValuable?

– Steve

On Apr 26, 2016, at 7:41 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Unrelated to this discussion about comparison operators, please remember
to put back .abs() or .absoluteValue() somewhere in FloatingPoint. Thanks!

On Tue, Apr 26, 2016 at 12:07 PM, Nicola Salmoria via swift-evolution < >>> swift-evolution@swift.org> wrote:

If performance is the only reasons to have a separate method, perhaps
it might make sense to have a note about this in the isLessThanOrEqualTo
description, and provide a default implementation that calls down on isLess
and isEqual.

Nicola

On Tue, Apr 26, 2016 at 4:59 PM, Stephen Canon <scanon@apple.com> >>>> wrote:

On Apr 26, 2016, at 10:03 AM, Nicola Salmoria via swift-evolution < >>>>> swift-evolution@swift.org> wrote:

it should be enough to do

func <= <T: FloatingPoint>(lhs: T, rhs: T) -> Bool
{
return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and
(x == y) are both false?

No, these are always equivalent.

However, there is a problem with this approach: the compiler knows
about the built-in floating-point types (Float, Double, Float80) and their
aliases (CGFloat, etc) and can fuse the two comparisons into a single
hardware operation. However, for soft-float types, without a
lessThanOrEqual method, there is no single comparison that the compiler
could fuse these to.

In some cases, if they are simple enough, the compiler may be able to
actually fuse the bodies of the two comparison operations, but we can’t
reasonably depend on that happening or even being possible in all cases.
So for performance, it’s important that there be an actual less than or
equal to method.

– Steve

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution