@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,214 @@
1
+ import { TypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
2
+ import { assert } from '@blackglory/errors'
3
+ import { computeNewCapacity } from '@utils/compute-new-capacity.js'
4
+
5
+ interface IResizableTypedArrayOptions {
6
+ maxCapacity: number
7
+
8
+ initialCapacity?: number
9
+ growthFactor?: number
10
+
11
+ fillValue?: number
12
+ }
13
+
14
+ export class ResizableTypedArray<
15
+ T extends TypedArrayConstructor
16
+ > implements Iterable<number> {
17
+ private array: TypedArrayOfConstructor<T, ArrayBuffer>
18
+
19
+ readonly maxCapacity: number
20
+ readonly growthFactor: number
21
+ readonly BYTES_PER_ELEMENT: number
22
+ readonly internalTypedArray: TypedArrayOfConstructor<T>
23
+ readonly fillValue: number
24
+
25
+ #length: number = 0
26
+
27
+ get [Symbol.toStringTag](): string {
28
+ return this.constructor.name
29
+ }
30
+
31
+ /**
32
+ * 数组当前的容量.
33
+ */
34
+ get capacity(): number {
35
+ return this.array.length
36
+ }
37
+
38
+ /**
39
+ * 数组逻辑上的长度, 总是小于或等于capacity.
40
+ */
41
+ get length(): number {
42
+ return this.#length
43
+ }
44
+
45
+ constructor(
46
+ typedArrayConstructor: T
47
+ , {
48
+ maxCapacity
49
+ , initialCapacity = 0
50
+ , growthFactor = 1.5
51
+ , fillValue = 0
52
+ }: IResizableTypedArrayOptions
53
+ ) {
54
+ assert(growthFactor >= 1, 'growthFactory must be greater than or equal to 1')
55
+ assert(initialCapacity >= 0, 'initialCapacity must be greater than or equal to 0')
56
+ assert(Number.isInteger(initialCapacity), 'capacity must be an integer')
57
+ assert(initialCapacity >= 0, 'capacity must be greater than or equal to 0')
58
+ assert(Number.isInteger(maxCapacity), 'maxCapacity must be an integer')
59
+ assert(maxCapacity >= initialCapacity, 'maxCapacity must be greater than or equal to capacity')
60
+
61
+ this.growthFactor = growthFactor
62
+ this.maxCapacity = maxCapacity
63
+ this.fillValue = fillValue
64
+
65
+ const buffer = new ArrayBuffer(
66
+ initialCapacity * typedArrayConstructor.BYTES_PER_ELEMENT
67
+ , { maxByteLength: maxCapacity * typedArrayConstructor.BYTES_PER_ELEMENT }
68
+ )
69
+ const array = new typedArrayConstructor(buffer)
70
+ if (fillValue !== 0) array.fill(fillValue)
71
+ this.array = array as TypedArrayOfConstructor<T, ArrayBuffer>
72
+
73
+ this.internalTypedArray = array as TypedArrayOfConstructor<T, ArrayBuffer>
74
+ this.BYTES_PER_ELEMENT = typedArrayConstructor.BYTES_PER_ELEMENT
75
+ }
76
+
77
+ [Symbol.iterator](): IterableIterator<number> {
78
+ return this.values()
79
+ }
80
+
81
+ * values(): IterableIterator<number> {
82
+ for (let i = 0; i < this.#length; i++) {
83
+ yield this.array[i]
84
+ }
85
+ }
86
+
87
+ set(index: number, value: number): void {
88
+ if (index >= this.capacity) {
89
+ assert(index < this.maxCapacity, 'index must be less than maxCapacity')
90
+
91
+ const newCapacity = Math.min(
92
+ computeNewCapacity(
93
+ this.capacity
94
+ , index + 1
95
+ , this.growthFactor
96
+ )
97
+ , this.maxCapacity
98
+ )
99
+
100
+ this.resize(newCapacity)
101
+ }
102
+
103
+ if (index >= this.#length) {
104
+ this.#length = index + 1
105
+ }
106
+
107
+ this.array[index] = value
108
+ }
109
+
110
+ setValues(index: number, values: ArrayLike<number>): void {
111
+ const endIndex = index + values.length
112
+ if (endIndex > this.capacity) {
113
+ assert(
114
+ endIndex <= this.maxCapacity
115
+ , 'endIndex must be less than or equal tomaxCapacity'
116
+ )
117
+
118
+ const newCapacity = Math.min(
119
+ computeNewCapacity(
120
+ this.capacity
121
+ , index + values.length
122
+ , this.growthFactor
123
+ )
124
+ , this.maxCapacity
125
+ )
126
+
127
+ this.resize(newCapacity)
128
+ }
129
+
130
+ if (endIndex > this.#length) {
131
+ this.#length = endIndex
132
+ }
133
+
134
+ this.array.set(values, index)
135
+ }
136
+
137
+ get(index: number): number | undefined {
138
+ return index < this.#length
139
+ ? this.array[index]
140
+ : undefined
141
+ }
142
+
143
+ push(...values: number[]): void {
144
+ const newLength = this.#length + values.length
145
+ if (newLength > this.capacity) {
146
+ assert(
147
+ newLength <= this.maxCapacity
148
+ , 'newLength must be less than or equal to maxCapacity'
149
+ )
150
+
151
+ const newCapacity = Math.min(
152
+ computeNewCapacity(
153
+ this.capacity
154
+ , newLength
155
+ , this.growthFactor
156
+ )
157
+ , this.maxCapacity
158
+ )
159
+
160
+ this.resize(newCapacity)
161
+ }
162
+
163
+ for (const value of values) {
164
+ this.array[this.#length++] = value
165
+ }
166
+ }
167
+
168
+ pop(): number | undefined {
169
+ if (this.#length > 0) {
170
+ const value = this.array[this.#length - 1]
171
+ this.#length--
172
+
173
+ return value
174
+ } else {
175
+ return undefined
176
+ }
177
+ }
178
+
179
+ clear(): void {
180
+ this.#length = 0
181
+ }
182
+
183
+ shrink(): void {
184
+ const newCapacity = computeNewCapacity(
185
+ this.capacity
186
+ , this.length
187
+ , this.growthFactor
188
+ )
189
+ this.resize(newCapacity)
190
+ }
191
+
192
+ sort(compare?: (a: number, b: number) => number): void {
193
+ const capacity = this.capacity
194
+ this.resize(this.length)
195
+ this.array.sort(compare)
196
+ this.resize(capacity)
197
+ }
198
+
199
+ private resize(newCapacity: number): void {
200
+ if (this.array.length === newCapacity) {
201
+ return
202
+ } else if (this.array.length < newCapacity) {
203
+ if (this.fillValue === 0) {
204
+ this.array.buffer.resize(newCapacity * this.BYTES_PER_ELEMENT)
205
+ } else {
206
+ const startIndex = this.array.length
207
+ this.array.buffer.resize(newCapacity * this.BYTES_PER_ELEMENT)
208
+ this.array.fill(this.fillValue, startIndex)
209
+ }
210
+ } else /* if (this.array.length > newCapacity) */ {
211
+ this.array.buffer.resize(newCapacity * this.BYTES_PER_ELEMENT)
212
+ }
213
+ }
214
+ }
@@ -0,0 +1,84 @@
1
+ export class CleanSparseMap<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
+ return this.sparse[key]
33
+ }
34
+
35
+ has(key: number): boolean {
36
+ return this.sparse[key] !== undefined
37
+ }
38
+
39
+ get(key: number): T | undefined {
40
+ const index = this.sparse[key]
41
+ if (index !== undefined) {
42
+ return this.denseValues[index]
43
+ } else {
44
+ return undefined
45
+ }
46
+ }
47
+
48
+ set(key: number, value: T): void {
49
+ const index = this.sparse[key]
50
+ if (index !== undefined) {
51
+ this.denseValues[index] = value
52
+ } else {
53
+ const index = this.denseKeys.length
54
+ this.denseKeys.push(key)
55
+ this.denseValues.push(value)
56
+ this.sparse[key] = index
57
+ }
58
+ }
59
+
60
+ delete(key: number): boolean {
61
+ const index = this.sparse[key]
62
+ if (index !== undefined) {
63
+ this.sparse[key] = undefined
64
+
65
+ const lastKey = this.denseKeys.pop()!
66
+ const lastValue = this.denseValues.pop()!
67
+ if (key !== lastKey) {
68
+ this.denseKeys[index] = lastKey
69
+ this.denseValues[index] = lastValue
70
+ this.sparse[lastKey] = index
71
+ }
72
+
73
+ return true
74
+ } else {
75
+ return false
76
+ }
77
+ }
78
+
79
+ clear(): void {
80
+ this.denseKeys.length = 0
81
+ this.denseValues.length = 0
82
+ this.sparse.length = 0
83
+ }
84
+ }
@@ -0,0 +1,109 @@
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 DynamicTypedCleanSparseMapLite<
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
+ return this.sparse[key]
58
+ }
59
+
60
+ has(key: number): boolean {
61
+ return this.sparse[key] !== undefined
62
+ }
63
+
64
+ get(key: number): number | undefined {
65
+ const index = this.sparse[key]
66
+ if (index !== undefined) {
67
+ return this.denseValues.internalTypedArray[index]
68
+ } else {
69
+ return undefined
70
+ }
71
+ }
72
+
73
+ set(key: number, value: number): void {
74
+ const index = this.sparse[key]
75
+ if (index !== undefined) {
76
+ this.denseValues.internalTypedArray[index] = value
77
+ } else {
78
+ const index = this.denseKeys.length
79
+ this.denseKeys.push(key)
80
+ this.denseValues.push(value)
81
+ this.sparse[key] = index
82
+ }
83
+ }
84
+
85
+ delete(key: number): boolean {
86
+ const index = this.sparse[key]
87
+ if (index !== undefined) {
88
+ this.sparse[key] = undefined
89
+
90
+ const lastKey = this.denseKeys.pop()!
91
+ const lastValue = this.denseValues.pop()!
92
+ if (key !== lastKey) {
93
+ this.denseKeys.internalTypedArray[index] = lastKey
94
+ this.denseValues.internalTypedArray[index] = lastValue
95
+ this.sparse[lastKey] = index
96
+ }
97
+
98
+ return true
99
+ } else {
100
+ return false
101
+ }
102
+ }
103
+
104
+ clear(): void {
105
+ this.denseKeys.clear()
106
+ this.denseValues.clear()
107
+ this.sparse.length = 0
108
+ }
109
+ }
@@ -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
+ }