-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPD5CompressedTable64.swift
92 lines (87 loc) · 2.51 KB
/
PD5CompressedTable64.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//
// PD5CompressedArray64.swift
// PD5UnitTests
//
// Created by Henry on 2019/05/23.
//
struct PD5CompressedTable64<T>: Sequence {
typealias Element = T
private var bitmap = UInt64(0b0)
private var slots = PD5ImmutableArray<T>()
@inlinable
var capacity: Int {
return 64
}
@inlinable
var count: Int {
return bitmap.nonzeroBitCount
}
@inlinable
func makeIterator() -> PD5ImmutableArray<T>.Iterator {
return slots.makeIterator()
}
@inlinable
func get(index k: UInt, default defv: @autoclosure() -> T) -> T {
assert(k < 64)
assert(0 <= k)
let mask = UInt64(0b1) << k
if (bitmap & mask).nonzeroBitCount == 0 {
// No value at index.
return defv()
}
else {
let countingMask = ~(UInt64(0xffff_ffff_ffff_ffff) << k)
let bitCount = (bitmap & countingMask).nonzeroBitCount
return slots[bitCount]
}
}
@inlinable
func get1(index k: UInt) -> T? {
assert(k < 64)
assert(0 <= k)
let mask = UInt64(0b1) << k
if (bitmap & mask).nonzeroBitCount == 0 {
// No value at index.
return nil
}
else {
let countingMask = ~(UInt64(0xffff_ffff_ffff_ffff) << k)
let bitCount = (bitmap & countingMask).nonzeroBitCount
return slots[bitCount]
}
}
@inlinable
mutating func set(index k: UInt, _ v: T) {
assert(k < 64)
assert(0 <= k)
let mask = UInt64(0b1) << k
let countingMask = ~(UInt64(0xffff_ffff_ffff_ffff) << k)
let bitCount = (bitmap & countingMask).nonzeroBitCount
if (bitmap & mask).nonzeroBitCount == 0 {
// No value at index.
bitmap |= mask
slots.insert(v, at: bitCount)
}
else {
slots[bitCount] = v
}
}
@inlinable
mutating func unset(index k: UInt) {
assert(k < 64)
assert(0 <= k)
let mask = UInt64(0b1) << k
let countingMask = ~(UInt64(0xffff_ffff_ffff_ffff) << k)
let bitCount = (bitmap & countingMask).nonzeroBitCount
if (bitmap & mask).nonzeroBitCount == 0 {
// No value at index.
// Nothing to do.
}
else {
slots.remove(at: bitCount)
bitmap &= ~mask
}
}
}
/// Two tables are equal if all elements at same positions are equal.
extension PD5CompressedTable64: Equatable where T: Equatable {}