Last active
January 10, 2023 11:55
-
-
Save stefc/513c89cc6319b7401554 to your computer and use it in GitHub Desktop.
BitArray based on CFBitVector Swift implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// BitArray.swift | |
// xFuncs | |
// | |
import Foundation | |
public class BitArray : CollectionType { | |
public typealias Index = Int | |
public typealias _Element = Bool | |
public private(set) var bitvector : CFBitVector | |
init(vector: CFBitVector) { | |
self.bitvector = CFBitVectorCreateCopy( kCFAllocatorDefault, vector) | |
} | |
public convenience init(_ values: [Bool]) { | |
let vector = CFBitVectorCreateMutable( kCFAllocatorDefault, values.count) | |
CFBitVectorSetCount(vector, values.count) | |
zip(0..<values.count, values) | |
.filter( {$0.1} ) | |
.map( {$0.0} ) | |
.forEach { CFBitVectorSetBitAtIndex(vector, $0, 1) } | |
self.init(vector: vector) | |
} | |
public init(rawValue: [UInt8]) { | |
let data = NSData(bytes: rawValue, length: rawValue.count) | |
let vector = CFBitVectorCreate(kCFAllocatorDefault, UnsafePointer(data.bytes), rawValue.count * 8) | |
self.bitvector = vector | |
} | |
public var startIndex: Index | |
{ | |
get { return 0 } | |
} | |
public var endIndex: Index | |
{ | |
get | |
{ | |
return CFBitVectorGetCount(bitvector) | |
} | |
} | |
public subscript (index: Index) -> _Element | |
{ | |
return CFBitVectorGetBitAtIndex(bitvector, index) == 1 | |
} | |
public func generate() -> Generator { | |
return Generator(vector: self.bitvector) | |
} | |
public struct Generator: GeneratorType { | |
let vector: CFBitVector | |
private var current : Int = 0 | |
private var count : Int = 0 | |
init(vector: CFBitVector) { | |
self.vector = vector | |
self.count = CFBitVectorGetCount(vector) | |
} | |
public mutating func next() -> Bool? { | |
if current >= count { | |
return nil | |
} | |
else { | |
let result = CFBitVectorGetBitAtIndex(vector, current) == 1 | |
current++ | |
return result | |
} | |
} | |
} | |
public var rawValue : [UInt8] { | |
get { | |
let count = self.count | |
let nbytes = (count + 7) / 8 | |
var bytes : [UInt8] = [UInt8](count: nbytes, repeatedValue: 0) | |
CFBitVectorGetBits(bitvector, CFRange(location: 0, length: count), &bytes) | |
return bytes | |
} | |
} | |
private func rol(step: Int, len: Int) -> BitArray { | |
let vector = CFBitVectorCreateMutable( kCFAllocatorDefault, len) | |
CFBitVectorSetCount(vector, len) | |
(0..<len).forEach { | |
CFBitVectorSetBitAtIndex(vector, $0, | |
CFBitVectorGetBitAtIndex(self.bitvector, ($0 + step) % len)) } | |
return BitArray(vector: vector) | |
} | |
func rol(step: Int) -> BitArray { | |
let len = CFBitVectorGetCount(bitvector) | |
return rol(step, len: len) | |
} | |
func ror(step: Int) -> BitArray { | |
let len = CFBitVectorGetCount(bitvector) | |
return rol(len - step, len: len) | |
} | |
func shl(step: Int) -> BitArray { | |
let len = CFBitVectorGetCount(bitvector) | |
let vector = CFBitVectorCreateMutable( kCFAllocatorDefault, len) | |
CFBitVectorSetCount(vector, len) | |
(0..<len-step).forEach { | |
CFBitVectorSetBitAtIndex(vector, $0, | |
CFBitVectorGetBitAtIndex(self.bitvector, $0 + step)) } | |
return BitArray(vector: vector) | |
} | |
func shr(step: Int) -> BitArray { | |
let len = CFBitVectorGetCount(bitvector) | |
let vector = CFBitVectorCreateMutable( kCFAllocatorDefault, len) | |
CFBitVectorSetCount(vector, len) | |
(step..<len).forEach { | |
CFBitVectorSetBitAtIndex(vector, $0, | |
CFBitVectorGetBitAtIndex(self.bitvector, $0 - step)) } | |
return BitArray(vector: vector) | |
} | |
} | |
// logical conjunction (And) | |
public func &(left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { $0.0 & $0.1 })) | |
} | |
infix operator ∧ { associativity left precedence 120 } | |
public func ∧ (left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { $0.0 & $0.1 })) | |
} | |
// logical disjunction (Or) | |
public func |(left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { $0.0 | $0.1 })) | |
} | |
infix operator ∨ { associativity left precedence 110 } | |
public func ∨ (left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { $0.0 | $0.1 })) | |
} | |
// Exclusive disjunction (Xor) | |
public func ^(left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { $0.0 ^ $0.1 })) | |
} | |
infix operator ⊻ { associativity left precedence 110 } // Unicode: U+22BB | |
public func ⊻ (left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { $0.0 ^ $0.1 })) | |
} | |
// Nand | |
infix operator ⊼ { associativity left precedence 110 } // Unicode: U+22BC | |
public func ⊼ (left: BitArray, right: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](zip(left.rawValue, right.rawValue).map { ~($0.0 & $0.1) })) | |
} | |
// logical negation (Negate) | |
public prefix func ~(operand: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](operand.rawValue.map { ~$0 })) | |
} | |
prefix operator ¬ {} | |
public prefix func ¬(operand: BitArray) -> BitArray { | |
return BitArray(rawValue: [UInt8](operand.rawValue.map { ~$0 })) | |
} | |
// logical rotation | |
infix operator ⟳ {} // Unicode: U+27F3 | |
infix operator ⟲ {} // Unicode: U+27F2 | |
public func ⟳(operand: BitArray, step: Int) -> BitArray { | |
return operand.ror(step) | |
} | |
public func ⟲(operand: BitArray, step: Int) -> BitArray { | |
return operand.rol(step) | |
} | |
// logical shift | |
infix operator ⊲ {} // Unicode: U+22B2 | |
infix operator ⊳ {} // Unicode: U+22B3 | |
public func ⊲(operand: BitArray, step: Int) -> BitArray { | |
return operand.shl(step) | |
} | |
public func ⊳(operand: BitArray, step: Int) -> BitArray { | |
return operand.shr(step) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment