One more stray thought: Is there a reason RawSignificand is declared in FloatingPoint but used only in BinaryFloatingPoint?
On Fri, Apr 22, 2016 at 10:02 AM, Xiaodi Wu <[email protected]> wrote: > Two stray thoughts: > > I agree with previous comments that `ulpOfOne` may not really be necessary. > > Of the following-- > ``` > init(signBit: Bool, exponent: Int, significand: Self) > init(magnitudeOf other: Self, signOf: Self) > ``` > --would it be more elegant to have the latter be `init(signOf: Self, > magnitudeOf other: Self)`? > > > On Fri, Apr 22, 2016 at 9:54 AM, Xiaodi Wu <[email protected]> wrote: >> On Fri, Apr 22, 2016 at 9:13 AM, Stephen Canon via swift-evolution >> <[email protected]> wrote: >>> >>> On Apr 21, 2016, at 9:13 PM, Jordan Rose <[email protected]> wrote: >>> >>> [Proposal: >>> https://github.com/apple/swift-evolution/blob/master/proposals/0067-floating-point-protocols.md] >>> >>> This is super impressive. I do have several bits I’m uncomfortable with, >>> however. I’ll try to separate that into “semantic” and “naming” sections. >>> >>> Semantic >>> >>> static var radix: Int { get } >>> >>> >>> Does it ever make sense to have a model type that allows different instances >>> to have different radices? >>> >>> >>> No. >>> >>> Is there an algorithm that makes use of a model’s radix, or is this just in >>> here for “completeness”? >>> >>> >>> If you know ulp, radix, and exponent range, you can infer basically all the >>> other numerical details of the type. One good example would be the constant >>> that Dave mentioned, “maxResultOfAdding1”. You can compute this if you know >>> radix and ulp. The radix is also the bound on how large the relative >>> spacing between consecutive numbers can get, which is sometimes important >>> for computing accurate bounds. These are all somewhat niche, but the >>> problem is that there’s no good way to get this value if you don’t have it, >>> and it imposes “zero” implementation burden. >>> >>> /// A signaling NaN (not-a-number). >>> @warn_unused_result >>> static func signalingNaN: Self { get } >>> >>> >>> I’m not sure it really makes sense for a Bignum / APFloat type to support >>> such a value. But really I think this is just underspecified. What does it >>> mean, in terms of this protocol and its uses, for a NaN to be signaling? Is >>> it just a specific “color" of NaN, with no semantic requirements other than >>> being distinguishable? >>> >>> >>> There are a variety of means that a softfloat type could use to implement >>> signaling NaNs. Here are two of the simpler ones: >>> >>> (a) if running on HW with hard-float support, use native-precision >>> hard-float instructions to set flags as needed. >>> (b) provide operation variants that take an inout flags / parameter: >>> >>> mutating func add(rhs: Self, inout flags: Flags) >>> >>> (Also, is ‘signalingNan.isNan’ true? I assume so but since ’nan’ is implied >>> to be a non-signaling NaN I’m not sure anymore.) >>> >>> >>> Yup, that should be clarified. >>> >>> var signBit: Bool { get } >>> >>> >>> Unlike Chris, I’m strongly against this property as it stands. You should >>> not be able to write “if someValue.signBit”; a bit is not a boolean value. >>> (Citation: "Uses of Boolean methods and properties should read as assertions >>> about the receiver.”) >>> >>> I’d be okay with Greg’s idea of changing the type to an enum. I’d also be >>> okay with renaming this to a predicate, whatever the name ends up being. >>> (“isSignBitSet”, “isSignNegative”, etc.) >>> >>> >>> Making it a predicate is weird, because then the three properties making up >>> the number become `isSignBitSet`, `exponent`, and `significand`; one of >>> these things is not like the other ones. If `signBit: Bool` were ruled out, >>> I would rather go with Greg’s enum proposal. >>> >>> var exponent: Int { get } >>> >>> >>> Nitpick: it’s probably worth noting in the doc comment that this is the >>> unbiased exponent value. >>> >>> Also, does it matter that this is insufficient for bignums, which may have >>> an exponent of greater than `sizeof(Int.self)` bits? (This is also a concern >>> for a number of members of BinaryFloatingPoint, like ‘significantBitCount’.) >>> >>> >>> An exponent of Int.max encodes a number >= 2**Int.max. This is a >>> staggeringly huge quantity, even when Int is 32 bits (it’s approximately >>> 1e646456992). There are a few extremely niche applications that require >>> numbers with greater magnitude, but they are *extremely* rare. To a good >>> approximation, `Int` is more than enough bits, and a reasonable tradeoff. >> >> Naive question: is it necessary to make a trade-off here? Why not an >> associated type Exponent that's Int for Float, Double, and Float80, >> allowing for something else for bignums? >> >>> Ditto `significandBitCount`. I haven’t seen usage of floating-point types >>> with more than a few thousand significand bits; billions of bits is enough. >>> It is plausible that one could build a type that runs into this limit on a >>> 32-bit system, but it wouldn’t be very useful; on a 64-bit system, you can’t >>> allocate the storage for even one such value. >>> >>> Naming >>> >>> On “NaN” vs. “Nan”: I’m not convinced that ignoring the case is the right >>> way to go here. IMHO the clearest lowercase form is “nan” and the clearest >>> capitalized form is “NaN”. >>> >>> The current draft API guidelines don’t cover this case, but if I were to add >>> something for this, I’d say “when a word is normally written with mixed >>> case, the lowercase form should be fully-lowercased if the first letter is >>> naturally uppercase, and the capitalized form should have the first letter >>> uppercased only.” That rule produces “iPhone/IPhone”, “next/NeXT”, and >>> “nan/NaN”. (The “if the first letter is naturally uppercase” could be thrown >>> out as well.) >>> >>> >>> Yup, this seems like a sensible rule to me. >>> >>> On 'isLessThanOrEqual(to:)’: I agree with Xiaodi that the argument label is >>> problematic here. I think the problem is that we have two prepositions that >>> apply to the argument, and “pick the second one” leaves the base name >>> feeling unbalanced. (Remember that we allow referring to a method by its >>> basename alone when using it as a function value.) >>> >>> On 'isTotallyOrdered(with:)’: I lost track of who said it, but I agree that >>> this sounds like it’s “!isUnordered(with: other)”. The only name that’s >>> coming to mind is ‘isTotallyOrderedBefore(_:)’, which isn’t great. >>> >>> On ‘binade’: At first I thought this was a confusing term and there had to >>> be a better one, but now I think it’s an “if you don’t know what this is, >>> you don’t need to use it” case. :-) >>> >>> >>> Yup. >>> >>> – Steve >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
