mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
It is replaced by debugPrint() family of functions, that are called by REPL. There is a regression in printing types that don't conform to Printable, this is tracked by rdar://16898708 Swift SVN r18006
498 lines
13 KiB
Swift
498 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)
|
|
|
|
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 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 <rdar://problem/14073102>.
|
|
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:
|