Files
swift-mirror/stdlib/core/FloatingPoint.swift.gyb
Jordan Rose cca27d02a0 Tag everything in the standard library with accessibility attributes.
Keep calm: remember that the standard library has many more public exports
than the average target, and that this contains ALL of them at once.
I also deliberately tried to tag nearly every top-level decl, even if that
was just to explicitly mark things @internal, to make sure I didn't miss
something.

This does export more than we might want to, mostly for protocol conformance
reasons, along with our simple-but-limiting typealias rule. I tried to also
mark things private where possible, but it's really going to be up to the
standard library owners to get this right. This is also only validated
against top-level access control; I haven't fully tested against member-level
access control yet, and none of our semantic restrictions are in place.

Along the way I also noticed bits of stdlib cruft; to keep this patch
understandable, I didn't change any of them.

Swift SVN r19145
2014-06-24 21:32:18 +00:00

500 lines
13 KiB
Swift

%# -*- 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)
@public struct ${Self} {
var value: Builtin.FPIEEE${bits}
@transparent @public
init() {
var zero: Int64 = 0
value = Builtin.uitofp_Int64_FPIEEE${bits}(zero.value)
}
@transparent
init(_ v: Builtin.FPIEEE${bits}) {
value = v
}
@transparent @public
init(_ value: ${Self}) { self = value }
}
extension ${Self} : Printable {
@public 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 {
@public typealias _BitsType = UInt${bits}
@public static func _fromBitPattern(bits: _BitsType) -> ${Self} {
return ${Self}(Builtin.bitcast_Int${bits}_FPIEEE${bits}(bits.value))
}
@public 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
}
@public static var infinity: ${Self} {
return _fromBitPattern(${getInfBitPattern(bits)})
}
@public static var NaN: ${Self} {
return quietNaN
}
@public static var quietNaN: ${Self} {
return _fromBitPattern(${getQuietNaNBitPattern(bits)})
}
@public var isSignMinus: Bool {
return __getSignBit() == 1
}
@public var isNormal: Bool {
var biasedExponent = __getBiasedExponent()
return biasedExponent != ${getInfinityExponent(bits)} &&
biasedExponent != 0
}
@public var isFinite: Bool {
return __getBiasedExponent() != ${getInfinityExponent(bits)}
}
@public var isZero: Bool {
// Mask out the sign bit.
var mask: _BitsType = (1 << (${bits} - 1)) - 1
return (_toBitPattern() & mask) == 0
}
@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.
}
@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()
}
@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
}
@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.
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 */ {
@public 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))
}
@public 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 <rdar://problem/14073102>.
return ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
% end
}
}
@transparent
extension ${Self} : FloatLiteralConvertible {
@public static func convertFromFloatLiteral(value: ${Self}) -> ${Self} {
return value
}
}
@transparent @public
func ==(lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.fcmp_oeq_FPIEEE${bits}(lhs.value, rhs.value))
}
@transparent @public
func <(lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.fcmp_olt_FPIEEE${bits}(lhs.value, rhs.value))
}
@transparent
extension ${Self} : Comparable {
}
extension ${Self} : Hashable {
@public 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
@public static func abs(x: ${Self}) -> ${Self} {
return ${Self}(Builtin.int_fabs_FPIEEE${bits}(x.value))
}
}
@prefix @transparent @public
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'
@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:
@public 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 @public
func + (rhs: ${Self}) -> ${Self} { return rhs }
@transparent @prefix @assignment @public
func ++ (inout rhs: ${Self}) -> ${Self} { rhs += 1.0; return rhs }
@transparent @prefix @assignment @public
func -- (inout rhs: ${Self}) -> ${Self} { rhs -= 1.0; return rhs }
@transparent @postfix @assignment @public
func ++ (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs += 1.0; return tmp }
@transparent @postfix @assignment @public
func -- (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs -= 1.0; return tmp }
@transparent
extension ${Self} : RandomAccessIndex {
@transparent @public
func successor() -> ${Self} {
return self + 1.0
}
@transparent @public
func predecessor() -> ${Self} {
return self - 1.0
}
@transparent @public
func distanceTo(other: ${Self}) -> ${Self}.DistanceType {
return Int(other-self)
}
@transparent @public
func advancedBy(amount: ${Self}.DistanceType) -> ${Self} {
return self + ${Self}(amount)
}
}
% for op, name in ('+','fadd'), ('-','fsub'),('*','fmul'), ('/','fdiv'):
@transparent @public
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)}")@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 @assignment @public
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)
@public init(_ v: ${That}) {
_precondition(v >= ${That}(${Self}.min),
"floating point value can not be converted to ${Self} because it is greater than ${Self}.min")
_precondition(v <= ${That}(${Self}.max),
"floating point value can not be converted to ${Self} because it is less than ${Self}.min")
value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(v.value)
}
% end
}
% end
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End: