I'd like to perform some math on a fairly large number of CGPoint instances stored in an array so I thought I'd look into using Accelerate and start by conforming CGPoint to AccelerateMutableBuffer, followed by extending Array to conform as well.
After some trial and error, I came up with the following, which compiles without any errors, but the result returned by vDSP.add(_:, _:, result:) is not correct: the variable p is still .zero at the end.
What am I missing?
Many thanks.
(You can try the code below on a Playground)
import Foundation
import CoreGraphics
import Accelerate
extension CGPoint: AccelerateMutableBuffer {
public typealias Element = Double
public var count: Int { 2 }
public func withUnsafeBufferPointer <R> (
_ body: (UnsafeBufferPointer<Element>) throws -> R
) rethrows -> R {
var varself = self
let ubp = withUnsafeBytes(of: &varself) { urbp in
urbp.bindMemory(to: Element.self)
}
return try body(ubp)
}
public mutating func withUnsafeMutableBufferPointer <R> (
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
) rethrows -> R {
var varself = self
var umbp = withUnsafeMutableBytes(of: &varself) { umrbp in
umrbp.bindMemory(to: Element.self)
}
return try body(&umbp)
}
}
let p1 = CGPoint(x: 1.5, y: 3.5)
let p2 = CGPoint(x: 0.5, y: 2.5)
var p: CGPoint = .zero
vDSP.add(p1, p2, result: &p)
p
Edit: I've since figured it out. Here's the correct solution, as far as I know. It compiles without errors, runs without problems, and gives the correct result. So, unless someone sees a problem I'm not seeing, I'm happy with considering this question resolved.
The problem with the previous implementation is that, in creating a local mutable copy of self
(var varself = self
) and operating on that, self
itself doesn't get changed.
import Foundation
import CoreGraphics
import Accelerate
extension CGPoint: AccelerateMutableBuffer {
public typealias Element = Double
public var count: Int { 2 }
public func withUnsafeBufferPointer<R>(_ body: (UnsafeBufferPointer<Double>) throws -> R) rethrows -> R {
try Swift.withUnsafeBytes(of: self) { urbp in
try body(urbp.bindMemory(to: Double.self))
}
}
public mutating func withUnsafeMutableBufferPointer <R> (
_ body: (inout UnsafeMutableBufferPointer<Double>) throws -> R
) rethrows -> R {
try Swift.withUnsafeMutableBytes(of: &self) { umrbp in
var umbp = umrbp.bindMemory(to: Double.self)
return try body(&umbp)
}
}
}
let p1 = CGPoint(x: 1.5, y: 3.5)
let p2 = CGPoint(x: 0.5, y: 2.5)
var p: CGPoint = .zero
vDSP.add(p1, p2, result: &p)
p // (x: 2, y: 6) ✅