Bit field larger than 64 shifts in Swift? - swift

How would I construct an OptionSetType with a raw value greater than 64 bit shifts (i.e. Int64) that is still able to be encoded using NSCoder? I have more than 64 potential bitwise options to combine.

So I eventually had to create my own primitive struct which was a pain in the ass, since the library #appzYourLife provided does not actually meet every protocol required of UnsignedIntegerTypes. The following is an extension I wrote that actually allows me to write things like
let a: UInt256 = 30
let b: UInt256 = 1 << 98
print(a + b)
which would output to the console:
0x00000000:00000000:00000000:00000000:00000004:00000000:00000000:0000001E
The extension is pretty lengthy and does not yet implement multiplication and devision or bit-shifting numbers other than 1. This version also supports encoding with and NSCoder
//
// UInt256.swift
// NoodleKit
//
// Created by NoodleOfDeath on 7/10/16.
// Copyright © 2016 NoodleOfDeath. All rights reserved.
//
import Foundation
// Bit Shifting only supports lhs = 1
#warn_unused_result
public func << (lhs: UInt256, rhs: UInt256) -> UInt256 {
if lhs > 1 { print("Warning: Only supports binary bitshifts (i.e. 1 << n, where n < 256. Shifting any other numbers than 1 may result in unexpected behavior.") }
if rhs > 255 { fatalError("shift amount is larger than type size in bits") }
let shift = UInt64(rhs.parts[7]) % 32
let offset = Int(rhs.parts[7] / 32)
var parts = [UInt32]()
for i in (0 ..< 8) {
let part: UInt64 = (i + offset < 8 ? UInt64(lhs.parts[i + offset]) : 0)
let sum32 = UInt32(part << shift)
parts.append(sum32)
}
return UInt256(parts)
}
#warn_unused_result
public func >> (lhs: UInt256, rhs: UInt256) -> UInt256 {
if lhs > 1 { print("Warning: Only supports binary bitshifts (i.e. 1 << n, where n < 256. Shifting any other numbers than 1 may result in unexpected behavior.") }
if rhs > 255 { fatalError("shift amount is larger than type size in bits") }
let shift = UInt64(rhs.parts[7]) % 32
let offset = Int(rhs.parts[7] / 32)
var parts = [UInt32]()
for i in (0 ..< 8) {
let part: UInt64 = (i - offset > 0 ? UInt64(lhs.parts[i - offset]) : 0)
let sum32 = UInt32(part >> shift)
parts.append(sum32)
}
return UInt256(parts)
}
#warn_unused_result
public func == (lhs: UInt256, rhs: UInt256) -> Bool {
return lhs.parts == rhs.parts
}
#warn_unused_result
public func < (lhs: UInt256, rhs: UInt256) -> Bool {
for i in 0 ..< 8 {
guard lhs.parts[i] < rhs.parts[i] else { continue }
return true
}
return false
}
#warn_unused_result
public func > (lhs: UInt256, rhs: UInt256) -> Bool {
for i in 0 ..< 8 {
guard lhs.parts[i] > rhs.parts[i] else { continue }
return true
}
return false
}
#warn_unused_result
public func <= (lhs: UInt256, rhs: UInt256) -> Bool {
return lhs < rhs || lhs == rhs
}
#warn_unused_result
public func >= (lhs: UInt256, rhs: UInt256) -> Bool {
return lhs > rhs || lhs == rhs
}
/// Adds `lhs` and `rhs`, returning the result and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
#warn_unused_result
public func + (lhs: UInt256, rhs: UInt256) -> UInt256 {
var parts = [UInt32]()
var carry = false
for i in (0 ..< 8).reverse() {
let lpart = UInt64(lhs.parts[i])
let rpart = UInt64(rhs.parts[i])
let comp = lpart == UInt64(UInt32.max) && rpart == UInt64(UInt32.max)
let sum64 = lpart + rpart + (carry || comp ? 1 : 0)
let sum32 = UInt32((sum64 << 32) >> 32)
carry = sum64 > UInt64(UInt32.max)
parts.insert(sum32, atIndex: 0)
}
return UInt256(parts)
}
/// Adds `lhs` and `rhs`, returning the result and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
public func += (inout lhs: UInt256, rhs: UInt256) {
lhs = lhs + rhs
}
/// Subtracts `lhs` and `rhs`, returning the result and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
#warn_unused_result
public func - (lhs: UInt256, rhs: UInt256) -> UInt256 {
var parts = [UInt32]()
var borrow = false
var gave = false
for i in (0 ..< 8).reverse() {
borrow = lhs.parts[i] < rhs.parts[i]
let lpart = UInt64(lhs.parts[i]) - (gave ? 1 : 0) + (borrow ? UInt64(UInt32.max) : 0)
let rpart = UInt64(rhs.parts[i])
let sum64 = lpart - rpart
let sum32 = UInt32((sum64 << 32) >> 32)
gave = borrow
parts.insert(sum32, atIndex: 0)
}
return UInt256(parts)
}
public func -= (inout lhs: UInt256, rhs: UInt256) {
lhs = lhs - rhs
}
/// Multiplies `lhs` and `rhs`, returning the result and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
/// - Complexity: O(64)
#warn_unused_result
public func * (lhs: UInt256, rhs: UInt256) -> UInt256 {
// TODO: - Not Implemented
return UInt256()
}
public func *= (inout lhs: UInt256, rhs: UInt256) {
lhs = lhs * rhs
}
/// Divides `lhs` and `rhs`, returning the result and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
#warn_unused_result
public func / (lhs: UInt256, rhs: UInt256) -> UInt256 {
// TODO: - Not Implemented
return UInt256()
}
public func /= (inout lhs: UInt256, rhs: UInt256) {
lhs = lhs / rhs
}
/// Divides `lhs` and `rhs`, returning the remainder and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
#warn_unused_result
public func % (lhs: UInt256, rhs: UInt256) -> UInt256 {
// TODO: - Not Implemented
return UInt256()
}
public func %= (inout lhs: UInt256, rhs: UInt256) {
lhs = lhs % rhs
}
public extension UInt256 {
#warn_unused_result
public func toIntMax() -> IntMax {
return Int64(parts[6] << 32) + Int64(parts[7])
}
#warn_unused_result
public func toUIntMax() -> UIntMax {
return UInt64(parts[6] << 32) + UInt64(parts[7])
}
/// Adds `lhs` and `rhs`, returning the result and a `Bool` that is
/// `true` iff the operation caused an arithmetic overflow.
public static func addWithOverflow(lhs: UInt256, _ rhs: UInt256) -> (UInt256, overflow: Bool) {
var parts = [UInt32]()
var carry = false
for i in (0 ..< 8).reverse() {
let lpart = UInt64(lhs.parts[i])
let rpart = UInt64(rhs.parts[i])
let comp = lpart == UInt64(UInt32.max) && rpart == UInt64(UInt32.max)
let sum64 = lpart + rpart + (carry || comp ? 1 : 0)
let sum32 = UInt32((sum64 << 32) >> 32)
carry = sum64 > UInt64(UInt32.max)
parts.insert(sum32, atIndex: 0)
}
return (UInt256(parts), parts[0] > 0x8fffffff)
}
/// Subtracts `lhs` and `rhs`, returning the result and a `Bool` that is
/// `true` iff the operation caused an arithmetic overflow.
public static func subtractWithOverflow(lhs: UInt256, _ rhs: UInt256) -> (UInt256, overflow: Bool) {
// TODO: -
var parts = [UInt32]()
var borrow = false
var gave = false
for i in (0 ..< 8).reverse() {
borrow = lhs.parts[i] < rhs.parts[i]
let lpart = UInt64(lhs.parts[i]) - (gave ? 1 : 0) + (borrow ? UInt64(UInt32.max) : 0)
let rpart = UInt64(rhs.parts[i])
let sum64 = lpart - rpart
let sum32 = UInt32((sum64 << 32) >> 32)
gave = borrow
parts.insert(sum32, atIndex: 0)
}
return (UInt256(parts), parts[0] > 0x8fffffff)
}
/// Multiplies `lhs` and `rhs`, returning the result and a `Bool` that is
/// `true` iff the operation caused an arithmetic overflow.
public static func multiplyWithOverflow(lhs: UInt256, _ rhs: UInt256) -> (UInt256, overflow: Bool) {
// TODO: - Not Implemented
return (UInt256(), false)
}
/// Divides `lhs` and `rhs`, returning the result and a `Bool` that is
/// `true` iff the operation caused an arithmetic overflow.
public static func divideWithOverflow(lhs: UInt256, _ rhs: UInt256) -> (UInt256, overflow: Bool) {
// TODO: - Not Implemented
return (UInt256(), false)
}
/// Divides `lhs` and `rhs`, returning the remainder and a `Bool` that is
/// `true` iff the operation caused an arithmetic overflow.
public static func remainderWithOverflow(lhs: UInt256, _ rhs: UInt256) -> (UInt256, overflow: Bool) {
// TODO: - Not Implemented
return (UInt256(), false)
}
}
public struct UInt256 : UnsignedIntegerType, Comparable, Equatable {
public typealias IntegerLiteralType = UInt256
public typealias Distance = Int32
public typealias Stride = Int32
private let parts: [UInt32]
private var part0: UInt32 { return parts[0] }
private var part1: UInt32 { return parts[1] }
private var part2: UInt32 { return parts[2] }
private var part3: UInt32 { return parts[3] }
private var part4: UInt32 { return parts[4] }
private var part5: UInt32 { return parts[5] }
private var part6: UInt32 { return parts[6] }
private var part7: UInt32 { return parts[7] }
public static var max: UInt256 {
return UInt256([.max, .max, .max, .max, .max, .max, .max, .max])
}
public var description: String {
var hex = "0x"
for i in 0 ..< parts.count {
let part = parts[i]
hex += String(format:"%08X", part)
if i + 1 < parts.count {
hex += ":"
}
}
return "\(hex)"
}
public var componentDescription: String {
return "\(parts)"
}
public var hashValue: Int {
return (part0.hashValue + part1.hashValue + part2.hashValue + part3.hashValue + part4.hashValue + part5.hashValue + part6.hashValue + part7.hashValue).hashValue
}
public var data: NSData {
let bytes = [part0, part1, part2, part3, part4, part5, part6, part7]
return NSData(bytes: bytes, length: 32)
}
public init(_builtinIntegerLiteral builtinIntegerLiteral: _MaxBuiltinIntegerType) {
self.init(UInt64(_builtinIntegerLiteral: builtinIntegerLiteral))
}
public init() { parts = [0, 0, 0, 0, 0, 0, 0, 0] }
public init(_ newParts: [UInt32]) {
var zeros = UInt256().parts
zeros.replaceRange((8 - newParts.count ..< 8), with: newParts)
parts = zeros
}
public init(_ v: Int8) {
self.init(UInt64(v))
}
public init(_ v: UInt8) {
self.init(UInt64(v))
}
public init(_ v: Int16) {
self.init(UInt64(v))
}
public init(_ v: UInt16) {
self.init(UInt64(v))
}
public init(_ v: Int32) {
self.init(UInt64(v))
}
public init(_ v: UInt32) {
self.init(UInt64(v))
}
public init(_ v: Int) {
self.init(UInt64(v))
}
public init(_ v: UInt) {
self.init(UInt64(v))
}
public init(_ v: Int64) {
self.init(UInt64(v))
}
public init(_ v: UInt64) {
self.init([UInt32(v >> 32), UInt32((v << 32) >> 32)])
}
public init(integerLiteral value: IntegerLiteralType) {
parts = value.parts
}
public init?(data: NSData) {
var parts = [UInt32]()
let size = sizeof(UInt32)
for i in 0 ..< 8 {
var part = UInt32()
data.getBytes(&part, range: NSMakeRange(i * size, size))
parts.append(part)
}
guard parts.count == 8 else { return nil }
self.init(parts)
}
#warn_unused_result
public func advancedBy(n: Stride) -> UInt256 {
return self + UInt256(n)
}
#warn_unused_result
public func advancedBy(n: Distance, limit: UInt256) -> UInt256 {
return limit - UInt256(n) > self ? self + UInt256(n) : limit
}
#warn_unused_result
public func distanceTo(end: UInt256) -> Distance {
return end - self
}
/// Returns the previous consecutive value in a discrete sequence.
///
/// If `UInt256` has a well-defined successor,
/// `UInt256.successor().predecessor() == UInt256`. If `UInt256` has a
/// well-defined predecessor, `UInt256.predecessor().successor() ==
/// UInt256`.
///
/// - Requires: `UInt256` has a well-defined predecessor.
#warn_unused_result
public func predecessor() -> UInt256 {
return advancedBy(-1)
}
#warn_unused_result
public func successor() -> UInt256 {
return advancedBy(1)
}
}
extension UInt256 : BitwiseOperationsType {}
/// Returns the intersection of bits set in `lhs` and `rhs`.
///
/// - Complexity: O(1).
#warn_unused_result
public func & (lhs: UInt256, rhs: UInt256) -> UInt256 {
var parts = [UInt32]()
for i in 0 ..< 8 {
parts.append(lhs.parts[i] & rhs.parts[i])
}
return UInt256(parts)
}
/// Returns the union of bits set in `lhs` and `rhs`.
///
/// - Complexity: O(1).
#warn_unused_result
public func | (lhs: UInt256, rhs: UInt256) -> UInt256 {
var parts = [UInt32]()
for i in 0 ..< 8 {
parts.append(lhs.parts[i] | rhs.parts[i])
}
return UInt256(parts)
}
/// Returns the bits that are set in exactly one of `lhs` and `rhs`.
///
/// - Complexity: O(1).
#warn_unused_result
public func ^ (lhs: UInt256, rhs: UInt256) -> UInt256 {
var parts = [UInt32]()
for i in 0 ..< 8 {
parts.append(lhs.parts[i] ^ rhs.parts[i])
}
return UInt256(parts)
}
/// Returns `x ^ ~UInt256.allZeros`.
///
/// - Complexity: O(1).
#warn_unused_result
prefix public func ~ (x: UInt256) -> UInt256 {
return x ^ ~UInt256.allZeros
}
public extension UInt256 {
public static var allZeros: UInt256 {
return UInt256()
}
}
public extension NSCoder {
public func encodeUInt256(unsignedInteger: UInt256, forKey key: String) {
encodeObject(unsignedInteger.data, forKey: key)
}
public func decodeUInt256ForKey(key: String) -> UInt256 {
guard let data = decodeObjectForKey(key) as? NSData else { return UInt256() }
return UInt256(data: data) ?? UInt256()
}
}

