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 <[email protected]> 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 <[email protected]
> <mailto:[email protected]>> 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 <[email protected]
>> <mailto:[email protected]>> 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 <[email protected]
>> <mailto:[email protected]>> 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
>>> <[email protected] <mailto:[email protected]>> 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
>>>> <[email protected] <mailto:[email protected]>> 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 <[email protected]
>>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> 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 <[email protected]
>>>>>> <mailto:[email protected]>> wrote:
>>>>>> > On Aug 26, 2016, at 6:06 PM, Jens Persson via swift-dev
>>>>>> > <[email protected] <mailto:[email protected]>> 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
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-dev
>>>> <https://lists.swift.org/mailman/listinfo/swift-dev>
>>>
>>> _______________________________________________
>>> swift-dev mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-dev
>>> <https://lists.swift.org/mailman/listinfo/swift-dev>
>>
>>
>
>
_______________________________________________
swift-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-dev