2016-11-13 49 views
1

我一直在学习有关Accelerate框架的知识,并且正在写一个Vector类以配合我的学习经验。我决定我需要实现序列协议,并且在几次错误的开始和大量搜索我的问题的相关信息之后,终于找到了一个似乎可行的解决方案。不知道我的解决方案是否合适,如果有更好的方法可以做到这一点,我们希望评论。目前的代码有点长,但不是超长的,所以我会在这里发布。在一个类中正确实现序列协议

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

您的Sequence协议的实施不正确。

首先,你的makeIterator()方法并不因为它的签名错误, 它不会返回Iterator使用。 (您可以在不改变任何内容的情况下从代码中删除该函数)。遍历向量元素的工作原理 ,因为对于所有声明符合Sequence的 迭代器,默认实现为makeIterator()

其次,您的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()从一开始,即使前面的迭代并 无法检索的所有元素将启动:使用stride()方法从雨燕标准 库

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) 
    } 

    // ... 
}