Disclaimer: I never tried
I suppose you can build your own Int128.
E.g. this library defined a UInt256 type.
Once you have your new type you can simply use it with OptionSetType I guess.
struct YourOptions : OptionSetType{
let rawValue : Int128
init(rawValue:Int128) {
self.rawValue = rawValue
}
}

Related

Convert into generic function

I am writing an iOS app in Swift. My class has below functions for reading bytebuffer. Below all functions do same task but work on different number types. So, how to convert these functions into a single function using generics?
var array = [UInt8]()
private var currentIndex: Int = 0
private let hostEndianness: Endianness = OSHostByteOrder() == OSLittleEndian ? .little : .big
private var currentEndianness: Endianness = .big
public func getUInt16() -> UInt16 {
let check=(currentIndex + MemoryLayout<UInt16>.size) - 1
if array.indices.contains(check){
let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<UInt16>.size]), UInt16.self)
currentIndex += MemoryLayout<UInt16>.size
return result.littleEndian
}else{
return 0
}
}
public func getInt32() -> Int32 {
let check=(currentIndex + MemoryLayout<Int32>.size) - 1
if array.indices.contains(check){
let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<Int32>.size]), Int32.self)
currentIndex += MemoryLayout<Int32>.size
return result.littleEndian
}else{
return 0
}
}
public func getFloat() -> Float {
let check=(currentIndex + MemoryLayout<UInt32>.size) - 1
if array.indices.contains(check){
let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<UInt32>.size]), UInt32.self)
currentIndex += MemoryLayout<UInt32>.size
return Float(bitPattern: result.littleEndian)
}else{
return 0.0
}
}
public func getDouble() -> Double {
let check=(currentIndex + MemoryLayout<UInt64>.size) - 1
if array.indices.contains(check){
let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<UInt64>.size]), UInt64.self)
currentIndex += MemoryLayout<UInt64>.size
return Double(bitPattern: result.bigEndian)
}else{
return 0.0
}
}
The only difference in the above functions is types: Float, double, UInt16, Int32.
From Function:
private func from<T>(_ value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBytes {
$0.load(fromByteOffset: 0, as: T.self)
}
}
My Solution:
public func getNumber<T:Numeric>() -> T {
let check=(currentIndex + MemoryLayout<T>.size) - 1
if array.indices.contains(check){
let result = from(Array(array[currentIndex..<currentIndex + MemoryLayout<T>.size]), T.self)
currentIndex += MemoryLayout<T>.size
return result.bigEndian
}else{
return 0
}
}
Error:
Value of type 'T' has no member 'bigEndian'

crc-16 cccitt problem - incorrect calculation

Trying to implement this CRC16 CITT checksum within my bluetooth ios mobile application:
extension Data {
typealias bit_order_16 = (_ value: UInt16) -> UInt16
typealias bit_order_8 = (_ value: UInt8) -> UInt8
func crc16Check() -> UInt16 {
let data = self as! NSData
let bytes = UnsafePointer<UInt8>(data.bytes.assumingMemoryBound(to: UInt8.self))
let length = data.length
return crc16ccitt(message: bytes, nBytes: length)
}
func straight_16(value: UInt16) -> UInt16 {
return value
}
func reverse_16(value: UInt16) -> UInt16 {
var value = value
var reversed: UInt16 = 0
for i in stride(from: 0, to: 16, by: 1) {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func straight_8(value: UInt8) -> UInt8 {
return value
}
func reverse_8(value: UInt8) -> UInt8 {
var value = value
var reversed: UInt8 = 0
for i in stride(from: 0, to: 8, by: 1) {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func crc16(message: UnsafePointer<UInt8>, nBytes: Int, data_order: bit_order_8, remainder_order: bit_order_16, remainder: UInt16, polynomial: UInt16) -> UInt16 {
var remainder = remainder
for byte in stride(from: 0, to: nBytes, by: 1) {
remainder ^= UInt16(data_order(message[byte]) << 8)
var bit = 8
while bit > 0 {
if (remainder & 0x8000) != 0 {
remainder = (remainder << 1) ^ 0x1021
} else {
remainder = (remainder << 1)
}
bit -= 1
}
}
return remainder_order(remainder)
}
func crc16ccitt(message: UnsafePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0xffff, polynomial: 0x1021)
}
func crc16ccitt_xmodem(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0x0000, polynomial: 0x1021)
}
func crc16ccitt_kermit(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
let swap = crc16(message: message, nBytes: nBytes, data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x1021)
return swap << 8 | swap >> 8
}
func crc16ccitt_1d0f(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0x1d0f, polynomial: 0x1021)
}
func crc16ibm(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x8005)
}
}
I set up a fixed data type of
let tData = Data.init(bytes: [0x05, 0x02, 0x03] as [UInt8], count: 3)
let crcString = String.init(format: "CRC error, calculated: %04X", tData.crc16Check())
print(crcString)
//Prints out CC9C
CC9C is incorrect.
The answer should be: 716D
Can't seem to find the error within the crc16 ccitt calculation. Can someone help to please spot the issue, as I'm really not sure where it's wrong. Been spending too long trying to figure it out. Would appreciate any time of help from the community. Thank you.
The error is the wrong order of operations here:
remainder ^= UInt16(data_order(message[byte]) << 8)
The 8-bit value data_order(message[byte]) is shifted by 8 bits to the left – the result will always be zero. It should be
remainder ^= UInt16(data_order(message[byte])) << 8
so that the number is converted to a 16-bit value before shifting it to the left.
That problem might not occur in a similar C program, where all integral operands are promoted to int before doing the calculation – such implicit type conversions are not done in Swift.
Another error is that your func crc16() uses the fixed polynomial 0x1021 instead of the polynomial argument. That causes a wrong result for the crc16ibm checksum.
Note also that the conversion to NSData in crc16Check() is not needed. That method can be simplified to
func crc16Check() -> UInt16 {
return self.withUnsafeBytes { [length = self.count] in
crc16ccitt(message: $0, nBytes: length)
}
}
Even better: Make all methods operator on self instead of passing Unsafe(Mutable)Pointers and lengths around:
extension Data {
typealias bit_order_16 = (_ value: UInt16) -> UInt16
typealias bit_order_8 = (_ value: UInt8) -> UInt8
func straight_16(value: UInt16) -> UInt16 {
return value
}
func reverse_16(value: UInt16) -> UInt16 {
var value = value
var reversed: UInt16 = 0
for _ in 0..<16 {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func straight_8(value: UInt8) -> UInt8 {
return value
}
func reverse_8(value: UInt8) -> UInt8 {
var value = value
var reversed: UInt8 = 0
for _ in 0..<8 {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func crc16(data_order: bit_order_8, remainder_order: bit_order_16, remainder: UInt16, polynomial: UInt16) -> UInt16 {
var remainder = remainder
for byte in self {
remainder ^= UInt16(data_order(byte)) << 8
for _ in 0..<8 {
if (remainder & 0x8000) != 0 {
remainder = (remainder << 1) ^ polynomial
} else {
remainder = (remainder << 1)
}
}
}
return remainder_order(remainder)
}
func crc16ccitt() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0xffff, polynomial: 0x1021)
}
func crc16ccitt_xmodem() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0x0000, polynomial: 0x1021)
}
func crc16ccitt_kermit() -> UInt16 {
let swap = crc16(data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x1021)
return swap.byteSwapped
}
func crc16ccitt_1d0f() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0x1d0f, polynomial: 0x1021)
}
func crc16ibm() -> UInt16 {
return crc16(data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x8005)
}
}
Example usage (code updated for Swift 4+):
let tData = Data([0x05, 0x02, 0x03])
print(String(format: "crc16ccitt: %04X", tData.crc16ccitt())) // 716D
print(String(format: "crc16ccitt_xmodem: %04X", tData.crc16ccitt_xmodem())) // BDF1
print(String(format: "crc16ccitt_kermit: %04X", tData.crc16ccitt_kermit())) // 9638
print(String(format: "crc16ccitt_1d0f: %04X", tData.crc16ccitt_1d0f())) // ACFD
print(String(format: "crc16ibm: %04X", tData.crc16ibm())) // 6051
These numbers coincide with the results from this Online CRC calculator.

Swift: error: cannot use mutating member on immutable value

I'm getting the above error in the following code. The Heap struct is from the Swift Algorithm Club. I'm using the Heap to solve a Hackerrank challenge: Heaps: Find the Running Median.
import Foundation
// Enter your code here
struct Heap<Element> {
var elements : [Element]
let priorityFunction : (Element, Element) -> Bool
init(elements: [Element] = [], priorityFunction: #escaping (Element, Element) -> Bool) {
self.elements = elements
self.priorityFunction = priorityFunction
buildHeap()
}
mutating func buildHeap() {
for index in (0 ..< count / 2).reversed() {
siftDown(elementAtIndex: index)
}
}
var isEmpty : Bool {
return elements.isEmpty
}
var count : Int {
return elements.count
}
func peek() -> Element? {
return elements.first
}
func isRoot(_ index: Int) -> Bool {
return (index == 0)
}
func leftChildIndex(of index: Int) -> Int {
return (2 * index) + 1
}
func rightChildIndex(of index: Int) -> Int {
return (2 * index) + 2
}
func parentIndex(of index: Int) -> Int {
return (index - 1) / 2
}
func isHigherPriority(at firstIndex: Int, than secondIndex: Int) -> Bool {
return priorityFunction(elements[firstIndex], elements[secondIndex])
}
func highestPriorityIndex(of parentIndex: Int, and childIndex: Int) -> Int {
guard childIndex < count && isHigherPriority(at: childIndex, than: parentIndex)
else { return parentIndex }
return childIndex
}
func highestPriorityIndex(for parent: Int) -> Int {
return highestPriorityIndex(of: highestPriorityIndex(of: parent, and: leftChildIndex(of: parent)), and: rightChildIndex(of: parent))
}
mutating func swapElement(at firstIndex: Int, with secondIndex: Int) {
guard firstIndex != secondIndex
else { return }
elements.swapAt(firstIndex, secondIndex)
}
mutating func enqueue(_ element: Element) {
elements.append(element)
siftUp(elementAtIndex: count - 1)
}
mutating func siftUp(elementAtIndex index: Int) {
let parent = parentIndex(of: index)
guard !isRoot(index),
isHigherPriority(at: index, than: parent)
else { return }
swapElement(at: index, with: parent)
siftUp(elementAtIndex: parent)
}
mutating func dequeue() -> Element? {
guard !isEmpty // 1
else { return nil }
swapElement(at: 0, with: count - 1) // 2
let element = elements.removeLast() // 3
if !isEmpty { // 4
siftDown(elementAtIndex: 0) // 5
}
return element // 6
}
mutating func siftDown(elementAtIndex index: Int) {
let childIndex = highestPriorityIndex(for: index) // 1
if index == childIndex { // 2
return
}
swapElement(at: index, with: childIndex) // 3
siftDown(elementAtIndex: childIndex)
}
}
var topHeap = Heap<Int>(priorityFunction: >)
var bottomHeap = Heap<Int>(priorityFunction: <)
let n = Int(readLine(strippingNewline: true)!)!
let val1 = Int(readLine(strippingNewline: true)!)!
print(String(format: "%.1f", Float(val1)))
if n > 1 {
let val2 = Int(readLine(strippingNewline: true)!)!
print(String(format: "%.1f", (Float(val1) + Float(val2)) / 2.0))
if val1 < val2 {
topHeap.enqueue(val1);
bottomHeap.enqueue(val2);
} else {
topHeap.enqueue(val2);
bottomHeap.enqueue(val1);
}
for _ in 2..<n {
let val = Int(readLine(strippingNewline: true)!)!
// Put in the proper heap
if val < topHeap.peek()! {
topHeap.enqueue(val)
} else if val > bottomHeap.peek()! {
bottomHeap.enqueue(val)
} else if topHeap.count < bottomHeap.count {
topHeap.enqueue(val)
} else {
bottomHeap.enqueue(val)
}
// If one heap has two more than the other, move one value
if topHeap.count == bottomHeap.count + 2 {
var element: Int = bottomHeap.dequeue
error: cannot use mutating member on immutable value: 'bottomHeap' is immutable
topHeap.enqueue(element)
} else if bottomHeap.count == topHeap.count + 2 {
bottomHeap.enqueue(topHeap.dequeue)
error: cannot use mutating member on immutable value: 'topHeap' is immutable
}
// If one heap has one more than the other, the top node of the larger heap holds the median
if topHeap.count == bottomHeap.count + 1 {
print(String(format: "%.1f", Float(topHeap.peek()!)))
} else if bottomHeap.count == topHeap.count + 1 {
print(String(format: "%.1f", Float(bottomHeap.peek()!)))
} else {
print(String(format: "%.1f", (Float(topHeap.peek()!) + Float(bottomHeap.peek()!)) / 2.0))
}
}
}
dequeue is a function. You need to add () to the calls.
Then you need to deal with the fact that dequeue() returns an optional Int.

