blob: 1e71b1bb4fac048577e3fd84b8fe3c3e25057779 [file] [log] [blame]
//===--- 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: