Has anyone implemented a Float8 / Quarter type?

Yes, I thought so too. Here's a program that prints each pair of mismatching conversions from Double to Float for all Double values in 1.0 ... 2.0:

func concrete(_ value: Double) -> Float {
    return Float.init(value) // Will call intrinsic
}
func generic<T: BinaryFloatingPoint>(_ value: T) -> Float {
    return Float.init(value) // Will call ._convert(from:)
}
extension String {
    func leftPadded(to minCount: Int, with char: Character=" ") -> String {
        return String(repeating: char, count: max(0, minCount-count)) + self
    }
}
extension BinaryFloatingPoint {
    var segmentedBinaryString: String {
        let e = String(exponentBitPattern, radix: 2)
        let s = String(significandBitPattern, radix: 2)
        return [self.sign == .plus ? "0" : "1", "_",
                e.leftPadded(to: Self.exponentBitCount, with: "0"), "_",
                s.leftPadded(to: Self.significandBitCount, with: "0")].joined()
    }
}
func test() {
    var d = Double(1)
    let step = d.ulp
    var mc = 0
    while d <= 2 {
        let a = concrete(d)
        let b = generic(d)
        if a != b {
            print("Found mismatched conversion (after \(mc) matching conversions):")
            print(" Double:  ", d.segmentedBinaryString, d)
            print(" concrete:", a.segmentedBinaryString, a)
            print(" generic: ", b.segmentedBinaryString, b)
            mc = 0
        } else {
            mc &+= 1
        }
        d += step
    }
}
test()

Here's what it will print:

Found mismatched conversion (after 805306368 matching conversions):
 Double:   0_01111111111_0000000000000000000000110000000000000000000000000000 1.0000001788139343
 concrete: 0_01111111_00000000000000000000010 1.0000002
 generic:  0_01111111_00000000000000000000001 1.0000001
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000001110000000000000000000000000000 1.0000004172325134
 concrete: 0_01111111_00000000000000000000100 1.0000005
 generic:  0_01111111_00000000000000000000011 1.0000004
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000010110000000000000000000000000000 1.0000006556510925
 concrete: 0_01111111_00000000000000000000110 1.0000007
 generic:  0_01111111_00000000000000000000101 1.0000006
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000011110000000000000000000000000000 1.0000008940696716
 concrete: 0_01111111_00000000000000000001000 1.000001
 generic:  0_01111111_00000000000000000000111 1.0000008
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000100110000000000000000000000000000 1.0000011324882507
 concrete: 0_01111111_00000000000000000001010 1.0000012
 generic:  0_01111111_00000000000000000001001 1.0000011
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000101110000000000000000000000000000 1.0000013709068298
 concrete: 0_01111111_00000000000000000001100 1.0000014
 generic:  0_01111111_00000000000000000001011 1.0000013
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000110110000000000000000000000000000 1.000001609325409
 concrete: 0_01111111_00000000000000000001110 1.0000017
 generic:  0_01111111_00000000000000000001101 1.0000015
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000000111110000000000000000000000000000 1.000001847743988
 concrete: 0_01111111_00000000000000000010000 1.0000019
 generic:  0_01111111_00000000000000000001111 1.0000018
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000001000110000000000000000000000000000 1.0000020861625671
 concrete: 0_01111111_00000000000000000010010 1.0000021
 generic:  0_01111111_00000000000000000010001 1.000002
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000001001110000000000000000000000000000 1.0000023245811462
 concrete: 0_01111111_00000000000000000010100 1.0000024
 generic:  0_01111111_00000000000000000010011 1.0000023
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000001010110000000000000000000000000000 1.0000025629997253
 concrete: 0_01111111_00000000000000000010110 1.0000026
 generic:  0_01111111_00000000000000000010101 1.0000025
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000001011110000000000000000000000000000 1.0000028014183044
 concrete: 0_01111111_00000000000000000011000 1.0000029
 generic:  0_01111111_00000000000000000010111 1.0000027
Found mismatched conversion (after 1073741823 matching conversions):
 Double:   0_01111111111_0000000000000000001100110000000000000000000000000000 1.0000030398368835
 concrete: 0_01111111_00000000000000000011010 1.0000031
 generic:  0_01111111_00000000000000000011001 1.000003

(I stopped it there (after a couple of minutes) :slight_smile: .)

The generic one does not behave according to its documentation, ie:

If two representable values are equally close, the result is the value with more trailing zeros in its significand bit pattern.

1 Like