Repository: apple/swift
File: stdlib/public/core/FloatingPointFromString.swift (Swift)

Code before:
      // Truncated exponent phrase: "0x1.234p+"
      return .failure
    }
    var explicitExponent = 0
    // Truncate exponents bigger than 1 million
    while i < input.count && hexdigit(input[i]) < 10 {
      if explicitExponent < 999999 {
        explicitExponent *= 10
        explicitExponent += Int(hexdigit(input[i]))
      }
      i += 1
    }
    binaryExponent += explicitExponent * exponentSign
  }
  if i < input.count { // Trailing garbage
    return .failure
  }
  if significand == 0 { // All digits were zero
    return .zero(sign: sign)
  }

  if binaryExponent > targetFormat.maxBinaryExponent {
    return .infinity(sign: sign) // Overflow
  }

  if binaryExponent < targetFormat.minBinaryExponent - targetFormat.significandBits + 1 {
    return .zero(sign: sign) // Underflow
  }

  // Select the appropriate number of bits for the target format,
  // and use the rest to correctly round the final result

  var significantBits: Int
  if binaryExponent >= targetFormat.minBinaryExponent {
    significantBits = targetFormat.significandBits
  } else {
    significantBits = binaryExponent - targetFormat.minBinaryExponent + targetFormat.significandBits
    binaryExponent = targetFormat.minBinaryExponent - 1 // Subnormal exponent
  }

  // Align the significand so the most-significant bit
  // is the MSbit of the accumulator.
  significand <<= significand.leadingZeroBitCount

  // Narrow to the target format and compute a 0.64 fraction
  // for the rest
  var targetSignificand = significand >> (64 - significantBits)

  // Folding in `remainderNonZero` here helps us distinguish
  // "1.00000000000000000000000000000000000000" (== 1.0) from
  // "1.00000000000000000000000000000000000001" (> 1.0)

Review comment (bug):
"If this value is so tiny that it _OBVIOUSLY_ rounds to zero, ...."

This check ensures that the full rounding logic below never has to consider ridiculous values like `0x1p-9999999999999` which might cause integer overflow.  But it was off by one, which caught values close to 1/2 of the smallest subnormal.  Such values need the full rounding analysis to determine whether they round down to zero or up to the smallest subnormal.

Code after:
      // Truncated exponent phrase: "0x1.234p+"
      return .failure
    }
    var explicitExponent = 0
    // Truncate exponents bigger than 1 million
    while i < input.count && hexdigit(input[i]) < 10 {
      if explicitExponent < 999999 {
        explicitExponent *= 10
        explicitExponent += Int(hexdigit(input[i]))
      }
      i += 1
    }
    binaryExponent += explicitExponent * exponentSign
  }
  if i < input.count { // Trailing garbage
    return .failure
  }
  if significand == 0 { // All digits were zero
    return .zero(sign: sign)
  }

  if binaryExponent > targetFormat.maxBinaryExponent {
    return .infinity(sign: sign) // Overflow
  }

  if binaryExponent < targetFormat.minBinaryExponent - targetFormat.significandBits {
    return .zero(sign: sign) // Underflow
  }

  // Select the appropriate number of bits for the target format,
  // and use the rest to correctly round the final result

  var significantBits: Int
  if binaryExponent >= targetFormat.minBinaryExponent {
    significantBits = targetFormat.significandBits
  } else {
    significantBits = binaryExponent - targetFormat.minBinaryExponent + targetFormat.significandBits
    binaryExponent = targetFormat.minBinaryExponent - 1 // Subnormal exponent
  }

  // Align the significand so the most-significant bit
  // is the MSbit of the accumulator.
  significand <<= significand.leadingZeroBitCount

  // Narrow to the target format and compute a 0.64 fraction
  // for the rest
  var targetSignificand = significand >> (64 - significantBits)

  // Folding in `remainderNonZero` here helps us distinguish
  // "1.00000000000000000000000000000000000000" (== 1.0) from
  // "1.00000000000000000000000000000000000001" (> 1.0)