@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
@@ -1,14 +1,25 @@
1
1
  import { UnsignedTypedArrayConstructor } from 'justypes'
2
2
  import { assert } from '@blackglory/errors'
3
- import { DynamicTypedArray } from './dynamic-typed-array.js'
3
+ import { ResizableTypedArray } from '@src/resizable-typed-array.js'
4
4
  import { trailingZeros } from '@utils/trailing-zeros.js'
5
5
 
6
- export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
6
+ export class ResizableTypedBitSet implements Iterable<number> {
7
7
  private bitsPerElement: number
8
8
  private length = 0
9
- private _size = 0
9
+ #size = 0
10
10
 
11
- constructor(private array: DynamicTypedArray<T>) {
11
+ private quotientShift = 0
12
+ private remainderMask = 0
13
+
14
+ get [Symbol.toStringTag](): string {
15
+ return this.constructor.name
16
+ }
17
+
18
+ get size(): number {
19
+ return this.#size
20
+ }
21
+
22
+ constructor(private array: ResizableTypedArray<UnsignedTypedArrayConstructor>) {
12
23
  const bitsPerElement = array.BYTES_PER_ELEMENT * 8
13
24
 
14
25
  assert(
@@ -21,19 +32,13 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
21
32
  )
22
33
  // `31`是该数据结构中能够处理的最大值
23
34
  assert(
24
- bitsPerElement <= 31
25
- , 'The mask of bitsPerElement must be less than or equal to 31'
35
+ bitsPerElement <= 32
36
+ , 'The bitsPerElement must be less than or equal to 31'
26
37
  )
27
38
 
28
39
  this.bitsPerElement = bitsPerElement
29
- }
30
-
31
- get [Symbol.toStringTag](): string {
32
- return this.constructor.name
33
- }
34
-
35
- get size(): number {
36
- return this._size
40
+ this.quotientShift = Math.log2(bitsPerElement)
41
+ this.remainderMask = bitsPerElement - 1
37
42
  }
38
43
 
39
44
  [Symbol.iterator](): IterableIterator<number> {
@@ -46,13 +51,12 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
46
51
  const maxArrayLength = ~~(this.length / this.bitsPerElement) + 1
47
52
 
48
53
  for (let index = 0; index < maxArrayLength; index++) {
49
- let element = this.array.internalTypedArray[index]
50
- let offset = 0
51
- let indexOfBit: number
52
- while ((indexOfBit = trailingZeros(element)) !== 32) {
53
- yield index * this.bitsPerElement + offset + indexOfBit
54
- offset += indexOfBit + 1
55
- element >>= indexOfBit + 1
54
+ let element = this.array.get(index) ?? 0
55
+ while (element !== 0) {
56
+ const indexOfBit = trailingZeros(element)
57
+ yield index * this.bitsPerElement + indexOfBit
58
+ // 移除最低位置的1, 以推进下一个indexOfBit的获取.
59
+ element &= element - 1
56
60
  }
57
61
  }
58
62
  }
@@ -61,7 +65,7 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
61
65
  _dumpBinaryStrings(): string[] {
62
66
  const result: string[] = []
63
67
  for (let i = 0; i < this.array.length; i++) {
64
- const binary = this.array.internalTypedArray[i].toString(2)
68
+ const binary = ((this.array.get(i) ?? 0) >>> 0).toString(2)
65
69
  if (binary.length < this.bitsPerElement) {
66
70
  result.push('0'.repeat(this.bitsPerElement - binary.length) + binary)
67
71
  } else {
@@ -78,20 +82,16 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
78
82
  }
79
83
 
80
84
  add(value: number): boolean {
81
- assert(value >= 0, 'value must be greater than or equal to 0')
82
- if (value >= this.length) {
83
- this.length = value + 1
84
- }
85
-
86
85
  const [index, mask] = this.getPosition(value)
87
86
 
88
87
  const element = this.array.get(index) ?? 0
89
88
  this.array.set(index, element | mask)
90
89
 
91
90
  const added = (element & mask) !== mask
92
- if (added) {
93
- this._size++
94
- }
91
+ if (added) this.#size++
92
+
93
+ if (value >= this.length) this.length = value + 1
94
+
95
95
  return added
96
96
  }
97
97
 
@@ -102,22 +102,24 @@ export class TypedBitSet<T extends UnsignedTypedArrayConstructor> {
102
102
  this.array.set(index, element & ~mask)
103
103
 
104
104
  const deleted = (element & mask) === mask
105
- if (deleted) {
106
- this._size--
107
- }
105
+ if (deleted) this.#size--
106
+
108
107
  return deleted
109
108
  }
110
109
 
111
110
  clear(): void {
112
- this._size = 0
111
+ this.#size = 0
112
+ this.length = 0
113
113
  this.array.clear()
114
114
  }
115
115
 
116
116
  private getPosition(value: number): [index: number, mask: number] {
117
- const remainder = value % this.bitsPerElement
118
- const quotient = (value - remainder) / this.bitsPerElement
117
+ const remainder = value & this.remainderMask
118
+ const quotient = value >>> this.quotientShift
119
+
119
120
  const index = quotient
120
121
  const mask = this.getMask(remainder)
122
+
121
123
  return [index, mask]
122
124
  }
123
125
 
@@ -0,0 +1,134 @@
1
+ import { UnsignedTypedArray } from 'justypes'
2
+ import { assert } from '@blackglory/errors'
3
+ import { trailingZeros } from '@utils/trailing-zeros.js'
4
+
5
+ export class TypedBitSet implements Iterable<number> {
6
+ private bitsPerElement: number
7
+ private length = 0
8
+ #size = 0
9
+
10
+ private quotientShift = 0
11
+ private remainderMask = 0
12
+
13
+ get [Symbol.toStringTag](): string {
14
+ return this.constructor.name
15
+ }
16
+
17
+ get capacity(): number {
18
+ return this.array.length * this.bitsPerElement
19
+ }
20
+
21
+ get size(): number {
22
+ return this.#size
23
+ }
24
+
25
+ constructor(private array: UnsignedTypedArray) {
26
+ const bitsPerElement = array.BYTES_PER_ELEMENT * 8
27
+
28
+ assert(
29
+ Number.isInteger(bitsPerElement)
30
+ , 'The bitsPerElement must be an integer'
31
+ )
32
+ assert(
33
+ bitsPerElement > 0
34
+ , 'The bitsPerElement must be greater than 0'
35
+ )
36
+ assert(
37
+ bitsPerElement <= 32
38
+ , 'The bitsPerElement must be less than or equal to 32'
39
+ )
40
+
41
+ this.bitsPerElement = bitsPerElement
42
+ this.quotientShift = Math.log2(bitsPerElement)
43
+ this.remainderMask = bitsPerElement - 1
44
+ }
45
+
46
+ [Symbol.iterator](): IterableIterator<number> {
47
+ return this.values()
48
+ }
49
+
50
+ * values(): IterableIterator<number> {
51
+ if (this.length > 0) {
52
+ // maxArrayLength = Math.ceil(this.length / this.bitsPerElement)
53
+ const maxArrayLength = ~~(this.length / this.bitsPerElement) + 1
54
+
55
+ for (let index = 0; index < maxArrayLength; index++) {
56
+ let element = this.array[index] ?? 0
57
+ while (element !== 0) {
58
+ const indexOfBit = trailingZeros(element)
59
+ yield index * this.bitsPerElement + indexOfBit
60
+ // 移除最低位置的1, 以推进下一个indexOfBit的获取.
61
+ element &= element - 1
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ _dumpBinaryStrings(): string[] {
68
+ const result: string[] = []
69
+ for (let i = 0; i < this.array.length; i++) {
70
+ const binary = ((this.array[i] ?? 0) >>> 0).toString(2)
71
+ if (binary.length < this.bitsPerElement) {
72
+ result.push('0'.repeat(this.bitsPerElement - binary.length) + binary)
73
+ } else {
74
+ result.push(binary)
75
+ }
76
+ }
77
+ return result
78
+ }
79
+
80
+ has(value: number): boolean {
81
+ const [index, mask] = this.getPosition(value)
82
+
83
+ return (this.array[index] & mask) === mask
84
+ }
85
+
86
+ add(value: number): boolean {
87
+ const [index, mask] = this.getPosition(value)
88
+ assert(index < this.capacity, `The array is not large enough`)
89
+
90
+ const element = this.array[index]
91
+ this.array[index] = element | mask
92
+
93
+ const added = (element & mask) !== mask
94
+ if (added) this.#size++
95
+
96
+ if (value >= this.length) this.length = value + 1
97
+
98
+ return added
99
+ }
100
+
101
+ delete(value: number): boolean {
102
+ const [index, mask] = this.getPosition(value)
103
+
104
+ const element = this.array[index]
105
+ this.array[index] = element & ~mask
106
+
107
+ const deleted = (element & mask) === mask
108
+ if (deleted) this.#size--
109
+
110
+ return deleted
111
+ }
112
+
113
+ clear(): void {
114
+ this.#size = 0
115
+ this.length = 0
116
+ this.array.fill(0)
117
+ }
118
+
119
+ private getPosition(value: number): [index: number, mask: number] {
120
+ const remainder = value & this.remainderMask
121
+ const quotient = value >>> this.quotientShift
122
+
123
+ const index = quotient
124
+ const mask = this.getMask(remainder)
125
+
126
+ return [index, mask]
127
+ }
128
+
129
+ // 输入一定是一个小于bitsPerElement的值, 取值范围是[0, bitsPerElement)
130
+ private getMask(value: number): number {
131
+ // return 2 ** value
132
+ return 1 << value
133
+ }
134
+ }
@@ -1,28 +1,30 @@
1
1
  import { TypedArrayConstructor, TypedArrayOfConstructor } from 'justypes'
2
2
  import { assert } from '@blackglory/errors'
3
+ import { computeNewCapacity } from '@utils/compute-new-capacity.js'
3
4
 
4
5
  interface IDynamicTypedArrayOptions {
5
- capacity?: number
6
6
  growthFactor?: number
7
+ initialCapacity?: number
8
+ fillValue?: number
7
9
  }
8
10
 
9
- // 相关提案: https://github.com/tc39/proposal-resizablearraybuffer
10
- export class DynamicTypedArray<T extends TypedArrayConstructor> {
11
+ export class DynamicTypedArray<
12
+ T extends TypedArrayConstructor
13
+ > implements Iterable<number> {
11
14
  private array: TypedArrayOfConstructor<T>
12
- private _length: number = 0
13
- private initialCapacity: number
15
+
14
16
  readonly growthFactor: number
17
+ readonly BYTES_PER_ELEMENT: number
18
+ readonly fillValue: number
15
19
 
16
- get internalTypedArray(): TypedArrayOfConstructor<T> {
17
- return this.array
18
- }
20
+ #length: number = 0
19
21
 
20
22
  get [Symbol.toStringTag](): string {
21
23
  return this.constructor.name
22
24
  }
23
25
 
24
- get BYTES_PER_ELEMENT(): number {
25
- return this.typedArrayConstructor.BYTES_PER_ELEMENT
26
+ get internalTypedArray(): TypedArrayOfConstructor<T> {
27
+ return this.array
26
28
  }
27
29
 
28
30
  /**
@@ -36,23 +38,39 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
36
38
  * 数组逻辑上的长度, 总是小于或等于capacity.
37
39
  */
38
40
  get length(): number {
39
- return this._length
41
+ return this.#length
40
42
  }
41
43
 
42
44
  constructor(
43
45
  private typedArrayConstructor: T
44
46
  , {
45
- capacity = 0
46
- , growthFactor = 1.5
47
+ growthFactor = 1.5
48
+ , initialCapacity = 0
49
+ , fillValue = 0
47
50
  }: IDynamicTypedArrayOptions = {}
48
51
  ) {
49
- assert(Number.isInteger(capacity), 'capacity must be an integer')
50
- assert(capacity >= 0, 'capacity must be greater than or equal to 0')
51
52
  assert(growthFactor >= 1, 'growthFactory must be greater than or equal to 1')
53
+ assert(Number.isInteger(initialCapacity), 'initialCapacity must be an integer')
54
+ assert(initialCapacity >= 0, 'initialCapacity must be greater than or equal to 0')
52
55
 
53
- this.initialCapacity = capacity
54
- this.array = new typedArrayConstructor(capacity) as TypedArrayOfConstructor<T>
55
56
  this.growthFactor = growthFactor
57
+ this.fillValue = fillValue
58
+
59
+ const array = new typedArrayConstructor(initialCapacity) as TypedArrayOfConstructor<T>
60
+ if (fillValue !== 0) array.fill(fillValue)
61
+ this.array = array
62
+
63
+ this.BYTES_PER_ELEMENT = typedArrayConstructor.BYTES_PER_ELEMENT
64
+ }
65
+
66
+ [Symbol.iterator](): IterableIterator<number> {
67
+ return this.values()
68
+ }
69
+
70
+ * values(): IterableIterator<number> {
71
+ for (let i = 0; i < this.#length; i++) {
72
+ yield this.array[i]
73
+ }
56
74
  }
57
75
 
58
76
  set(index: number, value: number): void {
@@ -65,38 +83,39 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
65
83
  this.resize(newCapacity)
66
84
  }
67
85
 
68
- if (index >= this._length) {
69
- this._length = index + 1
86
+ if (index >= this.#length) {
87
+ this.#length = index + 1
70
88
  }
71
89
 
72
90
  this.array[index] = value
73
91
  }
74
92
 
75
- setValues(index: number, values: TypedArrayOfConstructor<T>): void {
76
- if (index + values.length >= this.capacity) {
93
+ setValues(index: number, values: ArrayLike<number>): void {
94
+ const endIndex = index + values.length
95
+ if (endIndex > this.capacity) {
77
96
  const newCapacity = computeNewCapacity(
78
97
  this.capacity
79
- , index + values.length
98
+ , endIndex
80
99
  , this.growthFactor
81
100
  )
82
101
  this.resize(newCapacity)
83
102
  }
84
103
 
85
- if (index + values.length > this._length) {
86
- this._length = index + values.length
104
+ if (endIndex > this.#length) {
105
+ this.#length = endIndex
87
106
  }
88
107
 
89
- this.internalTypedArray.set(values, index)
108
+ this.array.set(values, index)
90
109
  }
91
110
 
92
111
  get(index: number): number | undefined {
93
- return index < this._length
112
+ return index < this.#length
94
113
  ? this.array[index]
95
114
  : undefined
96
115
  }
97
116
 
98
117
  push(...values: number[]): void {
99
- const newLength = this._length + values.length
118
+ const newLength = this.#length + values.length
100
119
  if (newLength > this.capacity) {
101
120
  const newCapacity = computeNewCapacity(
102
121
  this.capacity
@@ -107,21 +126,14 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
107
126
  }
108
127
 
109
128
  for (const value of values) {
110
- this.array[this._length++] = value
129
+ this.array[this.#length++] = value
111
130
  }
112
131
  }
113
132
 
114
133
  pop(): number | undefined {
115
- if (this._length > 0) {
116
- const value = this.array[this._length - 1]
117
- this._length--
118
-
119
- const newCapacity = computeNewCapacity(
120
- this.capacity
121
- , this.length
122
- , this.growthFactor
123
- )
124
- this.resize(newCapacity)
134
+ if (this.#length > 0) {
135
+ const value = this.array[this.#length - 1]
136
+ this.#length--
125
137
 
126
138
  return value
127
139
  } else {
@@ -130,9 +142,16 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
130
142
  }
131
143
 
132
144
  clear(): void {
133
- this._length = 0
134
- const newArray = new this.typedArrayConstructor(this.initialCapacity)
135
- this.array = newArray as TypedArrayOfConstructor<T>
145
+ this.#length = 0
146
+ }
147
+
148
+ shrink(): void {
149
+ const newCapacity = computeNewCapacity(
150
+ this.capacity
151
+ , this.length
152
+ , this.growthFactor
153
+ )
154
+ this.resize(newCapacity)
136
155
  }
137
156
 
138
157
  sort(compare?: (a: number, b: number) => number): void {
@@ -148,8 +167,14 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
148
167
  } else if (this.array.length < newCapacity) {
149
168
  const newArray = new this.typedArrayConstructor(newCapacity)
150
169
  newArray.set(this.array)
170
+
171
+ if (this.fillValue !== 0) {
172
+ const startIndex = this.array.length
173
+ newArray.fill(this.fillValue, startIndex)
174
+ }
175
+
151
176
  this.array = newArray as TypedArrayOfConstructor<T>
152
- } else if (this.array.length > newCapacity) {
177
+ } else /* if (this.array.length > newCapacity) */ {
153
178
  const newArray = new this.typedArrayConstructor(newCapacity)
154
179
  // 不需要的部分将被舍弃.
155
180
  for (let i = newCapacity; i--;) {
@@ -159,43 +184,3 @@ export class DynamicTypedArray<T extends TypedArrayConstructor> {
159
184
  }
160
185
  }
161
186
  }
162
-
163
- export function computeNewCapacity(
164
- oldCapacity: number
165
- , targetLength: number
166
- , growthFactor: number
167
- ): number {
168
- if (growthFactor === 1) {
169
- return targetLength
170
- } else {
171
- if (oldCapacity === targetLength) {
172
- return targetLength
173
- } else if (oldCapacity < targetLength) {
174
- // 增加容量以适配targetLength
175
- let newCapacity = Math.max(oldCapacity, 1)
176
- while (newCapacity < targetLength) {
177
- newCapacity *= growthFactor
178
- }
179
- return Math.floor(newCapacity)
180
- } else {
181
- // 尝试减少容量以适配targetLength
182
-
183
- // `targetLength = 0`是特殊情况,
184
- // 此时无论怎么将oldCapacity除以growthFactory几次, 都不可能得到比targetLength小的结果.
185
- if (targetLength === 0) {
186
- return 0
187
- } else {
188
- let newCapacity = oldCapacity
189
- while (true) {
190
- const temp = newCapacity / growthFactor
191
- if (temp < targetLength) {
192
- break
193
- } else {
194
- newCapacity = temp
195
- }
196
- }
197
- return Math.floor(newCapacity)
198
- }
199
- }
200
- }
201
- }
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './box.js'
2
2
  export * from './cons.js'
3
3
  export * from './array.js'
4
+ export * from './typed-array.js'
4
5
  export * from './emitter.js'
5
6
  export * from './generator-emitter.js'
6
7
  export * from './async-generator-emitter.js'
@@ -17,12 +18,10 @@ export * from './trie-map.js'
17
18
  export * from './string-trie-map.js'
18
19
  export { RadixTree } from './radix-tree.js'
19
20
  export { StringRadixTree } from './string-radix-tree.js'
20
- export * from './sparse-set.js'
21
- export * from './sparse-map.js'
22
- export * from './typed-sparse-map.js'
23
- export * from './typed-sparse-set.js'
24
- export { DynamicTypedArray } from './dynamic-typed-array.js'
21
+ export * from './dynamic-typed-array.js'
22
+ export * from './resizable-typed-array.js'
25
23
  export * from './sorted-set.js'
26
- export * from './bit-set.js'
27
- export * from './typed-bit-set.js'
28
24
  export * from './disjoint-set.js'
25
+ export * from './bit-set/index.js'
26
+ export * from './sparse-set/index.js'
27
+ export * from './sparse-map/index.js'