mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/accelerate-vDSP-linearInterpolation' into Accelerate_Swift-vDSP-Overlays
This commit is contained in:
@@ -7,6 +7,7 @@ add_swift_target_library(swiftAccelerate ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES
|
||||
ContiguousCollection.swift
|
||||
vForce_Operations.swift
|
||||
vDSP_SlidingWindow.swift
|
||||
vDSP_Interpolation.swift
|
||||
|
||||
"${SWIFT_SOURCE_DIR}/stdlib/linker-support/magic-symbols-for-install-name.c"
|
||||
|
||||
|
||||
312
stdlib/public/Darwin/Accelerate/vDSP_Interpolation.swift
Normal file
312
stdlib/public/Darwin/Accelerate/vDSP_Interpolation.swift
Normal file
@@ -0,0 +1,312 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Accelerate
|
||||
|
||||
extension vDSP {
|
||||
|
||||
/// Vector linear interpolation between vectors; single-precision.
|
||||
///
|
||||
/// - Parameter vectorA: The `A` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter vectorB: The `B` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter interpolationConstant: The `C` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Returns: The `D` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U>(_ vectorA: T,
|
||||
_ vectorB: U,
|
||||
using interpolationConstant: Float) -> [Float]
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
T.Element == Float, U.Element == Float{
|
||||
|
||||
let result = Array<Float>(unsafeUninitializedCapacity: vectorA.count) {
|
||||
buffer, initializedCount in
|
||||
|
||||
linearInterpolate(vectorA,
|
||||
vectorB,
|
||||
using: interpolationConstant,
|
||||
result: &buffer)
|
||||
|
||||
initializedCount = vectorA.count
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between vectors; single-precision.
|
||||
///
|
||||
/// - Parameter vectorA: The `A` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter vectorB: The `B` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter interpolationConstant: The `C` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter result: The `D` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U, V>(_ vectorA: T,
|
||||
_ vectorB: U,
|
||||
using interpolationConstant: Float,
|
||||
result: inout V)
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
V: _MutableContiguousCollection,
|
||||
T.Element == Float, U.Element == Float, V.Element == Float {
|
||||
|
||||
precondition(vectorA.count == result.count)
|
||||
precondition(vectorB.count == result.count)
|
||||
let n = vDSP_Length(result.count)
|
||||
|
||||
vectorA.withUnsafeBufferPointer { a in
|
||||
vectorB.withUnsafeBufferPointer { b in
|
||||
result.withUnsafeMutableBufferPointer { dest in
|
||||
|
||||
vDSP_vintb(a.baseAddress!, 1,
|
||||
b.baseAddress!, 1,
|
||||
[interpolationConstant],
|
||||
dest.baseAddress!, 1,
|
||||
n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between vectors; double-precision.
|
||||
///
|
||||
/// - Parameter vectorA: The `A` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter vectorB: The `B` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter interpolationConstant: The `C` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Returns: The `D` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U>(_ vectorA: T,
|
||||
_ vectorB: U,
|
||||
using interpolationConstant: Double) -> [Double]
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
T.Element == Double, U.Element == Double{
|
||||
|
||||
let result = Array<Double>(unsafeUninitializedCapacity: vectorA.count) {
|
||||
buffer, initializedCount in
|
||||
|
||||
linearInterpolate(vectorA,
|
||||
vectorB,
|
||||
using: interpolationConstant,
|
||||
result: &buffer)
|
||||
|
||||
initializedCount = vectorA.count
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between vectors; double-precision.
|
||||
///
|
||||
/// - Parameter vectorA: The `A` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter vectorB: The `B` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter interpolationConstant: The `C` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
/// - Parameter result: The `D` in `D[n] = A[n] + C * (B[n] - A[n])`.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U, V>(_ vectorA: T,
|
||||
_ vectorB: U,
|
||||
using interpolationConstant: Double,
|
||||
result: inout V)
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
V: _MutableContiguousCollection,
|
||||
T.Element == Double, U.Element == Double, V.Element == Double {
|
||||
|
||||
precondition(vectorA.count == result.count)
|
||||
precondition(vectorB.count == result.count)
|
||||
let n = vDSP_Length(result.count)
|
||||
|
||||
vectorA.withUnsafeBufferPointer { a in
|
||||
vectorB.withUnsafeBufferPointer { b in
|
||||
result.withUnsafeMutableBufferPointer { dest in
|
||||
|
||||
vDSP_vintbD(a.baseAddress!, 1,
|
||||
b.baseAddress!, 1,
|
||||
[interpolationConstant],
|
||||
dest.baseAddress!, 1,
|
||||
n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between neighboring elements; single-precision.
|
||||
///
|
||||
/// This function interpolates between the elements of `vector` using the following:
|
||||
///
|
||||
/// for (n = 0; n < N; ++n) {
|
||||
/// b = trunc(B[n]);
|
||||
/// a = B[n] - b;
|
||||
/// C[n] = A[b] + a * (A[b+1] - A[b]);
|
||||
/// }
|
||||
///
|
||||
/// Where `A` is the input vector, `B` is the control vector, and
|
||||
/// `C` is the output vector.
|
||||
///
|
||||
/// - Parameter vector: Input values.
|
||||
/// - Parameter controlVector: Vector that controls interpolation.
|
||||
/// - Returns: Output values.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U>(elementsOf vector: T,
|
||||
using controlVector: U) -> [Float]
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
T.Element == Float, U.Element == Float {
|
||||
|
||||
let result = Array<Float>(unsafeUninitializedCapacity: controlVector.count) {
|
||||
buffer, initializedCount in
|
||||
|
||||
linearInterpolate(elementsOf: vector,
|
||||
using: controlVector,
|
||||
result: &buffer)
|
||||
|
||||
initializedCount = controlVector.count
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between neighboring elements; single-precision.
|
||||
///
|
||||
/// This function interpolates between the elements of `vector` using the following:
|
||||
///
|
||||
/// for (n = 0; n < N; ++n) {
|
||||
/// b = trunc(B[n]);
|
||||
/// a = B[n] - b;
|
||||
/// C[n] = A[b] + a * (A[b+1] - A[b]);
|
||||
/// }
|
||||
///
|
||||
/// Where `A` is the input vector, `B` is the control vector, and
|
||||
/// `C` is the output vector.
|
||||
///
|
||||
/// - Parameter vector: Input values.
|
||||
/// - Parameter controlVector: Vector that controls interpolation.
|
||||
/// - Parameter result: Output values.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U, V>(elementsOf vector: T,
|
||||
using controlVector: U,
|
||||
result: inout V)
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
V: _MutableContiguousCollection,
|
||||
T.Element == Float, U.Element == Float, V.Element == Float {
|
||||
|
||||
precondition(controlVector.count == result.count)
|
||||
|
||||
let n = vDSP_Length(result.count)
|
||||
let m = vDSP_Length(vector.count)
|
||||
|
||||
vector.withUnsafeBufferPointer { a in
|
||||
controlVector.withUnsafeBufferPointer { b in
|
||||
result.withUnsafeMutableBufferPointer { dest in
|
||||
vDSP_vlint(a.baseAddress!,
|
||||
b.baseAddress!, 1,
|
||||
dest.baseAddress!, 1,
|
||||
n, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between neighboring elements; double-precision.
|
||||
///
|
||||
/// This function interpolates between the elements of `vector` using the following:
|
||||
///
|
||||
/// for (n = 0; n < N; ++n) {
|
||||
/// b = trunc(B[n]);
|
||||
/// a = B[n] - b;
|
||||
/// C[n] = A[b] + a * (A[b+1] - A[b]);
|
||||
/// }
|
||||
///
|
||||
/// Where `A` is the input vector, `B` is the control vector, and
|
||||
/// `C` is the output vector.
|
||||
///
|
||||
/// - Parameter vector: Input values.
|
||||
/// - Parameter controlVector: Vector that controls interpolation.
|
||||
/// - Returns: Output values.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U>(elementsOf vector: T,
|
||||
using controlVector: U) -> [Double]
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
T.Element == Double, U.Element == Double {
|
||||
|
||||
let result = Array<Double>(unsafeUninitializedCapacity: controlVector.count) {
|
||||
buffer, initializedCount in
|
||||
|
||||
linearInterpolate(elementsOf: vector,
|
||||
using: controlVector,
|
||||
result: &buffer)
|
||||
|
||||
initializedCount = controlVector.count
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/// Vector linear interpolation between neighboring elements; double-precision.
|
||||
///
|
||||
/// This function interpolates between the elements of `vector` using the following:
|
||||
///
|
||||
/// for (n = 0; n < N; ++n) {
|
||||
/// b = trunc(B[n]);
|
||||
/// a = B[n] - b;
|
||||
/// C[n] = A[b] + a * (A[b+1] - A[b]);
|
||||
/// }
|
||||
///
|
||||
/// Where `A` is the input vector, `B` is the control vector, and
|
||||
/// `C` is the output vector.
|
||||
///
|
||||
/// - Parameter vector: Input values.
|
||||
/// - Parameter controlVector: Vector that controls interpolation.
|
||||
/// - Parameter result: Output values.
|
||||
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
||||
@inline(__always)
|
||||
public static func linearInterpolate<T, U, V>(elementsOf vector: T,
|
||||
using controlVector: U,
|
||||
result: inout V)
|
||||
where
|
||||
T: _ContiguousCollection,
|
||||
U: _ContiguousCollection,
|
||||
V: _MutableContiguousCollection,
|
||||
T.Element == Double, U.Element == Double, V.Element == Double {
|
||||
|
||||
precondition(controlVector.count == result.count)
|
||||
|
||||
let n = vDSP_Length(result.count)
|
||||
let m = vDSP_Length(vector.count)
|
||||
|
||||
vector.withUnsafeBufferPointer { a in
|
||||
controlVector.withUnsafeBufferPointer { b in
|
||||
result.withUnsafeMutableBufferPointer { dest in
|
||||
vDSP_vlintD(a.baseAddress!,
|
||||
b.baseAddress!, 1,
|
||||
dest.baseAddress!, 1,
|
||||
n, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,4 +109,149 @@ if #available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) {
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Linear interpolation
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
if #available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) {
|
||||
|
||||
let n = 1024
|
||||
|
||||
AccelerateTests.test("vDSP/SinglePrecisionInterpolateBetweenVectors") {
|
||||
var result = [Float](repeating: 0, count: n)
|
||||
var legacyResult = [Float](repeating: -1, count: n)
|
||||
|
||||
let a: [Float] = (0 ..< n).map{ i in
|
||||
return sin(Float(i) * 0.025)
|
||||
}
|
||||
|
||||
let b: [Float] = (0 ..< n).map{ i in
|
||||
return sin(Float(i) * 0.05)
|
||||
}
|
||||
|
||||
let interpolationConstant: Float = 0.5
|
||||
|
||||
vDSP.linearInterpolate(a, b,
|
||||
using: interpolationConstant,
|
||||
result: &result)
|
||||
|
||||
vDSP_vintb(a, 1,
|
||||
b, 1,
|
||||
[interpolationConstant],
|
||||
&legacyResult, 1,
|
||||
vDSP_Length(n))
|
||||
|
||||
let returnedResult = vDSP.linearInterpolate(a, b,
|
||||
using: interpolationConstant)
|
||||
|
||||
expectTrue(result.elementsEqual(legacyResult))
|
||||
expectTrue(result.elementsEqual(returnedResult))
|
||||
}
|
||||
|
||||
AccelerateTests.test("vDSP/SinglePrecisionInterpolateBetweenNeighbours") {
|
||||
var result = [Float](repeating: 0, count: n)
|
||||
var legacyResult = [Float](repeating: -1, count: n)
|
||||
|
||||
let shortSignal: [Float] = (0 ... 10).map{ i in
|
||||
return sin(Float(i) * 0.1 * .pi * 4)
|
||||
}
|
||||
|
||||
let controlVector: [Float] = {
|
||||
var controlVector = [Float](repeating: 0, count: 1024)
|
||||
|
||||
vDSP_vgen([0],
|
||||
[Float(shortSignal.count)],
|
||||
&controlVector, 1,
|
||||
vDSP_Length(n))
|
||||
|
||||
return controlVector
|
||||
}()
|
||||
|
||||
vDSP.linearInterpolate(elementsOf: shortSignal,
|
||||
using: controlVector,
|
||||
result: &result)
|
||||
|
||||
vDSP_vlint(shortSignal,
|
||||
controlVector, 1,
|
||||
&legacyResult, 1,
|
||||
vDSP_Length(n),
|
||||
vDSP_Length(shortSignal.count))
|
||||
|
||||
let returnedResult = vDSP.linearInterpolate(elementsOf: shortSignal,
|
||||
using: controlVector)
|
||||
|
||||
expectTrue(result.elementsEqual(legacyResult))
|
||||
expectTrue(result.elementsEqual(returnedResult))
|
||||
}
|
||||
|
||||
AccelerateTests.test("vDSP/DoublePrecisionInterpolateBetweenVectors") {
|
||||
var result = [Double](repeating: 0, count: n)
|
||||
var legacyResult = [Double](repeating: -1, count: n)
|
||||
|
||||
let a: [Double] = (0 ..< n).map{ i in
|
||||
return sin(Double(i) * 0.025)
|
||||
}
|
||||
|
||||
let b: [Double] = (0 ..< n).map{ i in
|
||||
return sin(Double(i) * 0.05)
|
||||
}
|
||||
|
||||
let interpolationConstant: Double = 0.5
|
||||
|
||||
vDSP.linearInterpolate(a, b,
|
||||
using: interpolationConstant,
|
||||
result: &result)
|
||||
|
||||
vDSP_vintbD(a, 1,
|
||||
b, 1,
|
||||
[interpolationConstant],
|
||||
&legacyResult, 1,
|
||||
vDSP_Length(n))
|
||||
|
||||
let returnedResult = vDSP.linearInterpolate(a, b,
|
||||
using: interpolationConstant)
|
||||
|
||||
expectTrue(result.elementsEqual(legacyResult))
|
||||
expectTrue(result.elementsEqual(returnedResult))
|
||||
}
|
||||
|
||||
AccelerateTests.test("vDSP/DoublePrecisionInterpolateBetweenNeighbours") {
|
||||
var result = [Double](repeating: 0, count: n)
|
||||
var legacyResult = [Double](repeating: -1, count: n)
|
||||
|
||||
let shortSignal: [Double] = (0 ... 10).map{ i in
|
||||
return sin(Double(i) * 0.1 * .pi * 4)
|
||||
}
|
||||
|
||||
let controlVector: [Double] = {
|
||||
var controlVector = [Double](repeating: 0, count: 1024)
|
||||
|
||||
vDSP_vgenD([0],
|
||||
[Double(shortSignal.count)],
|
||||
&controlVector, 1,
|
||||
vDSP_Length(n))
|
||||
|
||||
return controlVector
|
||||
}()
|
||||
|
||||
vDSP.linearInterpolate(elementsOf: shortSignal,
|
||||
using: controlVector,
|
||||
result: &result)
|
||||
|
||||
vDSP_vlintD(shortSignal,
|
||||
controlVector, 1,
|
||||
&legacyResult, 1,
|
||||
vDSP_Length(n),
|
||||
vDSP_Length(shortSignal.count))
|
||||
|
||||
let returnedResult = vDSP.linearInterpolate(elementsOf: shortSignal,
|
||||
using: controlVector)
|
||||
|
||||
expectTrue(result.elementsEqual(legacyResult))
|
||||
expectTrue(result.elementsEqual(returnedResult))
|
||||
}
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
|
||||
Reference in New Issue
Block a user