@blackglory/structures 0.14.15 → 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.
Files changed (205) hide show
  1. package/README.md +661 -92
  2. package/lib/async-generator-emitter.js +2 -5
  3. package/lib/async-generator-emitter.js.map +1 -1
  4. package/lib/big-map.js +1 -3
  5. package/lib/big-map.js.map +1 -1
  6. package/lib/big-set.js +1 -3
  7. package/lib/big-set.js.map +1 -1
  8. package/lib/{bit-set.d.ts → bit-set/bit-set.d.ts} +5 -2
  9. package/lib/{bit-set.js → bit-set/bit-set.js} +43 -34
  10. package/lib/bit-set/bit-set.js.map +1 -0
  11. package/lib/{typed-bit-set.d.ts → bit-set/dynamic-typed-bit-set.d.ts} +6 -4
  12. package/lib/bit-set/dynamic-typed-bit-set.js +95 -0
  13. package/lib/bit-set/dynamic-typed-bit-set.js.map +1 -0
  14. package/lib/bit-set/index.d.ts +4 -0
  15. package/lib/bit-set/index.js +5 -0
  16. package/lib/bit-set/index.js.map +1 -0
  17. package/lib/bit-set/resizable-typed-bit-set.d.ts +22 -0
  18. package/lib/{typed-bit-set.js → bit-set/resizable-typed-bit-set.js} +37 -39
  19. package/lib/bit-set/resizable-typed-bit-set.js.map +1 -0
  20. package/lib/bit-set/typed-bit-set.d.ts +22 -0
  21. package/lib/bit-set/typed-bit-set.js +99 -0
  22. package/lib/bit-set/typed-bit-set.js.map +1 -0
  23. package/lib/box.js +1 -0
  24. package/lib/box.js.map +1 -1
  25. package/lib/disjoint-set.js +2 -4
  26. package/lib/disjoint-set.js.map +1 -1
  27. package/lib/dynamic-typed-array.d.ts +12 -9
  28. package/lib/dynamic-typed-array.js +51 -66
  29. package/lib/dynamic-typed-array.js.map +1 -1
  30. package/lib/emitter.js +3 -7
  31. package/lib/emitter.js.map +1 -1
  32. package/lib/expirable-map.js +9 -15
  33. package/lib/expirable-map.js.map +1 -1
  34. package/lib/generator-emitter.js +2 -5
  35. package/lib/generator-emitter.js.map +1 -1
  36. package/lib/hash-map.js +2 -1
  37. package/lib/hash-map.js.map +1 -1
  38. package/lib/hash-set.js +2 -1
  39. package/lib/hash-set.js.map +1 -1
  40. package/lib/index.d.ts +5 -7
  41. package/lib/index.js +5 -7
  42. package/lib/index.js.map +1 -1
  43. package/lib/lru-map.js +2 -1
  44. package/lib/lru-map.js.map +1 -1
  45. package/lib/queue.js +1 -3
  46. package/lib/queue.js.map +1 -1
  47. package/lib/radix-tree.js +3 -4
  48. package/lib/radix-tree.js.map +1 -1
  49. package/lib/resizable-typed-array.d.ts +32 -0
  50. package/lib/resizable-typed-array.js +127 -0
  51. package/lib/resizable-typed-array.js.map +1 -0
  52. package/lib/sorted-set.js +2 -1
  53. package/lib/sorted-set.js.map +1 -1
  54. package/lib/sparse-map/clean-sparse-map.d.ts +18 -0
  55. package/lib/sparse-map/clean-sparse-map.js +74 -0
  56. package/lib/sparse-map/clean-sparse-map.js.map +1 -0
  57. package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.d.ts +21 -0
  58. package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js +87 -0
  59. package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js.map +1 -0
  60. package/lib/sparse-map/dynamic-typed-sparse-map-lite.d.ts +21 -0
  61. package/lib/sparse-map/dynamic-typed-sparse-map-lite.js +94 -0
  62. package/lib/sparse-map/dynamic-typed-sparse-map-lite.js.map +1 -0
  63. package/lib/sparse-map/index.d.ts +10 -0
  64. package/lib/sparse-map/index.js +11 -0
  65. package/lib/sparse-map/index.js.map +1 -0
  66. package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.d.ts +21 -0
  67. package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js +85 -0
  68. package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js.map +1 -0
  69. package/lib/sparse-map/resizable-typed-sparse-map-lite.d.ts +21 -0
  70. package/lib/sparse-map/resizable-typed-sparse-map-lite.js +92 -0
  71. package/lib/sparse-map/resizable-typed-sparse-map-lite.js.map +1 -0
  72. package/lib/{sparse-map.d.ts → sparse-map/sparse-map.d.ts} +6 -5
  73. package/lib/sparse-map/sparse-map.js +86 -0
  74. package/lib/sparse-map/sparse-map.js.map +1 -0
  75. package/lib/sparse-map/typed-clean-sparse-map-lite.d.ts +21 -0
  76. package/lib/sparse-map/typed-clean-sparse-map-lite.js +92 -0
  77. package/lib/sparse-map/typed-clean-sparse-map-lite.js.map +1 -0
  78. package/lib/sparse-map/typed-clean-sparse-map.d.ts +22 -0
  79. package/lib/sparse-map/typed-clean-sparse-map.js +117 -0
  80. package/lib/sparse-map/typed-clean-sparse-map.js.map +1 -0
  81. package/lib/sparse-map/typed-sparse-map-lite.d.ts +21 -0
  82. package/lib/sparse-map/typed-sparse-map-lite.js +109 -0
  83. package/lib/sparse-map/typed-sparse-map-lite.js.map +1 -0
  84. package/lib/sparse-map/typed-sparse-map.d.ts +21 -0
  85. package/lib/sparse-map/typed-sparse-map.js +130 -0
  86. package/lib/sparse-map/typed-sparse-map.js.map +1 -0
  87. package/lib/sparse-set/clean-sparse-set.d.ts +13 -0
  88. package/lib/sparse-set/clean-sparse-set.js +57 -0
  89. package/lib/sparse-set/clean-sparse-set.js.map +1 -0
  90. package/lib/{typed-sparse-set.d.ts → sparse-set/dynamic-typed-clean-sparse-set-lite.d.ts} +6 -6
  91. package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js +51 -0
  92. package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js.map +1 -0
  93. package/lib/sparse-set/dynamic-typed-clean-sparse-set.d.ts +16 -0
  94. package/lib/sparse-set/dynamic-typed-clean-sparse-set.js +82 -0
  95. package/lib/sparse-set/dynamic-typed-clean-sparse-set.js.map +1 -0
  96. package/lib/sparse-set/dynamic-typed-sparse-set-lite.d.ts +15 -0
  97. package/lib/sparse-set/dynamic-typed-sparse-set-lite.js +52 -0
  98. package/lib/sparse-set/dynamic-typed-sparse-set-lite.js.map +1 -0
  99. package/lib/sparse-set/dynamic-typed-sparse-set.d.ts +15 -0
  100. package/lib/sparse-set/dynamic-typed-sparse-set.js +75 -0
  101. package/lib/sparse-set/dynamic-typed-sparse-set.js.map +1 -0
  102. package/lib/sparse-set/index.d.ts +14 -0
  103. package/lib/sparse-set/index.js +15 -0
  104. package/lib/sparse-set/index.js.map +1 -0
  105. package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.d.ts +15 -0
  106. package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js +51 -0
  107. package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js.map +1 -0
  108. package/lib/sparse-set/resizable-typed-clean-sparse-set.d.ts +16 -0
  109. package/lib/sparse-set/resizable-typed-clean-sparse-set.js +83 -0
  110. package/lib/sparse-set/resizable-typed-clean-sparse-set.js.map +1 -0
  111. package/lib/sparse-set/resizable-typed-sparse-set-lite.d.ts +15 -0
  112. package/lib/sparse-set/resizable-typed-sparse-set-lite.js +52 -0
  113. package/lib/sparse-set/resizable-typed-sparse-set-lite.js.map +1 -0
  114. package/lib/sparse-set/resizable-typed-sparse-set.d.ts +15 -0
  115. package/lib/sparse-set/resizable-typed-sparse-set.js +76 -0
  116. package/lib/sparse-set/resizable-typed-sparse-set.js.map +1 -0
  117. package/lib/{sparse-set.d.ts → sparse-set/sparse-set.d.ts} +3 -4
  118. package/lib/sparse-set/sparse-set.js +60 -0
  119. package/lib/sparse-set/sparse-set.js.map +1 -0
  120. package/lib/sparse-set/typed-clean-sparse-set-lite.d.ts +15 -0
  121. package/lib/sparse-set/typed-clean-sparse-set-lite.js +55 -0
  122. package/lib/sparse-set/typed-clean-sparse-set-lite.js.map +1 -0
  123. package/lib/sparse-set/typed-clean-sparse-set.d.ts +16 -0
  124. package/lib/sparse-set/typed-clean-sparse-set.js +80 -0
  125. package/lib/sparse-set/typed-clean-sparse-set.js.map +1 -0
  126. package/lib/sparse-set/typed-sparse-set-lite.d.ts +15 -0
  127. package/lib/sparse-set/typed-sparse-set-lite.js +60 -0
  128. package/lib/sparse-set/typed-sparse-set-lite.js.map +1 -0
  129. package/lib/sparse-set/typed-sparse-set.d.ts +15 -0
  130. package/lib/sparse-set/typed-sparse-set.js +81 -0
  131. package/lib/sparse-set/typed-sparse-set.js.map +1 -0
  132. package/lib/string-radix-tree.js +3 -4
  133. package/lib/string-radix-tree.js.map +1 -1
  134. package/lib/string-trie-map.js +3 -4
  135. package/lib/string-trie-map.js.map +1 -1
  136. package/lib/tlru-map.js +6 -6
  137. package/lib/tlru-map.js.map +1 -1
  138. package/lib/trie-map.js +3 -4
  139. package/lib/trie-map.js.map +1 -1
  140. package/lib/unique-queue.js +1 -3
  141. package/lib/unique-queue.js.map +1 -1
  142. package/lib/utils/compute-new-capacity.d.ts +1 -0
  143. package/lib/utils/compute-new-capacity.js +36 -0
  144. package/lib/utils/compute-new-capacity.js.map +1 -0
  145. package/lib/utils/get-max-value-of-unsigned-typed-array.d.ts +3 -0
  146. package/lib/utils/get-max-value-of-unsigned-typed-array.js +13 -0
  147. package/lib/utils/get-max-value-of-unsigned-typed-array.js.map +1 -0
  148. package/lib/utils/skip-list.js +11 -9
  149. package/lib/utils/skip-list.js.map +1 -1
  150. package/lib/utils/trailing-zeros.js +1 -1
  151. package/lib/utils/trailing-zeros.js.map +1 -1
  152. package/package.json +28 -31
  153. package/src/{bit-set.ts → bit-set/bit-set.ts} +47 -31
  154. package/src/bit-set/dynamic-typed-bit-set.ts +131 -0
  155. package/src/bit-set/index.ts +4 -0
  156. package/src/{typed-bit-set.ts → bit-set/resizable-typed-bit-set.ts} +38 -36
  157. package/src/bit-set/typed-bit-set.ts +134 -0
  158. package/src/dynamic-typed-array.ts +67 -82
  159. package/src/index.ts +5 -7
  160. package/src/resizable-typed-array.ts +214 -0
  161. package/src/sparse-map/clean-sparse-map.ts +84 -0
  162. package/src/sparse-map/dynamic-typed-clean-sparse-map-lite.ts +109 -0
  163. package/src/sparse-map/dynamic-typed-sparse-map-lite.ts +124 -0
  164. package/src/sparse-map/index.ts +11 -0
  165. package/src/sparse-map/resizable-typed-clean-sparse-map-lite.ts +107 -0
  166. package/src/sparse-map/resizable-typed-sparse-map-lite.ts +122 -0
  167. package/src/sparse-map/sparse-map.ts +104 -0
  168. package/src/sparse-map/typed-clean-sparse-map-lite.ts +116 -0
  169. package/src/sparse-map/typed-clean-sparse-map.ts +149 -0
  170. package/src/sparse-map/typed-sparse-map-lite.ts +141 -0
  171. package/src/sparse-map/typed-sparse-map.ts +169 -0
  172. package/src/sparse-set/clean-sparse-set.ts +76 -0
  173. package/src/sparse-set/dynamic-typed-clean-sparse-set-lite.ts +64 -0
  174. package/src/sparse-set/dynamic-typed-clean-sparse-set.ts +101 -0
  175. package/src/sparse-set/dynamic-typed-sparse-set-lite.ts +67 -0
  176. package/src/sparse-set/dynamic-typed-sparse-set.ts +93 -0
  177. package/src/sparse-set/index.ts +15 -0
  178. package/src/sparse-set/resizable-typed-clean-sparse-set-lite.ts +64 -0
  179. package/src/sparse-set/resizable-typed-clean-sparse-set.ts +108 -0
  180. package/src/sparse-set/resizable-typed-sparse-set-lite.ts +67 -0
  181. package/src/sparse-set/resizable-typed-sparse-set.ts +97 -0
  182. package/src/sparse-set/sparse-set.ts +79 -0
  183. package/src/sparse-set/typed-clean-sparse-set-lite.ts +67 -0
  184. package/src/sparse-set/typed-clean-sparse-set.ts +100 -0
  185. package/src/sparse-set/typed-sparse-set-lite.ts +74 -0
  186. package/src/sparse-set/typed-sparse-set.ts +102 -0
  187. package/src/utils/compute-new-capacity.ts +39 -0
  188. package/src/utils/get-max-value-of-unsigned-typed-array.ts +19 -0
  189. package/src/utils/skip-list.ts +1 -1
  190. package/src/utils/trailing-zeros.ts +2 -3
  191. package/lib/bit-set.js.map +0 -1
  192. package/lib/sparse-map.js +0 -76
  193. package/lib/sparse-map.js.map +0 -1
  194. package/lib/sparse-set.js +0 -63
  195. package/lib/sparse-set.js.map +0 -1
  196. package/lib/typed-bit-set.js.map +0 -1
  197. package/lib/typed-sparse-map.d.ts +0 -20
  198. package/lib/typed-sparse-map.js +0 -83
  199. package/lib/typed-sparse-map.js.map +0 -1
  200. package/lib/typed-sparse-set.js +0 -59
  201. package/lib/typed-sparse-set.js.map +0 -1
  202. package/src/sparse-map.ts +0 -82
  203. package/src/sparse-set.ts +0 -74
  204. package/src/typed-sparse-map.ts +0 -97
  205. package/src/typed-sparse-set.ts +0 -73
