Skip to content

Instantly share code, notes, and snippets.

@stefc
Last active January 10, 2023 11:55
Show Gist options
  • Save stefc/513c89cc6319b7401554 to your computer and use it in GitHub Desktop.
Save stefc/513c89cc6319b7401554 to your computer and use it in GitHub Desktop.
BitArray based on CFBitVector Swift implementation
//
// 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