blob: f4fa18528b8d293234b5269eddf9d00442ae8786 [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: cp %s %t/main.swift
// RUN: echo "typealias TestFloat = Float" > %t/float_type.swift
// RUN: %target-build-swift %t/main.swift %t/float_type.swift -o %t/float.out
// RUN: %target-codesign %t/float.out
// RUN: %target-run %t/float.out
// RUN: echo "typealias TestFloat = Double" > %t/double_type.swift
// RUN: %target-build-swift %t/main.swift %t/double_type.swift -o %t/double.out
// RUN: %target-codesign %t/double.out
// RUN: %target-run %t/double.out
// REQUIRES: executable_test
import StdlibUnittest
var FloatTests = TestSuite("Float")
//===---
// Helpers
//===---
func noinlinePlusZero() -> TestFloat {
return 0.0
}
func noinlineMinusZero() -> TestFloat {
return -0.0
}
//===---
// Normals
//===---
func checkNormal(_ normal: TestFloat) {
precondition(normal.isNormal)
precondition(normal.isFinite)
precondition(!normal.isZero)
precondition(!normal.isSubnormal)
precondition(!normal.isInfinite)
precondition(!normal.isNaN)
precondition(!normal.isSignalingNaN)
}
FloatTests.test("normal") {
let positiveNormal: TestFloat = 42.0
checkNormal(positiveNormal)
precondition(positiveNormal.sign == .plus)
precondition(positiveNormal.floatingPointClass == .positiveNormal)
let negativeNormal: TestFloat = -42.0
checkNormal(negativeNormal)
precondition(negativeNormal.sign == .minus)
precondition(negativeNormal.floatingPointClass == .negativeNormal)
precondition(positiveNormal == positiveNormal)
precondition(negativeNormal == negativeNormal)
precondition(positiveNormal != negativeNormal)
precondition(negativeNormal != positiveNormal)
precondition(positiveNormal == -negativeNormal)
precondition(negativeNormal == -positiveNormal)
}
//===---
// Zeroes
//===---
func checkZero(_ zero: TestFloat) {
precondition(!zero.isNormal)
precondition(zero.isFinite)
precondition(zero.isZero)
precondition(!zero.isSubnormal)
precondition(!zero.isInfinite)
precondition(!zero.isNaN)
precondition(!zero.isSignalingNaN)
}
FloatTests.test("zero") {
let plusZero = noinlinePlusZero()
checkZero(plusZero)
precondition(plusZero.sign == .plus)
precondition(plusZero.floatingPointClass == .positiveZero)
let minusZero = noinlineMinusZero()
checkZero(minusZero)
precondition(minusZero.sign == .minus)
precondition(minusZero.floatingPointClass == .negativeZero)
precondition(plusZero == 0.0)
precondition(plusZero == plusZero)
precondition(plusZero == minusZero)
precondition(minusZero == -0.0)
precondition(minusZero == plusZero)
precondition(minusZero == minusZero)
}
//===---
// Subnormals
//===---
func checkSubnormal(_ subnormal: TestFloat) {
precondition(!subnormal.isNormal)
precondition(subnormal.isFinite)
precondition(!subnormal.isZero)
precondition(subnormal.isSubnormal)
precondition(!subnormal.isInfinite)
precondition(!subnormal.isNaN)
precondition(!subnormal.isSignalingNaN)
}
func asUInt64(_ a: UInt64) -> UInt64 {
return a
}
func asUInt64(_ a: UInt32) -> UInt64 {
return UInt64(a)
}
#if !arch(arm)
FloatTests.test("subnormal") {
var iterations: Int
switch asUInt64(TestFloat.RawSignificand.max) {
case UInt64.max:
iterations = 1023
case asUInt64(UInt32.max):
iterations = 127
default:
preconditionFailure("unhandled float kind")
}
var positiveSubnormal: TestFloat = 1.0
for i in 0 ..< iterations {
positiveSubnormal /= 2.0 as TestFloat
}
checkSubnormal(positiveSubnormal)
precondition(positiveSubnormal.sign == .plus)
precondition(positiveSubnormal.floatingPointClass == .positiveSubnormal)
precondition(positiveSubnormal != 0.0)
var negativeSubnormal: TestFloat = -1.0
for i in 0 ..< iterations {
negativeSubnormal /= 2.0 as TestFloat
}
checkSubnormal(negativeSubnormal)
precondition(negativeSubnormal.sign == .minus)
precondition(negativeSubnormal.floatingPointClass == .negativeSubnormal)
precondition(negativeSubnormal != -0.0)
}
#endif
//===---
// Infinities
//===---
func checkInf(_ inf: TestFloat) {
precondition(!inf.isNormal)
precondition(!inf.isFinite)
precondition(!inf.isZero)
precondition(!inf.isSubnormal)
precondition(inf.isInfinite)
precondition(!inf.isNaN)
precondition(!inf.isSignalingNaN)
}
FloatTests.test("infinity") {
var stdlibPlusInf = TestFloat.infinity
checkInf(stdlibPlusInf)
precondition(stdlibPlusInf.sign == .plus)
precondition(stdlibPlusInf.floatingPointClass == .positiveInfinity)
var stdlibMinusInf = -TestFloat.infinity
checkInf(stdlibMinusInf)
precondition(stdlibMinusInf.sign == .minus)
precondition(stdlibMinusInf.floatingPointClass == .negativeInfinity)
var computedPlusInf = 1.0 / noinlinePlusZero()
checkInf(computedPlusInf)
precondition(computedPlusInf.sign == .plus)
precondition(computedPlusInf.floatingPointClass == .positiveInfinity)
var computedMinusInf = -1.0 / noinlinePlusZero()
checkInf(computedMinusInf)
precondition(computedMinusInf.sign == .minus)
precondition(computedMinusInf.floatingPointClass == .negativeInfinity)
precondition(stdlibPlusInf == computedPlusInf)
precondition(stdlibMinusInf == computedMinusInf)
precondition(stdlibPlusInf != computedMinusInf)
precondition(stdlibMinusInf != computedPlusInf)
}
//===---
// NaNs
//===---
func checkNaN(_ nan: TestFloat) {
precondition(nan.sign == .plus)
precondition(!nan.isNormal)
precondition(!nan.isFinite)
precondition(!nan.isZero)
precondition(!nan.isSubnormal)
precondition(!nan.isInfinite)
precondition(nan.isNaN)
}
func checkQNaN(_ qnan: TestFloat) {
checkNaN(qnan)
precondition(!qnan.isSignalingNaN)
precondition(qnan.floatingPointClass == .quietNaN)
}
func checkSNaN(_ snan: TestFloat) {
checkNaN(snan)
// sNaN cannot be fully supported on i386.
#if !arch(i386)
precondition(snan.isSignalingNaN)
precondition(snan.floatingPointClass == .signalingNaN)
#endif
}
FloatTests.test("nan") {
var stdlibDefaultNaN = TestFloat.nan
checkQNaN(stdlibDefaultNaN)
var stdlibQNaN = TestFloat.nan
checkQNaN(stdlibQNaN)
var stdlibSNaN = TestFloat.signalingNaN
checkSNaN(stdlibSNaN)
}
runAllTests()