@@ -0,0 +1,67 @@
1
+ import { DynamicTypedArray } from '@src/dynamic-typed-array.js'
2
+ import { assert } from '@blackglory/errors'
3
+ import { UnsignedTypedArrayConstructor } from 'justypes'
4
+
5
+ export class DynamicTypedSparseSetLite implements Iterable<number> {
6
+ private dense: DynamicTypedArray<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: DynamicTypedArray<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,93 @@
1
+ import { UnsignedTypedArrayConstructor } from 'justypes'
2
+ import { DynamicTypedArray } from '@src/dynamic-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 DynamicTypedSparseSet implements Iterable<number> {
8
+ private dense: DynamicTypedArray<UnsignedTypedArrayConstructor>
9
+ private sparse: DynamicTypedArray<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: DynamicTypedArray<UnsignedTypedArrayConstructor>) {
20
+ assert(array.length === 0, 'The array must be empty')
21
+
22
+ this.dense = array
23
+
24
+ const sparseInternalArrayConstructor = go(() => {
25
+ const maxIndex = getMaxValueOfUnsignedTypedArray(array.internalTypedArray)
26
+ + 1
27
+ if (
28
+ maxIndex <=
29
+ getMaxValueOfUnsignedTypedArrayConstructor(Uint8Array)
30
+ ) {
31
+ return Uint8Array
32
+ } else if (
33
+ maxIndex <=
34
+ getMaxValueOfUnsignedTypedArrayConstructor(Uint16Array)
35
+ ) {
36
+ return Uint16Array
37
+ } else if (
38
+ maxIndex <=
39
+ getMaxValueOfUnsignedTypedArrayConstructor(Uint32Array)
40
+ ) {
41
+ return Uint32Array
42
+ } else {
43
+ throw new Error('The array is too large')
44
+ }
45
+ })
46
+ this.sparse = new DynamicTypedArray(sparseInternalArrayConstructor)
47
+ }
48
+
49
+ [Symbol.iterator](): IterableIterator<number> {
50
+ return this.values()
51
+ }
52
+
53
+ values(): IterableIterator<number> {
54
+ return this.dense.values()
55
+ }
56
+
57
+ has(value: number): boolean {
58
+ const index = this.sparse.get(value)
59
+ return index !== undefined
60
+ && this.dense.get(index) === value
61
+ }
62
+
63
+ add(value: number): void {
64
+ if (!this.has(value)) {
65
+ const index = this.dense.length
66
+ this.dense.push(value)
67
+ this.sparse.set(value, index)
68
+ }
69
+ }
70
+
71
+ delete(value: number): boolean {
72
+ const index = this.sparse.get(value)
73
+ if (
74
+ index !== undefined &&
75
+ this.dense.get(index) === value
76
+ ) {
77
+ const lastValue = this.dense.pop()!
78
+ if (value !== lastValue) {
79
+ this.dense.internalTypedArray[index] = lastValue
80
+ this.sparse.set(lastValue, index)
81
+ }
82
+
83
+ return true
84
+ } else {
85
+ return false
86
+ }
87
+ }
88
+
89
+ clear(): void {
90
+ this.dense.clear()
91
+ // 无需清空sparse数组.
92
+ }
93
+ }
@@ -0,0 +1,15 @@
1
+ export * from './sparse-set.js'
2
+ export * from './typed-sparse-set.js'
3
+ export * from './typed-sparse-set-lite.js'
4
+ export * from './dynamic-typed-sparse-set.js'
5
+ export * from './dynamic-typed-sparse-set-lite.js'
6
+ export * from './resizable-typed-sparse-set.js'
7
+ export * from './resizable-typed-sparse-set-lite.js'
8
+
9
+ export * from './clean-sparse-set.js'
10
+ export * from './typed-clean-sparse-set.js'
11
+ export * from './typed-clean-sparse-set-lite.js'
12
+ export * from './dynamic-typed-clean-sparse-set.js'
13
+ export * from './dynamic-typed-clean-sparse-set-lite.js'
14
+ export * from './resizable-typed-clean-sparse-set.js'
15
+ export * from './resizable-typed-clean-sparse-set-lite.js'
@@ -0,0 +1,64 @@
1
+ import { UnsignedTypedArrayConstructor } from 'justypes'
2
+ import { ResizableTypedArray } from '@src/resizable-typed-array.js'
3
+ import { assert } from '@blackglory/errors'
4
+
5
+ export class ResizableTypedCleanSparseSetLite 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
+ return this.sparse[value] !== undefined
33
+ }
34
+
35
+ add(value: number): void {
36
+ if (!this.has(value)) {
37
+ const index = this.dense.length
38
+ this.dense.push(value)
39
+ this.sparse[value] = index
40
+ }
41
+ }
42
+
43
+ delete(value: number): boolean {
44
+ const index = this.sparse[value]
45
+ if (index !== undefined) {
46
+ this.sparse[value] = undefined
47
+
48
+ const lastValue = this.dense.pop()!
49
+ if (value !== lastValue) {
50
+ this.dense.internalTypedArray[index] = lastValue
51
+ this.sparse[lastValue] = index
52
+ }
53
+
54
+ return true
55
+ } else {
56
+ return false
57
+ }
58
+ }
59
+
60
+ clear(): void {
61
+ this.dense.clear()
62
+ this.sparse.length = 0
63
+ }
64
+ }
@@ -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
+ }