@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,108 @@
|
|
|
1
|
+
import { UnsignedTypedArrayConstructor } from 'justypes'
|
|
2
|
+
import { ResizableTypedArray } from '@src/resizable-typed-array.js'
|
|
3
|
+
import { assert } from '@blackglory/errors'
|
|
4
|
+
import { go } from '@blackglory/go'
|
|
5
|
+
import { getMaxValueOfUnsignedTypedArray, getMaxValueOfUnsignedTypedArrayConstructor } from '@utils/get-max-value-of-unsigned-typed-array.js'
|
|
6
|
+
|
|
7
|
+
export class ResizableTypedCleanSparseSet implements Iterable<number> {
|
|
8
|
+
private dense: ResizableTypedArray<UnsignedTypedArrayConstructor>
|
|
9
|
+
private sparse: ResizableTypedArray<UnsignedTypedArrayConstructor>
|
|
10
|
+
private readonly NULL: number
|
|
11
|
+
|
|
12
|
+
get [Symbol.toStringTag](): string {
|
|
13
|
+
return this.constructor.name
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get size(): number {
|
|
17
|
+
return this.dense.length
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor(array: ResizableTypedArray<UnsignedTypedArrayConstructor>) {
|
|
21
|
+
assert(array.length === 0, 'The array must be empty')
|
|
22
|
+
|
|
23
|
+
this.dense = array
|
|
24
|
+
|
|
25
|
+
const NULL = Math.min(
|
|
26
|
+
array.maxCapacity
|
|
27
|
+
, getMaxValueOfUnsignedTypedArray(array.internalTypedArray) + 1
|
|
28
|
+
)
|
|
29
|
+
this.NULL = NULL
|
|
30
|
+
|
|
31
|
+
const sparseInternalArrayConstructor = go(() => {
|
|
32
|
+
if (
|
|
33
|
+
NULL <=
|
|
34
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint8Array)
|
|
35
|
+
) {
|
|
36
|
+
return Uint8Array
|
|
37
|
+
} else if (
|
|
38
|
+
NULL <=
|
|
39
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint16Array)
|
|
40
|
+
) {
|
|
41
|
+
return Uint16Array
|
|
42
|
+
} else if (
|
|
43
|
+
NULL <=
|
|
44
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint32Array)
|
|
45
|
+
) {
|
|
46
|
+
return Uint32Array
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error('The array is too large')
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
const sparse = new ResizableTypedArray(
|
|
52
|
+
sparseInternalArrayConstructor
|
|
53
|
+
, {
|
|
54
|
+
maxCapacity: getMaxValueOfUnsignedTypedArray(array.internalTypedArray)
|
|
55
|
+
+ 1
|
|
56
|
+
, fillValue: NULL
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
this.sparse = sparse
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
63
|
+
return this.values()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
values(): IterableIterator<number> {
|
|
67
|
+
return this.dense.values()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
has(value: number): boolean {
|
|
71
|
+
const index = this.sparse.get(value)
|
|
72
|
+
return index !== undefined
|
|
73
|
+
&& index !== this.NULL
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
add(value: number): void {
|
|
77
|
+
if (!this.has(value)) {
|
|
78
|
+
const index = this.dense.length
|
|
79
|
+
this.dense.push(value)
|
|
80
|
+
this.sparse.set(value, index)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
delete(value: number): boolean {
|
|
85
|
+
const index = this.sparse.get(value)
|
|
86
|
+
if (
|
|
87
|
+
index !== undefined &&
|
|
88
|
+
index !== this.NULL
|
|
89
|
+
) {
|
|
90
|
+
this.sparse.internalTypedArray[value] = this.NULL
|
|
91
|
+
|
|
92
|
+
const lastValue = this.dense.pop()!
|
|
93
|
+
if (value !== lastValue) {
|
|
94
|
+
this.dense.internalTypedArray[index] = lastValue
|
|
95
|
+
this.sparse.internalTypedArray[lastValue] = index
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return true
|
|
99
|
+
} else {
|
|
100
|
+
return false
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
clear(): void {
|
|
105
|
+
this.dense.clear()
|
|
106
|
+
this.sparse.clear()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { UnsignedTypedArrayConstructor } from 'justypes'
|
|
2
|
+
import { ResizableTypedArray } from '@src/resizable-typed-array.js'
|
|
3
|
+
import { assert } from '@blackglory/errors'
|
|
4
|
+
|
|
5
|
+
export class ResizableTypedSparseSetLite implements Iterable<number> {
|
|
6
|
+
private dense: ResizableTypedArray<UnsignedTypedArrayConstructor>
|
|
7
|
+
private sparse: Array<number | undefined> = []
|
|
8
|
+
|
|
9
|
+
get [Symbol.toStringTag](): string {
|
|
10
|
+
return this.constructor.name
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get size(): number {
|
|
14
|
+
return this.dense.length
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
constructor(array: ResizableTypedArray<UnsignedTypedArrayConstructor>) {
|
|
18
|
+
assert(array.length === 0, 'The array must be empty')
|
|
19
|
+
|
|
20
|
+
this.dense = array
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
24
|
+
return this.values()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
values(): IterableIterator<number> {
|
|
28
|
+
return this.dense.values()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
has(value: number): boolean {
|
|
32
|
+
const index = this.sparse[value]
|
|
33
|
+
return index !== undefined
|
|
34
|
+
&& this.dense.get(index) === value
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
add(value: number): void {
|
|
38
|
+
if (!this.has(value)) {
|
|
39
|
+
const index = this.dense.length
|
|
40
|
+
this.dense.push(value)
|
|
41
|
+
this.sparse[value] = index
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
delete(value: number): boolean {
|
|
46
|
+
const index = this.sparse[value]
|
|
47
|
+
if (
|
|
48
|
+
index !== undefined &&
|
|
49
|
+
this.dense.get(index) === value
|
|
50
|
+
) {
|
|
51
|
+
const lastValue = this.dense.pop()!
|
|
52
|
+
if (value !== lastValue) {
|
|
53
|
+
this.dense.internalTypedArray[index] = lastValue
|
|
54
|
+
this.sparse[lastValue] = index
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return true
|
|
58
|
+
} else {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
clear(): void {
|
|
64
|
+
this.dense.clear()
|
|
65
|
+
// 无需清空sparse数组.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { UnsignedTypedArrayConstructor } from 'justypes'
|
|
2
|
+
import { ResizableTypedArray } from '@src/resizable-typed-array.js'
|
|
3
|
+
import { getMaxValueOfUnsignedTypedArray, getMaxValueOfUnsignedTypedArrayConstructor } from '@utils/get-max-value-of-unsigned-typed-array.js'
|
|
4
|
+
import { go } from '@blackglory/go'
|
|
5
|
+
import { assert } from '@blackglory/errors'
|
|
6
|
+
|
|
7
|
+
export class ResizableTypedSparseSet implements Iterable<number> {
|
|
8
|
+
private dense: ResizableTypedArray<UnsignedTypedArrayConstructor>
|
|
9
|
+
private sparse: ResizableTypedArray<UnsignedTypedArrayConstructor>
|
|
10
|
+
|
|
11
|
+
get [Symbol.toStringTag](): string {
|
|
12
|
+
return this.constructor.name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get size(): number {
|
|
16
|
+
return this.dense.length
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor(array: ResizableTypedArray<UnsignedTypedArrayConstructor>) {
|
|
20
|
+
assert(array.length === 0, 'The array must be empty')
|
|
21
|
+
|
|
22
|
+
this.dense = array
|
|
23
|
+
|
|
24
|
+
const sparseInternalArrayConstructor = go(() => {
|
|
25
|
+
const maxIndex = Math.min(
|
|
26
|
+
array.maxCapacity - 1
|
|
27
|
+
, getMaxValueOfUnsignedTypedArray(array.internalTypedArray) + 1
|
|
28
|
+
)
|
|
29
|
+
if (
|
|
30
|
+
maxIndex <=
|
|
31
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint8Array)
|
|
32
|
+
) {
|
|
33
|
+
return Uint8Array
|
|
34
|
+
} else if (
|
|
35
|
+
maxIndex <=
|
|
36
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint16Array)
|
|
37
|
+
) {
|
|
38
|
+
return Uint16Array
|
|
39
|
+
} else if (
|
|
40
|
+
maxIndex <=
|
|
41
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint32Array)
|
|
42
|
+
) {
|
|
43
|
+
return Uint32Array
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error('The array is too large')
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
this.sparse = new ResizableTypedArray(sparseInternalArrayConstructor, {
|
|
49
|
+
maxCapacity: getMaxValueOfUnsignedTypedArray(array.internalTypedArray) + 1
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
54
|
+
return this.values()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
values(): IterableIterator<number> {
|
|
58
|
+
return this.dense.values()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
has(value: number): boolean {
|
|
62
|
+
const index = this.sparse.get(value)
|
|
63
|
+
return index !== undefined
|
|
64
|
+
&& this.dense.get(index) === value
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
add(value: number): void {
|
|
68
|
+
if (!this.has(value)) {
|
|
69
|
+
const index = this.dense.length
|
|
70
|
+
this.dense.push(value)
|
|
71
|
+
this.sparse.set(value, index)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
delete(value: number): boolean {
|
|
76
|
+
const index = this.sparse.get(value)
|
|
77
|
+
if (
|
|
78
|
+
index !== undefined &&
|
|
79
|
+
this.dense.get(index) === value
|
|
80
|
+
) {
|
|
81
|
+
const lastValue = this.dense.pop()!
|
|
82
|
+
if (value !== lastValue) {
|
|
83
|
+
this.dense.internalTypedArray[index] = lastValue
|
|
84
|
+
this.sparse.set(lastValue, index)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return true
|
|
88
|
+
} else {
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
clear(): void {
|
|
94
|
+
this.dense.clear()
|
|
95
|
+
// 无需清空sparse数组.
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 稀疏集的标准实现.
|
|
3
|
+
*/
|
|
4
|
+
export class SparseSet implements Iterable<number> {
|
|
5
|
+
private dense: number[] = []
|
|
6
|
+
private sparse: Array<number | undefined> = []
|
|
7
|
+
|
|
8
|
+
get [Symbol.toStringTag](): string {
|
|
9
|
+
return this.constructor.name
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get size(): number {
|
|
13
|
+
return this.dense.length
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
17
|
+
return this.values()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
values(): IterableIterator<number> {
|
|
21
|
+
return this.dense.values()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
has(value: number): boolean {
|
|
25
|
+
const index = this.sparse[value]
|
|
26
|
+
return index !== undefined
|
|
27
|
+
&& index < this.dense.length // 用于改善JIT优化.
|
|
28
|
+
&& this.dense[index] === value
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
add(value: number): void {
|
|
32
|
+
if (!this.has(value)) {
|
|
33
|
+
const index = this.dense.length
|
|
34
|
+
this.dense.push(value)
|
|
35
|
+
this.sparse[value] = index
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
delete(value: number): boolean {
|
|
40
|
+
const index = this.sparse[value]
|
|
41
|
+
if (
|
|
42
|
+
index !== undefined &&
|
|
43
|
+
index < this.dense.length && // 用于改善JIT优化.
|
|
44
|
+
this.dense[index] === value
|
|
45
|
+
) {
|
|
46
|
+
const lastValue = this.dense.pop()!
|
|
47
|
+
if (value !== lastValue) {
|
|
48
|
+
this.dense[index] = lastValue
|
|
49
|
+
this.sparse[lastValue] = index
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true
|
|
53
|
+
} else {
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
clear(): void {
|
|
59
|
+
this.dense.length = 0
|
|
60
|
+
// 无需清空sparse数组.
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
clone(): SparseSet {
|
|
64
|
+
const clone = new SparseSet()
|
|
65
|
+
|
|
66
|
+
const dense = [...this.dense]
|
|
67
|
+
|
|
68
|
+
// 由于`sparse`是稀疏的, 不应用`[...sparse]`复制.
|
|
69
|
+
const sparse: Array<number | undefined> = []
|
|
70
|
+
for (const [index, value] of dense.entries()) {
|
|
71
|
+
sparse[value] = index
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
clone.dense = dense
|
|
75
|
+
clone.sparse = sparse
|
|
76
|
+
|
|
77
|
+
return clone
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { assert } from '@blackglory/errors'
|
|
2
|
+
import { UnsignedTypedArray } from 'justypes'
|
|
3
|
+
|
|
4
|
+
export class TypedCleanSparseSetLite implements Iterable<number> {
|
|
5
|
+
private dense: UnsignedTypedArray
|
|
6
|
+
private sparse: Array<number | undefined> = []
|
|
7
|
+
#length = 0
|
|
8
|
+
|
|
9
|
+
get [Symbol.toStringTag](): string {
|
|
10
|
+
return this.constructor.name
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get size(): number {
|
|
14
|
+
return this.#length
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
constructor(array: UnsignedTypedArray<ArrayBuffer>) {
|
|
18
|
+
assert(!array.buffer.resizable, 'The array buffer must not be resizable')
|
|
19
|
+
|
|
20
|
+
this.dense = array
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
24
|
+
return this.values()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
* values(): IterableIterator<number> {
|
|
28
|
+
for (let i = 0; i < this.#length; i++) {
|
|
29
|
+
yield this.dense[i]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
has(value: number): boolean {
|
|
34
|
+
return this.sparse[value] !== undefined
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
add(value: number): void {
|
|
38
|
+
if (!this.has(value)) {
|
|
39
|
+
const index = this.#length++
|
|
40
|
+
this.dense[index] = value
|
|
41
|
+
this.sparse[value] = index
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
delete(value: number): boolean {
|
|
46
|
+
const index = this.sparse[value]
|
|
47
|
+
if (index !== undefined) {
|
|
48
|
+
this.sparse[value] = undefined
|
|
49
|
+
|
|
50
|
+
const lastIndex = --this.#length
|
|
51
|
+
const lastValue = this.dense[lastIndex]
|
|
52
|
+
if (value !== lastValue) {
|
|
53
|
+
this.dense[index] = lastValue
|
|
54
|
+
this.sparse[lastValue] = index
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return true
|
|
58
|
+
} else {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
clear(): void {
|
|
64
|
+
this.#length = 0
|
|
65
|
+
this.sparse.length = 0
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
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 { UnsignedTypedArray } from 'justypes'
|
|
5
|
+
|
|
6
|
+
export class TypedCleanSparseSet implements Iterable<number> {
|
|
7
|
+
private dense: UnsignedTypedArray
|
|
8
|
+
private sparse: UnsignedTypedArray
|
|
9
|
+
private readonly NULL: number
|
|
10
|
+
#length = 0
|
|
11
|
+
|
|
12
|
+
get [Symbol.toStringTag](): string {
|
|
13
|
+
return this.constructor.name
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get size(): number {
|
|
17
|
+
return this.#length
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor(array: UnsignedTypedArray<ArrayBuffer>) {
|
|
21
|
+
assert(!array.buffer.resizable, 'The array buffer must not be resizable')
|
|
22
|
+
|
|
23
|
+
this.dense = array
|
|
24
|
+
|
|
25
|
+
const NULL = Math.min(
|
|
26
|
+
array.length
|
|
27
|
+
, getMaxValueOfUnsignedTypedArray(array) + 1
|
|
28
|
+
)
|
|
29
|
+
this.NULL = NULL
|
|
30
|
+
|
|
31
|
+
const sparseConstructor = go(() => {
|
|
32
|
+
if (
|
|
33
|
+
NULL <=
|
|
34
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint8Array)
|
|
35
|
+
) {
|
|
36
|
+
return Uint8Array
|
|
37
|
+
} else if (
|
|
38
|
+
NULL <=
|
|
39
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint16Array)
|
|
40
|
+
) {
|
|
41
|
+
return Uint16Array
|
|
42
|
+
} else if (
|
|
43
|
+
NULL <=
|
|
44
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint32Array)
|
|
45
|
+
) {
|
|
46
|
+
return Uint32Array
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error('The array is too large')
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
const sparse = new sparseConstructor(getMaxValueOfUnsignedTypedArray(array) + 1)
|
|
52
|
+
sparse.fill(NULL)
|
|
53
|
+
this.sparse = sparse
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
57
|
+
return this.values()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
* values(): IterableIterator<number> {
|
|
61
|
+
for (let i = 0; i < this.#length; i++) {
|
|
62
|
+
yield this.dense[i]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
has(value: number): boolean {
|
|
67
|
+
return this.sparse[value] !== this.NULL
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
add(value: number): void {
|
|
71
|
+
if (!this.has(value)) {
|
|
72
|
+
const index = this.#length++
|
|
73
|
+
this.dense[index] = value
|
|
74
|
+
this.sparse[value] = index
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
delete(value: number): boolean {
|
|
79
|
+
const index = this.sparse[value]
|
|
80
|
+
if (index !== this.NULL) {
|
|
81
|
+
this.sparse[value] = this.NULL
|
|
82
|
+
|
|
83
|
+
const lastIndex = --this.#length
|
|
84
|
+
const lastValue = this.dense[lastIndex]
|
|
85
|
+
if (value !== lastValue) {
|
|
86
|
+
this.dense[index] = lastValue
|
|
87
|
+
this.sparse[lastValue] = index
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return true
|
|
91
|
+
} else {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
clear(): void {
|
|
97
|
+
this.#length = 0
|
|
98
|
+
this.sparse.fill(this.NULL)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { assert } from '@blackglory/errors'
|
|
2
|
+
import { UnsignedTypedArray } from 'justypes'
|
|
3
|
+
|
|
4
|
+
export class TypedSparseSetLite implements Iterable<number> {
|
|
5
|
+
private dense: UnsignedTypedArray
|
|
6
|
+
private sparse: Array<number | undefined> = []
|
|
7
|
+
#length = 0
|
|
8
|
+
|
|
9
|
+
get [Symbol.toStringTag](): string {
|
|
10
|
+
return this.constructor.name
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get size(): number {
|
|
14
|
+
return this.#length
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
constructor(array: UnsignedTypedArray<ArrayBuffer>) {
|
|
18
|
+
assert(!array.buffer.resizable, 'The array buffer must not be resizable')
|
|
19
|
+
|
|
20
|
+
this.dense = array
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
24
|
+
return this.values()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
* values(): IterableIterator<number> {
|
|
28
|
+
for (let i = 0; i < this.#length; i++) {
|
|
29
|
+
yield this.dense[i]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
has(value: number): boolean {
|
|
34
|
+
const index = this.sparse[value]
|
|
35
|
+
return index !== undefined
|
|
36
|
+
&& index < this.#length
|
|
37
|
+
&& index < this.dense.length // 用于改善JIT优化.
|
|
38
|
+
&& this.dense[index] === value
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
add(value: number): void {
|
|
42
|
+
if (!this.has(value)) {
|
|
43
|
+
const index = this.#length++
|
|
44
|
+
this.dense[index] = value
|
|
45
|
+
this.sparse[value] = index
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
delete(value: number): boolean {
|
|
50
|
+
const index = this.sparse[value]
|
|
51
|
+
if (
|
|
52
|
+
index !== undefined &&
|
|
53
|
+
index < this.#length &&
|
|
54
|
+
index < this.dense.length && // 用于改善JIT优化.
|
|
55
|
+
this.dense[index] === value
|
|
56
|
+
) {
|
|
57
|
+
const lastIndex = --this.#length
|
|
58
|
+
const lastValue = this.dense[lastIndex]
|
|
59
|
+
if (value !== lastValue) {
|
|
60
|
+
this.dense[index] = lastValue
|
|
61
|
+
this.sparse[lastValue] = index
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return true
|
|
65
|
+
} else {
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
clear(): void {
|
|
71
|
+
this.#length = 0
|
|
72
|
+
// 无需清空dense和sparse数组.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
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 { UnsignedTypedArray } from 'justypes'
|
|
5
|
+
|
|
6
|
+
export class TypedSparseSet implements Iterable<number> {
|
|
7
|
+
private dense: UnsignedTypedArray
|
|
8
|
+
private sparse: UnsignedTypedArray
|
|
9
|
+
#length = 0
|
|
10
|
+
|
|
11
|
+
get [Symbol.toStringTag](): string {
|
|
12
|
+
return this.constructor.name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get size(): number {
|
|
16
|
+
return this.#length
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor(array: UnsignedTypedArray<ArrayBuffer>) {
|
|
20
|
+
assert(!array.buffer.resizable, 'The array buffer must not be resizable')
|
|
21
|
+
|
|
22
|
+
this.dense = array
|
|
23
|
+
|
|
24
|
+
const sparseConstructor = go(() => {
|
|
25
|
+
const maxIndex = Math.min(
|
|
26
|
+
array.length - 1
|
|
27
|
+
, getMaxValueOfUnsignedTypedArray(array) + 1
|
|
28
|
+
)
|
|
29
|
+
if (
|
|
30
|
+
maxIndex <=
|
|
31
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint8Array)
|
|
32
|
+
) {
|
|
33
|
+
return Uint8Array
|
|
34
|
+
} else if (
|
|
35
|
+
maxIndex <=
|
|
36
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint16Array)
|
|
37
|
+
) {
|
|
38
|
+
return Uint16Array
|
|
39
|
+
} else if (
|
|
40
|
+
maxIndex <=
|
|
41
|
+
getMaxValueOfUnsignedTypedArrayConstructor(Uint32Array)
|
|
42
|
+
) {
|
|
43
|
+
return Uint32Array
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error('The array is too large')
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
this.sparse = new sparseConstructor(getMaxValueOfUnsignedTypedArray(array) + 1)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
52
|
+
return this.values()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
* values(): IterableIterator<number> {
|
|
56
|
+
for (let i = 0; i < this.#length; i++) {
|
|
57
|
+
yield this.dense[i]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
has(value: number): boolean {
|
|
62
|
+
const index = this.sparse[value]
|
|
63
|
+
return index !== undefined
|
|
64
|
+
&& index < this.#length
|
|
65
|
+
&& index < this.dense.length // 用于改善JIT优化.
|
|
66
|
+
&& this.dense[index] === value
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
add(value: number): void {
|
|
70
|
+
if (!this.has(value)) {
|
|
71
|
+
const index = this.#length++
|
|
72
|
+
this.dense[index] = value
|
|
73
|
+
this.sparse[value] = index
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
delete(value: number): boolean {
|
|
78
|
+
const index = this.sparse[value]
|
|
79
|
+
if (
|
|
80
|
+
index !== undefined &&
|
|
81
|
+
index < this.#length &&
|
|
82
|
+
index < this.dense.length && // 用于改善JIT优化.
|
|
83
|
+
this.dense[index] === value
|
|
84
|
+
) {
|
|
85
|
+
const lastIndex = --this.#length
|
|
86
|
+
const lastValue = this.dense[lastIndex]
|
|
87
|
+
if (value !== lastValue) {
|
|
88
|
+
this.dense[index] = lastValue
|
|
89
|
+
this.sparse[lastValue] = index
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return true
|
|
93
|
+
} else {
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
clear(): void {
|
|
99
|
+
this.#length = 0
|
|
100
|
+
// 无需清空dense和sparse数组.
|
|
101
|
+
}
|
|
102
|
+
}
|