| //===--- FloatingPointTypes.swift.gyb -------------------------*- swift -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| import SwiftShims |
| |
| %{ |
| from __future__ import division |
| from SwiftIntTypes import all_integer_types |
| from SwiftFloatingPointTypes import all_floating_point_types |
| |
| # |
| # Utility code for later in this template |
| # |
| |
| # Number of bits in the Builtin.Word type |
| word_bits = int(CMAKE_SIZEOF_VOID_P) * 8 |
| |
| # Number of bits in integer literals. |
| builtinIntLiteralBits = 2048 |
| }% |
| |
| % for self_type in all_floating_point_types(): |
| %{ |
| Self = self_type.stdlib_name |
| bits = self_type.bits |
| cFuncSuffix = self_type.cFuncSuffix |
| SignificandSize = self_type.significand_size |
| SignificandBitCount = self_type.significand_bits |
| ExponentBitCount = self_type.exponent_bits |
| RawSignificand = 'UInt' + str(SignificandSize) |
| |
| def Availability(bits): |
| if bits == 16: |
| return '@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)' |
| return '' |
| |
| if Self == 'Float16': |
| SelfDocComment = '''\ |
| /// A half-precision (16b), floating-point value type.''' |
| |
| elif Self == 'Float': |
| SelfDocComment = '''\ |
| /// A single-precision, floating-point value type.''' |
| |
| elif Self == 'Double': |
| SelfDocComment = '''\ |
| /// A double-precision, floating-point value type.''' |
| |
| elif Self == 'Float80': |
| SelfDocComment = '''\ |
| /// An extended-precision, floating-point value type.''' |
| |
| else: |
| raise ValueError('Unhandled float type.') |
| }% |
| |
| % if bits == 80: |
| #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) |
| % elif bits == 16: |
| #if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) |
| % end |
| |
| ${SelfDocComment} |
| ${Availability(bits)} |
| @frozen |
| public struct ${Self} { |
| public // @testable |
| var _value: Builtin.FPIEEE${bits} |
| |
| @_transparent |
| public init() { |
| let zero: Int64 = 0 |
| self._value = Builtin.sitofp_Int64_FPIEEE${bits}(zero._value) |
| } |
| |
| @_transparent |
| public // @testable |
| init(_ _value: Builtin.FPIEEE${bits}) { |
| self._value = _value |
| } |
| } |
| |
| ${Availability(bits)} |
| extension ${Self}: CustomStringConvertible { |
| /// A textual representation of the value. |
| public var description: String { |
| if isNaN { |
| return "nan" |
| } else { |
| var (buffer, length) = _float${bits}ToString(self, debug: false) |
| return buffer.withBytes { (bufferPtr) in |
| String._fromASCII( |
| UnsafeBufferPointer(start: bufferPtr, count: length)) |
| } |
| } |
| } |
| } |
| |
| ${Availability(bits)} |
| extension ${Self}: CustomDebugStringConvertible { |
| /// A textual representation of the value, suitable for debugging. |
| public var debugDescription: String { |
| var (buffer, length) = _float${bits}ToString(self, debug: true) |
| return buffer.withBytes { (bufferPtr) in |
| String._fromASCII( |
| UnsafeBufferPointer(start: bufferPtr, count: length)) |
| } |
| } |
| } |
| |
| ${Availability(bits)} |
| extension ${Self}: TextOutputStreamable { |
| public func write<Target>(to target: inout Target) where Target: TextOutputStream { |
| var (buffer, length) = _float${bits}ToString(self, debug: true) |
| buffer.withBytes { (bufferPtr) in |
| let bufPtr = UnsafeBufferPointer(start: bufferPtr, count: length) |
| target._writeASCII(bufPtr) |
| } |
| } |
| } |
| |
| ${Availability(bits)} |
| extension ${Self}: BinaryFloatingPoint { |
| |
| // Floating-point types are always symmetric, so Magnitude is Self. |
| public typealias Magnitude = ${Self} |
| |
| public typealias Exponent = Int |
| |
| public typealias RawSignificand = ${RawSignificand} |
| |
| @inlinable |
| public static var exponentBitCount: Int { |
| return ${ExponentBitCount} |
| } |
| |
| %if bits == 80: |
| // `Float80.significandBitCount` is 63, even though 64 bits are used to |
| // store the significand in the memory representation of a `Float80` |
| // instance. Unlike other floating-point types, the `Float80` type |
| // explicitly stores the leading integral significand bit; we abstract |
| // that away to present the same user-facing interface as the floating- |
| // point types. |
| %end |
| @inlinable |
| public static var significandBitCount: Int { |
| return ${SignificandBitCount} |
| } |
| |
| // Implementation details. |
| @inlinable // FIXME(inline-always) was usableFromInline |
| internal static var _infinityExponent: UInt { |
| @inline(__always) get { return 1 &<< UInt(exponentBitCount) - 1 } |
| } |
| |
| @inlinable // FIXME(inline-always) was usableFromInline |
| internal static var _exponentBias: UInt { |
| @inline(__always) get { return _infinityExponent &>> 1 } |
| } |
| |
| @inlinable // FIXME(inline-always) was usableFromInline |
| internal static var _significandMask: ${RawSignificand} { |
| @inline(__always) get { |
| return 1 &<< ${RawSignificand}(significandBitCount) - 1 |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) was usableFromInline |
| internal static var _quietNaNMask: ${RawSignificand} { |
| @inline(__always) get { |
| return 1 &<< ${RawSignificand}(significandBitCount - 1) |
| } |
| } |
| |
| %if bits != 80: |
| // Conversions to/from integer encoding. These are not part of the |
| // BinaryFloatingPoint prototype because there's no guarantee that an |
| // integer type of the same size actually exists (e.g. Float80). |
| // |
| // If we want them in a protocol at some future point, that protocol should |
| // be "InterchangeFloatingPoint" or "PortableFloatingPoint" or similar, and |
| // apply to IEEE 754 "interchange types". |
| /// The bit pattern of the value's encoding. |
| /// |
| /// The bit pattern matches the binary interchange format defined by the |
| /// [IEEE 754 specification][spec]. |
| /// |
| /// [spec]: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933 |
| @inlinable |
| public var bitPattern: UInt${bits} { |
| return UInt${bits}(Builtin.bitcast_FPIEEE${bits}_Int${bits}(_value)) |
| } |
| |
| /// Creates a new value with the given bit pattern. |
| /// |
| /// The value passed as `bitPattern` is interpreted in the binary interchange |
| /// format defined by the [IEEE 754 specification][spec]. |
| /// |
| /// [spec]: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933 |
| /// |
| /// - Parameter bitPattern: The integer encoding of a `${Self}` instance. |
| @inlinable |
| public init(bitPattern: UInt${bits}) { |
| self.init(Builtin.bitcast_Int${bits}_FPIEEE${bits}(bitPattern._value)) |
| } |
| |
| @inlinable |
| public var sign: FloatingPointSign { |
| let shift = ${Self}.significandBitCount + ${Self}.exponentBitCount |
| return FloatingPointSign( |
| rawValue: Int(bitPattern &>> ${RawSignificand}(shift)) |
| )! |
| } |
| |
| @available(*, unavailable, renamed: "sign") |
| public var isSignMinus: Bool { Builtin.unreachable() } |
| |
| @inlinable |
| public var exponentBitPattern: UInt { |
| return UInt(bitPattern &>> UInt${bits}(${Self}.significandBitCount)) & |
| ${Self}._infinityExponent |
| } |
| |
| @inlinable |
| public var significandBitPattern: ${RawSignificand} { |
| return ${RawSignificand}(bitPattern) & ${Self}._significandMask |
| } |
| |
| @inlinable |
| public init( |
| sign: FloatingPointSign, |
| exponentBitPattern: UInt, |
| significandBitPattern: ${RawSignificand} |
| ) { |
| let signShift = ${Self}.significandBitCount + ${Self}.exponentBitCount |
| let sign = UInt${bits}(sign == .minus ? 1 : 0) |
| let exponent = UInt${bits}( |
| exponentBitPattern & ${Self}._infinityExponent |
| ) |
| let significand = UInt${bits}( |
| significandBitPattern & ${Self}._significandMask |
| ) |
| self.init(bitPattern: |
| sign &<< UInt${bits}(signShift) | |
| exponent &<< UInt${bits}(${Self}.significandBitCount) | |
| significand |
| ) |
| } |
| |
| @inlinable |
| public var isCanonical: Bool { |
| // All Float and Double encodings are canonical in IEEE 754. |
| // |
| // On platforms that do not support subnormals, we treat them as |
| // non-canonical encodings of zero. |
| if Self.leastNonzeroMagnitude == Self.leastNormalMagnitude { |
| if exponentBitPattern == 0 && significandBitPattern != 0 { |
| return false |
| } |
| } |
| return true |
| } |
| %else: |
| // Internal implementation details of x86 Float80 |
| @frozen |
| @usableFromInline |
| internal struct _Representation { |
| @usableFromInline |
| internal var _storage: (UInt64, UInt16, /* pad */ UInt16, UInt16, UInt16) |
| |
| @usableFromInline |
| @_transparent |
| internal var explicitSignificand: UInt64 { return _storage.0 } |
| |
| @usableFromInline |
| @_transparent |
| internal var signAndExponent: UInt16 { return _storage.1 } |
| |
| @usableFromInline |
| @_transparent |
| internal var sign: FloatingPointSign { |
| return FloatingPointSign(rawValue: Int(signAndExponent &>> 15))! |
| } |
| |
| @usableFromInline |
| @_transparent |
| internal var exponentBitPattern: UInt { |
| return UInt(signAndExponent) & 0x7fff |
| } |
| |
| @usableFromInline |
| @_transparent |
| internal init(explicitSignificand: UInt64, signAndExponent: UInt16) { |
| _storage = (explicitSignificand, signAndExponent, 0, 0, 0) |
| } |
| } |
| |
| @inlinable |
| internal var _representation: _Representation { |
| return unsafeBitCast(self, to: _Representation.self) |
| } |
| |
| @inlinable |
| public var sign: FloatingPointSign { |
| return _representation.sign |
| } |
| |
| @inlinable |
| internal static var _explicitBitMask: UInt64 { |
| @inline(__always) get { return 1 &<< 63 } |
| } |
| |
| @inlinable |
| public var exponentBitPattern: UInt { |
| let provisional = _representation.exponentBitPattern |
| if provisional == 0 { |
| if _representation.explicitSignificand >= Float80._explicitBitMask { |
| // Pseudo-denormals have an exponent of 0 but the leading bit of the |
| // significand field is set. These are noncanonical encodings of the |
| // same significand with an exponent of 1. |
| return 1 |
| } |
| // Exponent is zero, leading bit of significand is clear, so this is |
| // a canonical zero or subnormal number. |
| return 0 |
| } |
| if _representation.explicitSignificand < Float80._explicitBitMask { |
| // If the exponent is not-zero but the leading bit of the significand |
| // is clear, then we have an invalid operand (unnormal, pseudo-inf, or |
| // pseudo-NaN). All of these are noncanonical encodings of NaN. |
| return Float80._infinityExponent |
| } |
| // We have a canonical number, so the provisional exponent is correct. |
| return provisional |
| } |
| |
| @inlinable |
| public var significandBitPattern: UInt64 { |
| if _representation.exponentBitPattern > 0 && |
| _representation.explicitSignificand < Float80._explicitBitMask { |
| // If the exponent is nonzero and the leading bit of the significand |
| // is clear, then we have an invalid operand (unnormal, pseudo-inf, or |
| // pseudo-NaN). All of these are noncanonical encodings of qNaN. |
| return _representation.explicitSignificand | Float80._quietNaNMask |
| } |
| // Otherwise we always get the "right" significand by simply clearing the |
| // integral bit. |
| return _representation.explicitSignificand & Float80._significandMask |
| } |
| |
| @inlinable |
| public init(sign: FloatingPointSign, |
| exponentBitPattern: UInt, |
| significandBitPattern: UInt64) { |
| let signBit = UInt16(sign == .minus ? 0x8000 : 0) |
| let exponent = UInt16(exponentBitPattern) |
| var significand = significandBitPattern |
| if exponent != 0 { significand |= Float80._explicitBitMask } |
| let rep = _Representation( |
| explicitSignificand: significand, signAndExponent: signBit|exponent) |
| self = unsafeBitCast(rep, to: Float80.self) |
| } |
| |
| @inlinable |
| public var isCanonical: Bool { |
| if exponentBitPattern == 0 { |
| // If exponent field is zero, canonical numbers have the explicit |
| // significand bit clear. |
| return _representation.explicitSignificand < Float80._explicitBitMask |
| } |
| // If exponent is nonzero, canonical values have the explicit significand |
| // bit set. |
| return _representation.explicitSignificand >= Float80._explicitBitMask |
| } |
| %end |
| |
| @inlinable |
| public static var infinity: ${Self} { |
| %if bits == 32: |
| return ${Self}(bitPattern: 0x7f800000) |
| %elif bits == 64: |
| return ${Self}(bitPattern: 0x7ff0000000000000) |
| %elif bits == 80: |
| let rep = _Representation( |
| explicitSignificand: ${Self}._explicitBitMask, |
| signAndExponent: 0x7fff |
| ) |
| return unsafeBitCast(rep, to: ${Self}.self) |
| %else: |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: _infinityExponent, |
| significandBitPattern: 0 |
| ) |
| %end |
| } |
| |
| @inlinable |
| public static var nan: ${Self} { |
| %if bits == 32: |
| return ${Self}(bitPattern: 0x7fc00000) |
| %elif bits == 64: |
| return ${Self}(bitPattern: 0x7ff8000000000000) |
| %elif bits == 80: |
| let rep = _Representation( |
| explicitSignificand: ${Self}._explicitBitMask | ${Self}._quietNaNMask, |
| signAndExponent: 0x7fff |
| ) |
| return unsafeBitCast(rep, to: ${Self}.self) |
| %else: |
| return ${Self}(nan: 0, signaling: false) |
| %end |
| } |
| |
| @inlinable |
| public static var signalingNaN: ${Self} { |
| return ${Self}(nan: 0, signaling: true) |
| } |
| |
| @available(*, unavailable, renamed: "nan") |
| public static var quietNaN: ${Self} { Builtin.unreachable() } |
| |
| @inlinable |
| public static var greatestFiniteMagnitude: ${Self} { |
| %if bits == 32: |
| return 0x1.fffffep127 |
| %elif bits == 64: |
| return 0x1.fffffffffffffp1023 |
| %elif bits == 80: |
| return 0x1.fffffffffffffffep16383 |
| %else: |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: _infinityExponent - 1, |
| significandBitPattern: _significandMask |
| ) |
| %end |
| } |
| |
| @inlinable |
| public static var pi: ${Self} { |
| %if bits == 16: |
| return 0x1.92p1 |
| %elif bits == 32: |
| // Note: this is not the correctly rounded (to nearest) value of pi, |
| // because pi would round *up* in Float precision, which can result |
| // in angles in the wrong quadrant if users aren't careful. This is |
| // not a problem for Double or Float80, as pi rounds down in both of |
| // those formats. |
| return 0x1.921fb4p1 |
| %elif bits == 64: |
| return 0x1.921fb54442d18p1 |
| %elif bits == 80: |
| return 0x1.921fb54442d1846ap1 |
| %end |
| } |
| |
| @inlinable |
| public var ulp: ${Self} { |
| %if bits != 80: |
| guard _fastPath(isFinite) else { return .nan } |
| if _fastPath(isNormal) { |
| let bitPattern_ = bitPattern & ${Self}.infinity.bitPattern |
| return ${Self}(bitPattern: bitPattern_) * 0x1p-${SignificandBitCount} |
| } |
| // On arm, flush subnormal values to 0. |
| return .leastNormalMagnitude * 0x1p-${SignificandBitCount} |
| %else: |
| guard _fastPath(isFinite) else { return .nan } |
| if exponentBitPattern > UInt(${Self}.significandBitCount) { |
| // self is large enough that self.ulp is normal, so we just compute its |
| // exponent and construct it with a significand of zero. |
| let ulpExponent = |
| exponentBitPattern - UInt(${Self}.significandBitCount) |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: ulpExponent, |
| significandBitPattern: 0 |
| ) |
| } |
| if exponentBitPattern >= 1 { |
| // self is normal but ulp is subnormal. |
| let ulpShift = ${RawSignificand}(exponentBitPattern - 1) |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: 0, |
| significandBitPattern: 1 &<< ulpShift |
| ) |
| } |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: 0, |
| significandBitPattern: 1 |
| ) |
| %end |
| } |
| |
| @inlinable |
| public static var leastNormalMagnitude: ${Self} { |
| return 0x1.0p-${2**(ExponentBitCount-1)-2} |
| } |
| |
| @inlinable |
| public static var leastNonzeroMagnitude: ${Self} { |
| #if arch(arm) |
| // On 32b arm, the default FPCR has subnormals flushed to zero. |
| return leastNormalMagnitude |
| #else |
| return leastNormalMagnitude * ulpOfOne |
| #endif |
| } |
| |
| /// The unit in the last place of 1.0. |
| /// |
| /// The positive difference between 1.0 and the next greater representable |
| /// number. The `ulpOfOne` constant corresponds to the C macros |
| /// `FLT_EPSILON`, `DBL_EPSILON`, and others with a similar purpose. |
| @inlinable |
| public static var ulpOfOne: ${Self} { |
| return 0x1.0p-${SignificandBitCount} |
| } |
| |
| @inlinable |
| public var exponent: Int { |
| if !isFinite { return .max } |
| if isZero { return .min } |
| let provisional = Int(exponentBitPattern) - Int(${Self}._exponentBias) |
| if isNormal { return provisional } |
| let shift = |
| ${Self}.significandBitCount - significandBitPattern._binaryLogarithm() |
| return provisional + 1 - shift |
| } |
| |
| @inlinable |
| public var significand: ${Self} { |
| if isNaN { return self } |
| if isNormal { |
| return ${Self}(sign: .plus, |
| exponentBitPattern: ${Self}._exponentBias, |
| significandBitPattern: significandBitPattern) |
| } |
| if isSubnormal { |
| let shift = |
| ${Self}.significandBitCount - significandBitPattern._binaryLogarithm() |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: ${Self}._exponentBias, |
| significandBitPattern: significandBitPattern &<< shift |
| ) |
| } |
| // zero or infinity. |
| return ${Self}( |
| sign: .plus, |
| exponentBitPattern: exponentBitPattern, |
| significandBitPattern: 0 |
| ) |
| } |
| |
| @inlinable |
| public init(sign: FloatingPointSign, exponent: Int, significand: ${Self}) { |
| var result = significand |
| if sign == .minus { result = -result } |
| if significand.isFinite && !significand.isZero { |
| var clamped = exponent |
| let leastNormalExponent = 1 - Int(${Self}._exponentBias) |
| let greatestFiniteExponent = Int(${Self}._exponentBias) |
| if clamped < leastNormalExponent { |
| clamped = max(clamped, 3*leastNormalExponent) |
| while clamped < leastNormalExponent { |
| result *= ${Self}.leastNormalMagnitude |
| clamped -= leastNormalExponent |
| } |
| } |
| else if clamped > greatestFiniteExponent { |
| clamped = min(clamped, 3*greatestFiniteExponent) |
| let step = ${Self}(sign: .plus, |
| exponentBitPattern: ${Self}._infinityExponent - 1, |
| significandBitPattern: 0) |
| while clamped > greatestFiniteExponent { |
| result *= step |
| clamped -= greatestFiniteExponent |
| } |
| } |
| let scale = ${Self}( |
| sign: .plus, |
| exponentBitPattern: UInt(Int(${Self}._exponentBias) + clamped), |
| significandBitPattern: 0 |
| ) |
| result = result * scale |
| } |
| self = result |
| } |
| |
| /// Creates a NaN ("not a number") value with the specified payload. |
| /// |
| /// NaN values compare not equal to every value, including themselves. Most |
| /// operations with a NaN operand produce a NaN result. Don't use the |
| /// equal-to operator (`==`) to test whether a value is NaN. Instead, use |
| /// the value's `isNaN` property. |
| /// |
| /// let x = ${Self}(nan: 0, signaling: false) |
| /// print(x == .nan) |
| /// // Prints "false" |
| /// print(x.isNaN) |
| /// // Prints "true" |
| /// |
| /// - Parameters: |
| /// - payload: The payload to use for the new NaN value. |
| /// - signaling: Pass `true` to create a signaling NaN or `false` to create |
| /// a quiet NaN. |
| @inlinable |
| public init(nan payload: RawSignificand, signaling: Bool) { |
| // We use significandBitCount - 2 bits for NaN payload. |
| _precondition(payload < (${Self}._quietNaNMask &>> 1), |
| "NaN payload is not encodable.") |
| var significand = payload |
| significand |= ${Self}._quietNaNMask &>> (signaling ? 1 : 0) |
| self.init( |
| sign: .plus, |
| exponentBitPattern: ${Self}._infinityExponent, |
| significandBitPattern: significand |
| ) |
| } |
| |
| @inlinable |
| public var nextUp: ${Self} { |
| %if bits != 80: |
| // Silence signaling NaNs, map -0 to +0. |
| let x = self + 0 |
| #if arch(arm) |
| // On arm, treat subnormal values as zero. |
| if _slowPath(x == 0) { return .leastNonzeroMagnitude } |
| if _slowPath(x == -.leastNonzeroMagnitude) { return -0.0 } |
| #endif |
| if _fastPath(x < .infinity) { |
| let increment = Int${bits}(bitPattern: x.bitPattern) &>> ${bits - 1} | 1 |
| let bitPattern_ = x.bitPattern &+ UInt${bits}(bitPattern: increment) |
| return ${Self}(bitPattern: bitPattern_) |
| } |
| return x |
| %else: |
| if isNaN { /* Silence signaling NaNs. */ return self + 0 } |
| if sign == .minus { |
| if significandBitPattern == 0 { |
| if exponentBitPattern == 0 { |
| return .leastNonzeroMagnitude |
| } |
| return ${Self}(sign: .minus, |
| exponentBitPattern: exponentBitPattern - 1, |
| significandBitPattern: ${Self}._significandMask) |
| } |
| return ${Self}(sign: .minus, |
| exponentBitPattern: exponentBitPattern, |
| significandBitPattern: significandBitPattern - 1) |
| } |
| if isInfinite { return self } |
| if significandBitPattern == ${Self}._significandMask { |
| return ${Self}(sign: .plus, |
| exponentBitPattern: exponentBitPattern + 1, |
| significandBitPattern: 0) |
| } |
| return ${Self}(sign: .plus, |
| exponentBitPattern: exponentBitPattern, |
| significandBitPattern: significandBitPattern + 1) |
| %end |
| } |
| |
| // For core standard library floating-point types, LLVM can lower copysign |
| // for us; this gets somewhat better codegen than the generic implementation, |
| // but more importantly allows it to participate in other optimizations |
| // at the LLVM level. |
| @_transparent |
| public init(signOf sign: ${Self}, magnitudeOf mag: ${Self}) { |
| _value = Builtin.int_copysign_FPIEEE${bits}(mag._value, sign._value) |
| } |
| |
| @_transparent |
| public mutating func round(_ rule: FloatingPointRoundingRule) { |
| switch rule { |
| case .toNearestOrAwayFromZero: |
| _value = Builtin.int_round_FPIEEE${bits}(_value) |
| case .toNearestOrEven: |
| _value = Builtin.int_rint_FPIEEE${bits}(_value) |
| case .towardZero: |
| _value = Builtin.int_trunc_FPIEEE${bits}(_value) |
| case .awayFromZero: |
| if sign == .minus { |
| _value = Builtin.int_floor_FPIEEE${bits}(_value) |
| } |
| else { |
| _value = Builtin.int_ceil_FPIEEE${bits}(_value) |
| } |
| case .up: |
| _value = Builtin.int_ceil_FPIEEE${bits}(_value) |
| case .down: |
| _value = Builtin.int_floor_FPIEEE${bits}(_value) |
| @unknown default: |
| self._roundSlowPath(rule) |
| } |
| } |
| |
| // Slow path for new cases that might have been inlined into an old |
| // ABI-stable version of round(_:) called from a newer version. If this is |
| // the case, this non-inlinable function will call into the _newer_ version |
| // which _will_ support this rounding rule. |
| @usableFromInline |
| internal mutating func _roundSlowPath(_ rule: FloatingPointRoundingRule) { |
| self.round(rule) |
| } |
| |
| @_transparent |
| public mutating func negate() { |
| _value = Builtin.fneg_FPIEEE${bits}(self._value) |
| } |
| |
| @_transparent |
| public static func +=(lhs: inout ${Self}, rhs: ${Self}) { |
| lhs._value = Builtin.fadd_FPIEEE${bits}(lhs._value, rhs._value) |
| } |
| |
| @_transparent |
| public static func -=(lhs: inout ${Self}, rhs: ${Self}) { |
| lhs._value = Builtin.fsub_FPIEEE${bits}(lhs._value, rhs._value) |
| } |
| |
| @_transparent |
| public static func *=(lhs: inout ${Self}, rhs: ${Self}) { |
| lhs._value = Builtin.fmul_FPIEEE${bits}(lhs._value, rhs._value) |
| } |
| |
| @_transparent |
| public static func /=(lhs: inout ${Self}, rhs: ${Self}) { |
| lhs._value = Builtin.fdiv_FPIEEE${bits}(lhs._value, rhs._value) |
| } |
| |
| @inlinable // FIXME(inline-always) |
| @inline(__always) |
| public mutating func formRemainder(dividingBy other: ${Self}) { |
| % if bits == 16: |
| self = Float16(_stdlib_remainderf(Float(self), Float(other))) |
| % else: |
| self = _stdlib_remainder${cFuncSuffix}(self, other) |
| % end |
| } |
| |
| @inlinable // FIXME(inline-always) |
| @inline(__always) |
| public mutating func formTruncatingRemainder(dividingBy other: ${Self}) { |
| _value = Builtin.frem_FPIEEE${bits}(self._value, other._value) |
| } |
| |
| @_transparent |
| public mutating func formSquareRoot( ) { |
| % if bits == 16: |
| self = Float16(_stdlib_squareRootf(Float(self))) |
| % else: |
| self = _stdlib_squareRoot${cFuncSuffix}(self) |
| % end |
| } |
| |
| @_transparent |
| public mutating func addProduct(_ lhs: ${Self}, _ rhs: ${Self}) { |
| _value = Builtin.int_fma_FPIEEE${bits}(lhs._value, rhs._value, _value) |
| } |
| |
| @_transparent |
| public func isEqual(to other: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_oeq_FPIEEE${bits}(self._value, other._value)) |
| } |
| |
| @_transparent |
| public func isLess(than other: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_olt_FPIEEE${bits}(self._value, other._value)) |
| } |
| |
| @_transparent |
| public func isLessThanOrEqualTo(_ other: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_ole_FPIEEE${bits}(self._value, other._value)) |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isNormal: Bool { |
| @inline(__always) |
| get { |
| return exponentBitPattern > 0 && isFinite |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isFinite: Bool { |
| @inline(__always) |
| get { |
| return exponentBitPattern < ${Self}._infinityExponent |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isZero: Bool { |
| @inline(__always) |
| get { |
| return exponentBitPattern == 0 && significandBitPattern == 0 |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isSubnormal: Bool { |
| @inline(__always) |
| get { |
| return exponentBitPattern == 0 && significandBitPattern != 0 |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isInfinite: Bool { |
| @inline(__always) |
| get { |
| return !isFinite && significandBitPattern == 0 |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isNaN: Bool { |
| @inline(__always) |
| get { |
| return !isFinite && significandBitPattern != 0 |
| } |
| } |
| |
| @inlinable // FIXME(inline-always) |
| public var isSignalingNaN: Bool { |
| @inline(__always) |
| get { |
| return isNaN && (significandBitPattern & ${Self}._quietNaNMask) == 0 |
| } |
| } |
| |
| @inlinable |
| public var binade: ${Self} { |
| %if bits != 80: |
| guard _fastPath(isFinite) else { return .nan } |
| #if !arch(arm) |
| if _slowPath(isSubnormal) { |
| let bitPattern_ = |
| (self * 0x1p${SignificandBitCount}).bitPattern |
| & (-${Self}.infinity).bitPattern |
| return ${Self}(bitPattern: bitPattern_) * 0x1p-${SignificandBitCount} |
| } |
| #endif |
| return ${Self}(bitPattern: bitPattern & (-${Self}.infinity).bitPattern) |
| %else: |
| guard _fastPath(isFinite) else { return .nan } |
| if exponentBitPattern != 0 { |
| return ${Self}(sign: sign, exponentBitPattern: exponentBitPattern, |
| significandBitPattern: 0) |
| } |
| if significandBitPattern == 0 { return self } |
| // For subnormals, we isolate the leading significand bit. |
| let index = significandBitPattern._binaryLogarithm() |
| return ${Self}(sign: sign, exponentBitPattern: 0, |
| significandBitPattern: 1 &<< index) |
| %end |
| } |
| |
| @inlinable |
| public var significandWidth: Int { |
| let trailingZeroBits = significandBitPattern.trailingZeroBitCount |
| if isNormal { |
| guard significandBitPattern != 0 else { return 0 } |
| return ${Self}.significandBitCount &- trailingZeroBits |
| } |
| if isSubnormal { |
| let leadingZeroBits = significandBitPattern.leadingZeroBitCount |
| return ${RawSignificand}.bitWidth &- (trailingZeroBits &+ leadingZeroBits &+ 1) |
| } |
| return -1 |
| } |
| |
| @inlinable // FIXME(inline-always) |
| @inline(__always) |
| public init(floatLiteral value: ${Self}) { |
| self = value |
| } |
| } |
| |
| ${Availability(bits)} |
| extension ${Self}: _ExpressibleByBuiltinIntegerLiteral, ExpressibleByIntegerLiteral { |
| @_transparent |
| public |
| init(_builtinIntegerLiteral value: Builtin.IntLiteral){ |
| self = ${Self}(Builtin.itofp_with_overflow_IntLiteral_FPIEEE${bits}(value)) |
| } |
| |
| @_transparent |
| public init(integerLiteral value: Int64) { |
| self = ${Self}(Builtin.sitofp_Int64_FPIEEE${bits}(value._value)) |
| } |
| } |
| |
| % if bits != 80: |
| #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) |
| % end |
| |
| % builtinFloatLiteralBits = 80 |
| ${Availability(bits)} |
| extension ${Self}: _ExpressibleByBuiltinFloatLiteral { |
| @_transparent |
| public |
| init(_builtinFloatLiteral value: Builtin.FPIEEE${builtinFloatLiteralBits}) { |
| % if bits == builtinFloatLiteralBits: |
| self = ${Self}(value) |
| % elif bits == 16: |
| // workaround missing __truncxfhf |
| self = ${Self}(Float80(value)) |
| % elif bits < builtinFloatLiteralBits: |
| self = ${Self}(Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value)) |
| % else: |
| // FIXME: This is actually losing precision <rdar://problem/14073102>. |
| self = ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value)) |
| % end |
| } |
| } |
| |
| % if bits != 80: |
| #else |
| |
| % builtinFloatLiteralBits = 64 |
| ${Availability(bits)} |
| extension ${Self}: _ExpressibleByBuiltinFloatLiteral { |
| @_transparent |
| public |
| init(_builtinFloatLiteral value: Builtin.FPIEEE${builtinFloatLiteralBits}) { |
| % if bits == builtinFloatLiteralBits: |
| self = ${Self}(value) |
| % elif bits < builtinFloatLiteralBits: |
| // FIXME: This can result in double rounding errors (SR-7124). |
| self = ${Self}(Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value)) |
| % else: |
| // FIXME: This is actually losing precision <rdar://problem/14073102>. |
| self = ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value)) |
| % end |
| } |
| } |
| |
| #endif |
| % end |
| |
| ${Availability(bits)} |
| extension ${Self}: Hashable { |
| @inlinable |
| public func hash(into hasher: inout Hasher) { |
| var v = self |
| if isZero { |
| // To satisfy the axiom that equality implies hash equality, we need to |
| // finesse the hash value of -0.0 to match +0.0. |
| v = 0 |
| } |
| %if bits == 80: |
| hasher.combine(v._representation.signAndExponent) |
| hasher.combine(v.significandBitPattern) |
| %else: |
| hasher.combine(v.bitPattern) |
| %end |
| } |
| |
| @inlinable |
| public func _rawHashValue(seed: Int) -> Int { |
| // To satisfy the axiom that equality implies hash equality, we need to |
| // finesse the hash value of -0.0 to match +0.0. |
| let v = isZero ? 0 : self |
| %if bits == 80: |
| var hasher = Hasher(_seed: seed) |
| hasher.combine(v._representation.signAndExponent) |
| hasher.combine(v.significandBitPattern) |
| return hasher._finalize() |
| %elif bits == 64: |
| return Hasher._hash(seed: seed, v.bitPattern) |
| %elif bits < 64: |
| return Hasher._hash(seed: seed, bytes: UInt64(v.bitPattern), count: ${bits//8}) |
| %else: |
| #error("Unimplemented") |
| %end |
| } |
| } |
| |
| % if bits != 16: |
| extension ${Self}: _HasCustomAnyHashableRepresentation { |
| // Not @inlinable |
| public func _toCustomAnyHashable() -> AnyHashable? { |
| return AnyHashable(_box: _${Self}AnyHashableBox(self)) |
| } |
| } |
| % end |
| |
| ${Availability(bits)} |
| extension ${Self} { |
| @inlinable // FIXME(inline-always) |
| public var magnitude: ${Self} { |
| @inline(__always) |
| get { |
| return ${Self}(Builtin.int_fabs_FPIEEE${bits}(_value)) |
| } |
| } |
| } |
| |
| ${Availability(bits)} |
| extension ${Self} { |
| @_transparent |
| public static prefix func - (x: ${Self}) -> ${Self} { |
| return ${Self}(Builtin.fneg_FPIEEE${bits}(x._value)) |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Explicit conversions between types. |
| //===----------------------------------------------------------------------===// |
| |
| // Construction from other concrete types. |
| ${Availability(bits)} |
| extension ${Self} { |
| |
| // We "shouldn't" need this, but the typechecker barfs on an expression |
| // in the test suite without it. |
| // If replaced with @inline(__always) the init no longer gets |
| // inlined in -Onone and this breaks the abi_v7k test in a subtle way. |
| @_transparent |
| public init(_ v: Int) { |
| _value = Builtin.sitofp_Int${word_bits}_FPIEEE${bits}(v._value) |
| } |
| |
| // Fast-path for conversion when the source is representable as int, |
| // falling back on the generic _convert operation otherwise. |
| @inlinable // FIXME(inline-always) |
| @inline(__always) |
| public init<Source: BinaryInteger>(_ value: Source) { |
| if value.bitWidth <= ${word_bits} { |
| if Source.isSigned { |
| let asInt = Int(truncatingIfNeeded: value) |
| _value = Builtin.sitofp_Int${word_bits}_FPIEEE${bits}(asInt._value) |
| } else { |
| let asUInt = UInt(truncatingIfNeeded: value) |
| _value = Builtin.uitofp_Int${word_bits}_FPIEEE${bits}(asUInt._value) |
| } |
| } else { |
| // TODO: we can do much better than the generic _convert here for Float |
| // and Double by pulling out the high-order 32/64b of the integer, ORing |
| // in a sticky bit, and then using the builtin. |
| self = ${Self}._convert(from: value).value |
| } |
| } |
| |
| // Fast-path for conversion when the source is representable as int, |
| // falling back on the generic _convert operation otherwise. |
| @_alwaysEmitIntoClient @inline(never) |
| public init?<Source: BinaryInteger>(exactly value: Source) { |
| if value.bitWidth <= ${word_bits} { |
| // If the source is small enough to fit in a word, we can use the LLVM |
| // conversion intrinsic, then check if we can round-trip back to the |
| // the original value; if so, the conversion was exact. We need to be |
| // careful, however, to make sure that the first conversion does not |
| // round to a value that is out of the defined range of the second |
| // converion. E.g. Float(Int.max) rounds to Int.max + 1, and converting |
| // that back to Int will trap. For Float, Double, and Float80, this is |
| // only an issue for the upper bound (because the lower bound of [U]Int |
| // is either zero or a power of two, both of which are exactly |
| // representable). For Float16, we also need to check for overflow to |
| // -.infinity. |
| if Source.isSigned { |
| let extended = Int(truncatingIfNeeded: value) |
| _value = Builtin.sitofp_Int${word_bits}_FPIEEE${bits}(extended._value) |
| % if bits == 16: |
| guard self.isFinite && Int(self) == extended else { |
| % else: |
| guard self < 0x1.0p${word_bits-1} && Int(self) == extended else { |
| % end |
| return nil |
| } |
| } else { |
| let extended = UInt(truncatingIfNeeded: value) |
| _value = Builtin.uitofp_Int${word_bits}_FPIEEE${bits}(extended._value) |
| % if bits == 16: |
| guard self.isFinite && UInt(self) == extended else { |
| % else: |
| guard self < 0x1.0p${word_bits} && UInt(self) == extended else { |
| % end |
| return nil |
| } |
| } |
| } else { |
| // TODO: we can do much better than the generic _convert here for Float |
| // and Double by pulling out the high-order 32/64b of the integer, ORing |
| // in a sticky bit, and then using the builtin. |
| let (value_, exact) = Self._convert(from: value) |
| guard exact else { return nil } |
| self = value_ |
| } |
| } |
| |
| % for src_type in all_floating_point_types(): |
| % srcBits = src_type.bits |
| % That = src_type.stdlib_name |
| |
| % if srcBits == 80: |
| #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) |
| % elif srcBits == 16: |
| #if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) |
| % end |
| |
| % if srcBits == bits: |
| /// Creates a new instance initialized to the given value. |
| /// |
| /// The value of `other` is represented exactly by the new instance. A NaN |
| /// passed as `other` results in another NaN, with a signaling NaN value |
| /// converted to quiet NaN. |
| % else: |
| /// Creates a new instance that approximates the given value. |
| /// |
| /// The value of `other` is rounded to a representable value, if necessary. |
| /// A NaN passed as `other` results in another NaN, with a signaling NaN |
| /// value converted to quiet NaN. |
| % end |
| /// |
| /// let x: ${That} = 21.25 |
| /// let y = ${Self}(x) |
| /// // y == 21.25 |
| /// |
| /// let z = ${Self}(${That}.nan) |
| /// // z.isNaN == true |
| /// |
| /// - Parameter other: The value to use for the new instance. |
| ${Availability(srcBits)} |
| % if srcBits == 80 and bits == 16: |
| public init(_ other: ${That}) { |
| // If we use the Builtin for this operation, LLVM emits a call to |
| // __truncxfhf, which would be a compiler-rt intrinsic but doesn't exist. |
| // Workaround this by doing conversion in two stages, with the first stage |
| // rounding to odd to avoid double-rounding. |
| var flt = Float(other) |
| if flt.isFinite { |
| if Float80(flt).magnitude > other.magnitude { |
| flt = Float(bitPattern: flt.bitPattern &- (~flt.bitPattern & 1)) |
| } |
| else if Float80(flt).magnitude < other.magnitude { |
| flt = Float(bitPattern: flt.bitPattern | 1) |
| } |
| } |
| self = Float16(flt) |
| } |
| % else: |
| @inlinable // FIXME(inline-always) |
| @inline(__always) |
| public init(_ other: ${That}) { |
| % if srcBits > bits: |
| _value = Builtin.fptrunc_FPIEEE${srcBits}_FPIEEE${bits}(other._value) |
| % elif srcBits < bits: |
| _value = Builtin.fpext_FPIEEE${srcBits}_FPIEEE${bits}(other._value) |
| % else: |
| _value = other._value |
| % end |
| } |
| % end |
| |
| /// Creates a new instance initialized to the given value, if it can be |
| /// represented without rounding. |
| /// |
| /// If `other` can't be represented as an instance of `${Self}` without |
| /// rounding, the result of this initializer is `nil`. In particular, |
| /// passing NaN as `other` always results in `nil`. |
| /// |
| /// let x: ${That} = 21.25 |
| /// let y = ${Self}(exactly: x) |
| /// // y == Optional.some(21.25) |
| /// |
| /// let z = ${Self}(exactly: ${That}.nan) |
| /// // z == nil |
| /// |
| /// - Parameter other: The value to use for the new instance. |
| ${Availability(srcBits)} |
| @inlinable |
| @inline(__always) |
| public init?(exactly other: ${That}) { |
| self.init(other) |
| // Converting the infinity value is considered value preserving. |
| // In other cases, check that we can round-trip and get the same value. |
| // NaN always fails. |
| if ${That}(self) != other { |
| return nil |
| } |
| } |
| |
| % if srcBits in [16,80]: |
| #endif |
| % end |
| % end |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Standard Operator Table |
| //===----------------------------------------------------------------------===// |
| |
| // TODO: These should not be necessary, since they're already provided by |
| // <T: FloatingPoint>, but in practice they are currently needed to |
| // disambiguate overloads. We should find a way to remove them, either by |
| // tweaking the overload resolution rules, or by removing the other |
| // definitions in the standard lib, or both. |
| |
| ${Availability(bits)} |
| extension ${Self} { |
| @_transparent |
| public static func + (lhs: ${Self}, rhs: ${Self}) -> ${Self} { |
| var lhs = lhs |
| lhs += rhs |
| return lhs |
| } |
| |
| @_transparent |
| public static func - (lhs: ${Self}, rhs: ${Self}) -> ${Self} { |
| var lhs = lhs |
| lhs -= rhs |
| return lhs |
| } |
| |
| @_transparent |
| public static func * (lhs: ${Self}, rhs: ${Self}) -> ${Self} { |
| var lhs = lhs |
| lhs *= rhs |
| return lhs |
| } |
| |
| @_transparent |
| public static func / (lhs: ${Self}, rhs: ${Self}) -> ${Self} { |
| var lhs = lhs |
| lhs /= rhs |
| return lhs |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Strideable Conformance |
| //===----------------------------------------------------------------------===// |
| |
| ${Availability(bits)} |
| extension ${Self}: Strideable { |
| @_transparent |
| public func distance(to other: ${Self}) -> ${Self} { |
| return other - self |
| } |
| |
| @_transparent |
| public func advanced(by amount: ${Self}) -> ${Self} { |
| return self + amount |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // AnyHashable |
| //===----------------------------------------------------------------------===// |
| |
| % if bits != 16: |
| internal struct _${Self}AnyHashableBox: _AnyHashableBox { |
| internal typealias Base = ${Self} |
| internal let _value: Base |
| |
| internal init(_ value: Base) { |
| self._value = value |
| } |
| |
| internal var _canonicalBox: _AnyHashableBox { |
| // Float and Double are bridged with NSNumber, so we have to follow |
| // NSNumber's rules for equality. I.e., we need to make sure equal |
| // numerical values end up in identical boxes after canonicalization, so |
| // that _isEqual will consider them equal and they're hashed the same way. |
| // |
| // Note that these AnyHashable boxes don't currently feed discriminator bits |
| // to the hasher, so we allow repeatable collisions. E.g., -1 will always |
| // collide with UInt64.max. |
| if _value < 0 { |
| if let i = Int64(exactly: _value) { |
| return _IntegerAnyHashableBox(i) |
| } |
| } else { |
| if let i = UInt64(exactly: _value) { |
| return _IntegerAnyHashableBox(i) |
| } |
| } |
| if let d = Double(exactly: _value) { |
| return _DoubleAnyHashableBox(d) |
| } |
| // If a value can't be represented by a Double, keep it in its original |
| // representation so that it won't compare equal to approximations. (So that |
| // we don't round off Float80 values.) |
| return self |
| } |
| |
| internal func _isEqual(to box: _AnyHashableBox) -> Bool? { |
| _internalInvariant(Int64(exactly: _value) == nil, "self isn't canonical") |
| _internalInvariant(UInt64(exactly: _value) == nil, "self isn't canonical") |
| if let box = box as? _${Self}AnyHashableBox { |
| return _value == box._value |
| } |
| return nil |
| } |
| |
| internal var _hashValue: Int { |
| return _rawHashValue(_seed: 0) |
| } |
| |
| internal func _hash(into hasher: inout Hasher) { |
| _internalInvariant(Int64(exactly: _value) == nil, "self isn't canonical") |
| _internalInvariant(UInt64(exactly: _value) == nil, "self isn't canonical") |
| hasher.combine(_value) |
| } |
| |
| internal func _rawHashValue(_seed: Int) -> Int { |
| var hasher = Hasher(_seed: _seed) |
| _hash(into: &hasher) |
| return hasher.finalize() |
| } |
| |
| internal var _base: Any { |
| return _value |
| } |
| |
| internal func _unbox<T: Hashable>() -> T? { |
| return _value as? T |
| } |
| |
| internal func _downCastConditional<T>( |
| into result: UnsafeMutablePointer<T> |
| ) -> Bool { |
| guard let value = _value as? T else { return false } |
| result.initialize(to: value) |
| return true |
| } |
| } |
| % end |
| |
| //===----------------------------------------------------------------------===// |
| // Deprecated operators |
| //===----------------------------------------------------------------------===// |
| |
| % if bits in [16,80]: |
| #else |
| |
| ${SelfDocComment} |
| @frozen |
| % if bits == 16: |
| @available(iOS 14, tvOS 14, watchOS 7, *) |
| @available(macOS, unavailable) |
| @available(macCatalyst, unavailable) |
| % else: |
| @available(*, unavailable, message: "${Self} is not available on target platform.") |
| % end |
| public struct ${Self} { |
| /// Creates a value initialized to zero. |
| @_transparent |
| public init() { |
| fatalError("${Self} is not available") |
| } |
| } |
| |
| #endif |
| % end |
| % end # for bits in all_floating_point_types |
| |
| @_transparent |
| @available(*, unavailable, |
| message: "For floating point numbers use truncatingRemainder instead") |
| public func % <T: BinaryFloatingPoint>(lhs: T, rhs: T) -> T { |
| fatalError("% is not available.") |
| } |
| |
| @_transparent |
| @available(*, unavailable, |
| message: "For floating point numbers use formTruncatingRemainder instead") |
| public func %= <T: BinaryFloatingPoint> (lhs: inout T, rhs: T) { |
| fatalError("%= is not available.") |
| } |
| |
| // ${'Local Variables'}: |
| // eval: (read-only-mode 1) |
| // End: |