| //===--- FloatingPoint.swift.gyb ------------------------------*- swift -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| import SwiftShims |
| |
| %{ |
| # |
| # Utility code for later in this template |
| # |
| |
| # // Bit counts for all floating point types. |
| # // 80-bit floating point types are only permitted on x86 architectures. This |
| # // restriction is handled via #if's in the generated code. |
| allFloatBits = [32, 64, 80] |
| |
| # Bit counts for all int types |
| allIntBits = [8, 16, 32, 64, 'Int'] |
| |
| # Number of bits in the Builtin.Word type |
| word_bits = int(CMAKE_SIZEOF_VOID_P) * 8 |
| |
| # Number of bits in integer literals. |
| builtinIntLiteralBits = 2048 |
| |
| def allInts(): |
| for bits in allIntBits: |
| for signed in False, True: |
| yield bits,signed |
| |
| def baseIntName(name): |
| return 'Int' if name == 'Int' else 'Int' + str(name) |
| |
| def builtinIntName(name): |
| return 'Int' + str(word_bits) if name == 'Int' else 'Int' + str(name) |
| |
| def intName(name, signed): |
| return ('' if signed else 'U') + baseIntName(name) |
| |
| def floatName(bits): |
| if bits == 32: |
| return 'Float' |
| if bits == 64: |
| return 'Double' |
| if bits == 80: |
| return 'Float80' |
| |
| def cFuncSuffix(bits): |
| if bits == 32: |
| return 'f' |
| if bits == 64: |
| return '' |
| if bits == 80: |
| return 'l' |
| |
| def llvmIntrinsicSuffix(bits): |
| if bits == 32: |
| return 'f32' |
| if bits == 64: |
| return 'f64' |
| if bits == 80: |
| return 'f80' |
| |
| def getInfBitPattern(bits): |
| if bits == 32: |
| return '0x7f800000' |
| if bits == 64: |
| return '0x7ff0000000000000' |
| return 'error' |
| |
| def getQuietNaNBitPattern(bits): |
| if bits == 32: |
| return '0x7fc00000' |
| if bits == 64: |
| return '0x7ff8000000000000' |
| return 'error' |
| |
| def getSignalingNanBitPattern(bits): |
| if bits == 32: |
| return '0x7fa00000' |
| if bits == 64: |
| return '0x7ff4000000000000' |
| return 'error' |
| |
| def getMinNormalBitPattern(bits): |
| if bits == 32: |
| return '0x00800000' |
| if bits == 64: |
| return '0x0010000000000000' |
| return 'error' |
| |
| def getExponentBitCount(bits): |
| if bits == 32: |
| return '8' |
| if bits == 64: |
| return '11' |
| return 'error' |
| |
| def getSignificantBitCount(bits): |
| if bits == 32: |
| return '23' |
| if bits == 64: |
| return '52' |
| return 'error' |
| |
| def getInfinityExponent(bits): |
| if bits == 32: |
| return '0xff' |
| if bits == 64: |
| return '0x7ff' |
| return 'error' |
| |
| def mantissaOffset(floatBits): |
| if floatBits == 32: |
| return 23 |
| if floatBits == 64: |
| return 52 |
| if floatBits == 80: |
| return 63 |
| |
| def intFormatFix(bits): |
| if bits == 'Int': |
| return int(CMAKE_SIZEOF_VOID_P) * 8 |
| return bits |
| |
| def positivePrefix(floatBits): |
| return 0b1 << (floatBits - 2) |
| |
| def positiveExponent(floatBits, intBits): |
| return ((intBits - 3) << mantissaOffset(floatBits)) |
| |
| def mantissaBits(floatBits, intBits): |
| offset = mantissaOffset(floatBits) |
| if intBits > offset: |
| return ((1 << intBits) - 4) >> (intBits - offset) |
| else: |
| return ((1 << intBits) - 4) << (offset - intBits) |
| |
| def getMaxFloat(floatBits, intBits): |
| maxFloat = (positivePrefix(floatBits) + |
| positiveExponent(floatBits, intBits) + mantissaBits(floatBits, intBits)) |
| return "0x%0.x" % maxFloat |
| |
| def negativePrefix(floatBits): |
| return 0b11 << (floatBits - 2) |
| |
| def negativeExponent(floatBits, intBits): |
| return ((intBits - 2) << mantissaOffset(floatBits)) |
| |
| def getMinFloat(floatBits, intBits): |
| minFloat = negativePrefix(floatBits) + negativeExponent(floatBits, intBits) |
| return "0x%0.x" % minFloat |
| |
| def incIfSigned(bits, signed): |
| if not(signed): |
| return bits + 1 |
| else: |
| return bits |
| |
| }% |
| |
| % for bits in allFloatBits: |
| % Self = floatName(bits) |
| |
| % if bits == 80: |
| #if arch(i386) || arch(x86_64) |
| % end |
| |
| public struct ${Self} { |
| public // @testable |
| var _value: Builtin.FPIEEE${bits} |
| |
| /// Create an instance initialized to zero. |
| @_transparent public |
| init() { |
| let zero: Int64 = 0 |
| self._value = Builtin.sitofp_Int64_FPIEEE${bits}(zero._value) |
| } |
| |
| @_transparent |
| public // @testable |
| init(_bits v: Builtin.FPIEEE${bits}) { |
| self._value = v |
| } |
| |
| /// Create an instance initialized to `value`. |
| @_transparent public |
| init(_ value: ${Self}) { self = value } |
| } |
| |
| extension ${Self} : CustomStringConvertible { |
| /// A textual representation of `self`. |
| public var description: String { |
| return _float${bits}ToString(self, debug: false) |
| } |
| } |
| |
| extension ${Self} : CustomDebugStringConvertible { |
| /// A textual representation of `self`. |
| public var debugDescription: String { |
| return _float${bits}ToString(self, debug: true) |
| } |
| } |
| |
| % if bits in allIntBits: |
| // Not transparent because the compiler crashes in that case. |
| //@_transparent |
| extension ${Self} : FloatingPointType { |
| public typealias _BitsType = UInt${bits} |
| |
| public static func _fromBitPattern(bits: _BitsType) -> ${Self} { |
| return ${Self}(_bits: Builtin.bitcast_Int${bits}_FPIEEE${bits}(bits._value)) |
| } |
| |
| public func _toBitPattern() -> _BitsType { |
| return _BitsType(Builtin.bitcast_FPIEEE${bits}_Int${bits}(_value)) |
| } |
| |
| @warn_unused_result |
| func __getSignBit() -> Int { |
| return Int(_toBitPattern() >> ${bits - 1}) & 1 |
| } |
| |
| @warn_unused_result |
| func __getBiasedExponent() -> _BitsType { |
| return (_toBitPattern() >> ${getSignificantBitCount(bits)}) & ${getInfinityExponent(bits)} |
| } |
| |
| @warn_unused_result |
| func __getSignificand() -> _BitsType { |
| let mask: _BitsType = (1 << ${getSignificantBitCount(bits)}) - 1 |
| return _toBitPattern() & mask |
| } |
| |
| /// The positive infinity. |
| public static var infinity: ${Self} { |
| return _fromBitPattern(${getInfBitPattern(bits)}) |
| } |
| |
| /// A quiet NaN. |
| public static var NaN: ${Self} { |
| return quietNaN |
| } |
| |
| /// A quiet NaN. |
| public static var quietNaN: ${Self} { |
| return _fromBitPattern(${getQuietNaNBitPattern(bits)}) |
| } |
| |
| /// `true` iff `self` is negative. |
| public var isSignMinus: Bool { |
| return __getSignBit() == 1 |
| } |
| |
| /// `true` iff `self` is normal (not zero, subnormal, infinity, or |
| /// NaN). |
| public var isNormal: Bool { |
| let biasedExponent = __getBiasedExponent() |
| return biasedExponent != ${getInfinityExponent(bits)} && |
| biasedExponent != 0 |
| } |
| |
| /// `true` iff `self` is zero, subnormal, or normal (not infinity |
| /// or NaN). |
| public var isFinite: Bool { |
| return __getBiasedExponent() != ${getInfinityExponent(bits)} |
| } |
| |
| /// `true` iff `self` is +0.0 or -0.0. |
| public var isZero: Bool { |
| // Mask out the sign bit. |
| let mask: _BitsType = (1 << (${bits} - 1)) - 1 |
| return (_toBitPattern() & mask) == 0 |
| } |
| |
| /// `true` iff `self` is subnormal. |
| public var isSubnormal: Bool { |
| if __getBiasedExponent() == 0 { |
| return __getSignificand() != 0 |
| } |
| return false |
| |
| // Alternative implementation: |
| // return !isNan() && |
| // abs(self) < ${Self}._fromBitPattern(${getMinNormalBitPattern(bits)}) |
| // |
| // But because we need to check for !isNan(), and do it safely in case of |
| // SNaN, we need to go down to the bit level, so open-coding the combined |
| // condition is going to be faster. |
| } |
| |
| /// `true` iff `self` is infinity. |
| public var isInfinite: Bool { |
| if __getBiasedExponent() == ${getInfinityExponent(bits)} { |
| return __getSignificand() == 0 |
| } |
| return false |
| |
| // Alternative implementation that is not safe in case of SNaN: |
| // return abs(self) == ${Self}.infinity() |
| } |
| |
| /// `true` iff `self` is NaN. |
| public var isNaN: Bool { |
| if __getBiasedExponent() == ${getInfinityExponent(bits)} { |
| return __getSignificand() != 0 |
| } |
| return false |
| |
| // Alternative implementation that is not safe in case of SNaN: |
| // return self != self |
| } |
| |
| /// `true` iff `self` is a signaling NaN. |
| public var isSignaling: Bool { |
| if __getBiasedExponent() == ${getInfinityExponent(bits)} { |
| // IEEE-754R 2008 6.2.1: A signaling NaN bit string should be encoded |
| // with the first bit of the trailing significand being 0. If the first |
| // bit of the trailing significand field is 0, some other bit of the |
| // trailing significand field must be non-zero to distinguish the NaN |
| // from infinity. |
| let significand = __getSignificand() |
| if significand != 0 { |
| return (significand >> (${getSignificantBitCount(bits)} - 1)) == 0 |
| } |
| } |
| return false |
| } |
| } |
| |
| // Not @_transparent because the function is too complex. |
| extension ${Self} /* : FloatingPointType */ { |
| /// The IEEE 754 "class" of this type. |
| public var floatingPointClass: FloatingPointClassification { |
| get { |
| let biasedExponent = __getBiasedExponent() |
| if biasedExponent == ${getInfinityExponent(bits)} { |
| let significand = __getSignificand() |
| // This is either +/-inf or NaN. |
| if significand == 0 { |
| return isSignMinus ? .NegativeInfinity : .PositiveInfinity |
| } |
| let isQNaN = (significand >> (${getSignificantBitCount(bits)} - 1)) == 1 |
| return isQNaN ? .QuietNaN : .SignalingNaN |
| } |
| |
| // OK, the number is finite. |
| let isMinus = isSignMinus |
| if biasedExponent != 0 { |
| return isMinus ? .NegativeNormal : .PositiveNormal |
| } |
| |
| // Exponent is zero. |
| if __getSignificand() == 0 { |
| return isMinus ? .NegativeZero : .PositiveZero |
| } |
| return isMinus ? .NegativeSubnormal : .PositiveSubnormal |
| } |
| } |
| } |
| % end |
| |
| @_transparent |
| extension ${Self} : _BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible { |
| public |
| init(_builtinIntegerLiteral value: Builtin.Int${builtinIntLiteralBits}){ |
| self = ${Self}(_bits: Builtin.itofp_with_overflow_Int${builtinIntLiteralBits}_FPIEEE${bits}(value)) |
| } |
| |
| /// Create an instance initialized to `value`. |
| public init(integerLiteral value: Int64) { |
| self = ${Self}(_bits: Builtin.sitofp_Int64_FPIEEE${bits}(value._value)) |
| } |
| } |
| |
| #if arch(i386) || arch(x86_64) |
| |
| % builtinFloatLiteralBits = 80 |
| @_transparent |
| extension ${Self} : _BuiltinFloatLiteralConvertible { |
| public |
| init(_builtinFloatLiteral value: Builtin.FPIEEE${builtinFloatLiteralBits}) { |
| % if bits == builtinFloatLiteralBits: |
| self = ${Self}(_bits: value) |
| % elif bits < builtinFloatLiteralBits: |
| self = ${Self}(_bits: 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 |
| } |
| } |
| |
| #else |
| |
| % builtinFloatLiteralBits = 64 |
| @_transparent |
| extension ${Self} : _BuiltinFloatLiteralConvertible { |
| public |
| init(_builtinFloatLiteral value: Builtin.FPIEEE${builtinFloatLiteralBits}) { |
| % if bits == builtinFloatLiteralBits: |
| self = ${Self}(_bits: value) |
| % elif bits < builtinFloatLiteralBits: |
| self = ${Self}(_bits: 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 |
| |
| @_transparent |
| extension ${Self} : FloatLiteralConvertible { |
| /// Create an instance initialized to `value`. |
| public init(floatLiteral value: ${Self}) { |
| self = value |
| } |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func ==(lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_oeq_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func != (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_une_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func <(lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_olt_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func > (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_ogt_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func <= (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_ole_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func >= (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.fcmp_oge_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| extension ${Self} : Comparable, Equatable { |
| } |
| |
| extension ${Self} : Hashable { |
| /// The hash value. |
| /// |
| /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`. |
| /// |
| /// - Note: The hash value is not guaranteed to be stable across |
| /// different invocations of the same program. Do not persist the |
| /// hash value across program runs. |
| public var hashValue: Int { |
| // FIXME: Float80 does not have _toBitPattern. |
| % if bits != 80: |
| // -0.0.hashValue must == 0.0.hashValue. So we need to check for -0.0. |
| % if bits == 32: |
| if self._toBitPattern() == 0x8000_0000 { |
| % elif bits == 64: |
| if self._toBitPattern() == 0x8000_0000_0000_0000 { |
| % else: |
| error unhandled float size ${bits} |
| % end |
| return 0.0.hashValue |
| } else { |
| % end |
| let asBuiltinInt = Builtin.bitcast_FPIEEE${bits}_Int${bits}(_value) |
| % if bits >= 64: |
| return Int(Builtin.truncOrBitCast_Int${bits}_Word(asBuiltinInt)) |
| % elif bits <= 32: |
| return Int(Builtin.sextOrBitCast_Int${bits}_Word(asBuiltinInt)) |
| % else: |
| error unhandled float size ${bits} |
| % end |
| % if bits != 80: |
| } |
| % end |
| } |
| } |
| |
| @_transparent |
| extension ${Self} : AbsoluteValuable { |
| /// Returns the absolute value of `x`. |
| @_transparent |
| @warn_unused_result |
| public static func abs(x: ${Self}) -> ${Self} { |
| return ${Self}(_bits: Builtin.int_fabs_FPIEEE${bits}(x._value)) |
| } |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public prefix func +(x: ${Self}) -> ${Self} { |
| return x |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public prefix func -(x: ${Self}) -> ${Self} { |
| return ${Self}(_bits: Builtin.fneg_FPIEEE${bits}(x._value)) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Explicit conversions between types. |
| //===----------------------------------------------------------------------===// |
| |
| // Construction from integers. |
| @_transparent |
| extension ${Self} { |
| % for (srcBits, srcSigned) in allInts(): |
| % That = intName(srcBits, srcSigned) |
| % ThatBuiltinName = builtinIntName(srcBits) |
| % sign = 's' if srcSigned else 'u' |
| public init(_ v: ${That}) { |
| _value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(v._value) |
| } |
| % end |
| } |
| |
| // Construction from other floating point numbers. |
| @_transparent |
| extension ${Self} { |
| % for srcBits in allFloatBits: |
| % That = floatName(srcBits) |
| % if Self != That: |
| |
| % if srcBits == 80: |
| #if arch(i386) || arch(x86_64) |
| % end |
| |
| /// Construct an instance that approximates `other`. |
| public init(_ other: ${That}) { |
| % if srcBits > bits: |
| _value = Builtin.fptrunc_FPIEEE${srcBits}_FPIEEE${bits}(other._value) |
| % else: |
| _value = Builtin.fpext_FPIEEE${srcBits}_FPIEEE${bits}(other._value) |
| % end |
| } |
| |
| % if srcBits == 80: |
| #endif |
| % end |
| |
| % end |
| % end |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Standard Operator Table |
| //===----------------------------------------------------------------------===// |
| |
| @_transparent |
| @available(*, deprecated, message="it will be removed in Swift 3") |
| public prefix func ++ (inout rhs: ${Self}) -> ${Self} { rhs += 1.0; return rhs } |
| @_transparent |
| @available(*, deprecated, message="it will be removed in Swift 3") |
| public prefix func -- (inout rhs: ${Self}) -> ${Self} { rhs -= 1.0; return rhs } |
| @_transparent |
| @available(*, deprecated, message="it will be removed in Swift 3") |
| public postfix func ++ (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs += 1.0; return tmp } |
| @_transparent |
| @available(*, deprecated, message="it will be removed in Swift 3") |
| public postfix func -- (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs -= 1.0; return tmp } |
| |
| |
| |
| @_transparent |
| extension ${Self} : Strideable { |
| /// Returns a stride `x` such that `self.advancedBy(x)` approximates |
| /// `other`. |
| /// |
| /// - Complexity: O(1). |
| @_transparent public |
| func distanceTo(other: ${Self}) -> ${Self} { |
| return other - self |
| } |
| |
| /// Returns a `Self` `x` such that `self.distanceTo(x)` approximates |
| /// `n`. |
| /// |
| /// - Complexity: O(1). |
| @_transparent public |
| func advancedBy(amount: ${Self}) -> ${Self} { |
| return self + amount |
| } |
| } |
| |
| % for op, name in ('+','fadd'), ('-','fsub'),('*','fmul'), ('/','fdiv'): |
| @_transparent |
| @warn_unused_result |
| public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { |
| return ${Self}(_bits: Builtin.${name}_FPIEEE${bits}(lhs._value, rhs._value)) |
| } |
| % end |
| |
| // Binary Remainder. |
| // The sign of the result matches the sign of the dividend. |
| // 1) This is consistent with '%' in C#, D, Java, and JavaScript |
| // 2) C99 requires this behavior for fmod*() |
| // 3) C++11 requires this behavior for std::fmod*() |
| @warn_unused_result |
| @_silgen_name("_swift_fmod${cFuncSuffix(bits)}") |
| public func % (lhs: ${Self}, rhs: ${Self}) -> ${Self} |
| |
| // See Bool.swift for && and || |
| // In C, 120 is && |
| // In C, 110 is || |
| |
| // In C, 100 is ?: |
| // In C, 90 is =, *=, += etc. |
| |
| % for op in '+', '-', '*', '/', '%': |
| @_transparent |
| public func ${op}= (inout lhs: ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs } |
| % end |
| |
| % if bits == 80: |
| #endif |
| % end |
| |
| % end # for bits in allFloatBits |
| |
| // Construction of integers from floating point numbers. |
| % for (bits, signed) in allInts(): |
| % sign = 's' if signed else 'u' |
| % Self = intName(bits, signed) |
| % BuiltinName = builtinIntName(bits) |
| @_transparent |
| extension ${Self} { |
| % for srcBits in allFloatBits: |
| % That = floatName(srcBits) |
| |
| % if srcBits == 80: |
| #if arch(i386) || arch(x86_64) |
| % end |
| |
| /// Construct an instance that approximates `other`. |
| public init(_ other: ${That}) { |
| % if srcBits != 80: |
| // FIXME: Float80 does not have 'isFinite' property. |
| // <rdar://problem/17958458> Int(Float80.quietNaN) is garbage |
| // <rdar://problem/17959546> Float80.isFinite is missing |
| _precondition( |
| other.isFinite, |
| "floating point value cannot be converted to ${Self} because it is either infinite or NaN") |
| % if signed: |
| // FIXME: Float80 doesn't have a _fromBitPattern |
| // ${That}(roundTowardsZero: ${Self}.min) |
| // > ${getMinFloat(srcBits, incIfSigned(intFormatFix(bits), signed))} |
| _precondition(other >= ${That}._fromBitPattern(${getMinFloat(srcBits, |
| incIfSigned(intFormatFix(bits), signed))}), |
| "floating point value cannot be converted to ${Self} because it is less than ${Self}.min") |
| % else: |
| _precondition(other >= (0.0 as ${That}), |
| "floating point value cannot be converted to ${Self} because it is less than ${Self}.min") |
| % end |
| // ${That}(roundTowardsZero: ${Self}.max) |
| // > ${getMaxFloat(srcBits, incIfSigned(intFormatFix(bits), signed))} |
| _precondition(other <= ${That}._fromBitPattern(${getMaxFloat(srcBits, |
| incIfSigned(intFormatFix(bits), signed))}), |
| "floating point value cannot be converted to ${Self} because it is greater than ${Self}.max") |
| |
| % end |
| self._value = |
| Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(other._value) |
| } |
| |
| % if srcBits == 80: |
| #endif |
| % end |
| |
| % end |
| } |
| |
| % end |
| |
| // ${'Local Variables'}: |
| // eval: (read-only-mode 1) |
| // End: |