@blackglory/structures 0.14.14 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +661 -92
- package/lib/async-generator-emitter.js +2 -5
- package/lib/async-generator-emitter.js.map +1 -1
- package/lib/big-map.js +1 -3
- package/lib/big-map.js.map +1 -1
- package/lib/big-set.js +1 -3
- package/lib/big-set.js.map +1 -1
- package/lib/{bit-set.d.ts → bit-set/bit-set.d.ts} +5 -2
- package/lib/{bit-set.js → bit-set/bit-set.js} +43 -34
- package/lib/bit-set/bit-set.js.map +1 -0
- package/lib/{typed-bit-set.d.ts → bit-set/dynamic-typed-bit-set.d.ts} +6 -4
- package/lib/bit-set/dynamic-typed-bit-set.js +95 -0
- package/lib/bit-set/dynamic-typed-bit-set.js.map +1 -0
- package/lib/bit-set/index.d.ts +4 -0
- package/lib/bit-set/index.js +5 -0
- package/lib/bit-set/index.js.map +1 -0
- package/lib/bit-set/resizable-typed-bit-set.d.ts +22 -0
- package/lib/{typed-bit-set.js → bit-set/resizable-typed-bit-set.js} +37 -39
- package/lib/bit-set/resizable-typed-bit-set.js.map +1 -0
- package/lib/bit-set/typed-bit-set.d.ts +22 -0
- package/lib/bit-set/typed-bit-set.js +99 -0
- package/lib/bit-set/typed-bit-set.js.map +1 -0
- package/lib/box.js +1 -0
- package/lib/box.js.map +1 -1
- package/lib/disjoint-set.js +2 -4
- package/lib/disjoint-set.js.map +1 -1
- package/lib/dynamic-typed-array.d.ts +12 -9
- package/lib/dynamic-typed-array.js +51 -66
- package/lib/dynamic-typed-array.js.map +1 -1
- package/lib/emitter.js +3 -7
- package/lib/emitter.js.map +1 -1
- package/lib/expirable-map.js +9 -15
- package/lib/expirable-map.js.map +1 -1
- package/lib/generator-emitter.js +2 -5
- package/lib/generator-emitter.js.map +1 -1
- package/lib/hash-map.js +2 -1
- package/lib/hash-map.js.map +1 -1
- package/lib/hash-set.js +2 -1
- package/lib/hash-set.js.map +1 -1
- package/lib/index.d.ts +5 -7
- package/lib/index.js +5 -7
- package/lib/index.js.map +1 -1
- package/lib/lru-map.js +2 -1
- package/lib/lru-map.js.map +1 -1
- package/lib/queue.js +1 -3
- package/lib/queue.js.map +1 -1
- package/lib/radix-tree.js +6 -7
- package/lib/radix-tree.js.map +1 -1
- package/lib/resizable-typed-array.d.ts +32 -0
- package/lib/resizable-typed-array.js +127 -0
- package/lib/resizable-typed-array.js.map +1 -0
- package/lib/sorted-set.js +2 -1
- package/lib/sorted-set.js.map +1 -1
- package/lib/sparse-map/clean-sparse-map.d.ts +18 -0
- package/lib/sparse-map/clean-sparse-map.js +74 -0
- package/lib/sparse-map/clean-sparse-map.js.map +1 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js +87 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.js +94 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/index.d.ts +10 -0
- package/lib/sparse-map/index.js +11 -0
- package/lib/sparse-map/index.js.map +1 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js +85 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.js +92 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.js.map +1 -0
- package/lib/{sparse-map.d.ts → sparse-map/sparse-map.d.ts} +6 -5
- package/lib/sparse-map/sparse-map.js +86 -0
- package/lib/sparse-map/sparse-map.js.map +1 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.js +92 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/typed-clean-sparse-map.d.ts +22 -0
- package/lib/sparse-map/typed-clean-sparse-map.js +117 -0
- package/lib/sparse-map/typed-clean-sparse-map.js.map +1 -0
- package/lib/sparse-map/typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/typed-sparse-map-lite.js +109 -0
- package/lib/sparse-map/typed-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/typed-sparse-map.d.ts +21 -0
- package/lib/sparse-map/typed-sparse-map.js +130 -0
- package/lib/sparse-map/typed-sparse-map.js.map +1 -0
- package/lib/sparse-set/clean-sparse-set.d.ts +13 -0
- package/lib/sparse-set/clean-sparse-set.js +57 -0
- package/lib/sparse-set/clean-sparse-set.js.map +1 -0
- package/lib/{typed-sparse-set.d.ts → sparse-set/dynamic-typed-clean-sparse-set-lite.d.ts} +6 -6
- package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js +51 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.js +82 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.js +52 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.js +75 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.js.map +1 -0
- package/lib/sparse-set/index.d.ts +14 -0
- package/lib/sparse-set/index.js +15 -0
- package/lib/sparse-set/index.js.map +1 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js +51 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.js +83 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.js +52 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/resizable-typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-sparse-set.js +76 -0
- package/lib/sparse-set/resizable-typed-sparse-set.js.map +1 -0
- package/lib/{sparse-set.d.ts → sparse-set/sparse-set.d.ts} +3 -4
- package/lib/sparse-set/sparse-set.js +60 -0
- package/lib/sparse-set/sparse-set.js.map +1 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.js +55 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/typed-clean-sparse-set.js +80 -0
- package/lib/sparse-set/typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/typed-sparse-set-lite.js +60 -0
- package/lib/sparse-set/typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/typed-sparse-set.js +81 -0
- package/lib/sparse-set/typed-sparse-set.js.map +1 -0
- package/lib/string-radix-tree.js +6 -7
- package/lib/string-radix-tree.js.map +1 -1
- package/lib/string-trie-map.js +3 -4
- package/lib/string-trie-map.js.map +1 -1
- package/lib/tlru-map.js +6 -6
- package/lib/tlru-map.js.map +1 -1
- package/lib/trie-map.js +3 -4
- package/lib/trie-map.js.map +1 -1
- package/lib/unique-queue.js +1 -3
- package/lib/unique-queue.js.map +1 -1
- package/lib/utils/compute-new-capacity.d.ts +1 -0
- package/lib/utils/compute-new-capacity.js +36 -0
- package/lib/utils/compute-new-capacity.js.map +1 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.d.ts +3 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.js +13 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.js.map +1 -0
- package/lib/utils/skip-list.js +11 -9
- package/lib/utils/skip-list.js.map +1 -1
- package/lib/utils/trailing-zeros.js +1 -1
- package/lib/utils/trailing-zeros.js.map +1 -1
- package/package.json +28 -31
- package/src/{bit-set.ts → bit-set/bit-set.ts} +47 -31
- package/src/bit-set/dynamic-typed-bit-set.ts +131 -0
- package/src/bit-set/index.ts +4 -0
- package/src/{typed-bit-set.ts → bit-set/resizable-typed-bit-set.ts} +38 -36
- package/src/bit-set/typed-bit-set.ts +134 -0
- package/src/dynamic-typed-array.ts +67 -82
- package/src/index.ts +5 -7
- package/src/radix-tree.ts +3 -3
- package/src/resizable-typed-array.ts +214 -0
- package/src/sparse-map/clean-sparse-map.ts +84 -0
- package/src/sparse-map/dynamic-typed-clean-sparse-map-lite.ts +109 -0
- package/src/sparse-map/dynamic-typed-sparse-map-lite.ts +124 -0
- package/src/sparse-map/index.ts +11 -0
- package/src/sparse-map/resizable-typed-clean-sparse-map-lite.ts +107 -0
- package/src/sparse-map/resizable-typed-sparse-map-lite.ts +122 -0
- package/src/sparse-map/sparse-map.ts +104 -0
- package/src/sparse-map/typed-clean-sparse-map-lite.ts +116 -0
- package/src/sparse-map/typed-clean-sparse-map.ts +149 -0
- package/src/sparse-map/typed-sparse-map-lite.ts +141 -0
- package/src/sparse-map/typed-sparse-map.ts +169 -0
- package/src/sparse-set/clean-sparse-set.ts +76 -0
- package/src/sparse-set/dynamic-typed-clean-sparse-set-lite.ts +64 -0
- package/src/sparse-set/dynamic-typed-clean-sparse-set.ts +101 -0
- package/src/sparse-set/dynamic-typed-sparse-set-lite.ts +67 -0
- package/src/sparse-set/dynamic-typed-sparse-set.ts +93 -0
- package/src/sparse-set/index.ts +15 -0
- package/src/sparse-set/resizable-typed-clean-sparse-set-lite.ts +64 -0
- package/src/sparse-set/resizable-typed-clean-sparse-set.ts +108 -0
- package/src/sparse-set/resizable-typed-sparse-set-lite.ts +67 -0
- package/src/sparse-set/resizable-typed-sparse-set.ts +97 -0
- package/src/sparse-set/sparse-set.ts +79 -0
- package/src/sparse-set/typed-clean-sparse-set-lite.ts +67 -0
- package/src/sparse-set/typed-clean-sparse-set.ts +100 -0
- package/src/sparse-set/typed-sparse-set-lite.ts +74 -0
- package/src/sparse-set/typed-sparse-set.ts +102 -0
- package/src/string-radix-tree.ts +3 -3
- package/src/utils/compute-new-capacity.ts +39 -0
- package/src/utils/get-max-value-of-unsigned-typed-array.ts +19 -0
- package/src/utils/skip-list.ts +1 -1
- package/src/utils/trailing-zeros.ts +2 -3
- package/lib/bit-set.js.map +0 -1
- package/lib/sparse-map.js +0 -76
- package/lib/sparse-map.js.map +0 -1
- package/lib/sparse-set.js +0 -63
- package/lib/sparse-set.js.map +0 -1
- package/lib/typed-bit-set.js.map +0 -1
- package/lib/typed-sparse-map.d.ts +0 -20
- package/lib/typed-sparse-map.js +0 -83
- package/lib/typed-sparse-map.js.map +0 -1
- package/lib/typed-sparse-set.js +0 -59
- package/lib/typed-sparse-set.js.map +0 -1
- package/src/sparse-map.ts +0 -82
- package/src/sparse-set.ts +0 -74
- package/src/typed-sparse-map.ts +0 -97
- package/src/typed-sparse-set.ts +0 -73
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { assert } from '@blackglory/errors'
|
|
2
|
+
import { TypedArrayConstructor, UnsignedTypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
|
|
3
|
+
import { ResizableTypedArray } from '@src/resizable-typed-array.js'
|
|
4
|
+
|
|
5
|
+
export class ResizableTypedSparseMapLite<
|
|
6
|
+
K extends UnsignedTypedArrayConstructor
|
|
7
|
+
, V extends TypedArrayConstructor
|
|
8
|
+
> {
|
|
9
|
+
private denseKeys: ResizableTypedArray<K>
|
|
10
|
+
private denseValues: ResizableTypedArray<V>
|
|
11
|
+
private sparse: Array<number | undefined> = []
|
|
12
|
+
|
|
13
|
+
readonly internalKeyArray: TypedArrayOfConstructor<K>
|
|
14
|
+
readonly internalValueArray: TypedArrayOfConstructor<V>
|
|
15
|
+
|
|
16
|
+
get [Symbol.toStringTag](): string {
|
|
17
|
+
return this.constructor.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get size(): number {
|
|
21
|
+
return this.denseKeys.length
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
keys: ResizableTypedArray<K>
|
|
26
|
+
, values: ResizableTypedArray<V>
|
|
27
|
+
) {
|
|
28
|
+
assert(keys.length === 0, 'values must be empty')
|
|
29
|
+
|
|
30
|
+
this.denseKeys = keys
|
|
31
|
+
this.denseValues = values
|
|
32
|
+
|
|
33
|
+
this.internalKeyArray = keys.internalTypedArray
|
|
34
|
+
this.internalValueArray = values.internalTypedArray
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
* entries(): IterableIterator<[key: number, value: number]> {
|
|
38
|
+
for (let i = 0; i < this.denseKeys.length; i++) {
|
|
39
|
+
yield [
|
|
40
|
+
this.denseKeys.internalTypedArray[i]
|
|
41
|
+
, this.denseValues.internalTypedArray[i]
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
keys(): IterableIterator<number> {
|
|
47
|
+
return this.denseKeys.values()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
values(): IterableIterator<number> {
|
|
51
|
+
return this.denseValues.values()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getInternalIndexOfKey(key: number): number | undefined {
|
|
55
|
+
const index = this.sparse[key]
|
|
56
|
+
if (
|
|
57
|
+
index !== undefined &&
|
|
58
|
+
this.denseKeys.get(index) === key
|
|
59
|
+
) {
|
|
60
|
+
return index
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
has(key: number): boolean {
|
|
65
|
+
const index = this.sparse[key]
|
|
66
|
+
return index !== undefined
|
|
67
|
+
&& this.denseKeys.get(index) === key
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get(key: number): number | undefined {
|
|
71
|
+
const index = this.sparse[key]
|
|
72
|
+
if (
|
|
73
|
+
index !== undefined &&
|
|
74
|
+
this.denseKeys.get(index) === key
|
|
75
|
+
) {
|
|
76
|
+
return this.denseValues.internalTypedArray[index]
|
|
77
|
+
} else {
|
|
78
|
+
return undefined
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
set(key: number, value: number): void {
|
|
83
|
+
const index = this.sparse[key]
|
|
84
|
+
if (
|
|
85
|
+
index !== undefined &&
|
|
86
|
+
this.denseKeys.get(index) === key
|
|
87
|
+
) {
|
|
88
|
+
this.denseValues.internalTypedArray[index] = value
|
|
89
|
+
} else {
|
|
90
|
+
const index = this.denseKeys.length
|
|
91
|
+
this.denseKeys.push(key)
|
|
92
|
+
this.denseValues.push(value)
|
|
93
|
+
this.sparse[key] = index
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
delete(key: number): boolean {
|
|
98
|
+
const index = this.sparse[key]
|
|
99
|
+
if (
|
|
100
|
+
index !== undefined &&
|
|
101
|
+
this.denseKeys.get(index) === key
|
|
102
|
+
) {
|
|
103
|
+
const lastKey = this.denseKeys.pop()!
|
|
104
|
+
const lastValue = this.denseValues.pop()!
|
|
105
|
+
if (key !== lastKey) {
|
|
106
|
+
this.denseKeys.internalTypedArray[index] = lastKey
|
|
107
|
+
this.denseValues.internalTypedArray[index] = lastValue
|
|
108
|
+
this.sparse[lastKey] = index
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return true
|
|
112
|
+
} else {
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
clear(): void {
|
|
118
|
+
this.denseKeys.clear()
|
|
119
|
+
this.denseValues.clear()
|
|
120
|
+
// 无需清空sparse数组.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export class SparseMap<T> {
|
|
2
|
+
private denseKeys: number[] = []
|
|
3
|
+
private denseValues: T[] = []
|
|
4
|
+
private sparse: Array<number | undefined> = []
|
|
5
|
+
|
|
6
|
+
get [Symbol.toStringTag](): string {
|
|
7
|
+
return this.constructor.name
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get size(): number {
|
|
11
|
+
return this.denseKeys.length
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
readonly internalKeyArray: readonly number[] = this.denseKeys
|
|
15
|
+
readonly internalValueArray: T[] = this.denseValues
|
|
16
|
+
|
|
17
|
+
;* entries(): IterableIterator<[key: number, value: T]> {
|
|
18
|
+
for (let i = 0; i < this.denseKeys.length; i++) {
|
|
19
|
+
yield [this.denseKeys[i], this.denseValues[i]]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
keys(): IterableIterator<number> {
|
|
24
|
+
return this.denseKeys.values()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
values(): IterableIterator<T> {
|
|
28
|
+
return this.denseValues.values()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getInternalIndexOfKey(key: number): number | undefined {
|
|
32
|
+
const index = this.sparse[key]
|
|
33
|
+
if (
|
|
34
|
+
index !== undefined &&
|
|
35
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
36
|
+
this.denseKeys[index] === key
|
|
37
|
+
) {
|
|
38
|
+
return index
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
has(key: number): boolean {
|
|
43
|
+
const index = this.sparse[key]
|
|
44
|
+
return index !== undefined
|
|
45
|
+
&& index < this.denseKeys.length // 用于改善JIT优化.
|
|
46
|
+
&& this.denseKeys[index] === key
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get(key: number): T | undefined {
|
|
50
|
+
const index = this.sparse[key]
|
|
51
|
+
if (
|
|
52
|
+
index !== undefined &&
|
|
53
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
54
|
+
this.denseKeys[index] === key
|
|
55
|
+
) {
|
|
56
|
+
return this.denseValues[index]
|
|
57
|
+
} else {
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
set(key: number, value: T): void {
|
|
63
|
+
const index = this.sparse[key]
|
|
64
|
+
if (
|
|
65
|
+
index !== undefined &&
|
|
66
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
67
|
+
this.denseKeys[index] === key
|
|
68
|
+
) {
|
|
69
|
+
this.denseValues[index] = value
|
|
70
|
+
} else {
|
|
71
|
+
const index = this.denseKeys.length
|
|
72
|
+
this.denseKeys.push(key)
|
|
73
|
+
this.denseValues.push(value)
|
|
74
|
+
this.sparse[key] = index
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
delete(key: number): boolean {
|
|
79
|
+
const index = this.sparse[key]
|
|
80
|
+
if (
|
|
81
|
+
index !== undefined &&
|
|
82
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
83
|
+
this.denseKeys[index] === key
|
|
84
|
+
) {
|
|
85
|
+
const lastKey = this.denseKeys.pop()!
|
|
86
|
+
const lastValue = this.denseValues.pop()!
|
|
87
|
+
if (key !== lastKey) {
|
|
88
|
+
this.denseKeys[index] = lastKey
|
|
89
|
+
this.denseValues[index] = lastValue
|
|
90
|
+
this.sparse[lastKey] = index
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return true
|
|
94
|
+
} else {
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
clear(): void {
|
|
100
|
+
this.denseKeys.length = 0
|
|
101
|
+
this.denseValues.length = 0
|
|
102
|
+
// 无需清空sparse数组.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { assert } from '@blackglory/errors'
|
|
2
|
+
import { TypedArrayConstructor, UnsignedTypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
|
|
3
|
+
|
|
4
|
+
export class TypedCleanSparseMapLite<
|
|
5
|
+
K extends UnsignedTypedArrayConstructor
|
|
6
|
+
, V extends TypedArrayConstructor
|
|
7
|
+
> {
|
|
8
|
+
private denseKeys: TypedArrayOfConstructor<K>
|
|
9
|
+
private denseValues: TypedArrayOfConstructor<V>
|
|
10
|
+
private sparse: Array<number | undefined> = []
|
|
11
|
+
#length = 0
|
|
12
|
+
|
|
13
|
+
readonly internalKeyArray: TypedArrayOfConstructor<K, ArrayBuffer>
|
|
14
|
+
readonly internalValueArray: TypedArrayOfConstructor<V, ArrayBuffer>
|
|
15
|
+
|
|
16
|
+
get [Symbol.toStringTag](): string {
|
|
17
|
+
return this.constructor.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get size(): number {
|
|
21
|
+
return this.#length
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
keys: TypedArrayOfConstructor<K, ArrayBuffer>
|
|
26
|
+
, values: TypedArrayOfConstructor<V, ArrayBuffer>
|
|
27
|
+
) {
|
|
28
|
+
assert(!keys.buffer.resizable, 'The keys buffer must not be resizable')
|
|
29
|
+
assert(!values.buffer.resizable, 'The values buffer must not be resizable')
|
|
30
|
+
assert(
|
|
31
|
+
values.length >= keys.length
|
|
32
|
+
, 'The values.length must greater than or equal to keys.length'
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
this.denseKeys = keys
|
|
36
|
+
this.denseValues = values
|
|
37
|
+
|
|
38
|
+
this.internalKeyArray = keys
|
|
39
|
+
this.internalValueArray = values
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
* entries(): IterableIterator<[key: number, value: number]> {
|
|
43
|
+
for (let i = 0; i < this.#length; i++) {
|
|
44
|
+
yield [
|
|
45
|
+
this.denseKeys[i]
|
|
46
|
+
, this.denseValues[i]
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
* keys(): IterableIterator<number> {
|
|
52
|
+
for (let i = 0; i < this.#length; i++) {
|
|
53
|
+
yield this.denseKeys[i]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
* values(): IterableIterator<number> {
|
|
58
|
+
for (let i = 0; i < this.#length; i++) {
|
|
59
|
+
yield this.denseValues[i]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getInternalIndexOfKey(key: number): number | undefined {
|
|
64
|
+
return this.sparse[key]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
has(key: number): boolean {
|
|
68
|
+
return this.sparse[key] !== undefined
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get(key: number): number | undefined {
|
|
72
|
+
const index = this.sparse[key]
|
|
73
|
+
if (index !== undefined) {
|
|
74
|
+
return this.denseValues[index]
|
|
75
|
+
} else {
|
|
76
|
+
return undefined
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
set(key: number, value: number): void {
|
|
81
|
+
const index = this.sparse[key]
|
|
82
|
+
if (index !== undefined) {
|
|
83
|
+
this.denseValues[index] = value
|
|
84
|
+
} else {
|
|
85
|
+
const index = this.#length++
|
|
86
|
+
this.denseKeys[index] = key
|
|
87
|
+
this.denseValues[index] = value
|
|
88
|
+
this.sparse[key] = index
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
delete(key: number): boolean {
|
|
93
|
+
const index = this.sparse[key]
|
|
94
|
+
if (index !== undefined) {
|
|
95
|
+
this.sparse[key] = undefined
|
|
96
|
+
|
|
97
|
+
const lastIndex = --this.#length
|
|
98
|
+
const lastKey = this.denseKeys[lastIndex]
|
|
99
|
+
const lastValue = this.denseValues[lastIndex]
|
|
100
|
+
if (key !== lastKey) {
|
|
101
|
+
this.denseKeys[index] = lastKey
|
|
102
|
+
this.denseValues[index] = lastValue
|
|
103
|
+
this.sparse[lastKey] = index
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true
|
|
107
|
+
} else {
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
clear(): void {
|
|
113
|
+
this.#length = 0
|
|
114
|
+
this.sparse.length = 0
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { assert } from '@blackglory/errors'
|
|
2
|
+
import { go } from '@blackglory/go'
|
|
3
|
+
import { getMaxValueOfUnsignedTypedArray, getMaxValueOfUnsignedTypedArrayConstructor } from '@utils/get-max-value-of-unsigned-typed-array.js'
|
|
4
|
+
import { TypedArrayConstructor, UnsignedTypedArrayConstructor, TypedArrayOfConstructor, UnsignedTypedArray } from 'justypes'
|
|
5
|
+
|
|
6
|
+
export class TypedCleanSparseMap<
|
|
7
|
+
K extends UnsignedTypedArrayConstructor
|
|
8
|
+
, V extends TypedArrayConstructor
|
|
9
|
+
> {
|
|
10
|
+
private denseKeys: TypedArrayOfConstructor<K>
|
|
11
|
+
private denseValues: TypedArrayOfConstructor<V>
|
|
12
|
+
private sparse: UnsignedTypedArray
|
|
13
|
+
private readonly NULL: number
|
|
14
|
+
#length = 0
|
|
15
|
+
|
|
16
|
+
readonly internalKeyArray: TypedArrayOfConstructor<K, ArrayBuffer>
|
|
17
|
+
readonly internalValueArray: TypedArrayOfConstructor<V, ArrayBuffer>
|
|
18
|
+
|
|
19
|
+
get [Symbol.toStringTag](): string {
|
|
20
|
+
return this.constructor.name
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get size(): number {
|
|
24
|
+
return this.#length
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
keys: TypedArrayOfConstructor<K, ArrayBuffer>
|
|
29
|
+
, values: TypedArrayOfConstructor<V, ArrayBuffer>
|
|
30
|
+
) {
|
|
31
|
+
assert(!keys.buffer.resizable, 'The keys buffer must not be resizable')
|
|
32
|
+
assert(!values.buffer.resizable, 'The values buffer must not be resizable')
|
|
33
|
+
assert(
|
|
34
|
+
values.length >= keys.length
|
|
35
|
+
, 'The values.length must greater than or equal to keys.length'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
this.denseKeys = keys
|
|
39
|
+
this.denseValues = values
|
|
40
|
+
|
|
41
|
+
this.internalKeyArray = keys
|
|
42
|
+
this.internalValueArray = values
|
|
43
|
+
|
|
44
|
+
const NULL = Math.min(
|
|
45
|
+
keys.length
|
|
46
|
+
, getMaxValueOfUnsignedTypedArray(keys) + 1
|
|
47
|
+
)
|
|
48
|
+
this.NULL = NULL
|
|
49
|
+
|
|
50
|
+
const sparseConstructor = go(() => {
|
|
51
|
+
if (
|
|
52
|
+
NULL <=
|
|
53
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint8Array)
|
|
54
|
+
) {
|
|
55
|
+
return Uint8Array
|
|
56
|
+
} else if (
|
|
57
|
+
NULL <=
|
|
58
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint16Array)
|
|
59
|
+
) {
|
|
60
|
+
return Uint16Array
|
|
61
|
+
} else if (
|
|
62
|
+
NULL <=
|
|
63
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint32Array)
|
|
64
|
+
) {
|
|
65
|
+
return Uint32Array
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error('The array is too large')
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
const sparse = new sparseConstructor(getMaxValueOfUnsignedTypedArray(keys) + 1)
|
|
71
|
+
sparse.fill(NULL)
|
|
72
|
+
this.sparse = sparse
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
* entries(): IterableIterator<[key: number, value: number]> {
|
|
76
|
+
for (let i = 0; i < this.#length; i++) {
|
|
77
|
+
yield [
|
|
78
|
+
this.denseKeys[i]
|
|
79
|
+
, this.denseValues[i]
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
* keys(): IterableIterator<number> {
|
|
85
|
+
for (let i = 0; i < this.#length; i++) {
|
|
86
|
+
yield this.denseKeys[i]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
* values(): IterableIterator<number> {
|
|
91
|
+
for (let i = 0; i < this.#length; i++) {
|
|
92
|
+
yield this.denseValues[i]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getInternalIndexOfKey(key: number): number | undefined {
|
|
97
|
+
return this.sparse[key]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
has(key: number): boolean {
|
|
101
|
+
return this.sparse[key] !== this.NULL
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get(key: number): number | undefined {
|
|
105
|
+
const index = this.sparse[key]
|
|
106
|
+
if (index !== this.NULL) {
|
|
107
|
+
return this.denseValues[index]
|
|
108
|
+
} else {
|
|
109
|
+
return undefined
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
set(key: number, value: number): void {
|
|
114
|
+
const index = this.sparse[key]
|
|
115
|
+
if (index !== this.NULL) {
|
|
116
|
+
this.denseValues[index] = value
|
|
117
|
+
} else {
|
|
118
|
+
const index = this.#length++
|
|
119
|
+
this.denseKeys[index] = key
|
|
120
|
+
this.denseValues[index] = value
|
|
121
|
+
this.sparse[key] = index
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
delete(key: number): boolean {
|
|
126
|
+
const index = this.sparse[key]
|
|
127
|
+
if (index !== this.NULL) {
|
|
128
|
+
this.sparse[key] = this.NULL
|
|
129
|
+
|
|
130
|
+
const lastIndex = --this.#length
|
|
131
|
+
const lastKey = this.denseKeys[lastIndex]
|
|
132
|
+
const lastValue = this.denseValues[lastIndex]
|
|
133
|
+
if (key !== lastKey) {
|
|
134
|
+
this.denseKeys[index] = lastKey
|
|
135
|
+
this.denseValues[index] = lastValue
|
|
136
|
+
this.sparse[lastKey] = index
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return true
|
|
140
|
+
} else {
|
|
141
|
+
return false
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
clear(): void {
|
|
146
|
+
this.#length = 0
|
|
147
|
+
this.sparse.fill(this.NULL)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { assert } from '@blackglory/errors'
|
|
2
|
+
import { TypedArrayConstructor, UnsignedTypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
|
|
3
|
+
|
|
4
|
+
export class TypedSparseMapLite<
|
|
5
|
+
K extends UnsignedTypedArrayConstructor
|
|
6
|
+
, V extends TypedArrayConstructor
|
|
7
|
+
> {
|
|
8
|
+
private denseKeys: TypedArrayOfConstructor<K>
|
|
9
|
+
private denseValues: TypedArrayOfConstructor<V>
|
|
10
|
+
private sparse: Array<number | undefined> = []
|
|
11
|
+
#length = 0
|
|
12
|
+
|
|
13
|
+
readonly internalKeyArray: TypedArrayOfConstructor<K, ArrayBuffer>
|
|
14
|
+
readonly internalValueArray: TypedArrayOfConstructor<V, ArrayBuffer>
|
|
15
|
+
|
|
16
|
+
get [Symbol.toStringTag](): string {
|
|
17
|
+
return this.constructor.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get size(): number {
|
|
21
|
+
return this.#length
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
keys: TypedArrayOfConstructor<K, ArrayBuffer>
|
|
26
|
+
, values: TypedArrayOfConstructor<V, ArrayBuffer>
|
|
27
|
+
) {
|
|
28
|
+
assert(!keys.buffer.resizable, 'The keys buffer must not be resizable')
|
|
29
|
+
assert(!values.buffer.resizable, 'The values buffer must not be resizable')
|
|
30
|
+
assert(
|
|
31
|
+
values.length >= keys.length
|
|
32
|
+
, 'The values.length must greater than or equal to keys.length'
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
this.denseKeys = keys
|
|
36
|
+
this.denseValues = values
|
|
37
|
+
|
|
38
|
+
this.internalKeyArray = keys
|
|
39
|
+
this.internalValueArray = values
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
* entries(): IterableIterator<[key: number, value: number]> {
|
|
43
|
+
for (let i = 0; i < this.#length; i++) {
|
|
44
|
+
yield [
|
|
45
|
+
this.denseKeys[i]
|
|
46
|
+
, this.denseValues[i]
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
* keys(): IterableIterator<number> {
|
|
52
|
+
for (let i = 0; i < this.#length; i++) {
|
|
53
|
+
yield this.denseKeys[i]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
* values(): IterableIterator<number> {
|
|
58
|
+
for (let i = 0; i < this.#length; i++) {
|
|
59
|
+
yield this.denseValues[i]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getInternalIndexOfKey(key: number): number | undefined {
|
|
64
|
+
const index = this.sparse[key]
|
|
65
|
+
if (
|
|
66
|
+
index !== undefined &&
|
|
67
|
+
index < this.#length &&
|
|
68
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
69
|
+
this.denseKeys[index] === key
|
|
70
|
+
) {
|
|
71
|
+
return index
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
has(key: number): boolean {
|
|
76
|
+
const index = this.sparse[key]
|
|
77
|
+
return index !== undefined
|
|
78
|
+
&& index < this.#length
|
|
79
|
+
&& index < this.denseKeys.length // 用于改善JIT优化.
|
|
80
|
+
&& this.denseKeys[index] === key
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get(key: number): number | undefined {
|
|
84
|
+
const index = this.sparse[key]
|
|
85
|
+
if (
|
|
86
|
+
index !== undefined &&
|
|
87
|
+
index < this.#length &&
|
|
88
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
89
|
+
this.denseKeys[index] === key
|
|
90
|
+
) {
|
|
91
|
+
return this.denseValues[index]
|
|
92
|
+
} else {
|
|
93
|
+
return undefined
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
set(key: number, value: number): void {
|
|
98
|
+
const index = this.sparse[key]
|
|
99
|
+
if (
|
|
100
|
+
index !== undefined &&
|
|
101
|
+
index < this.#length &&
|
|
102
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
103
|
+
this.denseKeys[index] === key
|
|
104
|
+
) {
|
|
105
|
+
this.denseValues[index] = value
|
|
106
|
+
} else {
|
|
107
|
+
const index = this.#length++
|
|
108
|
+
this.denseKeys[index] = key
|
|
109
|
+
this.denseValues[index] = value
|
|
110
|
+
this.sparse[key] = index
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
delete(key: number): boolean {
|
|
115
|
+
const index = this.sparse[key]
|
|
116
|
+
if (
|
|
117
|
+
index !== undefined &&
|
|
118
|
+
index < this.#length &&
|
|
119
|
+
index < this.denseKeys.length && // 用于改善JIT优化.
|
|
120
|
+
this.denseKeys[index] === key
|
|
121
|
+
) {
|
|
122
|
+
const lastIndex = --this.#length
|
|
123
|
+
const lastKey = this.denseKeys[lastIndex]
|
|
124
|
+
const lastValue = this.denseValues[lastIndex]
|
|
125
|
+
if (key !== lastKey) {
|
|
126
|
+
this.denseKeys[index] = lastKey
|
|
127
|
+
this.denseValues[index] = lastValue
|
|
128
|
+
this.sparse[lastKey] = index
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return true
|
|
132
|
+
} else {
|
|
133
|
+
return false
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
clear(): void {
|
|
138
|
+
this.#length = 0
|
|
139
|
+
// 无需清空dense和sparse数组.
|
|
140
|
+
}
|
|
141
|
+
}
|