blob: 2dd538dd68044b692a47348f7074414e0af4c98b [file] [log] [blame]
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
#if os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
import Glibc
// FIXME: this is a quick hack for non Darwin platforms
// where they doesn't have CoreGraphics module.
#if arch(i386) || arch(arm)
typealias CGFloat = Float
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
typealias CGFloat = Double
#endif
#else
import Darwin.C.tgmath
import CoreGraphics
#endif
import StdlibUnittest
let MathTests = TestSuite("TGMath")
func expectEqualWithAccuracy(_ actualDouble: Double, _ expectedDouble: Double, ulps: Int, _ message: String = "", file: String = #file, line: UInt = #line) {
let epsilonDouble = Double(ulps) * expectedDouble.ulp
let minDouble = expectedDouble - epsilonDouble
let maxDouble = expectedDouble + epsilonDouble
let messageDouble = "Expected: \(expectedDouble) != Actual: \(actualDouble)"
expectTrue((actualDouble.isNaN && expectedDouble.isNaN) || (actualDouble >= minDouble && actualDouble <= maxDouble), messageDouble, file: file, line: line)
}
func expectEqualWithAccuracy(_ actualFloat: Float, _ expectedFloat: Float, ulps: Int, _ message: String = "", file: String = #file, line: UInt = #line) {
let epsilonFloat = Float(ulps) * expectedFloat.ulp
let minFloat = expectedFloat - epsilonFloat
let maxFloat = expectedFloat + epsilonFloat
let messageFloat = "Expected: \(expectedFloat) != Actual: \(actualFloat) (actualFloat.isNaN=\(actualFloat.isNaN) , expectedFloat.isNaN=\(expectedFloat.isNaN), minFloat=\(minFloat), maxFloat = \(maxFloat)"
expectTrue((actualFloat.isNaN && expectedFloat.isNaN) || (actualFloat >= minFloat && actualFloat <= maxFloat), messageFloat, file: file, line: line)
}
func expectEqualWithAccuracy(_ actualDouble: Double, _ actualFloat: Float, _ actualCGFloat: CGFloat, _ expected: Double, ulps: Int, _ message: String = "", file: String = #file, line: UInt = #line) {
expectEqualWithAccuracy(actualDouble, expected, ulps: ulps, message, file: file, line: line)
expectEqualWithAccuracy(actualFloat, Float(expected), ulps: ulps, message, file: file, line: line)
#if arch(i386) || arch(arm)
expectEqualWithAccuracy(Float(actualCGFloat), Float(expected), ulps: ulps, message, file: file, line: line)
#else
expectEqualWithAccuracy(Double(actualCGFloat), Double(expected), ulps: ulps, message, file: file, line: line)
#endif
}
// inputs
let dx = Double(0.1)
let dy = Double(2.2)
let dz = Double(3.3)
let fx = Float(0.1)
let fy = Float(2.2)
let fz = Float(3.3)
let gx = CGFloat(0.1)
let gy = CGFloat(2.2)
let gz = CGFloat(3.3)
let ix = Int(11)
/* Note on error tolerances:
*
* These tests are *not* intended to test the underlying math library; rather,
* they are only testing that the Swift wrappers call the right functions.
* Because of this, there's nothing wrong with relaxing these tolerances
* from 1 ulp to 3 or more, as needed to support platforms with less accurate
* implementations.
*
* The 0-ulp tolerances should be preserved, however, and XFAILED or #if'd
* out for platforms that do not satisfy them. */
MathTests.test("Unary functions") {
expectEqualWithAccuracy(acos(dx), acos(fx), acos(gx), 1.4706289056333368, ulps: 1)
expectEqualWithAccuracy(asin(dx), asin(fx), asin(gx), 0.1001674211615598, ulps: 1)
expectEqualWithAccuracy(atan(dx), atan(fx), atan(gx), 0.09966865249116204, ulps: 1)
expectEqualWithAccuracy(cos(dx), cos(fx), cos(gx), 0.9950041652780257, ulps: 1)
expectEqualWithAccuracy(sin(dx), sin(fx), sin(gx), 0.09983341664682815, ulps: 1)
expectEqualWithAccuracy(tan(dx), tan(fx), tan(gx), 0.10033467208545055, ulps: 1)
expectEqualWithAccuracy(acosh(dx), acosh(fx), acosh(gx), Double.nan, ulps: 1)
expectEqualWithAccuracy(asinh(dx), asinh(fx), asinh(gx), 0.09983407889920758, ulps: 1)
expectEqualWithAccuracy(atanh(dx), atanh(fx), atanh(gx), 0.10033534773107558, ulps: 1)
expectEqualWithAccuracy(cosh(dx), cosh(fx), cosh(gx), 1.0050041680558035, ulps: 1)
expectEqualWithAccuracy(sinh(dx), sinh(fx), sinh(gx), 0.10016675001984403, ulps: 1)
expectEqualWithAccuracy(tanh(dx), tanh(fx), tanh(gx), 0.09966799462495582, ulps: 1)
expectEqualWithAccuracy(exp(dx), exp(fx), exp(gx), 1.1051709180756477, ulps: 1)
expectEqualWithAccuracy(exp2(dx), exp2(fx), exp2(gx), 1.0717734625362931, ulps: 1)
expectEqualWithAccuracy(expm1(dx), expm1(fx), expm1(gx), 0.10517091807564763, ulps: 1)
expectEqualWithAccuracy(log(dx), log(fx), log(gx), -2.3025850929940455, ulps: 1)
expectEqualWithAccuracy(log10(dx), log10(fx), log10(gx), -1.0, ulps: 1)
expectEqualWithAccuracy(log2(dx), log2(fx), log2(gx), -3.321928094887362, ulps: 1)
expectEqualWithAccuracy(log1p(dx), log1p(fx), log1p(gx), 0.09531017980432487, ulps: 1)
expectEqualWithAccuracy(logb(dx), logb(fx), logb(gx), -4.0, ulps: 1)
expectEqualWithAccuracy(fabs(dx), fabs(fx), fabs(gx), 0.1, ulps: 1)
expectEqualWithAccuracy(cbrt(dx), cbrt(fx), cbrt(gx), 0.4641588833612779, ulps: 1)
expectEqualWithAccuracy(sqrt(dx), sqrt(fx), sqrt(gx), 0.31622776601683794, ulps: 1)
expectEqualWithAccuracy(erf(dx), erf(fx), erf(gx), 0.1124629160182849, ulps: 1)
expectEqualWithAccuracy(erfc(dx), erfc(fx), erfc(gx), 0.8875370839817152, ulps: 1)
expectEqualWithAccuracy(tgamma(dx), tgamma(fx), tgamma(gx), 9.51350769866873, ulps: 1)
expectEqualWithAccuracy(ceil(dx), ceil(fx), ceil(gx), 1.0, ulps: 0)
expectEqualWithAccuracy(floor(dx), floor(fx), floor(gx), 0.0, ulps: 0)
expectEqualWithAccuracy(nearbyint(dx), nearbyint(fx), nearbyint(gx), 0.0, ulps: 0)
expectEqualWithAccuracy(rint(dx), rint(fx), rint(gx), 0.0, ulps: 0)
expectEqualWithAccuracy(round(dx), round(fx), round(gx), 0.0, ulps: 0)
expectEqualWithAccuracy(trunc(dx), trunc(fx), trunc(gx), 0.0, ulps: 0)
}
MathTests.test("Binary functions") {
expectEqualWithAccuracy(atan2(dx, dy), atan2(fx, fy), atan2(gx, gy), 0.04542327942157701, ulps: 1)
expectEqualWithAccuracy(hypot(dx, dy), hypot(fx, fy), hypot(gx, gy), 2.202271554554524, ulps: 1)
expectEqualWithAccuracy(pow(dx, dy), pow(fx, fy), pow(gx, gy), 0.00630957344480193, ulps: 1)
expectEqualWithAccuracy(fmod(dx, dy), fmod(fx, fy), fmod(gx, gy), 0.1, ulps: 0)
expectEqualWithAccuracy(remainder(dx, dy), remainder(fx, fy), remainder(gx, gy), 0.1, ulps: 0)
expectEqualWithAccuracy(copysign(dx, dy), copysign(fx, fy), copysign(gx, gy), 0.1, ulps: 0)
expectEqual(nextafter(dx, dy), dx.nextUp)
expectEqual(nextafter(fx, fy), fx.nextUp)
expectEqual(nextafter(gx, gy), gx.nextUp)
expectEqual(nextafter(dx, dx - 1.0), dx.nextDown)
expectEqual(nextafter(fx, fx - 1.0), fx.nextDown)
expectEqual(nextafter(gx, gx - 1.0), gx.nextDown)
expectEqualWithAccuracy(fdim(dx, dy), fdim(fx, fy), fdim(gx, gy), 0.0, ulps: 0)
expectEqualWithAccuracy(fmax(dx, dy), fmax(fx, fy), fmax(gx, gy), 2.2, ulps: 0)
expectEqualWithAccuracy(fmin(dx, dy), fmin(fx, fy), fmin(gx, gy), 0.1, ulps: 0)
}
MathTests.test("Other functions") {
expectEqual(modf(dy), (2.0, 0.20000000000000018))
expectEqual(modf(fy), (2.0, 0.20000005))
#if arch(i386) || arch(arm)
expectEqual(modf(gy), (2.0, 0.20000005))
#else
expectEqual(modf(gy), (2.0, 0.20000000000000018))
#endif
expectEqualWithAccuracy(ldexp(dx, ix), ldexp(fx, ix), ldexp(gx, ix), 204.8, ulps: 0)
expectEqual(frexp(dy), (0.55, 2))
expectEqual(frexp(fy), (0.55, 2))
expectEqual(frexp(gy), (0.55, 2))
expectEqual(ilogb(dy), 1)
expectEqual(ilogb(fy), 1)
expectEqual(ilogb(gy), 1)
expectEqualWithAccuracy(scalbn(dx, ix), scalbn(fx, ix), scalbn(gx, ix), 204.8, ulps: 0)
expectEqual(lgamma(dx).1, 1)
expectEqual(lgamma(fx).1, 1)
expectEqual(lgamma(gx).1, 1)
expectEqualWithAccuracy(lgamma(dx).0, lgamma(fx).0, lgamma(gx).0, 2.2527126517342055, ulps: 1)
// ISO C only requires the last 3 bits to be correct
expectEqual(remquo(dz, dy).1 & 7, 1)
expectEqual(remquo(fz, fy).1 & 7, 1)
expectEqual(remquo(gz, gy).1 & 7, 1)
expectEqualWithAccuracy(remquo(dz, dy).0, remquo(fz, fy).0, remquo(gz, gy).0, 1.0999999999999996, ulps: 1)
expectEqualWithAccuracy(nan("12345"), nan("12345"), nan("12345"), Double.nan, ulps: 0)
expectEqualWithAccuracy(fma(dx, dy, dz), fma(fx, fy, fz), fma(gx, gy, gz), 3.52, ulps: 0)
expectEqualWithAccuracy(j0(dx), 0.99750156206604, ulps: 1)
expectEqualWithAccuracy(j1(dx), 0.049937526036242, ulps: 1)
expectEqualWithAccuracy(jn(ix, dx), 1.2229926610356451e-22, ulps: 1)
expectEqualWithAccuracy(y0(dx), -1.5342386513503667, ulps: 1)
expectEqualWithAccuracy(y1(dx), -6.458951094702027, ulps: 1)
expectEqualWithAccuracy(yn(ix, dx), -2.3662012944869576e+20, ulps: 1)
}
runAllTests()