//===--- 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 }% % for bits in allFloatBits: %{ Self = floatName(bits) if 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 arch(i386) || arch(x86_64) % end ${SelfDocComment} 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} : FloatingPoint { 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} /* : FloatingPoint */ { /// 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 . 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 . 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 ++ (rhs: inout ${Self}) -> ${Self} { rhs += 1.0; return rhs } @_transparent @available(*, deprecated, message="it will be removed in Swift 3") public prefix func -- (rhs: inout ${Self}) -> ${Self} { rhs -= 1.0; return rhs } @_transparent @available(*, deprecated, message="it will be removed in Swift 3") public postfix func ++ (lhs: inout ${Self}) -> ${Self} { let tmp = lhs; lhs += 1.0; return tmp } @_transparent @available(*, deprecated, message="it will be removed in Swift 3") public postfix func -- (lhs: inout ${Self}) -> ${Self} { let tmp = lhs; lhs -= 1.0; return tmp } @_transparent extension ${Self} : Strideable { /// Returns a stride `x` such that `self.advanced(by: x)` approximates /// `other`. /// /// - Complexity: O(1). @_transparent public func distance(to other: ${Self}) -> ${Self} { return other - self } /// Returns a `Self` `x` such that `self.distance(to: x)` approximates /// `n`. /// /// - Complexity: O(1). @_transparent public func advanced(by 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}= (lhs: inout ${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) % intBits = intFormatFix(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. // Int(Float80.quietNaN) is garbage // 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, intBits)} _precondition(other >= ${That}._fromBitPattern(${getMinFloat(srcBits, intBits)}), "floating point value cannot be converted to ${Self} because it is less than ${Self}.min") // ${That}(roundTowardsZero: ${Self}.max) // > ${getMaxFloat(srcBits, intBits)} _precondition(other <= ${That}._fromBitPattern(${getMaxFloat(srcBits, intBits)}), "floating point value cannot be converted to ${Self} because it is greater than ${Self}.max") % else: _precondition(other >= (0.0 as ${That}), "floating point value cannot be converted to ${Self} because it is less than ${Self}.min") % # NOTE: Since unsigned ints effectively have one more bit than signed ints % # for storing positive numbers, we use `intBits + 1` when calculating the % # max acceptable float value in the following lines. // ${That}(roundTowardsZero: ${Self}.max) // > ${getMaxFloat(srcBits, intBits + 1)} _precondition(other <= ${That}._fromBitPattern(${getMaxFloat(srcBits, intBits + 1)}), "floating point value cannot be converted to ${Self} because it is greater than ${Self}.max") % end % 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: