@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,124 @@
1
+ import { assert } from '@blackglory/errors'
2
+ import { TypedArrayConstructor, UnsignedTypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
3
+ import { DynamicTypedArray } from '@src/dynamic-typed-array.js'
4
+
5
+ export class DynamicTypedSparseMapLite<
6
+ K extends UnsignedTypedArrayConstructor
7
+ , V extends TypedArrayConstructor
8
+ > {
9
+ private denseKeys: DynamicTypedArray<K>
10
+ private denseValues: DynamicTypedArray<V>
11
+ private sparse: Array<number | undefined> = []
12
+
13
+ get [Symbol.toStringTag](): string {
14
+ return this.constructor.name
15
+ }
16
+
17
+ get size(): number {
18
+ return this.denseKeys.length
19
+ }
20
+
21
+ get internalKeyArray(): TypedArrayOfConstructor<K> {
22
+ return this.denseKeys.internalTypedArray
23
+ }
24
+
25
+ get internalValueArray(): TypedArrayOfConstructor<V> {
26
+ return this.denseValues.internalTypedArray
27
+ }
28
+
29
+ constructor(
30
+ keys: DynamicTypedArray<K>
31
+ , values: DynamicTypedArray<V>
32
+ ) {
33
+ assert(keys.length === 0, 'keys must be empty')
34
+
35
+ this.denseKeys = keys
36
+ this.denseValues = values
37
+ }
38
+
39
+ * entries(): IterableIterator<[key: number, value: number]> {
40
+ for (let i = 0; i < this.denseKeys.length; i++) {
41
+ yield [
42
+ this.denseKeys.internalTypedArray[i]
43
+ , this.denseValues.internalTypedArray[i]
44
+ ]
45
+ }
46
+ }
47
+
48
+ keys(): IterableIterator<number> {
49
+ return this.denseKeys.values()
50
+ }
51
+
52
+ values(): IterableIterator<number> {
53
+ return this.denseValues.values()
54
+ }
55
+
56
+ getInternalIndexOfKey(key: number): number | undefined {
57
+ const index = this.sparse[key]
58
+ if (
59
+ index !== undefined &&
60
+ this.denseKeys.get(index) === key
61
+ ) {
62
+ return index
63
+ }
64
+ }
65
+
66
+ has(key: number): boolean {
67
+ const index = this.sparse[key]
68
+ return index !== undefined
69
+ && this.denseKeys.get(index) === key
70
+ }
71
+
72
+ get(key: number): number | undefined {
73
+ const index = this.sparse[key]
74
+ if (
75
+ index !== undefined &&
76
+ this.denseKeys.get(index) === key
77
+ ) {
78
+ return this.denseValues.internalTypedArray[index]
79
+ } else {
80
+ return undefined
81
+ }
82
+ }
83
+
84
+ set(key: number, value: number): void {
85
+ const index = this.sparse[key]
86
+ if (
87
+ index !== undefined &&
88
+ this.denseKeys.get(index) === key
89
+ ) {
90
+ this.denseValues.internalTypedArray[index] = value
91
+ } else {
92
+ const index = this.denseKeys.length
93
+ this.denseKeys.push(key)
94
+ this.denseValues.push(value)
95
+ this.sparse[key] = index
96
+ }
97
+ }
98
+
99
+ delete(key: number): boolean {
100
+ const index = this.sparse[key]
101
+ if (
102
+ index !== undefined &&
103
+ this.denseKeys.get(index) === key
104
+ ) {
105
+ const lastKey = this.denseKeys.pop()!
106
+ const lastValue = this.denseValues.pop()!
107
+ if (key !== lastKey) {
108
+ this.denseKeys.internalTypedArray[index] = lastKey
109
+ this.denseValues.internalTypedArray[index] = lastValue
110
+ this.sparse[lastKey] = index
111
+ }
112
+
113
+ return true
114
+ } else {
115
+ return false
116
+ }
117
+ }
118
+
119
+ clear(): void {
120
+ this.denseKeys.clear()
121
+ this.denseValues.clear()
122
+ // 无需清空sparse数组.
123
+ }
124
+ }
@@ -0,0 +1,11 @@
1
+ export * from './sparse-map.js'
2
+ export * from './typed-sparse-map.js'
3
+ export * from './typed-sparse-map-lite.js'
4
+ export * from './dynamic-typed-sparse-map-lite.js'
5
+ export * from './resizable-typed-sparse-map-lite.js'
6
+
7
+ export * from './clean-sparse-map.js'
8
+ export * from './typed-clean-sparse-map.js'
9
+ export * from './typed-clean-sparse-map-lite.js'
10
+ export * from './dynamic-typed-clean-sparse-map-lite.js'
11
+ export * from './resizable-typed-clean-sparse-map-lite.js'
@@ -0,0 +1,107 @@
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 ResizableTypedCleanSparseMapLite<
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, 'keys 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
+ return this.sparse[key]
56
+ }
57
+
58
+ has(key: number): boolean {
59
+ return this.sparse[key] !== undefined
60
+ }
61
+
62
+ get(key: number): number | undefined {
63
+ const index = this.sparse[key]
64
+ if (index !== undefined) {
65
+ return this.denseValues.internalTypedArray[index]
66
+ } else {
67
+ return undefined
68
+ }
69
+ }
70
+
71
+ set(key: number, value: number): void {
72
+ const index = this.sparse[key]
73
+ if (index !== undefined) {
74
+ this.denseValues.internalTypedArray[index] = value
75
+ } else {
76
+ const index = this.denseKeys.length
77
+ this.denseKeys.push(key)
78
+ this.denseValues.push(value)
79
+ this.sparse[key] = index
80
+ }
81
+ }
82
+
83
+ delete(key: number): boolean {
84
+ const index = this.sparse[key]
85
+ if (index !== undefined) {
86
+ this.sparse[key] = undefined
87
+
88
+ const lastKey = this.denseKeys.pop()!
89
+ const lastValue = this.denseValues.pop()!
90
+ if (key !== lastKey) {
91
+ this.denseKeys.internalTypedArray[index] = lastKey
92
+ this.denseValues.internalTypedArray[index] = lastValue
93
+ this.sparse[lastKey] = index
94
+ }
95
+
96
+ return true
97
+ } else {
98
+ return false
99
+ }
100
+ }
101
+
102
+ clear(): void {
103
+ this.denseKeys.clear()
104
+ this.denseValues.clear()
105
+ this.sparse.length = 0
106
+ }
107
+ }
@@ -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
+ }