since ArraySlice<Double> conforms to AccelerateBuffer.
What would be the equivalent Accelerate magic for var stack: [Complex] (where Complex is defined the usual way).
Bonus points if it is simple to use in a generic. i.e.
func evaluate(T:Computable) { // Double and Complex conform to Computable
var stack:[T]
etc...
vDSP_zvaddD looks promising, but [Complex] interleaves real and imaginary parts, and to use vDSP_zvaddD would seem to require getting an UnsafePointer<DSPDoubleSplitComplex> from ArraySlice<Double>.
(I will be needing all the usual arithmetic and transcendental operations on double precision Double and Complex, and mixed vector-scalar operations, as well....)
My initial thought here is to provide a split complex buffer type that conforms to Collection with Element == Complex, but also has contiguous real and imaginary parts that can be used to make nice wrappers for the vDSP interfaces. This is something that I've been meaning to design out and add, but simply haven't gotten around to yet.
Extremely sketchy draft of what I'm talking about here:
Note that the actual implementation here is not at all what I would end up doing eventually, but it at least outlines what such a project would look like and how it could interoperate with Accelerate.
Finally getting around to implementing the vector-scalar ops, and again, [Double] conformance to AccelerateBuffer makes the Double version simple, but my attempt for the Complex version seems overly verbose. Any suggestions for simplifying:
static func vsMul(_ scalar: Complex, _ stack: inout [Complex], sp: Int, spResult: Int, n: Int) {
stack.withUnsafeMutablePointerToDouble { p in
var re = scalar.re, im = scalar.im
withUnsafeMutablePointer(to: &re) { pRe in
withUnsafeMutablePointer(to: &im) { pIm in
let p1 = p + 2*sp + 2
let p2 = p + 2*spResult + 2
var dsc1 = DSPDoubleSplitComplex(realp: p1, imagp: p1 + 1)
var dsc2 = DSPDoubleSplitComplex(realp: p2, imagp: p2 + 1)
var dscScalar = DSPDoubleSplitComplex(realp: pRe, imagp: pIm)
vDSP_zvzsmlD(&dsc1, 2, &dscScalar, &dsc2, 2, UInt(n))
}
}
}
}
which seems to work to do:
for i in 1...n { stack[spResult + i] = stack[sp + i] * scalar }