Reputation: 22246
I need to perform the following operations in Swift with Accelerate Multiply, Complex Conjugate, and Exp. I've done this already using the Complex Swift code by dankogai, but it is just too slow for the work I'm doing. I'm having trouble creating a working version using the Accelerate framework and I'm hoping to accelerate my understanding.
let frequencyShift = (2 * M_PI * Double(self.centralFrequency) * delays).i / Double(self.samplingFrequencyHertz)
let result = conj(exp(frequencyShift))
delays
is an array of about 200k doubles and these lines will be called a couple of hundred times. I convert them to Complex numbers a la Swift Complex style and then call the complex exp() and conj() methods on the result.
Double-precision complex vector-scalar multiply.
vDSP_zvzsmlD
Complex vector conjugate; double precision.
vDSP_zvconjD
Is there an exp()
equivalent in Accelerate and how would you reorganize this code to perform an equivalent Accelerate'd version of the operations?
Upvotes: 2
Views: 1005
Reputation: 22246
I find it helpful to first attempt to convert your code from a naive implementation using for-loops to maps. If your code is structured to work with maps then it becomes pretty easy to switch to accelerate since you have already tackled structuring your algorithm into vectorized operations.
let array: [Int] = [1, 2, 3, 4]
let array2 = [Int]()
for value in array {
array2 = value * 2
}
let array: [Int] = [1, 2, 3, 4]
array.map({ (value: Int) -> Int in
return value * 2
})
If you find that you want to enumerate two or more arrays of the same size then the above can combine map with enumerate
let alphas: [Double] = betas.enumerate().map({ (index: Int, beta: Double) -> Double in
return beta * phis[index]
})
The way to use Accelerate is not always obvious and specifically the UnsafePointer
and UnsafeMutablePointer
syntax. This is basically unnecessary.
var alphaLowers = [Double](count: elementDelays.count, repeatedValue: 0)
vDSP_vmulD(&alphas, 1, &x_ns, 1, &alphaLowers, 1, UInt(elementDelays.count))
So Swift avoids the hassles of malloc and free by allowing you to create an automatic memory managed object and then simply passing it along with the ampersand. I mention this because it avoids trying things like wrapping the object in this UnsafeMutablePointer<Double>(alphaLowers)
.
Most of what I wanted to do relied on operations involving complex numbers. So to create an object you can use in Accelerate you might try the following.
var reals = [Double](count: 100, repeatedValue: 0)
var imaginaries = [Double](count: 100, repeatedValue: 0)
var complexNumbers = DSPDoubleSplitComplex(realp: &reals, imagp: &imaginaries)
I didn't find an Accelerate equivalent of exp, but you can break up the values and perform the necessary operation on the reals and imaginaries using Euler's method illustrated below using the Complex Swift library.
public func exp<T:RealType>(z:Complex<T>) -> Complex<T> {
let r = T.exp(z.re)
let a = z.im
return Complex(r * T.cos(a), r * T.sin(a))
}
I haven't found a good way of avoiding this problem so I actually do this step without using Accelerate. The complex conjugate is calculated simply by negating the imaginary portion.
Upvotes: 1