[swift-evolution] [Proposal draft] Enhanced floating-point protocols
Brent Royal-Gordon
brent at architechies.com
Thu Apr 14 22:34:25 CDT 2016
First of all: I do *not* do crazy things with floating-point numbers, so there's a good chance I'm missing the point with some of this. Consider anything having to do with NaNs, subnormals, or other such strange denizens of the FPU to be prefixed with "I may be totally missing the point, but…"
> public protocol Arithmetic
Is there a rationale for the name "Arithmetic"? There's probably nothing wrong with it, but I would have guessed you'd use the name "Number".
> : Equatable, IntegerLiteralConvertible
Are there potential conforming types which aren't Comparable?
> func adding(rhs: Self) -> Self
> mutating func add(rhs: Self)
Is there a reason we're introducing methods and calling them from the operators, rather than listing the operators themselves as requirements?
> func negate() -> Self
Should this be `negated()`? Should there be a mutating `negate()` variant, even if we won't have an operator for it?
(If a mutating `negate` would be an attractive nuisance, we can use `negative()`/`formNegative()` instead.)
> /// NaN `payloads`. `FloatingPoint` types should either treat inadmissible
> /// payloads as zero, or mask them to create an admissible payload.
> static func nan(payload payload: RawSignificand, signaling: Bool) -> Self
This seems unusually tolerant of bad inputs. Should this instead be a precondition, and have an (elidable in unchecked mode) trap if it's violated?
> static var greatestFiniteMagnitude: Self { get }
> static var leastNormalMagnitude: Self { get }
> static var leastMagnitude: Self { get }
Reading these, I find the use of "least" a little bit misleading—it seems like they should be negative. I wonder if instead, we can use ClosedIntervals/ClosedRanges to group together related values:
static var positiveNormals: ClosedRange<Self> { get }
static var positiveSubnormals: ClosedRange<Self> { get }
Double.positiveNormals.upperBound // DBL_MAX
Double.positiveNormals.lowerBound // DBL_MIN
Double.positiveSubnormals.upperBound // Self.positiveNormals.lowerBound.nextDown
Double.positiveSubnormals.lowerBound // 0.nextUp
// Alternatively, you could have `positives`, running from 0.nextUp to infinity
Technically, you could probably implement calls like e.g. isNormal in terms of the positiveNormals property, but I'm sure separate calls are much, much faster.
(It might also be helpful if you could negate signed ClosedIntervals, which would negate and swap the bounds.)
> public protocol FloatingPoint: SignedArithmetic, Comparable {
> func isLess(than other: Self) -> Bool
> func totalOrder(with other: Self) -> Bool
Swift 2's Comparable demands a strict total order. However, the documentation here seems to imply that totalOrder is *not* what you get from the < operator. Is something getting reshuffled here?
> init<Source: Integer>(_ value: Source)
> init?<Source: Integer>(exactly value: Source)
> init<Source: BinaryFloatingPoint>(_ value: Source)
> init?<Source: BinaryFloatingPoint>(exactly value: Source)
It's great to have both of these, but I wonder how they're going to be implemented—if Integer can be either signed or unsigned, I'm not sure how you get the top bit of an unsigned integer out.
Also, since `init(_:)` is lossy and `init(exactly:)` is not, shouldn't their names technically be switched? Or perhaps `init(_:)` should be exact and trapping, `init(exactly:)` should be failable, and `init(closest:)` should always return something or other?
--
Brent Royal-Gordon
Architechies
More information about the swift-evolution
mailing list