Files
swift-mirror/test/stdlib/Accelerate_Quadrature.swift
Steve (Numerics) Canon d4b90f4837 Temporarily disable all the Accelerate tests.
These are testing for bitwise identical results, but don't guarantee that
the buffers being used always have identical alignment. This will result
in small rounding differences when vector codepaths are used for different
elements of some results.

This is partially an underlying bug in Accelerate (which is outside the
scope of this project to fix), and partly a test bug (which we can address
by adopting approximate comparisons here). In the short term, though, I'm
going to disable these.
2019-05-03 09:12:30 -04:00

311 lines
13 KiB
Swift

// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: rdar50301438
// REQUIRES: objc_interop
// UNSUPPORTED: OS=watchos
import StdlibUnittest
import Accelerate
var AccelerateQuadratureTests = TestSuite("Accelerate_Quadrature")
//===----------------------------------------------------------------------===//
//
// Quadrature Tests
//
//===----------------------------------------------------------------------===//
if #available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) {
func vectorExp(x: UnsafeBufferPointer<Double>,
y: UnsafeMutableBufferPointer<Double>) {
let radius: Double = 12.5
for i in 0 ..< x.count {
y[i] = sqrt(radius * radius - pow(x[i] - radius, 2))
}
}
AccelerateQuadratureTests.test("Quadrature/QNG") {
var diameter: Double = 25
// New API: Scalar
let quadrature = Quadrature(integrator: .nonAdaptive,
absoluteTolerance: 1.0e-8,
relativeTolerance: 1.0e-2)
let result = quadrature.integrate(over: 0.0 ... diameter) { x in
let radius = diameter * 0.5
return sqrt(radius * radius - pow(x - radius, 2))
}
// New API: Vectorized
let vQuadrature = Quadrature(integrator: .nonAdaptive,
absoluteTolerance: 1.0e-8,
relativeTolerance: 1.0e-2)
let vRresult = vQuadrature.integrate(over: 0.0 ... diameter,
integrand: vectorExp)
// Legacy API
var integrateFunction: quadrature_integrate_function = {
return quadrature_integrate_function(
fun: { (arg: UnsafeMutableRawPointer?,
n: Int,
x: UnsafePointer<Double>,
y: UnsafeMutablePointer<Double>
) in
guard let diameter = arg?.load(as: Double.self) else {
return
}
let r = diameter * 0.5
(0 ..< n).forEach { i in
y[i] = sqrt(r * r - pow(x[i] - r, 2))
}
},
fun_arg: &diameter)
}()
var options = quadrature_integrate_options(integrator: QUADRATURE_INTEGRATE_QNG,
abs_tolerance: 1.0e-8,
rel_tolerance: 1.0e-2,
qag_points_per_interval: 0,
max_intervals: 0)
var status = QUADRATURE_SUCCESS
var legacyEstimatedAbsoluteError: Double = 0
let legacyResult = quadrature_integrate(&integrateFunction,
0.0,
diameter,
&options,
&status,
&legacyEstimatedAbsoluteError,
0,
nil)
switch result {
case .success(let integralResult, let estimatedAbsoluteError):
expectEqual(integralResult, legacyResult)
expectEqual(estimatedAbsoluteError, legacyEstimatedAbsoluteError)
switch vRresult {
case .success(let vIntegralResult, let vEstimatedAbsoluteError):
expectEqual(integralResult, vIntegralResult)
expectEqual(estimatedAbsoluteError, vEstimatedAbsoluteError)
case .failure(_):
expectationFailure("Vectorized non-adaptive integration failed.", trace: "",
stackTrace: SourceLocStack())
}
case .failure( _):
expectationFailure("Non-adaptive integration failed.", trace: "",
stackTrace: SourceLocStack())
}
}
AccelerateQuadratureTests.test("Quadrature/QAGS") {
var diameter: Double = 25
// New API
let quadrature = Quadrature(integrator: .adaptiveWithSingularities(maxIntervals: 11),
absoluteTolerance: 1.0e-8,
relativeTolerance: 1.0e-2)
let result = quadrature.integrate(over: 0.0 ... diameter) { x in
let radius = diameter * 0.5
return sqrt(radius * radius - pow(x - radius, 2))
}
// New API: Vectorized
let vQuadrature = Quadrature(integrator: .adaptiveWithSingularities(maxIntervals: 11),
absoluteTolerance: 1.0e-8,
relativeTolerance: 1.0e-2)
let vRresult = vQuadrature.integrate(over: 0.0 ... diameter,
integrand: vectorExp)
// Legacy API
var integrateFunction: quadrature_integrate_function = {
return quadrature_integrate_function(
fun: { (arg: UnsafeMutableRawPointer?,
n: Int,
x: UnsafePointer<Double>,
y: UnsafeMutablePointer<Double>
) in
guard let diameter = arg?.load(as: Double.self) else {
return
}
let r = diameter * 0.5
(0 ..< n).forEach { i in
y[i] = sqrt(r * r - pow(x[i] - r, 2))
}
},
fun_arg: &diameter)
}()
var options = quadrature_integrate_options(integrator: QUADRATURE_INTEGRATE_QAGS,
abs_tolerance: 1.0e-8,
rel_tolerance: 1.0e-2,
qag_points_per_interval: 0,
max_intervals: 11)
var status = QUADRATURE_SUCCESS
var legacyEstimatedAbsoluteError = Double(0)
let legacyResult = quadrature_integrate(&integrateFunction,
0,
diameter,
&options,
&status,
&legacyEstimatedAbsoluteError,
0,
nil)
switch result {
case .success(let integralResult, let estimatedAbsoluteError):
expectEqual(integralResult, legacyResult)
expectEqual(estimatedAbsoluteError, legacyEstimatedAbsoluteError)
switch vRresult {
case .success(let vIntegralResult, let vEstimatedAbsoluteError):
expectEqual(integralResult, vIntegralResult)
expectEqual(estimatedAbsoluteError, vEstimatedAbsoluteError)
case .failure(_):
expectationFailure("Vectorized adaptive with singularities integration failed.", trace: "",
stackTrace: SourceLocStack())
}
case .failure( _):
expectationFailure("Adaptive with singularities integration failed.", trace: "",
stackTrace: SourceLocStack())
}
}
AccelerateQuadratureTests.test("Quadrature/QAG") {
var diameter: Double = 25
// New API
let quadrature = Quadrature(integrator: .adaptive(pointsPerInterval: .sixtyOne,
maxIntervals: 7),
absoluteTolerance: 1.0e-8,
relativeTolerance: 1.0e-2)
let result = quadrature.integrate(over: 0.0 ... diameter) { x in
let radius: Double = diameter * 0.5
return sqrt(radius * radius - pow(x - radius, 2))
}
// New API: Vectorized
let vQuadrature = Quadrature(integrator: .adaptive(pointsPerInterval: .sixtyOne,
maxIntervals: 7),
absoluteTolerance: 1.0e-8,
relativeTolerance: 1.0e-2)
let vRresult = vQuadrature.integrate(over: 0.0 ... diameter,
integrand: vectorExp)
// Legacy API
var integrateFunction: quadrature_integrate_function = {
return quadrature_integrate_function(
fun: { (arg: UnsafeMutableRawPointer?,
n: Int,
x: UnsafePointer<Double>,
y: UnsafeMutablePointer<Double>
) in
guard let diameter = arg?.load(as: Double.self) else {
return
}
let r = diameter * 0.5
(0 ..< n).forEach { i in
y[i] = sqrt(r * r - pow(x[i] - r, 2))
}
},
fun_arg: &diameter)
}()
var options = quadrature_integrate_options(integrator: QUADRATURE_INTEGRATE_QAG,
abs_tolerance: 1.0e-8,
rel_tolerance: 1.0e-2,
qag_points_per_interval: 61,
max_intervals: 7)
var status = QUADRATURE_SUCCESS
var legacyEstimatedAbsoluteError = Double(0)
let legacyResult = quadrature_integrate(&integrateFunction,
0,
diameter,
&options,
&status,
&legacyEstimatedAbsoluteError,
0,
nil)
switch result {
case .success(let integralResult, let estimatedAbsoluteError):
expectEqual(integralResult, legacyResult)
expectEqual(estimatedAbsoluteError, legacyEstimatedAbsoluteError)
switch vRresult {
case .success(let vIntegralResult, let vEstimatedAbsoluteError):
expectEqual(integralResult, vIntegralResult)
expectEqual(estimatedAbsoluteError, vEstimatedAbsoluteError)
case .failure(_):
expectationFailure("Vectorized adaptive integration failed.", trace: "",
stackTrace: SourceLocStack())
}
case .failure( _):
expectationFailure("Adaptive integration failed.", trace: "",
stackTrace: SourceLocStack())
}
}
AccelerateQuadratureTests.test("Quadrature/ToleranceProperties") {
var quadrature = Quadrature(integrator: .qng,
absoluteTolerance: 1,
relativeTolerance: 2)
expectEqual(quadrature.absoluteTolerance, 1)
expectEqual(quadrature.relativeTolerance, 2)
quadrature.absoluteTolerance = 101
quadrature.relativeTolerance = 102
expectEqual(quadrature.absoluteTolerance, 101)
expectEqual(quadrature.relativeTolerance, 102)
}
AccelerateQuadratureTests.test("Quadrature/QAGPointsPerInterval") {
expectEqual(Quadrature.QAGPointsPerInterval.fifteen.points, 15)
expectEqual(Quadrature.QAGPointsPerInterval.twentyOne.points, 21)
expectEqual(Quadrature.QAGPointsPerInterval.thirtyOne.points, 31)
expectEqual(Quadrature.QAGPointsPerInterval.fortyOne.points, 41)
expectEqual(Quadrature.QAGPointsPerInterval.fiftyOne.points, 51)
expectEqual(Quadrature.QAGPointsPerInterval.sixtyOne.points, 61)
}
AccelerateQuadratureTests.test("Quadrature/ErrorDescription") {
let a = Quadrature.Error(quadratureStatus: QUADRATURE_ERROR)
expectEqual(a.errorDescription, "Generic error.")
let b = Quadrature.Error(quadratureStatus: QUADRATURE_INVALID_ARG_ERROR)
expectEqual(b.errorDescription, "Invalid Argument.")
let c = Quadrature.Error(quadratureStatus: QUADRATURE_INTERNAL_ERROR)
expectEqual(c.errorDescription, "This is a bug in the Quadrature code, please file a bug report.")
let d = Quadrature.Error(quadratureStatus: QUADRATURE_INTEGRATE_MAX_EVAL_ERROR)
expectEqual(d.errorDescription, "The requested accuracy limit could not be reached with the allowed number of evals/subdivisions.")
let e = Quadrature.Error(quadratureStatus: QUADRATURE_INTEGRATE_BAD_BEHAVIOUR_ERROR)
expectEqual(e.errorDescription, "Extremely bad integrand behaviour, or excessive roundoff error occurs at some points of the integration interval.")
}
}
runAllTests()