我一直在研究有关Accelerate框架的一些知识,并且正在编写一个Vector类来配合我的学习经历。我决定我需要实现Sequence协议,经过几次错误的启动,并且在我的问题中搜索相关信息后,最终找到了一个似乎有用的解决方案。不确定我的解决方案是否合适,如果有更好的方法可以评论。当前代码有点长但不是超长,所以我会在这里发布。
import Foundation
import Accelerate
public class Vdsp{
public class VectorD: Sequence, IteratorProtocol {
var vindex = 0
public func makeIterator() -> Double? {
return next()
}
public func next() -> Double? {
let nextIndex = self.vindex * self.s + self.o
guard self.vindex < self.l && nextIndex < self.count
else {
self.vindex = 0
return nil
}
self.vindex += 1
return self.data[nextIndex]
}
public let count : Int
fileprivate var l: Int
fileprivate var o: Int
fileprivate var s: Int
public var length : Int {
get {
return self.l
}
set (value){
let l = (value - 1) * self.s + self.o
if l < 0 || l >= self.count {
preconditionFailure("length exceeds vector boundary")
}
self.l = value
}
}
public var stride : Int {
get {
return self.s
}
set (value){
let l = (self.l - 1) * value + self.o
if l < 0 || l >= self.count {
preconditionFailure("stride will cause vector to exceed vector boundary")
}
self.s = value
}
}
public var offset : Int {
get {
return self.o
}
set (value){
let l = (self.l - 1) * self.s + value
if l < 0 || l >= self.count {
preconditionFailure("stride will cause vector to exceed vector boundary")
}
self.o = value
}
}
// length * stride + offset >= 0 and <= count
public var data : Array<Double>
public init(length: Int){
self.count = length
self.l = length
self.s = 1
self.o = 0
data = Array(repeating: 0.0, count: count)
}
// MARK: - Utility functions
public var empty : VectorD { // Create a new vector unit stride, zero offset
get{
return VectorD(length: length)
}
}
public func display(decimals: Int) -> String {
let fmt = String("%0." + String(decimals) + "f\n")
var aString = ""
for i in 0..<length {
aString += String(format: fmt!, self.data[offset + i * stride])
}
return aString
}
// MARK: - Subscripts and Operators
public subscript(index: Int) -> Double {
get {
if index > length {
preconditionFailure("index \(index) out of bounds")
} else {
return data[self.offset + index * self.stride]
}
}
set(newValue) {
if index > self.length {
preconditionFailure("index \(index) out of bounds")
} else {
self.data[self.offset + index * self.stride] = newValue
}
}
}
public static func + (left: VectorD, right: VectorD) -> VectorD {
return Vdsp.add(left, right)
}
public static func + (left: Double, right: VectorD) -> VectorD {
return Vdsp.add(left, right)
}
public static func + (left: VectorD, right: Double) -> VectorD {
return Vdsp.add(right, left)
}
public static func * (left: VectorD, right: VectorD) -> VectorD {
return Vdsp.mul(left, right)
}
public static func * (left: Double, right: VectorD) -> VectorD {
return Vdsp.mul(left, right)
}
public static func * (left: VectorD, right: Double) -> VectorD {
return Vdsp.mul(right, left)
}
// MARK: - vDSP routines as methods of VectorD
public func fill(value: Double){
var v = value
vDSP_vfillD(&v, &data + offset, stride, vDSP_Length(length))
}
public func ramp(start: Double, increment: Double){
var s = start
var i = increment
vDSP_vrampD(&s, &i, &data + offset, stride, vDSP_Length(length))
}
public var sumval : Double {
get {
var s : Double = 0.0
vDSP_sveD(&data + offset, stride, &s, vDSP_Length(length))
return s
}
}
}
// MARK: - vDSP routines as class functions of Vdsp
public static func add(_ v1: VectorD, _ v2: VectorD) -> VectorD {
let v3 = v1.empty
vDSP_vaddD( &v1.data + v1.offset, v1.stride, &v2.data + v2.offset , v2.stride, &v3.data, 1, vDSP_Length(v3.length))
return v3
}
public static func add(_ s: Double, _ v: VectorD) -> VectorD {
var sdta = s
let r = v.empty
vDSP_vsaddD( &v.data + v.offset, v.stride, &sdta, &r.data, 1, vDSP_Length(v.length))
return r
}
public static func mul(_ v1: VectorD, _ v2: VectorD) -> VectorD {
let v3 = v1.empty
vDSP_vmulD( &v1.data + v1.offset, v1.stride, &v2.data + v2.offset, v2.stride, &v3.data, 1, vDSP_Length(v3.length))
return v3
}
public static func mul(_ s: Double, _ v: VectorD) -> VectorD {
var sdta = s
let r = v.empty
vDSP_vsmulD( &v.data + v.offset, v.stride, &sdta, &r.data, 1, vDSP_Length(v.length))
return r
}
}
我正在练习
//: Playground for Accelerate
import UIKit
let V = Vdsp.VectorD(length: 10);V.ramp(start: 0.1, increment: 0.2)
print("Vector V after ramp(0.1,0.2)");print(V.display(decimals: 3))
V.length = 4
V.stride = 2
V.offset = 1
print("Vector V after attribute modification")
print(V.display(decimals: 3))
let Q = V.empty
Q.ramp(start: 1.0, increment: 1.0)
print("Vector Q after ramp(1.0,1.0)");print(Q.display(decimals: 3))
print("V * Q"); var R = V * Q
for i in 0..<V.length {
print("\(V[i]) * \(Q[i]) = \(R[i])")
}
R = V + Q; print("V + Q = R")
for i in 0..<V.length {
print("\(V[i]) + \(Q[i]) = \(R[i])")
}
print("\n")
for item in V.data {
print(item)
}
print("\n")
for item in V {
print(item)
}
print("\n")
V.offset = 3
for item in V {
print(item)
}
我似乎得到了正确的输出。 Sequence协议位于VectorD类的前几行。
答案 0 :(得分:2)
Sequence
协议的实施不正确。
首先,您的makeIterator()
方法根本没有使用,因为它的签名错误,
它不会返回Iterator
。 (您可以从代码中删除该函数而不进行任何更改。)迭代向量元素有效
因为所有人都有makeIterator()
的默认实现
声明符合Sequence
的迭代器。
其次,您的next()
方法使用实例变量vindex
在到达迭代结束后重置为零。
换句话说,假设之前检索到所有元素
再次迭代相同的向量。这给出了意想不到的输出:
let V = Vdsp.VectorD(length: 10)
V.ramp(start: 1.0, increment: 1.0)
print(Array(V.prefix(4))) // [1.0, 2.0, 3.0, 4.0]
print(Array(V.prefix(4))) // [5.0, 6.0, 7.0, 8.0]
print(Array(V.prefix(4))) // [9.0, 10.0]
print(Array(V.prefix(4))) // [1.0, 2.0, 3.0, 4.0]
以下是Sequence
协议的可能实现:
public class VectorD: Sequence {
public func makeIterator() -> AnyIterator<Double> {
var vindex = 0
return AnyIterator {
let nextIndex = vindex * self.s + self.o
guard vindex < self.l && nextIndex < self.count else {
return nil
}
vindex += 1
return self.data[nextIndex]
}
}
// ...
}
请注意,vindex
现在是makeIterator()
的局部变量
并被关闭所捕获。再次致电makeIterator()
即使前一次迭代完成,也会从头开始
不检索所有元素:
print(Array(V.prefix(4))) // [1.0, 2.0, 3.0, 4.0]
print(Array(V.prefix(4))) // [1.0, 2.0, 3.0, 4.0]
另一种可能的实施方式是
public class VectorD: Sequence {
public func makeIterator() -> AnyIterator<Double> {
let upperBound = Swift.min(count, o + l * s)
let it = Swift.stride(from: o, to: upperBound, by: s)
.lazy.map { self.data[$0] }.makeIterator()
return AnyIterator(it)
}
// ...
}
使用Swift标准中的stride()
方法
库。