mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1389 lines
54 KiB
Swift
1389 lines
54 KiB
Swift
// RUN: %target-run-simple-swiftgyb(-parse-stdlib)
|
|
// REQUIRES: executable_test
|
|
|
|
// rdar://104232602
|
|
// UNSUPPORTED: CPU=x86_64 && (DARWIN_SIMULATOR=ios || DARWIN_SIMULATOR=watchos || DARWIN_SIMULATOR=tvos)
|
|
|
|
import Swift
|
|
import StdlibUnittest
|
|
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
|
|
struct Float80Bits : Equatable, CustomStringConvertible {
|
|
var signAndExponent: UInt16
|
|
var significand: UInt64
|
|
|
|
init(_ signAndExponent: UInt16, _ significand: UInt64) {
|
|
self.signAndExponent = signAndExponent
|
|
self.significand = significand
|
|
}
|
|
|
|
var description: String {
|
|
return "(\(String(signAndExponent, radix: 16)) \(String(significand, radix: 16)))"
|
|
}
|
|
}
|
|
|
|
func == (lhs: Float80Bits, rhs: Float80Bits) -> Bool {
|
|
return
|
|
lhs.signAndExponent == rhs.signAndExponent &&
|
|
lhs.significand == rhs.significand
|
|
}
|
|
|
|
extension Float80 {
|
|
var bitPattern: Float80Bits {
|
|
let bits = Builtin.bitcast_FPIEEE80_Int80(self._value)
|
|
let sixtyFour = Builtin.zextOrBitCast_Int64_Int80((64 as Int64)._value)
|
|
return Float80Bits(
|
|
UInt16(Builtin.truncOrBitCast_Int80_Int16(
|
|
Builtin.lshr_Int80(bits, sixtyFour))),
|
|
UInt64(Builtin.truncOrBitCast_Int80_Int64(bits)))
|
|
}
|
|
|
|
init(bitPattern: Float80Bits) {
|
|
var result = Builtin.shl_Int80(
|
|
Builtin.zextOrBitCast_Int16_Int80(bitPattern.signAndExponent._value),
|
|
Builtin.zextOrBitCast_Int64_Int80((64 as Int64)._value))
|
|
result = Builtin.or_Int80(
|
|
result, Builtin.zextOrBitCast_Int64_Int80(bitPattern.significand._value))
|
|
self = Float80(Builtin.bitcast_Int80_FPIEEE80(result))
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
% for (FloatTy, BitPatternTy) in [
|
|
% ('Float', 'UInt32'),
|
|
% ('Double', 'UInt64'),
|
|
% ('Float80', 'Float80Bits')
|
|
% ]:
|
|
% if FloatTy == 'Float80':
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
% end
|
|
func expectBitwiseEqual(
|
|
_ expected: ${FloatTy}, _ actual: ${FloatTy},
|
|
_ message: @autoclosure () -> String = "",
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
expectEqual(expected.bitPattern, actual.bitPattern, message(),
|
|
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
|
|
}
|
|
func expectBitwiseEqual(
|
|
bitPattern expected: ${BitPatternTy}, _ actual: ${FloatTy},
|
|
_ message: @autoclosure () -> String = "",
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
expectBitwiseEqual(${FloatTy}(bitPattern: expected), actual, message(),
|
|
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
|
|
}
|
|
% if FloatTy == 'Float80':
|
|
#endif
|
|
% end
|
|
% end
|
|
|
|
var FloatingPoint = TestSuite("FloatingPoint")
|
|
|
|
FloatingPoint.test("BinaryFloatingPoint/genericIntegerConversion") {
|
|
expectTrue(Double._convert(from: 0) == (value: 0, exact: true))
|
|
|
|
expectTrue(Double._convert(from: 1) == (value: 1, exact: true))
|
|
expectTrue(Double._convert(from: -1) == (value: -1, exact: true))
|
|
|
|
expectTrue(Double._convert(from: 42) == (value: 42, exact: true))
|
|
expectTrue(Double._convert(from: -42) == (value: -42, exact: true))
|
|
|
|
expectTrue(Double._convert(from: 100) == (value: 100, exact: true))
|
|
expectTrue(Double._convert(from: -100) == (value: -100, exact: true))
|
|
|
|
expectEqual(Double._convert(from: Int64.max).value, Double(Int64.max))
|
|
expectEqual(Double._convert(from: Int64.min).value, Double(Int64.min))
|
|
|
|
var x = ((Int64.max >> 11) + 1) << 11
|
|
expectEqual(Double._convert(from: x).value, Double(x))
|
|
x = (Int64.max >> 12) << 12 + 1
|
|
expectEqual(Double._convert(from: x).value, Double(x))
|
|
x = Int64.min + 1
|
|
expectEqual(Double._convert(from: x).value, Double(x))
|
|
|
|
expectEqual(Float._convert(from: Int64.max).value, Float(Int64.max))
|
|
expectEqual(Float._convert(from: Int64.min).value, Float(Int64.min))
|
|
|
|
}
|
|
|
|
FloatingPoint.test("BinaryFloatingPoint/genericFloatingPointConversion") {
|
|
func convert<
|
|
T: BinaryFloatingPoint, U: BinaryFloatingPoint
|
|
>(exactly value: T, to: U.Type) -> U? { U(exactly: value) }
|
|
|
|
expectEqual(convert(exactly: 0 as Float, to: Double.self), 0.0)
|
|
expectEqual(convert(exactly: -0.0 as Float, to: Double.self), -0.0)
|
|
expectEqual(
|
|
convert(exactly: -0.0 as Float, to: Double.self)?.sign,
|
|
FloatingPointSign.minus)
|
|
expectEqual(convert(exactly: 0 as Double, to: Float.self), 0.0 as Float)
|
|
expectEqual(convert(exactly: -0.0 as Double, to: Float.self), -0.0 as Float)
|
|
expectEqual(
|
|
convert(exactly: -0.0 as Double, to: Float.self)?.sign,
|
|
FloatingPointSign.minus)
|
|
expectEqual(convert(exactly: 1 as Float, to: Double.self), 1.0)
|
|
expectEqual(convert(exactly: -1 as Float, to: Double.self), -1.0)
|
|
expectEqual(convert(exactly: 1 as Double, to: Float.self), 1.0 as Float)
|
|
expectEqual(convert(exactly: -1 as Double, to: Float.self), -1.0 as Float)
|
|
expectEqual(
|
|
convert(exactly: Float.infinity, to: Double.self), Double.infinity)
|
|
expectEqual(
|
|
convert(exactly: -Float.infinity, to: Double.self), -Double.infinity)
|
|
expectEqual(
|
|
convert(exactly: Double.infinity, to: Float.self), Float.infinity)
|
|
expectEqual(
|
|
convert(exactly: -Double.infinity, to: Float.self), -Float.infinity)
|
|
expectEqual(convert(exactly: Float.nan, to: Double.self), nil)
|
|
expectEqual(convert(exactly: Double.nan, to: Float.self), nil)
|
|
expectEqual(convert(exactly: Float.nan, to: Float.self), nil)
|
|
expectEqual(convert(exactly: Double.nan, to: Double.self), nil)
|
|
expectEqual(
|
|
convert(exactly: Double.leastNonzeroMagnitude, to: Float.self), nil)
|
|
expectEqual(
|
|
convert(exactly: Float.leastNonzeroMagnitude, to: Double.self),
|
|
Double(Float.leastNonzeroMagnitude))
|
|
expectEqual(
|
|
convert(exactly: Double.greatestFiniteMagnitude, to: Float.self), nil)
|
|
expectEqual(
|
|
convert(exactly: Float.greatestFiniteMagnitude, to: Double.self),
|
|
Double(Float.greatestFiniteMagnitude))
|
|
|
|
expectTrue(Double._convert(from: 0 as Float) == (value: 0, exact: true))
|
|
expectTrue(Double._convert(from: -0.0 as Float) == (value: -0.0, exact: true))
|
|
expectTrue(Double._convert(from: 1 as Float) == (value: 1, exact: true))
|
|
expectTrue(Double._convert(from: -1 as Float) == (value: -1, exact: true))
|
|
expectTrue(
|
|
Double._convert(from: Float.infinity) == (value: .infinity, exact: true))
|
|
expectTrue(
|
|
Double._convert(from: -Float.infinity) == (value: -.infinity, exact: true))
|
|
expectTrue(Double._convert(from: Float.nan).value.isNaN)
|
|
expectTrue(Float._convert(from: Double.nan).value.isNaN)
|
|
expectFalse(Double._convert(from: Float.nan).value.isSignalingNaN)
|
|
expectFalse(Float._convert(from: Double.nan).value.isSignalingNaN)
|
|
expectTrue(Double._convert(from: Float.signalingNaN).value.isNaN)
|
|
expectTrue(Float._convert(from: Double.signalingNaN).value.isNaN)
|
|
|
|
let x = Float(bitPattern: Float.nan.bitPattern | 0xf)
|
|
expectEqual(
|
|
Float._convert(from: Double._convert(from: x).value).value.bitPattern,
|
|
x.bitPattern)
|
|
var y = Double(bitPattern: Double.nan.bitPattern | 0xf)
|
|
expectEqual(
|
|
Double._convert(from: Float._convert(from: y).value).value.bitPattern,
|
|
y.bitPattern)
|
|
y = Double(bitPattern: Double.nan.bitPattern | (1 << 32 - 1))
|
|
expectNotEqual(
|
|
Double._convert(from: Float._convert(from: y).value).value.bitPattern,
|
|
y.bitPattern)
|
|
expectTrue(Float._convert(from: y).value.isNaN)
|
|
expectFalse(Float._convert(from: y).exact)
|
|
|
|
expectTrue(
|
|
Float._convert(from: Double.leastNonzeroMagnitude) ==
|
|
(value: 0, exact: false))
|
|
expectTrue(
|
|
Float._convert(from: -Double.leastNonzeroMagnitude) ==
|
|
(value: -0.0, exact: false))
|
|
expectTrue(
|
|
Double._convert(from: Double.leastNonzeroMagnitude) ==
|
|
(value: .leastNonzeroMagnitude, exact: true))
|
|
expectTrue(
|
|
Double._convert(from: -Double.leastNonzeroMagnitude) ==
|
|
(value: -.leastNonzeroMagnitude, exact: true))
|
|
|
|
y = Double._convert(from: Float.leastNonzeroMagnitude).value / 2
|
|
expectTrue(Float._convert(from: y) == (value: 0, exact: false))
|
|
y.negate()
|
|
expectTrue(Float._convert(from: y) == (value: -0.0, exact: false))
|
|
y.negate()
|
|
y = y.nextUp
|
|
expectTrue(
|
|
Float._convert(from: y) == (value: .leastNonzeroMagnitude, exact: false))
|
|
y.negate()
|
|
expectTrue(
|
|
Float._convert(from: y) == (value: -.leastNonzeroMagnitude, exact: false))
|
|
|
|
expectEqual(
|
|
Float._convert(from: Double.leastNormalMagnitude).value,
|
|
Float(Double.leastNormalMagnitude))
|
|
expectEqual(
|
|
Float._convert(from: -Double.leastNormalMagnitude).value,
|
|
Float(-Double.leastNormalMagnitude))
|
|
|
|
expectEqual(Float._convert(from: Double.pi).value, 3.14159265)
|
|
|
|
y = Double._convert(from: Float._convert(from: Double.pi).value).value.nextUp
|
|
expectEqual(Float._convert(from: y).value, 3.14159265)
|
|
y.negate()
|
|
expectEqual(Float._convert(from: y).value, -3.14159265)
|
|
|
|
expectTrue(
|
|
Float._convert(from: Double.greatestFiniteMagnitude) ==
|
|
(value: .infinity, exact: false))
|
|
expectTrue(
|
|
Float._convert(from: -Double.greatestFiniteMagnitude) ==
|
|
(value: -.infinity, exact: false))
|
|
expectTrue(
|
|
Double._convert(from: Double.greatestFiniteMagnitude) ==
|
|
(value: .greatestFiniteMagnitude, exact: true))
|
|
expectTrue(
|
|
Double._convert(from: -Double.greatestFiniteMagnitude) ==
|
|
(value: -.greatestFiniteMagnitude, exact: true))
|
|
|
|
expectEqual(
|
|
Float._convert(
|
|
from: Double._convert(from: Float.greatestFiniteMagnitude).value).value,
|
|
Float.greatestFiniteMagnitude)
|
|
expectEqual(
|
|
Float._convert(
|
|
from: Double._convert(from: Float.leastNonzeroMagnitude).value).value,
|
|
Float.leastNonzeroMagnitude)
|
|
|
|
if #available(macOS 11, iOS 14, watchOS 7, tvOS 14, *) {
|
|
// The behavior tested here was introduced in
|
|
// https://github.com/apple/swift/pull/30194
|
|
|
|
// Let's make sure that the correct value is returned when two representable
|
|
// values are equally close to the original value.
|
|
let bitPattern: UInt64 = 0b01111111111_0000000000000000000000110000000000000000000000000000
|
|
var z = Double(bitPattern: bitPattern)
|
|
expectEqual(Float._convert(from: z).value, Float(z))
|
|
|
|
z = Double(Float.greatestFiniteMagnitude) +
|
|
Double(Float.greatestFiniteMagnitude.ulp / 2)
|
|
expectEqual(Float._convert(from: z).value, Float(z))
|
|
}
|
|
}
|
|
|
|
func positiveOne<T: ExpressibleByIntegerLiteral>() -> T {
|
|
return 1
|
|
}
|
|
func negativeOne<T: ExpressibleByIntegerLiteral>() -> T {
|
|
return -1
|
|
}
|
|
|
|
FloatingPoint.test("Float/ExpressibleByIntegerLiteral") {
|
|
expectEqual(positiveOne(), 1.0 as Float)
|
|
expectEqual(negativeOne(), -1.0 as Float)
|
|
}
|
|
|
|
FloatingPoint.test("Float/ExpressibleByFloatLiteral") {
|
|
let x: Float = -0.0
|
|
expectBitwiseEqual(bitPattern: 0x8000_0000, x)
|
|
}
|
|
|
|
FloatingPoint.test("Float/staticProperties") {
|
|
typealias Ty = Float
|
|
// From the FloatingPoint protocol.
|
|
expectEqual(2, Ty.radix)
|
|
expectBitwiseEqual(bitPattern: 0x7fc0_0000, Ty.nan)
|
|
#if !arch(i386) // i386 does not support a signaling nans.
|
|
expectBitwiseEqual(bitPattern: 0x7fa0_0000, Ty.signalingNaN)
|
|
#endif
|
|
expectBitwiseEqual(bitPattern: 0x7f80_0000, Ty.infinity)
|
|
expectBitwiseEqual(0x1.ffff_fe__p127, Ty.greatestFiniteMagnitude)
|
|
expectBitwiseEqual(0x1.921f_b4__p1, Ty.pi)
|
|
expectBitwiseEqual(0x1.0p-23, Ty.ulpOfOne)
|
|
expectBitwiseEqual(0x1.0p-126, Ty.leastNormalMagnitude)
|
|
#if arch(arm)
|
|
expectBitwiseEqual(0x1.0p-126, Ty.leastNonzeroMagnitude)
|
|
#else
|
|
expectBitwiseEqual(0x1.0p-149, Ty.leastNonzeroMagnitude)
|
|
#endif
|
|
|
|
// From the BinaryFloatingPoint protocol.
|
|
expectEqual(8, Ty.exponentBitCount)
|
|
expectEqual(23, Ty.significandBitCount)
|
|
}
|
|
|
|
// Tests the float and int conversions work correctly. Each case is special.
|
|
|
|
#if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst))
|
|
if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
|
|
FloatingPoint.test("Float16/Int") {
|
|
expectNil(Int(exactly: Float16.infinity))
|
|
expectNil(Int(exactly: -Float16.infinity))
|
|
}
|
|
}
|
|
#endif
|
|
|
|
FloatingPoint.test("Float/UInt8") {
|
|
expectEqual(UInt8.min, UInt8(Float(UInt8.min)))
|
|
expectEqual(UInt8.max, UInt8(Float(UInt8.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Float/Int8") {
|
|
expectEqual(Int8.min, Int8(Float(Int8.min)))
|
|
expectEqual(Int8.max, Int8(Float(Int8.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Float/UInt16") {
|
|
expectEqual(UInt16.min, UInt16(Float(UInt16.min)))
|
|
expectEqual(UInt16.max, UInt16(Float(UInt16.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Float/Int16") {
|
|
expectEqual(Int16.min, Int16(Float(Int16.min)))
|
|
expectEqual(Int16.max, Int16(Float(Int16.max)))
|
|
}
|
|
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
FloatingPoint.test("Float/UInt32") {
|
|
expectEqual(UInt32.min, UInt32(Float(UInt32.min)))
|
|
expectCrashLater()
|
|
expectEqual(UInt32.max, UInt32(Float(UInt32.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Float/Int32") {
|
|
expectEqual(Int32.min, Int32(Float(Int32.min)))
|
|
expectCrashLater()
|
|
expectEqual(Int32.max, Int32(Float(Int32.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Float/UInt64") {
|
|
expectEqual(UInt64.min, UInt64(Float(UInt64.min)))
|
|
expectCrashLater()
|
|
expectEqual(UInt64.max, UInt64(Float(UInt64.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Float/Int64") {
|
|
expectEqual(Int64.min, Int64(Float(Int64.min)))
|
|
expectCrashLater()
|
|
expectEqual(Int64.max, Int64(Float(Int64.max)))
|
|
}
|
|
#endif
|
|
|
|
FloatingPoint.test("Double/ExpressibleByIntegerLiteral") {
|
|
expectEqual(positiveOne(), 1.0 as Double)
|
|
expectEqual(negativeOne(), -1.0 as Double)
|
|
}
|
|
|
|
FloatingPoint.test("Double/ExpressibleByFloatLiteral") {
|
|
let x: Double = -0.0
|
|
expectBitwiseEqual(bitPattern: 0x8000_0000_0000_0000, x)
|
|
}
|
|
|
|
FloatingPoint.test("Double/staticProperties") {
|
|
typealias Ty = Double
|
|
// From the FloatingPoint protocol.
|
|
expectEqual(2, Ty.radix)
|
|
expectBitwiseEqual(bitPattern: 0x7ff8_0000_0000_0000, Ty.nan)
|
|
#if !arch(i386) // i386 does not support a signaling nans.
|
|
expectBitwiseEqual(bitPattern: 0x7ff4_0000_0000_0000, Ty.signalingNaN)
|
|
#endif
|
|
expectBitwiseEqual(bitPattern: 0x7ff0_0000_0000_0000, Ty.infinity)
|
|
expectBitwiseEqual(0x1.ffff_ffff_ffff_f__p1023, Ty.greatestFiniteMagnitude)
|
|
expectBitwiseEqual(0x1.921f_b544_42d1_8__p1, Ty.pi)
|
|
expectBitwiseEqual(0x1.0p-52, Ty.ulpOfOne)
|
|
expectBitwiseEqual(0x1.0p-1022, Ty.leastNormalMagnitude)
|
|
#if arch(arm)
|
|
expectBitwiseEqual(0x1.0p-1022, Ty.leastNonzeroMagnitude)
|
|
#else
|
|
expectBitwiseEqual(0x1.0p-1074, Ty.leastNonzeroMagnitude)
|
|
#endif
|
|
|
|
// From the BinaryFloatingPoint protocol.
|
|
expectEqual(11, Ty.exponentBitCount)
|
|
expectEqual(52, Ty.significandBitCount)
|
|
}
|
|
|
|
FloatingPoint.test("Double/UInt8") {
|
|
expectEqual(UInt8.min, UInt8(Double(UInt8.min)))
|
|
expectEqual(UInt8.max, UInt8(Double(UInt8.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Double/Int8") {
|
|
expectEqual(Int8.min, Int8(Double(Int8.min)))
|
|
expectEqual(Int8.max, Int8(Double(Int8.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Double/UInt16") {
|
|
expectEqual(UInt16.min, UInt16(Double(UInt16.min)))
|
|
expectEqual(UInt16.max, UInt16(Double(UInt16.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Double/Int16") {
|
|
expectEqual(Int16.min, Int16(Double(Int16.min)))
|
|
expectEqual(Int16.max, Int16(Double(Int16.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Double/UInt32") {
|
|
expectEqual(UInt32.min, UInt32(Double(UInt32.min)))
|
|
expectEqual(UInt32.max, UInt32(Double(UInt32.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Double/Int32") {
|
|
expectEqual(Int32.min, Int32(Double(Int32.min)))
|
|
expectEqual(Int32.max, Int32(Double(Int32.max)))
|
|
}
|
|
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
FloatingPoint.test("Double/UInt64") {
|
|
expectEqual(UInt64.min, UInt64(Double(UInt64.min)))
|
|
expectCrashLater()
|
|
expectEqual(UInt64.max, UInt64(Double(UInt64.max)))
|
|
}
|
|
|
|
FloatingPoint.test("Double/Int64") {
|
|
expectEqual(Int64.min, Int64(Double(Int64.min)))
|
|
expectCrashLater()
|
|
expectEqual(Int64.max, Int64(Double(Int64.max)))
|
|
}
|
|
#endif
|
|
|
|
FloatingPoint.test("Float/HashValueZero") {
|
|
let zero: Float = getFloat32(0.0)
|
|
let negativeZero: Float = getFloat32(-0.0)
|
|
expectNotEqual(zero.bitPattern, negativeZero.bitPattern)
|
|
expectEqual(zero.hashValue, negativeZero.hashValue)
|
|
}
|
|
|
|
FloatingPoint.test("Double/HashValueZero") {
|
|
let zero: Double = getFloat64(0.0)
|
|
let negativeZero: Double = getFloat64(-0.0)
|
|
expectNotEqual(zero.bitPattern, negativeZero.bitPattern)
|
|
expectEqual(zero.hashValue, negativeZero.hashValue)
|
|
}
|
|
|
|
#if arch(arm)
|
|
% for FloatSelf in ['Float32', 'Float64']:
|
|
func testSubNormalFlush(_ f: ${FloatSelf}) {
|
|
if !f.isSubnormal {
|
|
return
|
|
}
|
|
switch f.sign {
|
|
case .plus:
|
|
expectBitwiseEqual(.leastNonzeroMagnitude, f.nextUp)
|
|
expectBitwiseEqual(0.0, f.nextDown)
|
|
case .minus:
|
|
expectBitwiseEqual(-0.0, f.nextUp)
|
|
expectBitwiseEqual(-.leastNonzeroMagnitude, f.nextDown)
|
|
}
|
|
}
|
|
% end
|
|
#endif
|
|
|
|
extension FloatingPoint {
|
|
public var isQuietNaN: Bool { return isNaN && !isSignalingNaN }
|
|
}
|
|
|
|
func genericAbs<T: SignedNumeric & Comparable>(_ x: T) -> T {
|
|
return abs(x)
|
|
}
|
|
|
|
|
|
%for Self in ['Float', 'Double', 'Float80']:
|
|
% if Self == 'Float80':
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
% end
|
|
FloatingPoint.test("${Self}.round") {
|
|
for rule in [FloatingPointRoundingRule.toNearestOrAwayFromZero,
|
|
FloatingPointRoundingRule.toNearestOrEven,
|
|
FloatingPointRoundingRule.towardZero,
|
|
FloatingPointRoundingRule.awayFromZero,
|
|
FloatingPointRoundingRule.up,
|
|
FloatingPointRoundingRule.down] {
|
|
|
|
// Zeros, integers and infinities round to themselves:
|
|
for value in [${Self}(), 1, 1/${Self}.ulpOfOne,
|
|
.greatestFiniteMagnitude, .infinity] {
|
|
expectBitwiseEqual(value, value.rounded(rule))
|
|
expectBitwiseEqual(-value, (-value).rounded(rule))
|
|
}
|
|
|
|
// NaNs "round" to NaNs:
|
|
expectTrue(${Self}.nan.rounded(rule).isNaN)
|
|
|
|
// Now let's try some inexact cases; we're going to stay close to zero,
|
|
// and check values close to (half-)integers, because those are the cases
|
|
// that people usually get wrong, and they'll reveal simple blunders like
|
|
// simply implementing the wrong rounding mode.
|
|
for base in stride(from: ${Self}(-3.5), to: 4, by: 0.5) {
|
|
for value in [base.nextDown, base, base.nextUp] {
|
|
let result = value.rounded(rule)
|
|
// Result must be integral. Since we're testing small values, we
|
|
// can simply check that Self(Int(result)) == result. For larger
|
|
// values this wouldn't be a correct test.'
|
|
expectEqual(${Self}(Int(result)), result)
|
|
let residual = value - result
|
|
// For any rounding rule, abs(residual) must be less than 1, however
|
|
// due to rounding the computation can produce 1 exactly.
|
|
expectTrue(abs(residual) <= 1)
|
|
// Remaining validation checks depend on the rounding rule.
|
|
switch rule {
|
|
case .toNearestOrAwayFromZero:
|
|
expectTrue(abs(residual) < 0.5 ||
|
|
abs(residual) == 0.5 && abs(result) > abs(value))
|
|
case .toNearestOrEven:
|
|
expectTrue(abs(residual) < 0.5 ||
|
|
abs(residual) == 0.5 && Int(result) % 2 == 0)
|
|
case .towardZero:
|
|
expectTrue(abs(result) <= abs(value))
|
|
case .awayFromZero:
|
|
expectTrue(abs(result) >= abs(value))
|
|
case .up:
|
|
expectTrue(result >= value)
|
|
case .down:
|
|
expectTrue(result <= value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FloatingPoint.test("${Self}.remainder") {
|
|
// Basic soundness tests only; these are only sufficient to provide reassurance
|
|
// that a known-good remainder function (e.g. from the C stdlib) has been
|
|
// shimmed correctly. They are not sufficient for development of such a
|
|
// function, and should not be employed for that purpose.
|
|
expectTrue(${Self}(0).remainder(dividingBy: 0).isNaN)
|
|
expectTrue(${Self}(1).remainder(dividingBy: 0).isNaN)
|
|
expectTrue(${Self}.infinity.remainder(dividingBy: 0).isNaN)
|
|
expectTrue(${Self}.infinity.remainder(dividingBy: 1).isNaN)
|
|
expectEqual(0, ${Self}(0).remainder(dividingBy: .infinity))
|
|
expectEqual(1, ${Self}(1).remainder(dividingBy: .infinity))
|
|
expectEqual(-1, ${Self}(2).remainder(dividingBy: 3))
|
|
expectEqual(-1, ${Self}(3).remainder(dividingBy: 2))
|
|
expectEqual(1, ${Self}(5).remainder(dividingBy: 2))
|
|
}
|
|
|
|
FloatingPoint.test("${Self}.squareRoot") {
|
|
// Basic soundness tests only; these are only sufficient to provide reassurance
|
|
// that a known-good square root function (e.g. from the C stdlib) has been
|
|
// shimmed correctly. They are not sufficient for development of such a
|
|
// function, and should not be employed for that purpose.
|
|
expectTrue(${Self}(-1).squareRoot().isNaN)
|
|
expectTrue(${Self}.nan.squareRoot().isNaN)
|
|
expectEqual(-0, ${Self}(-0).squareRoot())
|
|
expectEqual(0, ${Self}(0).squareRoot())
|
|
expectEqual(1, ${Self}(1).squareRoot())
|
|
expectEqual(2, ${Self}(4).squareRoot())
|
|
expectEqual(.infinity, ${Self}.infinity.squareRoot())
|
|
}
|
|
|
|
FloatingPoint.test("${Self}.addingProduct") {
|
|
// Fails if fma( ) is incorrectly implemented using separate + and *,
|
|
// and validates that we have the argument order right for the shimmed
|
|
// function.
|
|
let one = ${Self}(1)
|
|
let ulp = ${Self}.ulpOfOne
|
|
expectEqual(ulp*ulp, one.addingProduct(ulp + one, ulp - one))
|
|
}
|
|
|
|
FloatingPoint.test("${Self}/LosslessStringConvertible") {
|
|
let instances = [
|
|
1.0, -1.0,
|
|
0.0, -0.0,
|
|
${Self}.infinity, -${Self}.infinity
|
|
]
|
|
|
|
checkLosslessStringConvertible(instances)
|
|
expectTrue(Float(String(Float.nan))!.isNaN)
|
|
}
|
|
|
|
FloatingPoint.test("${Self}.significandWidth") {
|
|
expectEqual(-1, ${Self}(0).significandWidth)
|
|
expectEqual(-1, ${Self}.infinity.significandWidth)
|
|
expectEqual(-1, ${Self}.nan.significandWidth)
|
|
expectEqual(${Self}.significandBitCount, ${Self}(1).nextUp.significandWidth)
|
|
expectEqual(${Self}.significandBitCount, ${Self}(1).nextDown.significandWidth)
|
|
expectEqual(0, ${Self}.ulpOfOne.significandWidth)
|
|
expectEqual(0, ${Self}(1).significandWidth)
|
|
expectEqual(0, ${Self}(2).significandWidth)
|
|
expectEqual(1, ${Self}(3).significandWidth)
|
|
}
|
|
|
|
FloatingPoint.test("${Self}.absNegativeZero") {
|
|
expectEqual(abs(${Self}(-0.0)), ${Self}(0.0))
|
|
expectEqual(genericAbs(${Self}(-0.0)), ${Self}(0.0))
|
|
}
|
|
|
|
% if Self == 'Float80':
|
|
#endif
|
|
% end
|
|
%end
|
|
|
|
let floatNextUpDownTests: [(Float, Float)] = [
|
|
(.greatestFiniteMagnitude, .infinity),
|
|
(0x1.ffff_fe__p-1, 1.0), (1.0, 0x1.0000_02__p+0),
|
|
(0.0, .leastNonzeroMagnitude),
|
|
(0x1.efff_fe__p-1, 0x1.fp-1), (0x1.fp-1, 0x1.f000_02__p-1),
|
|
]
|
|
|
|
FloatingPoint.test("Float.nextUp, .nextDown")
|
|
.forEach(in: floatNextUpDownTests) {
|
|
(prev, succ) in
|
|
#if arch(arm)
|
|
if prev.isSubnormal || succ.isSubnormal {
|
|
testSubNormalFlush(prev)
|
|
testSubNormalFlush(succ)
|
|
return
|
|
}
|
|
#endif
|
|
expectBitwiseEqual(succ, prev.nextUp)
|
|
expectBitwiseEqual(prev, succ.nextDown)
|
|
expectBitwiseEqual(-succ, (-prev).nextDown)
|
|
expectBitwiseEqual(-prev, (-succ).nextUp)
|
|
}
|
|
|
|
let doubleNextUpDownTests: [(Double, Double)] = [
|
|
(.greatestFiniteMagnitude, .infinity),
|
|
(0x1.ffff_ffff_ffff_fp-1, 1.0), (1.0, 0x1.0000_0000_0000_1p+0),
|
|
(0.0, .leastNonzeroMagnitude),
|
|
(0x1.efff_ffff_ffff_fp-1, 0x1.fp-1), (0x1.fp-1, 0x1.f000_0000_0000_1p-1),
|
|
]
|
|
|
|
FloatingPoint.test("Double.nextUp, .nextDown")
|
|
.forEach(in: doubleNextUpDownTests) {
|
|
(prev, succ) in
|
|
#if arch(arm)
|
|
if prev.isSubnormal || succ.isSubnormal {
|
|
testSubNormalFlush(prev)
|
|
testSubNormalFlush(succ)
|
|
return
|
|
}
|
|
#endif
|
|
expectBitwiseEqual(succ, prev.nextUp)
|
|
expectBitwiseEqual(prev, succ.nextDown)
|
|
expectBitwiseEqual(-succ, (-prev).nextDown)
|
|
expectBitwiseEqual(-prev, (-succ).nextUp)
|
|
}
|
|
|
|
%for Self in ['Float', 'Double']:
|
|
FloatingPoint.test("${Self}.nextUp, .nextDown/nan") {
|
|
let x = ${Self}.nan
|
|
expectTrue(x.nextUp.isNaN)
|
|
expectTrue(x.nextDown.isNaN)
|
|
expectTrue((-x).nextDown.isNaN)
|
|
expectTrue((-x).nextUp.isNaN)
|
|
}
|
|
%end
|
|
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
|
|
FloatingPoint.test("Float80/ExpressibleByIntegerLiteral") {
|
|
expectEqual(positiveOne(), 1.0 as Float80)
|
|
expectEqual(negativeOne(), -1.0 as Float80)
|
|
}
|
|
|
|
FloatingPoint.test("Float80/ExpressibleByFloatLiteral") {
|
|
let x: Float80 = -0.0
|
|
expectBitwiseEqual(bitPattern: Float80Bits(0x8000, 0), x)
|
|
}
|
|
|
|
FloatingPoint.test("Float80/staticProperties") {
|
|
typealias Ty = Double
|
|
// From the FloatingPoint protocol.
|
|
expectEqual(2, Ty.radix)
|
|
expectBitwiseEqual(bitPattern: 0x7ff8_0000_0000_0000, Ty.nan)
|
|
#if !arch(i386) // i386 does not support a signaling nans.
|
|
expectBitwiseEqual(bitPattern: 0x7ff4_0000_0000_0000, Ty.signalingNaN)
|
|
#endif
|
|
expectBitwiseEqual(bitPattern: 0x7ff0_0000_0000_0000, Ty.infinity)
|
|
expectBitwiseEqual(0x1.ffff_ffff_ffff_f__p1023, Ty.greatestFiniteMagnitude)
|
|
expectBitwiseEqual(0x1.921f_b544_42d1_8__p1, Ty.pi)
|
|
expectBitwiseEqual(0x1.0p-52, Ty.ulpOfOne)
|
|
expectBitwiseEqual(0x1.0p-1022, Ty.leastNormalMagnitude)
|
|
expectBitwiseEqual(0x1.0p-1074, Ty.leastNonzeroMagnitude)
|
|
|
|
// From the BinaryFloatingPoint protocol.
|
|
expectEqual(11, Ty.exponentBitCount)
|
|
expectEqual(52, Ty.significandBitCount)
|
|
}
|
|
|
|
FloatingPoint.test("Float80/HashValueZero") {
|
|
let zero: Float80 = getFloat80(0.0)
|
|
let negativeZero: Float80 = getFloat80(-0.0)
|
|
expectNotEqual(zero.bitPattern, negativeZero.bitPattern)
|
|
expectEqual(zero.hashValue, negativeZero.hashValue)
|
|
}
|
|
|
|
let float80NextUpDownTests: [(Float80, Float80)] = [
|
|
(.nan, .nan),
|
|
(.greatestFiniteMagnitude, .infinity),
|
|
(0x1.ffff_ffff_ffff_fffep-1, 1.0), (1.0, 0x1.0000_0000_0000_0002p+0),
|
|
(0.0, .leastNonzeroMagnitude),
|
|
(0x1.efff_ffff_ffff_fffep-1, 0x1.fp-1),
|
|
(0x1.fp-1, 0x1.f000_0000_0000_0002p-1),
|
|
]
|
|
|
|
FloatingPoint.test("Float80.nextUp, .nextDown")
|
|
.forEach(in: float80NextUpDownTests) {
|
|
(prev, succ) in
|
|
|
|
expectBitwiseEqual(succ, prev.nextUp)
|
|
expectBitwiseEqual(prev, succ.nextDown)
|
|
expectBitwiseEqual(-succ, (-prev).nextDown)
|
|
expectBitwiseEqual(-prev, (-succ).nextUp)
|
|
}
|
|
|
|
#endif
|
|
|
|
% for FloatSelf in ['Float32', 'Float64']:
|
|
|
|
func checkFloatingPointComparison_${FloatSelf}(
|
|
_ expected: ExpectedComparisonResult,
|
|
_ lhs: ${FloatSelf}, _ rhs: ${FloatSelf},
|
|
//===--- TRACE boilerplate ----------------------------------------------===//
|
|
// @autoclosure _ message: () -> String = "",
|
|
showFrame: Bool = true,
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
|
|
let message = { "expected: lhs=\(lhs) \(expected) rhs=\(rhs)" }
|
|
expectEqual(expected.isEQ(), lhs == rhs, message(), stackTrace: newTrace)
|
|
expectEqual(expected.isNE(), lhs != rhs, message(), stackTrace: newTrace)
|
|
checkHashable(
|
|
expectedEqual: expected.isEQ(),
|
|
lhs, rhs, message(), stackTrace: newTrace)
|
|
|
|
expectEqual(expected.isLT(), lhs < rhs, message(), stackTrace: newTrace)
|
|
expectEqual(expected.isLE(), lhs <= rhs, message(), stackTrace: newTrace)
|
|
expectEqual(expected.isGE(), lhs >= rhs, message(), stackTrace: newTrace)
|
|
expectEqual(expected.isGT(), lhs > rhs, message(), stackTrace: newTrace)
|
|
checkComparable(expected, lhs, rhs, message(), stackTrace: newTrace)
|
|
}
|
|
|
|
FloatingPoint.test("${FloatSelf}/{Comparable,Hashable,Equatable}") {
|
|
// On arm we flush subnormals to zero so testing subnormals won't work.
|
|
#if arch(arm)
|
|
let interestingValues: [${FloatSelf}] = [
|
|
// Interesting floating point values, sorted.
|
|
-${FloatSelf}.infinity,
|
|
-${FloatSelf}.greatestFiniteMagnitude,
|
|
-1.0,
|
|
-${FloatSelf}.ulpOfOne,
|
|
-${FloatSelf}.leastNormalMagnitude,
|
|
-0.0,
|
|
0.0,
|
|
${FloatSelf}.leastNormalMagnitude,
|
|
${FloatSelf}.ulpOfOne,
|
|
1.0,
|
|
${FloatSelf}.greatestFiniteMagnitude,
|
|
${FloatSelf}.infinity,
|
|
${FloatSelf}.nan,
|
|
${FloatSelf}.signalingNaN,
|
|
]
|
|
#else
|
|
let interestingValues: [${FloatSelf}] = [
|
|
// Interesting floating point values, sorted.
|
|
-${FloatSelf}.infinity,
|
|
-${FloatSelf}.greatestFiniteMagnitude,
|
|
-1.0,
|
|
-${FloatSelf}.ulpOfOne,
|
|
-${FloatSelf}.leastNormalMagnitude,
|
|
-${FloatSelf}.leastNormalMagnitude/2,
|
|
-${FloatSelf}.leastNonzeroMagnitude,
|
|
-0.0,
|
|
0.0,
|
|
${FloatSelf}.leastNonzeroMagnitude,
|
|
${FloatSelf}.leastNormalMagnitude/2,
|
|
${FloatSelf}.leastNormalMagnitude,
|
|
${FloatSelf}.ulpOfOne,
|
|
1.0,
|
|
${FloatSelf}.greatestFiniteMagnitude,
|
|
${FloatSelf}.infinity,
|
|
${FloatSelf}.nan,
|
|
${FloatSelf}.signalingNaN,
|
|
]
|
|
#endif
|
|
|
|
for lhsIdx in interestingValues.indices {
|
|
for rhsIdx in interestingValues.indices {
|
|
let lhs = interestingValues[lhsIdx]
|
|
let rhs = interestingValues[rhsIdx]
|
|
if lhs.isZero && rhs.isZero {
|
|
// Special case: 0.0 and -0.0 compare equal.
|
|
checkFloatingPointComparison_${FloatSelf}(
|
|
ExpectedComparisonResult.eq, lhs, rhs)
|
|
} else if lhs.isNaN || rhs.isNaN {
|
|
// Special case: NaN is unordered wrt other values.
|
|
// - equality comparison with NaN returns false,
|
|
// - NaN is not equal to anything, including NaN.
|
|
expectFalse(lhs == rhs)
|
|
expectTrue(lhs != rhs)
|
|
|
|
expectFalse(lhs < rhs)
|
|
expectFalse(lhs <= rhs)
|
|
expectFalse(lhs >= rhs)
|
|
expectFalse(lhs > rhs)
|
|
} else {
|
|
// The sound case.
|
|
checkFloatingPointComparison_${FloatSelf}(
|
|
lhsIdx < rhsIdx ?
|
|
ExpectedComparisonResult.lt :
|
|
(lhsIdx == rhsIdx ?
|
|
ExpectedComparisonResult.eq :
|
|
ExpectedComparisonResult.gt),
|
|
lhs, rhs)
|
|
}
|
|
|
|
// Check minimum, maximum, minimumMagnitude and maximumMagnitude.
|
|
let min = ${FloatSelf}.minimum(lhs, rhs)
|
|
let max = ${FloatSelf}.maximum(lhs, rhs)
|
|
let minMag = ${FloatSelf}.minimumMagnitude(lhs, rhs)
|
|
let maxMag = ${FloatSelf}.maximumMagnitude(lhs, rhs)
|
|
// If either lhs or rhs is signaling, or if both are quiet NaNs, the
|
|
// result is a quiet NaN.
|
|
if lhs.isSignalingNaN || rhs.isSignalingNaN || (lhs.isNaN && rhs.isNaN) {
|
|
// FIXME: <rdar://problem/48917925>
|
|
// expectTrue(min.isQuietNaN)
|
|
// expectTrue(max.isQuietNaN)
|
|
// expectTrue(minMag.isQuietNaN)
|
|
// expectTrue(maxMag.isQuietNaN)
|
|
}
|
|
// If only one of lhs and rhs is NaN, the result of the min/max
|
|
// operations is always the other value. While contrary to all other
|
|
// IEEE 754 basic operations, this property is critical to ensure
|
|
// that clamping to a valid range behaves as expected.
|
|
else if lhs.isNaN && !rhs.isNaN {
|
|
expectEqual(min.bitPattern, rhs.bitPattern)
|
|
expectEqual(max.bitPattern, rhs.bitPattern)
|
|
expectEqual(minMag.bitPattern, rhs.bitPattern)
|
|
expectEqual(maxMag.bitPattern, rhs.bitPattern)
|
|
}
|
|
else if rhs.isNaN && !lhs.isNaN {
|
|
expectEqual(min.bitPattern, lhs.bitPattern)
|
|
expectEqual(max.bitPattern, lhs.bitPattern)
|
|
expectEqual(minMag.bitPattern, lhs.bitPattern)
|
|
expectEqual(maxMag.bitPattern, lhs.bitPattern)
|
|
}
|
|
// If lhs and rhs are equal, min is lhs and max is rhs. This ensures
|
|
// that the set {lhs, rhs} is the same as the set {min, max} so long
|
|
// as lhs and rhs are non-NaN. This is less important for min/max than
|
|
// it is for minMag and maxMag, but it makes sense to define this way.
|
|
if lhs <= rhs {
|
|
expectEqual(min.bitPattern, lhs.bitPattern)
|
|
expectEqual(max.bitPattern, rhs.bitPattern)
|
|
} else if lhs > rhs {
|
|
expectEqual(max.bitPattern, lhs.bitPattern)
|
|
expectEqual(min.bitPattern, rhs.bitPattern)
|
|
}
|
|
// If lhs and rhs have equal magnitude, minMag is lhs and maxMag is rhs.
|
|
// This ensures that the set {lhs, rhs} is the same as the set
|
|
// {minMag, maxMag} so long as lhs and rhs are non-NaN; this is a
|
|
// restriction of the IEEE 754 rules, but it makes good sense and also
|
|
// makes this primitive more useful for building head-tail arithmetic
|
|
// operations.
|
|
if abs(lhs) <= abs(rhs) {
|
|
expectEqual(minMag.bitPattern, lhs.bitPattern)
|
|
expectEqual(maxMag.bitPattern, rhs.bitPattern)
|
|
} else if abs(lhs) > abs(rhs) {
|
|
expectEqual(maxMag.bitPattern, lhs.bitPattern)
|
|
expectEqual(minMag.bitPattern, rhs.bitPattern)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
% end
|
|
|
|
% for Self in ['Float32', 'Float64', 'Float80']:
|
|
#if ${'!os(Windows) && (arch(i386) || arch(x86_64))' if Self == 'Float80' else 'true'}
|
|
FloatingPoint.test("${Self}/Strideable") {
|
|
// FIXME: the test data could probably be better chosen here, to
|
|
// exercise more cases. Note: NaNs (and possibly Infs) are singular
|
|
// values with respect to Strideable conformance and aren't expected
|
|
// to pass these tests.
|
|
let instances: [${Self}] = [-1.0, 0.0, 0.5, 1.0, 1E20]
|
|
checkStrideable(
|
|
instances, strides: instances,
|
|
distanceOracle: { instances[$1] - instances[$0] },
|
|
advanceOracle: { instances[$0] + instances[$1] })
|
|
}
|
|
#endif
|
|
% end
|
|
|
|
FloatingPoint.test("Float32/Literals") {
|
|
do {
|
|
let f: Float32 = 0.0
|
|
expectEqual(0x0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -0.0
|
|
expectEqual(0x8000_0000, f.bitPattern)
|
|
}
|
|
|
|
do {
|
|
let f: Float32 = 1.0
|
|
expectEqual(0x3f80_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -1.0
|
|
expectEqual(0xbf80_0000, f.bitPattern)
|
|
}
|
|
|
|
do {
|
|
let f: Float32 = 0.999999
|
|
expectEqual(0x3f7fffef, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = 0.9999999
|
|
expectEqual(0x3f7ffffe, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = 0.99999999
|
|
expectEqual(0x3f80_0000, f.bitPattern)
|
|
}
|
|
|
|
// Smallest subnormal.
|
|
do {
|
|
let f: Float32 = 1.4e-45
|
|
expectEqual(0x0000_0001, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -1.4e-45
|
|
expectEqual(0x8000_0001, f.bitPattern)
|
|
}
|
|
|
|
// Rounded to zero.
|
|
do {
|
|
let f: Float32 = 0.7e-45
|
|
expectEqual(0x0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -0.7e-45
|
|
expectEqual(0x8000_0000, f.bitPattern)
|
|
}
|
|
|
|
// Second largest normal.
|
|
do {
|
|
let f: Float32 = 3.4028232e+38
|
|
expectEqual(0x7f7f_fffe, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -3.4028232e+38
|
|
expectEqual(0xff7f_fffe, f.bitPattern)
|
|
}
|
|
|
|
// Largest normal.
|
|
do {
|
|
let f: Float32 = 3.4028234e+38
|
|
expectEqual(0x7f7f_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = 340282340000000000000000000000000000000.0
|
|
expectEqual(0x7f7f_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = 340282340000000000000000000000000000000
|
|
expectEqual(0x7f7f_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -3.4028234e+38
|
|
expectEqual(0xff7f_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -340282340000000000000000000000000000000.0
|
|
expectEqual(0xff7f_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float32 = -340282340000000000000000000000000000000
|
|
expectEqual(0xff7f_ffff, f.bitPattern)
|
|
}
|
|
}
|
|
|
|
FloatingPoint.test("Float64/Literals") {
|
|
do {
|
|
let f: Float64 = 0.0
|
|
expectEqual(0x0000_0000_0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -0.0
|
|
expectEqual(0x8000_0000_0000_0000, f.bitPattern)
|
|
}
|
|
|
|
do {
|
|
let f: Float64 = 1.0
|
|
expectEqual(0x3ff0_0000_0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -1.0
|
|
expectEqual(0xbff0_0000_0000_0000, f.bitPattern)
|
|
}
|
|
|
|
do {
|
|
let f: Float64 = 0.999999999999999
|
|
expectEqual(0x3fef_ffff_ffff_fff7, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = 0.9999999999999999
|
|
expectEqual(0x3fef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = 0.99999999999999999
|
|
expectEqual(0x3ff0_0000_0000_0000, f.bitPattern)
|
|
}
|
|
|
|
// Smallest subnormal.
|
|
do {
|
|
let f: Float64 = 4.0e-324
|
|
expectEqual(0x0000_0000_0000_0001, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -4.0e-324
|
|
expectEqual(0x8000_0000_0000_0001, f.bitPattern)
|
|
}
|
|
|
|
// Rounded to zero.
|
|
do {
|
|
let f: Float64 = 2.4e-324
|
|
expectEqual(0x0000_0000_0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -2.4e-324
|
|
expectEqual(0x8000_0000_0000_0000, f.bitPattern)
|
|
}
|
|
|
|
// Second largest normal.
|
|
do {
|
|
let f: Float64 = 1.79769313486231551e+308
|
|
expectEqual(0x7fef_ffff_ffff_fffe, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -1.79769313486231551e+308
|
|
expectEqual(0xffef_ffff_ffff_fffe, f.bitPattern)
|
|
}
|
|
|
|
// Largest normal.
|
|
do {
|
|
let f: Float64 = 1.7976931348623157e+308
|
|
expectEqual(0x7fef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0
|
|
expectEqual(0x7fef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
expectEqual(0x7fef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -1.7976931348623157e+308
|
|
expectEqual(0xffef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0
|
|
expectEqual(0xffef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float64 = -179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
expectEqual(0xffef_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
}
|
|
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
|
|
FloatingPoint.test("Float80/Literals") {
|
|
do {
|
|
let f: Float80 = 0.0
|
|
expectEqual(Float80Bits(0x0000, 0x0000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = -0.0
|
|
expectEqual(Float80Bits(0x8000, 0x0000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
|
|
do {
|
|
let f: Float80 = 1.0
|
|
expectEqual(Float80Bits(0x3fff, 0x8000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = -1.0
|
|
expectEqual(Float80Bits(0xbfff, 0x8000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
|
|
do {
|
|
let f: Float80 = 0.999999999999999999
|
|
expectEqual(Float80Bits(0x3ffe, 0xffff_ffff_ffff_ffee), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = 0.9999999999999999999
|
|
expectEqual(Float80Bits(0x3ffe, 0xffff_ffff_ffff_fffe), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = 0.99999999999999999995
|
|
expectEqual(Float80Bits(0x3ffe, 0xffff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = 0.99999999999999999999
|
|
expectEqual(Float80Bits(0x3fff, 0x8000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
|
|
// Smallest subnormal.
|
|
do {
|
|
// 3.645199531882474602528e-4951
|
|
let f: Float80 = 3.6e-4951
|
|
expectEqual(Float80Bits(0x0000, 0x0000_0000_0000_0001), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = -3.6e-4951
|
|
expectEqual(Float80Bits(0x8000, 0x0000_0000_0000_0001), f.bitPattern)
|
|
}
|
|
|
|
// Rounded to zero.
|
|
do {
|
|
let f: Float80 = 1.8e-4951
|
|
expectEqual(Float80Bits(0x0000, 0x0000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = -1.8e-4951
|
|
expectEqual(Float80Bits(0x8000, 0x0000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
|
|
// Largest normal.
|
|
do {
|
|
let f: Float80 = 1.189731495357231765e+4932
|
|
expectEqual(Float80Bits(0x7ffe, 0xffff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = 1189731495357231765000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0
|
|
expectEqual(Float80Bits(0x7ffe, 0xffff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = -1.189731495357231765e+4932
|
|
expectEqual(Float80Bits(0xfffe, 0xffff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
do {
|
|
let f: Float80 = -1189731495357231765000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0
|
|
expectEqual(Float80Bits(0xfffe, 0xffff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
FloatingPoint.test("Float32/quietNaN") {
|
|
do {
|
|
let f: Float32 = .nan
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
expectEqual(0x7fc0_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
// Empty payload
|
|
let f: Float32 = Float32(bitPattern: 0x7fc0_0000)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Full payload
|
|
let f: Float32 = Float32(bitPattern: 0x7fff_ffff)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Highest payload `init(nan:signaling:)` can handle
|
|
let f: Float32 = Float32(nan: 0x1f_ffff, signaling: false)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
expectEqual(0x7fdf_ffff, f.bitPattern)
|
|
}
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
do {
|
|
// Payload overflow
|
|
expectCrashLater()
|
|
_ = Float32(nan: 0x20_0000, signaling: false)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
FloatingPoint.test("Float64/quietNaN") {
|
|
do {
|
|
let f: Float64 = .nan
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
expectEqual(0x7ff8_0000_0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
// Empty payload
|
|
let f: Float64 = Float64(bitPattern: 0x7ff8_0000_0000_0000)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Full payload
|
|
let f: Float64 = Float64(bitPattern: 0x7fff_ffff_ffff_ffff)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Highest payload `init(nan:signaling:)` can handle
|
|
let f: Float64 = Float64(nan: 0x3_ffff_ffff_ffff, signaling: false)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
expectEqual(0x7ffb_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
do {
|
|
// Payload overflow
|
|
expectCrashLater()
|
|
_ = Float64(nan: 0x4_0000_0000_0000, signaling: false)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
|
|
FloatingPoint.test("Float80/quietNaN") {
|
|
do {
|
|
let f: Float80 = .nan
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
expectEqual(Float80Bits(0x7fff, 0xc000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
do {
|
|
// Empty payload
|
|
let f: Float80 = Float80(bitPattern: Float80Bits(0x7fff, 0xc000_0000_0000_0000))
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Full payload
|
|
let f: Float80 = Float80(bitPattern: Float80Bits(0x7fff, 0xffff_ffff_ffff_ffff))
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Highest payload `init(nan:signaling:)` can handle
|
|
let f: Float80 = Float80(nan: 0x1fff_ffff_ffff_ffff, signaling: false)
|
|
expectTrue(f.isNaN && !f.isSignalingNaN)
|
|
expectEqual(Float80Bits(0x7fff, 0xdfff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
do {
|
|
// Payload overflow
|
|
expectCrashLater()
|
|
_ = Float80(nan: 0x2000_0000_0000_0000, signaling: false)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !arch(i386)
|
|
|
|
FloatingPoint.test("Float32/signalingNaN") {
|
|
do {
|
|
let f: Float32 = .signalingNaN
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
expectEqual(0x7fa0_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
// Empty payload
|
|
let f: Float32 = Float32(bitPattern: 0x7fa0_0000)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Full payload
|
|
let f: Float32 = Float32(bitPattern: 0x7fbf_ffff)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Highest payload `init(nan:signaling:)` can handle
|
|
let f: Float32 = Float32(nan: 0x1f_ffff, signaling: true)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
expectEqual(0x7fbf_ffff, f.bitPattern)
|
|
}
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
do {
|
|
// payload overflow
|
|
expectCrashLater()
|
|
_ = Float32(nan: 0x20_0000, signaling: true)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
FloatingPoint.test("Float64/signalingNaN") {
|
|
do {
|
|
let f: Float64 = .signalingNaN
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
expectEqual(0x7ff4_0000_0000_0000, f.bitPattern)
|
|
}
|
|
do {
|
|
// Empty payload
|
|
let f: Float64 = Float64(bitPattern: 0x7ff4_0000_0000_0000)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Full payload
|
|
let f: Float64 = Float64(bitPattern: 0x7ff7_ffff_ffff_ffff)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Highest payload `init(nan:signaling:)` can handle
|
|
let f: Float64 = Float64(nan: 0x3_ffff_ffff_ffff, signaling: true)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
expectEqual(0x7ff7_ffff_ffff_ffff, f.bitPattern)
|
|
}
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
do {
|
|
// payload overflow
|
|
expectCrashLater()
|
|
_ = Float64(nan: 0x4_0000_0000_0000, signaling: true)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !os(Windows) && arch(x86_64)
|
|
|
|
FloatingPoint.test("Float80/signalingNaN") {
|
|
do {
|
|
let f: Float80 = .signalingNaN
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
expectEqual(Float80Bits(0x7fff, 0xa000_0000_0000_0000), f.bitPattern)
|
|
}
|
|
do {
|
|
// Empty payload
|
|
let f: Float80 = Float80(bitPattern: Float80Bits(0x7fff, 0xa000_0000_0000_0000))
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Full payload
|
|
let f: Float80 = Float80(bitPattern: Float80Bits(0x7fff, 0xbfff_ffff_ffff_ffff))
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
}
|
|
do {
|
|
// Highest payload `init(nan:signaling:)` can handle
|
|
let f: Float80 = Float80(nan: 0x1fff_ffff_ffff_ffff, signaling: true)
|
|
expectTrue(f.isNaN && f.isSignalingNaN)
|
|
expectEqual(Float80Bits(0x7fff, 0xbfff_ffff_ffff_ffff), f.bitPattern)
|
|
}
|
|
#if !os(WASI)
|
|
// Trap tests aren't available on WASI.
|
|
do {
|
|
// payload overflow
|
|
expectCrashLater()
|
|
_ = Float80(nan: 0x2000_0000_0000_0000, signaling: true)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
var FloatingPointClassification = TestSuite("FloatingPointClassification")
|
|
|
|
FloatingPointClassification.test("FloatingPointClassification/Hashable") {
|
|
let values: [FloatingPointClassification] = [
|
|
.signalingNaN,
|
|
.quietNaN,
|
|
.negativeInfinity,
|
|
.negativeNormal,
|
|
.negativeSubnormal,
|
|
.negativeZero,
|
|
.positiveZero,
|
|
.positiveSubnormal,
|
|
.positiveNormal,
|
|
.positiveInfinity
|
|
]
|
|
// Values should be equal iff indices equal
|
|
checkHashable(values, equalityOracle: { $0 == $1 })
|
|
}
|
|
|
|
runAllTests()
|