[swift-dev] Why are BinaryFloatingPoint's RawSignificand and RawExponent different type?

Jens Persson jens at bitcycle.com
Sat Aug 27 03:34:02 CDT 2016


Oh, I just saw that SE-0104 was accepted for Swift 3:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160627/022977.html

Sorry for the noise, I will try to check basic things like this up before
asking here next time.


On Sat, Aug 27, 2016 at 10:20 AM, Jens Persson <jens at bitcycle.com> wrote:

> Btw, I had a look quick at the development snapshot 08-25-a toolchain and
> it seems like it has SE-0104 partly implemented.
>
> (For example Double doesn't conform to SignedArithmetic while it does
> conform to Arithmetic. And the Integer types doesn't conform to Arithmetic)
>
> Is SE-0104 not part of Swift 3, and will thus not be included in Xcode 8
> GM?
>
> /Jens
>
>
>
> On Sat, Aug 27, 2016 at 2:31 AM, Jens Persson <jens at bitcycle.com> wrote:
>
>> Ok, I've learned a lot, thanks!
>> /Jens
>>
>> On Sat, Aug 27, 2016 at 2:26 AM, Stephen Canon <scanon at apple.com> wrote:
>>
>>> For any given concrete type, it’s pretty straightforward to map [0,
>>> .max] to [0,1) — note that this is a bit different from what you seem to
>>> have been doing originally, mapping e.g. [0, 2**52) to [0, 1):
>>>
>>>     init(unitRange s: UInt64) {
>>>         self = Self(s >> UInt64(63 - Self.significandBitCount)) * .
>>> ulpOfOne/2
>>>     }
>>>
>>> Making this generic over integer types is painful without the SE-0104
>>> integer protocols, however.
>>>
>>> – Steve
>>>
>>>
>>> On Aug 26, 2016, at 8:13 PM, Jens Persson <jens at bitcycle.com> wrote:
>>>
>>> Ah, right! Thanks again.
>>> How would you make all integer type (UIntN, IntN) convertible/mappable
>>> from their respective [.min, .max] range to Double/Float unit range [0, 1)?
>>> /Jens
>>>
>>> On Sat, Aug 27, 2016 at 2:06 AM, Stephen Canon <scanon at apple.com> wrote:
>>>
>>>> Note that with the bug fixed, the result will still not be 1.nextDown,
>>>> because the size of an ulp changes at 1; the values you produce will be
>>>> space .ulpOfOne apart, but 1.nextDown is 1 - ulpOfOne/2.
>>>>
>>>> – Steve
>>>>
>>>> On Aug 26, 2016, at 8:00 PM, Jens Persson <jens at bitcycle.com> wrote:
>>>>
>>>> Thanks, but there seem to be something not working the same as in my
>>>> original code, here is a quick test of your code:
>>>>
>>>> protocol BinaryFloatingPointWithBitPattern: BinaryFloatingPoint {
>>>>     init(bitPattern: RawSignificand)
>>>>     var bitPattern: RawSignificand { get }
>>>> }
>>>>
>>>> extension Float: BinaryFloatingPointWithBitPattern { }
>>>> extension Double: BinaryFloatingPointWithBitPattern { }
>>>>
>>>> extension BinaryFloatingPointWithBitPattern {
>>>>     init(unitRangeFromRawSignificand s: RawSignificand) {
>>>>         self = Self(bitPattern: Self(1).bitPattern | s) - 1
>>>>     }
>>>> }
>>>>
>>>> typealias T = Double
>>>> // typealias T = Float
>>>>
>>>> let allSignificantBitsSet = T.RawSignificand((1 <<
>>>> T.significandBitCount) - 1)
>>>> print("bits set in signigicant:", String(allSignificantBitsSet, radix:
>>>> 2).characters.count) // 52
>>>> let a = T.init(bitPattern: 0)
>>>> let b = T.init(bitPattern: allSignificantBitsSet)
>>>> print(a) // 0.0, correct.
>>>> print(b) // 2.2250738585072e-308. Wrong, this should be (1.0).nextDown.
>>>>
>>>>
>>>> On Sat, Aug 27, 2016 at 1:57 AM, Stephen Canon <scanon at apple.com>
>>>> wrote:
>>>>
>>>>> If BinaryFloatingPoint had init(_: RawSignificand), you could also
>>>>> just write:
>>>>>
>>>>> extension BinaryFloatingPoint {
>>>>>     init(unitRangeFromRawSignificand s: RawSignificand) {
>>>>>         self = Self(s) * .ulpOfOne
>>>>>     }
>>>>> }
>>>>>
>>>>> (this is why I ask if RawSignificand is really the type you want; if
>>>>> you use some concrete integer type this will work).  But once we have all
>>>>> the new integer protocol conformances, we’ll have a generic init from any
>>>>> integer type (this was already reviewed for FloatingPoint, but isn’t
>>>>> implementable without the Integer support), which will also make this
>>>>> possible.
>>>>>
>>>>> On Aug 26, 2016, at 7:47 PM, Stephen Canon via swift-dev <
>>>>> swift-dev at swift.org> wrote:
>>>>>
>>>>> Assuming RawSignificand really is the type you want, I think this does
>>>>> what you’re looking for?
>>>>>
>>>>> protocol BinaryFloatingPointWithBitPattern: BinaryFloatingPoint {
>>>>>     init(bitPattern: RawSignificand)
>>>>>     var bitPattern: RawSignificand { get }
>>>>> }
>>>>>
>>>>> extension Float: BinaryFloatingPointWithBitPattern { }
>>>>> extension Double: BinaryFloatingPointWithBitPattern { }
>>>>>
>>>>> extension BinaryFloatingPointWithBitPattern {
>>>>>     init(unitRangeFromRawSignificand s: RawSignificand) {
>>>>>         self = Self(bitPattern: Self(1).bitPattern | s) - 1
>>>>>     }
>>>>> }
>>>>>
>>>>> On Aug 26, 2016, at 7:38 PM, Stephen Canon via swift-dev <
>>>>> swift-dev at swift.org> wrote:
>>>>>
>>>>> Where does your RawSignificand input come from?  Is that really the
>>>>> type that you want?
>>>>>
>>>>> I don’t think you really need very much boilerplate at all here.
>>>>>
>>>>> On Aug 26, 2016, at 7:30 PM, Jens Persson <jens at bitcycle.com> wrote:
>>>>>
>>>>> I understand.
>>>>> It's just very tempting to try and use the new static computed
>>>>> properties for eg 23 and 52 etc.
>>>>> I guess I'll just have to write a lot of boilerplate, or perhaps a
>>>>> protocol that is just implemented by Double and Float (that will be very
>>>>> similar to BinaryFloatingPoint in a lot of ways).
>>>>> /Jens
>>>>>
>>>>> On Sat, Aug 27, 2016 at 1:25 AM, Stephen Canon <scanon at apple.com
>>>>> > wrote:
>>>>> This doesn’t really scale up very well, though.  BinaryFloatingPoint
>>>>> needs to also be able to model e.g. Float2048 or similar; we generally
>>>>> don't want to require that RawExponent to be the same type as
>>>>> RawSignificand (which I think is what you’re really suggesting), because in
>>>>> typical bignum usage significands are much larger than exponents.
>>>>>
>>>>> It sounds like maybe you actually want to be operating directly on
>>>>> bitPatterns, rather than the abstract fields of the types.
>>>>>
>>>>> – Steve
>>>>>
>>>>> On Aug 26, 2016, at 7:21 PM, Jens Persson <jens at bitcycle.com> wrote:
>>>>>
>>>>> Oh, to more directly answer your question: I don't like having to
>>>>> create a UInt (UInt64) value when all my bit manipulaton code happens in
>>>>> UInt32 (for Float) for example.
>>>>>
>>>>> The most probable context for using these computed properties and
>>>>> types of BinaryFloatingPoint is one in which specific fixed width types
>>>>> really matters a lot (look at the name of the protocol and the properties
>>>>> and assocated types we are talking about).
>>>>>
>>>>> /Jens
>>>>>
>>>>>
>>>>> On Sat, Aug 27, 2016 at 1:15 AM, Jens Persson <jens at bitcycle.com> wr
>>>>> ote:
>>>>> Reason for asking is that I have this:
>>>>>
>>>>> extension Double {
>>>>>     init(unitRangeFromRawSignificand s: RawSignificand) {
>>>>>         let bitPattern = s | (1023 << 52)
>>>>>         self = unsafeBitCast(bitPattern, to: Double.self) - 1.0
>>>>>     }
>>>>> }
>>>>> extension Float {
>>>>>     init(unitRangeFromRawSignificand s: RawSignificand) {
>>>>>         let bitPattern = s | (127 << 23)
>>>>>         self = unsafeBitCast(bitPattern, to: Float.self) - 1.0
>>>>>     }
>>>>> }
>>>>>
>>>>> But they would be better as:
>>>>> extension BinaryFloatingPoint {
>>>>>     init(unitRangeFromRawSignificand s: RawSignificand) {
>>>>>         ... problems here, have to try casting things into
>>>>> RawSignificand's type ...
>>>>>     }
>>>>> }
>>>>>
>>>>> Please have a go at that and perhaps you see what I mean or you will
>>>>> come up with a nice solution that I have missed. (Speed is very important
>>>>> btw.)
>>>>>
>>>>> /Jens
>>>>>
>>>>>
>>>>> On Sat, Aug 27, 2016 at 1:02 AM, Stephen Canon <scanon at apple.com
>>>>> > wrote:
>>>>> > On Aug 26, 2016, at 6:06 PM, Jens Persson via swift-dev <
>>>>> swift-dev at swift.org> wrote:
>>>>> >
>>>>> > I can understand why
>>>>> > Double.RawSignificand is UInt64
>>>>> > and
>>>>> > Float.RawSignificand is UInt32
>>>>> >
>>>>> > But I can't understand why both
>>>>> > Double.RawExponent
>>>>> > and
>>>>> > Float.RawExponent
>>>>> > should be UInt.
>>>>> >
>>>>> > Why aren't they also just UInt64 and UInt32, resp.?
>>>>>
>>>>> Let me flip the question: why would they be UInt64 and UInt32?  Absent
>>>>> a reason to prefer a specific fixed-with type, Swift integers should
>>>>> generally default to being [U]Int (and ideally Int, but RawExponent
>>>>> is Unsigned).
>>>>>
>>>>> – Steve
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-dev mailing list
>>>>> swift-dev at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-dev
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-dev mailing list
>>>>> swift-dev at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-dev
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160827/826ca547/attachment-0001.html>


More information about the swift-dev mailing list