// 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()