@# -*- mode: swift -*- @# Ignore the following admonition; it applies to the resulting .swift file only //// Automatically Generated From FloatingPoint.gyb. Do Not Edit Directly //===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 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 // //===----------------------------------------------------------------------===// @{ # # Utility code for later in this template # if CMAKE_SYSTEM_PROCESSOR in ('i386', 'x86_64'): allFloatBits = [32, 64, 80] else: # Compile only 32-bit and 64-bit floating point on non-x86 architectures allFloatBits = [32, 64] # Bit counts for all int types allIntBits = [8, 16, 32, 64, 'Int'] # Number of bits in integer literals. builtinIntLiteralBits = 2048 # Number of bits in floating point literals. builtinFloatLiteralBits = 64 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 'Word' if name == 'Int' else 'Int' + str(name) def intName(name, signed): return ('' if signed else 'U') + baseIntName(name) def floatName(bits): return 'Float' + str(bits) 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' }@ @ for bits in allFloatBits: @ Self = floatName(bits) struct ${Self} : ReplPrintable { var value: Builtin.FPIEEE${bits} @@transparent init() { var zero: Int64 = 0 value = Builtin.uitofp_Int64_FPIEEE${bits}(zero.value) } @@transparent init(v: Builtin.FPIEEE${bits}) { value = v } func replPrint() { @if bits == 64: print(self) @else: print(Double(self)) @end } } @ if bits in allIntBits: // Not transparent because the compiler crashes in that case. //@@transparent extension ${Self} : FloatingPointNumber { typealias _BitsType = UInt${bits} static func _fromBitPattern(bits: _BitsType) -> ${Self} { return ${Self}(Builtin.bitcast_Int${bits}_FPIEEE${bits}(bits.value)) } func _toBitPattern() -> _BitsType { return _BitsType(Builtin.bitcast_FPIEEE${bits}_Int${bits}(value)) } func __getSignBit() -> Int { return Int(_toBitPattern() >> ${bits - 1}) & 1 } func __getBiasedExponent() -> _BitsType { return (_toBitPattern() >> ${getSignificantBitCount(bits)}) & ${getInfinityExponent(bits)} } func __getSignificand() -> _BitsType { var mask: _BitsType = (1 << ${getSignificantBitCount(bits)}) - 1 return _toBitPattern() & mask } static func inf() -> ${Self} { return _fromBitPattern(${getInfBitPattern(bits)}) } static func NaN() -> ${Self} { return quietNaN() } static func quietNaN() -> ${Self} { return _fromBitPattern(${getQuietNaNBitPattern(bits)}) } func isSignMinus() -> Bool { return __getSignBit() == 1 } func isNormal() -> Bool { var biasedExponent = __getBiasedExponent() return biasedExponent != ${getInfinityExponent(bits)} && biasedExponent != 0 } func isFinite() -> Bool { return __getBiasedExponent() != ${getInfinityExponent(bits)} } func isZero() -> Bool { // Mask out the sign bit. var mask: _BitsType = (1 << (${bits} - 1)) - 1 return (_toBitPattern() & mask) == 0 } func 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. } func 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}.inf() } func isNaN() -> Bool { if __getBiasedExponent() == ${getInfinityExponent(bits)} { return __getSignificand() != 0 } return false // Alternative implementation that is not safe in case of SNaN: // return self != self } func 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. var significand = __getSignificand() if significand != 0 { return (significand >> (${getSignificantBitCount(bits)} - 1)) == 0 } } return false } } // Not @transparent because the function is too complex. extension ${Self} /* : FloatingPointNumber */ { var floatingPointClass: FloatingPointClassification { get { var biasedExponent = __getBiasedExponent() if biasedExponent == ${getInfinityExponent(bits)} { var significand = __getSignificand() // This is either +/-inf or NaN. if significand == 0 { return isSignMinus() ? .NegativeInfinity : .PositiveInfinity } var isQNaN = (significand >> (${getSignificantBitCount(bits)} - 1)) == 1 return isQNaN ? .QuietNaN : .SignalingNaN } // OK, the number is finite. var 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 { static func _convertFromBuiltinIntegerLiteral(value: Builtin.Int${builtinIntLiteralBits}) -> ${Self} { return ${Self}(Builtin.itofp_with_overflow_Int${builtinIntLiteralBits}_FPIEEE${bits}(value)) } static func convertFromIntegerLiteral(value: Int64) -> ${Self} { return ${Self}(Builtin.uitofp_Int64_FPIEEE${bits}(value.value)) } } @@transparent extension ${Self} : BuiltinFloatLiteralConvertible { static func _convertFromBuiltinFloatLiteral(value: Builtin.FPIEEE${builtinFloatLiteralBits}) -> ${Self} { @ if bits == builtinFloatLiteralBits: return ${Self}(value) @ elif bits < builtinFloatLiteralBits: return ${Self}(Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value)) @ else: // FIXME: This is actually losing precision . return ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value)) @ end } } @@transparent extension ${Self} : FloatLiteralConvertible { static func convertFromFloatLiteral(value: ${Self}) -> ${Self} { return value } } @@transparent func ==(lhs: ${Self}, rhs: ${Self}) -> Bool { return Bool(Builtin.fcmp_oeq_FPIEEE${bits}(lhs.value, rhs.value)) } @@transparent func <(lhs: ${Self}, rhs: ${Self}) -> Bool { return Bool(Builtin.fcmp_olt_FPIEEE${bits}(lhs.value, rhs.value)) } @@transparent extension ${Self} : Comparable { } extension ${Self} : Hashable { func hashValue() -> Int { var 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 } } extension ${Self} : SignedNumber { @@transparent static func negate(rhs: ${Self}) -> (${Self}, Bool) { return (${Self}(Builtin.fneg_FPIEEE${bits}(rhs.value)), false) } @@transparent static func abs(rhs: ${Self}) -> (${Self}, Bool) { return (${Self}(Builtin.int_fabs_FPIEEE${bits}(rhs.value)), false) } @@transparent func isNegative() -> Bool { return self < 0 } } //===----------------------------------------------------------------------===// // 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' 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: init(v: ${That}) { @ if srcBits > bits: value = Builtin.fptrunc_FPIEEE${srcBits}_FPIEEE${bits}(v.value) @ else: value = Builtin.fpext_FPIEEE${srcBits}_FPIEEE${bits}(v.value) @ end } @ end @ end } //===----------------------------------------------------------------------===// // Standard Operator Table //===----------------------------------------------------------------------===// // Unary plus @@transparent @@prefix func + (rhs: ${Self}) -> ${Self} { return rhs } @@transparent @@prefix @@assignment func ++ (inout rhs: ${Self}) -> ${Self} { rhs += 1.0; return rhs } @@transparent @@prefix @@assignment func -- (inout rhs: ${Self}) -> ${Self} { rhs -= 1.0; return rhs } @@transparent @@postfix @@assignment func ++ (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs += 1.0; return tmp } @@transparent @@postfix @@assignment func -- (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs -= 1.0; return tmp } @ for op, name in ('+','fadd'), ('-','fsub'),('*','fmul'), ('/','fdiv'): @@transparent func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { return ${Self}(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*() @@asmname="fmod${cFuncSuffix(bits)}" 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 @@assignment func ${op}= (inout lhs: ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs } @ 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) init(v: ${That}) { value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(v.value) } @ end } @ end