mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
311 lines
13 KiB
Swift
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()
|