%# -*- 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): 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' }% % for bits in allFloatBits: % Self = floatName(bits) struct ${Self} { 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 } @transparent init(_ value: ${Self}) { self = value } } extension ${Self} : Printable { var description: String { % if bits == 64: return _doubleToString(self) % else: return _doubleToString(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 var infinity: ${Self} { return _fromBitPattern(${getInfBitPattern(bits)}) } static var NaN: ${Self} { return quietNaN } static var quietNaN: ${Self} { return _fromBitPattern(${getQuietNaNBitPattern(bits)}) } var isSignMinus: Bool { return __getSignBit() == 1 } var isNormal: Bool { var biasedExponent = __getBiasedExponent() return biasedExponent != ${getInfinityExponent(bits)} && biasedExponent != 0 } var isFinite: Bool { return __getBiasedExponent() != ${getInfinityExponent(bits)} } var isZero: Bool { // Mask out the sign bit. var mask: _BitsType = (1 << (${bits} - 1)) - 1 return (_toBitPattern() & mask) == 0 } 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. } 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() } 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 } 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. 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 { var 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 } } @transparent extension ${Self} : AbsoluteValuable { @transparent static func abs(x: ${Self}) -> ${Self} { return ${Self}(Builtin.int_fabs_FPIEEE${bits}(x.value)) } } @prefix @transparent func -(x: ${Self}) -> ${Self} { return ${Self}(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' 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 } @transparent extension ${Self} : RandomAccessIndex { @transparent func succ() -> ${Self} { return self + 1.0 } @transparent func pred() -> ${Self} { return self - 1.0 } @transparent func distanceTo(other: ${Self}) -> ${Self}.DistanceType { return Int(other-self) } @transparent func advancedBy(amount: ${Self}.DistanceType) -> ${Self} { return self + ${Self}(amount) } } % 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}) { assert(v >= ${That}(${Self}.min)) assert(v <= ${That}(${Self}.max)) value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(v.value) } % end } % end // ${'Local Variables'}: // eval: (read-only-mode 1) // End: