@blackglory/structures 0.14.15 → 0.15.1

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 +681 -99
  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 +6 -7
  41. package/lib/index.js +6 -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/typed-array.d.ts +3 -0
  141. package/lib/typed-array.js +13 -0
  142. package/lib/typed-array.js.map +1 -0
  143. package/lib/unique-queue.js +1 -3
  144. package/lib/unique-queue.js.map +1 -1
  145. package/lib/utils/compute-new-capacity.d.ts +1 -0
  146. package/lib/utils/compute-new-capacity.js +36 -0
  147. package/lib/utils/compute-new-capacity.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 +6 -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/typed-array.ts +19 -0
  188. package/src/utils/compute-new-capacity.ts +39 -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,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 '@src/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
+ }