Compiler issues when chaining multiple calls to the same method

I'm trying to fix this bug by overloading prefix(_ maxLength) for all lazy sequences and collections, but I'm running into weird compiler issues.
I'm using Xcode 9.0 beta 6 (9M214v), but it's also reproducable in all of the latest snapshots for 4.0.
Given the following iterator,...
public struct LazyPrefixIterator <Base: IteratorProtocol>: IteratorProtocol {
public typealias Element = Base.Element
private var baseIterator: Base
private let maxLength: Int
private var taken = 0
internal init (_ baseIterator: Base, _ maxLength: Int) {
precondition(maxLength >= 0, "Can't take a prefix of negative length from an iterator")
self.baseIterator = baseIterator
self.maxLength = maxLength
}
public mutating func next () -> Element? {
if self.taken >= self.maxLength {
return nil
}
self.taken += 1
return self.baseIterator.next()
}
}
...the following sequence,...
public struct LazyPrefixSequence <Base: Sequence>: LazySequenceProtocol {
public typealias Iterator = LazyPrefixIterator<Base.Iterator>
private let baseSequence: Base
private let maxLength: Int
internal init (_ baseSequence: Base, _ maxLength: Int) {
precondition(maxLength >= 0, "Can't take a prefix of negative length from a sequence")
self.baseSequence = baseSequence
self.maxLength = maxLength
}
public func makeIterator() -> Iterator {
return LazyPrefixIterator(self.baseSequence.makeIterator(), self.maxLength)
}
}
...the following collection...
public struct LazyPrefixCollection <Base: Collection>: LazyCollectionProtocol {
public typealias Iterator = LazyPrefixIterator<Base.Iterator>
public typealias Index = Base.Index
public typealias Element = Base.Element
private let baseCollection: Base
private let maxLength: Int
internal init (_ baseCollection: Base, _ maxLength: Int) {
precondition(maxLength >= 0, "Can't take a prefix of negative length from a collection")
self.baseCollection = baseCollection
self.maxLength = maxLength
}
public func makeIterator() -> Iterator {
return LazyPrefixIterator(self.baseCollection.makeIterator(), self.maxLength)
}
public var startIndex: Index {
return self.baseCollection.startIndex
}
public var endIndex: Index {
var maxLength = 0
var index = self.baseCollection.startIndex
let baseCollectionEndIndex = self.baseCollection.endIndex
while maxLength < self.maxLength && index != baseCollectionEndIndex {
index = self.baseCollection.index(after: index)
maxLength += 1
}
return index
}
public func index (after i: Index) -> Index {
precondition(i != self.endIndex, "Can't advance past endIndex")
return self.baseCollection.index(after: i)
}
public subscript (position: Index) -> Element {
precondition(position >= self.startIndex && position < self.endIndex, "Index out of range")
return self.baseCollection[position]
}
}
...and the following overloads (to squash ambiguity issues),...
public extension LazySequence {
func prefix (_ maxLength: Int) -> LazyPrefixSequence<Elements> {
return LazyPrefixSequence(self.elements, maxLength)
}
}
public extension LazySequenceProtocol {
func prefix (_ maxLength: Int) -> LazyPrefixSequence<Self> {
return LazyPrefixSequence(self, maxLength)
}
}
public extension LazyCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<Base> {
return LazyPrefixCollection(self.elements, maxLength)
}
}
public extension LazyCollectionProtocol {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<Self> {
return LazyPrefixCollection(self, maxLength)
}
}
public extension LazyDropWhileBidirectionalCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<LazyDropWhileBidirectionalCollection<Base>> {
return LazyPrefixCollection(self, maxLength)
}
}
public extension LazyPrefixWhileBidirectionalCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<LazyPrefixWhileBidirectionalCollection<Base>> {
return LazyPrefixCollection(self, maxLength)
}
}
public extension LazyRandomAccessCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<LazyRandomAccessCollection<Base>> {
return LazyPrefixCollection(self, maxLength)
}
}
...the following works as expected (each one of these prints true)...
print(Array(AnySequence(sequence(first: 0, next: {$0 + 1})).lazy.prefix(2)) == [0, 1])
print(Array(sequence(first: 0, next: {$0 + 1}).lazy.drop(while: {_ in false}).prefix(2)) == [0, 1])
print(Array(sequence(first: 0, next: {$0 + 1}).lazy.filter{_ in true}.prefix(2)) == [0, 1])
print(Array(sequence(first: 0, next: {$0 + 1}).lazy.map{$0}.prefix(2)) == [0, 1])
print(Array(sequence(first: 0, next: {$0 + 1}).lazy.prefix(while: {_ in true}).prefix(2)) == [0, 1])
print(Array(sequence(first: 0, next: {$0 + 1}).lazy.prefix(2)) == [0, 1])
print(Array(AnyCollection([0, 1, 2]).lazy.prefix(2)) == [0, 1])
print(Array(([0, 1, 2].lazy as LazyBidirectionalCollection).prefix(2)) == [0, 1])
print(Array([0, 1, 2].lazy.drop(while: {_ in false}).prefix(2)) == [0, 1])
print(Array(([0, 1, 2].lazy.drop(while: {_ in false}) as LazyDropWhileCollection).prefix(2)) == [0, 1])
print(Array([0, 1, 2].lazy.filter{_ in true}.prefix(2)) == [0, 1])
print(Array(([0, 1, 2].lazy.filter{_ in true} as LazyFilterCollection).prefix(2)) == [0, 1])
print(Array(([0, 1, 2].lazy.map{$0} as LazyMapBidirectionalCollection).prefix(2)) == [0, 1])
print(Array(([0, 1, 2].lazy.map{$0} as LazyMapCollection).prefix(2)) == [0, 1])
print(Array([0, 1, 2].lazy.map{$0}.prefix(2)) == [0, 1])
print(Array([0, 1, 2].lazy.prefix(while: {_ in true}).prefix(2)) == [0, 1])
print(Array(([0, 1, 2].lazy.prefix(while: {_ in true}) as LazyPrefixWhileCollection).prefix(2)) == [0, 1])
print(Array([0, 1, 2].lazy.prefix(2)) == [0, 1])
..., but, when chaining the method multiple times on a collection, weird compiler behaviour occurs. The following works with a return type of LazyPrefixCollection<LazyRandomAccessCollection<[Int]>>:
_ = [0, 1, 2].lazy.prefix(3)
The following works too, with a return type of LazyPrefixCollection<LazyPrefixCollection<LazyRandomAccessCollection<[Int]>>>:
_ = [0, 1, 2].lazy.prefix(3).prefix(3)
But once we add another method, it hiccups. It tells me that Expression type '()' is ambiguous without more context:
_ = [0, 1, 2].lazy.prefix(3).prefix(3).prefix(3)
If we add another one it segment faults while type-checking:
_ = [0, 1, 2].lazy.prefix(3).prefix(3).prefix(3).prefix(3)
Of course, creating intermediate variables for each 'step' works:
let a = [0, 1, 2].lazy.prefix(3)
let b = a.prefix(3)
let c = b.prefix(3)
let d = c.prefix(3)
// Etc.
It's also worth noting that it works when we use a sequence instead of a collection:
_ = sequence(first: 0, next: {(e: Int) -> Int in e + 1}).lazy.prefix(3).prefix(3).prefix(3).prefix(3).prefix(3)
Chaining multiple maps or any of the other methods from the standard library on a collection doesn't cause any issues. The compiler gladly excepts this monstrosity:
_ = [0, 1, 2].lazy.map{$0}.map{$0}.map{$0}.map{$0}.map{$0}.map{$0}
Which makes me believe I'm doing something wrong in my code, particularly in LazyPrefixCollection.
What could be causing this behaviour?
Adding overloads for prefix(_ maxLength) on LazyPrefixSequence and LazyPrefixCollection makes all compiler issues go away. The code then becomes the following:
public struct LazyPrefixIterator <Base: IteratorProtocol>: IteratorProtocol {
public typealias Element = Base.Element
private var baseIterator: Base
private let maxLength: Int
private var taken = 0
internal init (_ baseIterator: Base, _ maxLength: Int) {
precondition(maxLength >= 0, "Can't take a prefix of negative length from an iterator")
self.baseIterator = baseIterator
self.maxLength = maxLength
}
public mutating func next () -> Element? {
if self.taken >= self.maxLength {
return nil
}
self.taken += 1
return self.baseIterator.next()
}
}
public struct LazyPrefixSequence <Base: Sequence>: LazySequenceProtocol {
public typealias Iterator = LazyPrefixIterator<Base.Iterator>
private let baseSequence: Base
private let maxLength: Int
internal init (_ baseSequence: Base, _ maxLength: Int) {
precondition(maxLength >= 0, "Can't take a prefix of negative length from a sequence")
self.baseSequence = baseSequence
self.maxLength = maxLength
}
public func makeIterator() -> Iterator {
return LazyPrefixIterator(self.baseSequence.makeIterator(), self.maxLength)
}
}
public extension LazyPrefixSequence where Base.SubSequence: Sequence {
func prefix (_ maxLength: Int) -> LazyPrefixSequence {
return LazyPrefixSequence(self.baseSequence, Swift.min(self.maxLength, maxLength))
}
}
public struct LazyPrefixCollection <Base: Collection>: LazyCollectionProtocol {
public typealias Iterator = LazyPrefixIterator<Base.Iterator>
public typealias Index = Base.Index
public typealias Element = Base.Element
private let baseCollection: Base
private let maxLength: Int
internal init (_ baseCollection: Base, _ maxLength: Int) {
precondition(maxLength >= 0, "Can't take a prefix of negative length from a collection")
self.baseCollection = baseCollection
self.maxLength = maxLength
}
public func makeIterator() -> Iterator {
return LazyPrefixIterator(self.baseCollection.makeIterator(), self.maxLength)
}
public var startIndex: Index {
return self.baseCollection.startIndex
}
public var endIndex: Index {
var maxLength = 0
var index = self.baseCollection.startIndex
while maxLength < self.maxLength && index != self.baseCollection.endIndex {
index = self.baseCollection.index(after: index)
maxLength += 1
}
return index
}
public func index (after i: Index) -> Index {
precondition(i != self.endIndex, "Can't advance past endIndex")
return self.baseCollection.index(after: i)
}
public subscript (position: Index) -> Element {
precondition(position >= self.startIndex && position < self.endIndex, "Index out of range")
return self.baseCollection[position]
}
public func prefix (_ maxLength: Int) -> LazyPrefixCollection {
return LazyPrefixCollection(self.baseCollection, Swift.min(self.maxLength, maxLength))
}
}
public extension LazySequence {
func prefix (_ maxLength: Int) -> LazyPrefixSequence<Elements> {
return LazyPrefixSequence(self.elements, maxLength)
}
}
public extension LazySequenceProtocol {
func prefix (_ maxLength: Int) -> LazyPrefixSequence<Self> {
return LazyPrefixSequence(self, maxLength)
}
}
public extension LazyCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<Base> {
return LazyPrefixCollection(self.elements, maxLength)
}
}
public extension LazyCollectionProtocol {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<Self> {
return LazyPrefixCollection(self, maxLength)
}
}
public extension LazyDropWhileBidirectionalCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<LazyDropWhileBidirectionalCollection<Base>> {
return LazyPrefixCollection(self, maxLength)
}
}
public extension LazyPrefixWhileBidirectionalCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<LazyPrefixWhileBidirectionalCollection<Base>> {
return LazyPrefixCollection(self, maxLength)
}
}
public extension LazyRandomAccessCollection {
func prefix (_ maxLength: Int) -> LazyPrefixCollection<LazyRandomAccessCollection<Base>> {
return LazyPrefixCollection(self, maxLength)
}
}
Testing it:
let xs = [0, 1, 2, 3, 4].lazy.prefix(3).prefix(10).prefix(100).prefix(10).prefix(5).prefix(1)
let ys = sequence(first: 0, next: {$0 + 1}).lazy.prefix(3).prefix(10).prefix(100).prefix(10).prefix(5).prefix(1)
print(Array(xs)) // [0]
print(type(of: xs)) // LazyPrefixCollection<LazyRandomAccessCollection<Array<Int>>>
print(Array(ys)) // [0]
print(type(of: ys)) // LazyPrefixSequence<UnfoldSequence<Int, (Optional<Int>, Bool)>>
Feedback appreciated. Especially when it comes to the correct typealiases and where clauses. That stuff still feels like arbitrary voodoo black magic to me; if I don't put in the where Base.SubSequence: Sequence restriction on LazyPrefixSequence then it will ask me for a whole bunch of useless overloads on other methods. Why SubSequence doesn't conform to Sequence makes no sense to me.

