Fix or remove Swift.min and Swift.max?


(Jens Persson) #1

Hi all!

Swift.min (and Swift.max) propagates nan or not depending on the order of
its args:

Swift.min(1.0, .nan) // 1.0
Swift.min(.nan, 1.0) // nan (!)

Double.minimum(1.0, .nan) // 1.0
Double.minimum(.nan, 1.0) // 1.0

fmin(1.0, .nan) // 1.0
fmin(.nan, 1.0) // 1.0

The new static minimum and maximum funcs on FloatingPoint in Swift 3 shows
the expected behaviour (ie the same as fmin, fmax and IEEE-754), so what
should happen with Swift.min and Swift.max?

Fix, remove or perhaps something else?

https://bugs.swift.org/browse/SR-1011

/Jens


(Pyry Jahkola) #2

+1, and bumping this topic.

The background — which I'm sure Jens is aware of — is that IEEE-754 floating point numbers can't truly conform to Comparable. (The problematic case being that neither of `x < .nan`, `x == .nan`, or `x > .nan` can be `true`.)

But given that the NaN-abolishing semantics of `fmin` is quite useful, and since we also want that Double and Float remain conforming to Comparable (albeit brokenly), could we consider fixing this issue by moving `min(_:_:)` and `max(_:_:)` into Comparable?

The Comparable protocol would become:

    public protocol Comparable : Equatable {
      func < (lhs: Self, rhs: Self) -> Bool
      func <= (lhs: Self, rhs: Self) -> Bool
      func >= (lhs: Self, rhs: Self) -> Bool
      func > (lhs: Self, rhs: Self) -> Bool
      static func minimum(lhs: Self, rhs: Self) -> Self
      static func maximum(lhs: Self, rhs: Self) -> Self
    }

with default implementations added for the new static functions, and custom implementations for FloatingPoint types. The `Swift.min` and `Swift.max` functions would then forward their logic to `Comparable.minimum` and `Comparable.maximum`.

— Pyry

···

On 29 Jun 2016, Jens Persson wrote:

Hi all!

Swift.min (and Swift.max) propagates nan or not depending on the order of its args:

Swift.min(1.0, .nan) // 1.0
Swift.min(.nan, 1.0) // nan (!)

Double.minimum(1.0, .nan) // 1.0
Double.minimum(.nan, 1.0) // 1.0

fmin(1.0, .nan) // 1.0
fmin(.nan, 1.0) // 1.0

The new static minimum and maximum funcs on FloatingPoint in Swift 3 shows the expected behaviour (ie the same as fmin, fmax and IEEE-754), so what should happen with Swift.min and Swift.max?

Fix, remove or perhaps something else?

https://bugs.swift.org/browse/SR-1011


(Haravikk) #3

There was a proposal a little while ago to change Comparable to have an operator producing an enum (with ordered before, same and ordered after cases) which provides strict ordering requirements (unlike the current comparable methods). I think this would serve as a better basis for replacing Swift.min(), and was intended specifically to solve the floating point problem.

It doesn't look like it has a proposal though, maybe I'm not searching for the right terms?

···

On 3 Jul 2016, at 22:28, Pyry Jahkola via swift-evolution <swift-evolution@swift.org> wrote:

+1, and bumping this topic.

The background — which I'm sure Jens is aware of — is that IEEE-754 floating point numbers can't truly conform to Comparable. (The problematic case being that neither of `x < .nan`, `x == .nan`, or `x > .nan` can be `true`.)

But given that the NaN-abolishing semantics of `fmin` is quite useful, and since we also want that Double and Float remain conforming to Comparable (albeit brokenly), could we consider fixing this issue by moving `min(_:_:)` and `max(_:_:)` into Comparable?

The Comparable protocol would become:

    public protocol Comparable : Equatable {
      func < (lhs: Self, rhs: Self) -> Bool
      func <= (lhs: Self, rhs: Self) -> Bool
      func >= (lhs: Self, rhs: Self) -> Bool
      func > (lhs: Self, rhs: Self) -> Bool
      static func minimum(lhs: Self, rhs: Self) -> Self
      static func maximum(lhs: Self, rhs: Self) -> Self
    }

with default implementations added for the new static functions, and custom implementations for FloatingPoint types. The `Swift.min` and `Swift.max` functions would then forward their logic to `Comparable.minimum` and `Comparable.maximum`.

— Pyry

On 29 Jun 2016, Jens Persson wrote:

Hi all!

Swift.min (and Swift.max) propagates nan or not depending on the order of its args:

Swift.min(1.0, .nan) // 1.0
Swift.min(.nan, 1.0) // nan (!)

Double.minimum(1.0, .nan) // 1.0
Double.minimum(.nan, 1.0) // 1.0

fmin(1.0, .nan) // 1.0
fmin(.nan, 1.0) // 1.0

The new static minimum and maximum funcs on FloatingPoint in Swift 3 shows the expected behaviour (ie the same as fmin, fmax and IEEE-754), so what should happen with Swift.min and Swift.max?

Fix, remove or perhaps something else?

https://bugs.swift.org/browse/SR-1011

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


(Dave Abrahams) #4

There was a proposal a little while ago to change Comparable to have
an operator producing an enum (with ordered before, same and ordered
after cases) which provides strict ordering requirements (unlike the
current comparable methods). I think this would serve as a better
basis for replacing Swift.min(), and was intended specifically to
solve the floating point problem.

+1

It doesn't look like it has a proposal though, maybe I'm not searching for the right terms?

It's the direction I'd like to pursue, but no proposal has been written.

···

on Sun Jul 03 2016, Haravikk <swift-evolution@swift.org> wrote:

On 3 Jul 2016, at 22:28, Pyry Jahkola via swift-evolution <swift-evolution@swift.org> wrote:

+1, and bumping this topic.

The background — which I'm sure Jens is aware of — is that IEEE-754 floating point numbers can't truly conform to Comparable. (The problematic case being that neither of `x < .nan`, `x == .nan`, or `x > .nan` can be `true`.)

But given that the NaN-abolishing semantics of `fmin` is quite useful, and since we also want that Double and Float remain conforming to Comparable (albeit brokenly), could we consider fixing this issue by moving `min(_:_:)` and `max(_:_:)` into Comparable?

The Comparable protocol would become:

    public protocol Comparable : Equatable {
      func < (lhs: Self, rhs: Self) -> Bool
      func <= (lhs: Self, rhs: Self) -> Bool
      func >= (lhs: Self, rhs: Self) -> Bool
      func > (lhs: Self, rhs: Self) -> Bool
      static func minimum(lhs: Self, rhs: Self) -> Self
      static func maximum(lhs: Self, rhs: Self) -> Self
    }

with default implementations added for the new static functions, and custom implementations for FloatingPoint types. The `Swift.min` and `Swift.max` functions would then forward their logic to `Comparable.minimum` and `Comparable.maximum`.

— Pyry

On 29 Jun 2016, Jens Persson wrote:

Hi all!

Swift.min (and Swift.max) propagates nan or not depending on the order of its args:

Swift.min(1.0, .nan) // 1.0
Swift.min(.nan, 1.0) // nan (!)

Double.minimum(1.0, .nan) // 1.0
Double.minimum(.nan, 1.0) // 1.0

fmin(1.0, .nan) // 1.0
fmin(.nan, 1.0) // 1.0

The new static minimum and maximum funcs on FloatingPoint in Swift
3 shows the expected behaviour (ie the same as fmin, fmax and
IEEE-754), so what should happen with Swift.min and Swift.max?

Fix, remove or perhaps something else?

https://bugs.swift.org/browse/SR-1011

_______________________________________________
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

--
-Dave