1

我想对存储在数组中的大量 CGPoint 实例执行一些数学运算,所以我想我会考虑使用 Accelerate 并首先将 CGPoint 与 AccelerateMutableBuffer 一致,然后扩展 Array 以使其一致。

经过一些试验和错误,我想出了以下内容,它编译没有任何错误,但是 vDSP.add(_:, _:, result:) 返回的结果不正确:变量 p 仍然是 .zero 在结尾。

我错过了什么?

非常感谢。

(您可以在 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

编辑:我已经想通了。据我所知,这是正确的解决方案。它编译没有错误,运行没有问题,并给出正确的结果。因此,除非有人看到我没有看到的问题,否则我很乐意考虑解决这个问题。

先前实现的问题在于,在创建self( var varself = self) 的本地可变副本并对其进行操作时self本身并没有改变。

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)  ✅
4

0 回答 0