Proper implementation of Sequence Protocol in a Class

I have been working on learning something about the Accelerate framework and am writing a Vector class to go along with my learning experience. I decided I needed to implement the Sequence protocol and after several false starts and much searching for relevant information to my problem finally came up with a solution that seems to work. Not sure if my solution is proper or not and would like comment if there are better ways to do this. Current code is a bit long but not super long so I will post it here.
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
}
}
I am exercising this with
//: 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)
}
and I seem to get the proper output. The Sequence protocol is in the first few lines of the VectorD class.
Your implementation of the Sequence protocol is not correct.
First, your makeIterator() method is not used at all because it has the wrong signature,
it does not return an Iterator. (You can remove that function from your code without changing anything.) Iterating over the vector elements works
because there is a default implementation of makeIterator() for all
iterators which are declared to conform to Sequence.
Second, your next() method uses an instance variable vindex
which is reset to zero after reaching the end of the iteration.
In other words, it is assumed that all elements are retrieved before
iterating the same vector again. This gives the unexpected output:
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]
Here is a possible implementation of the Sequence protocol:
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]
}
}
// ...
}
Note that vindex is now a local variable of makeIterator()
and captured by the closure. Calling makeIterator() again
will start from the beginning even if the previous iteration did
not retrieve all elements:
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]
Another possible implementation would be
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)
}
// ...
}
using the stride() method from the Swift standard
library.