@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.
- package/README.md +661 -92
- package/lib/async-generator-emitter.js +2 -5
- package/lib/async-generator-emitter.js.map +1 -1
- package/lib/big-map.js +1 -3
- package/lib/big-map.js.map +1 -1
- package/lib/big-set.js +1 -3
- package/lib/big-set.js.map +1 -1
- package/lib/{bit-set.d.ts → bit-set/bit-set.d.ts} +5 -2
- package/lib/{bit-set.js → bit-set/bit-set.js} +43 -34
- package/lib/bit-set/bit-set.js.map +1 -0
- package/lib/{typed-bit-set.d.ts → bit-set/dynamic-typed-bit-set.d.ts} +6 -4
- package/lib/bit-set/dynamic-typed-bit-set.js +95 -0
- package/lib/bit-set/dynamic-typed-bit-set.js.map +1 -0
- package/lib/bit-set/index.d.ts +4 -0
- package/lib/bit-set/index.js +5 -0
- package/lib/bit-set/index.js.map +1 -0
- package/lib/bit-set/resizable-typed-bit-set.d.ts +22 -0
- package/lib/{typed-bit-set.js → bit-set/resizable-typed-bit-set.js} +37 -39
- package/lib/bit-set/resizable-typed-bit-set.js.map +1 -0
- package/lib/bit-set/typed-bit-set.d.ts +22 -0
- package/lib/bit-set/typed-bit-set.js +99 -0
- package/lib/bit-set/typed-bit-set.js.map +1 -0
- package/lib/box.js +1 -0
- package/lib/box.js.map +1 -1
- package/lib/disjoint-set.js +2 -4
- package/lib/disjoint-set.js.map +1 -1
- package/lib/dynamic-typed-array.d.ts +12 -9
- package/lib/dynamic-typed-array.js +51 -66
- package/lib/dynamic-typed-array.js.map +1 -1
- package/lib/emitter.js +3 -7
- package/lib/emitter.js.map +1 -1
- package/lib/expirable-map.js +9 -15
- package/lib/expirable-map.js.map +1 -1
- package/lib/generator-emitter.js +2 -5
- package/lib/generator-emitter.js.map +1 -1
- package/lib/hash-map.js +2 -1
- package/lib/hash-map.js.map +1 -1
- package/lib/hash-set.js +2 -1
- package/lib/hash-set.js.map +1 -1
- package/lib/index.d.ts +5 -7
- package/lib/index.js +5 -7
- package/lib/index.js.map +1 -1
- package/lib/lru-map.js +2 -1
- package/lib/lru-map.js.map +1 -1
- package/lib/queue.js +1 -3
- package/lib/queue.js.map +1 -1
- package/lib/radix-tree.js +3 -4
- package/lib/radix-tree.js.map +1 -1
- package/lib/resizable-typed-array.d.ts +32 -0
- package/lib/resizable-typed-array.js +127 -0
- package/lib/resizable-typed-array.js.map +1 -0
- package/lib/sorted-set.js +2 -1
- package/lib/sorted-set.js.map +1 -1
- package/lib/sparse-map/clean-sparse-map.d.ts +18 -0
- package/lib/sparse-map/clean-sparse-map.js +74 -0
- package/lib/sparse-map/clean-sparse-map.js.map +1 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js +87 -0
- package/lib/sparse-map/dynamic-typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.js +94 -0
- package/lib/sparse-map/dynamic-typed-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/index.d.ts +10 -0
- package/lib/sparse-map/index.js +11 -0
- package/lib/sparse-map/index.js.map +1 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js +85 -0
- package/lib/sparse-map/resizable-typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.js +92 -0
- package/lib/sparse-map/resizable-typed-sparse-map-lite.js.map +1 -0
- package/lib/{sparse-map.d.ts → sparse-map/sparse-map.d.ts} +6 -5
- package/lib/sparse-map/sparse-map.js +86 -0
- package/lib/sparse-map/sparse-map.js.map +1 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.js +92 -0
- package/lib/sparse-map/typed-clean-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/typed-clean-sparse-map.d.ts +22 -0
- package/lib/sparse-map/typed-clean-sparse-map.js +117 -0
- package/lib/sparse-map/typed-clean-sparse-map.js.map +1 -0
- package/lib/sparse-map/typed-sparse-map-lite.d.ts +21 -0
- package/lib/sparse-map/typed-sparse-map-lite.js +109 -0
- package/lib/sparse-map/typed-sparse-map-lite.js.map +1 -0
- package/lib/sparse-map/typed-sparse-map.d.ts +21 -0
- package/lib/sparse-map/typed-sparse-map.js +130 -0
- package/lib/sparse-map/typed-sparse-map.js.map +1 -0
- package/lib/sparse-set/clean-sparse-set.d.ts +13 -0
- package/lib/sparse-set/clean-sparse-set.js +57 -0
- package/lib/sparse-set/clean-sparse-set.js.map +1 -0
- package/lib/{typed-sparse-set.d.ts → sparse-set/dynamic-typed-clean-sparse-set-lite.d.ts} +6 -6
- package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js +51 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.js +82 -0
- package/lib/sparse-set/dynamic-typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.js +52 -0
- package/lib/sparse-set/dynamic-typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.js +75 -0
- package/lib/sparse-set/dynamic-typed-sparse-set.js.map +1 -0
- package/lib/sparse-set/index.d.ts +14 -0
- package/lib/sparse-set/index.js +15 -0
- package/lib/sparse-set/index.js.map +1 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js +51 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.js +83 -0
- package/lib/sparse-set/resizable-typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.js +52 -0
- package/lib/sparse-set/resizable-typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/resizable-typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/resizable-typed-sparse-set.js +76 -0
- package/lib/sparse-set/resizable-typed-sparse-set.js.map +1 -0
- package/lib/{sparse-set.d.ts → sparse-set/sparse-set.d.ts} +3 -4
- package/lib/sparse-set/sparse-set.js +60 -0
- package/lib/sparse-set/sparse-set.js.map +1 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.js +55 -0
- package/lib/sparse-set/typed-clean-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/typed-clean-sparse-set.d.ts +16 -0
- package/lib/sparse-set/typed-clean-sparse-set.js +80 -0
- package/lib/sparse-set/typed-clean-sparse-set.js.map +1 -0
- package/lib/sparse-set/typed-sparse-set-lite.d.ts +15 -0
- package/lib/sparse-set/typed-sparse-set-lite.js +60 -0
- package/lib/sparse-set/typed-sparse-set-lite.js.map +1 -0
- package/lib/sparse-set/typed-sparse-set.d.ts +15 -0
- package/lib/sparse-set/typed-sparse-set.js +81 -0
- package/lib/sparse-set/typed-sparse-set.js.map +1 -0
- package/lib/string-radix-tree.js +3 -4
- package/lib/string-radix-tree.js.map +1 -1
- package/lib/string-trie-map.js +3 -4
- package/lib/string-trie-map.js.map +1 -1
- package/lib/tlru-map.js +6 -6
- package/lib/tlru-map.js.map +1 -1
- package/lib/trie-map.js +3 -4
- package/lib/trie-map.js.map +1 -1
- package/lib/unique-queue.js +1 -3
- package/lib/unique-queue.js.map +1 -1
- package/lib/utils/compute-new-capacity.d.ts +1 -0
- package/lib/utils/compute-new-capacity.js +36 -0
- package/lib/utils/compute-new-capacity.js.map +1 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.d.ts +3 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.js +13 -0
- package/lib/utils/get-max-value-of-unsigned-typed-array.js.map +1 -0
- package/lib/utils/skip-list.js +11 -9
- package/lib/utils/skip-list.js.map +1 -1
- package/lib/utils/trailing-zeros.js +1 -1
- package/lib/utils/trailing-zeros.js.map +1 -1
- package/package.json +28 -31
- package/src/{bit-set.ts → bit-set/bit-set.ts} +47 -31
- package/src/bit-set/dynamic-typed-bit-set.ts +131 -0
- package/src/bit-set/index.ts +4 -0
- package/src/{typed-bit-set.ts → bit-set/resizable-typed-bit-set.ts} +38 -36
- package/src/bit-set/typed-bit-set.ts +134 -0
- package/src/dynamic-typed-array.ts +67 -82
- package/src/index.ts +5 -7
- package/src/resizable-typed-array.ts +214 -0
- package/src/sparse-map/clean-sparse-map.ts +84 -0
- package/src/sparse-map/dynamic-typed-clean-sparse-map-lite.ts +109 -0
- package/src/sparse-map/dynamic-typed-sparse-map-lite.ts +124 -0
- package/src/sparse-map/index.ts +11 -0
- package/src/sparse-map/resizable-typed-clean-sparse-map-lite.ts +107 -0
- package/src/sparse-map/resizable-typed-sparse-map-lite.ts +122 -0
- package/src/sparse-map/sparse-map.ts +104 -0
- package/src/sparse-map/typed-clean-sparse-map-lite.ts +116 -0
- package/src/sparse-map/typed-clean-sparse-map.ts +149 -0
- package/src/sparse-map/typed-sparse-map-lite.ts +141 -0
- package/src/sparse-map/typed-sparse-map.ts +169 -0
- package/src/sparse-set/clean-sparse-set.ts +76 -0
- package/src/sparse-set/dynamic-typed-clean-sparse-set-lite.ts +64 -0
- package/src/sparse-set/dynamic-typed-clean-sparse-set.ts +101 -0
- package/src/sparse-set/dynamic-typed-sparse-set-lite.ts +67 -0
- package/src/sparse-set/dynamic-typed-sparse-set.ts +93 -0
- package/src/sparse-set/index.ts +15 -0
- package/src/sparse-set/resizable-typed-clean-sparse-set-lite.ts +64 -0
- package/src/sparse-set/resizable-typed-clean-sparse-set.ts +108 -0
- package/src/sparse-set/resizable-typed-sparse-set-lite.ts +67 -0
- package/src/sparse-set/resizable-typed-sparse-set.ts +97 -0
- package/src/sparse-set/sparse-set.ts +79 -0
- package/src/sparse-set/typed-clean-sparse-set-lite.ts +67 -0
- package/src/sparse-set/typed-clean-sparse-set.ts +100 -0
- package/src/sparse-set/typed-sparse-set-lite.ts +74 -0
- package/src/sparse-set/typed-sparse-set.ts +102 -0
- package/src/utils/compute-new-capacity.ts +39 -0
- package/src/utils/get-max-value-of-unsigned-typed-array.ts +19 -0
- package/src/utils/skip-list.ts +1 -1
- package/src/utils/trailing-zeros.ts +2 -3
- package/lib/bit-set.js.map +0 -1
- package/lib/sparse-map.js +0 -76
- package/lib/sparse-map.js.map +0 -1
- package/lib/sparse-set.js +0 -63
- package/lib/sparse-set.js.map +0 -1
- package/lib/typed-bit-set.js.map +0 -1
- package/lib/typed-sparse-map.d.ts +0 -20
- package/lib/typed-sparse-map.js +0 -83
- package/lib/typed-sparse-map.js.map +0 -1
- package/lib/typed-sparse-set.js +0 -59
- package/lib/typed-sparse-set.js.map +0 -1
- package/src/sparse-map.ts +0 -82
- package/src/sparse-set.ts +0 -74
- package/src/typed-sparse-map.ts +0 -97
- package/src/typed-sparse-set.ts +0 -73
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trailing-zeros.js","sourceRoot":"","sources":["../../src/utils/trailing-zeros.ts"],"names":[],"mappings":"AACA,MAAM,iBAAiB,GAAa;IAClC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACjC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;IAClC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACpC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;CACxB,CAAA;
|
|
1
|
+
{"version":3,"file":"trailing-zeros.js","sourceRoot":"","sources":["../../src/utils/trailing-zeros.ts"],"names":[],"mappings":"AACA,MAAM,iBAAiB,GAAa;IAClC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACjC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;IAClC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACpC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;CACxB,CAAA;AAKD,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;AACzD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blackglory/structures",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib",
|
|
@@ -14,58 +14,55 @@
|
|
|
14
14
|
"author": "BlackGlory <woshenmedoubuzhidao@blackglory.me>",
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
|
-
"prepare": "ts-patch install -s",
|
|
21
20
|
"lint": "eslint --ext .js,.jsx,.ts,.tsx --quiet src __tests__",
|
|
22
21
|
"test": "vitest --run",
|
|
23
|
-
"prepublishOnly": "run-s
|
|
22
|
+
"prepublishOnly": "run-s clean build",
|
|
24
23
|
"clean": "rimraf lib",
|
|
25
|
-
"build": "tsc --project tsconfig.build.json --
|
|
24
|
+
"build": "tsc --project tsconfig.build.json && tsc-alias --project tsconfig.build.json",
|
|
26
25
|
"bench": "run-s bench:*",
|
|
27
26
|
"bench:bit-set": "tsx benches/bit-set.ts",
|
|
28
27
|
"bench:sparse-map": "tsx benches/sparse-map.ts",
|
|
29
28
|
"bench:sparse-set": "tsx benches/sparse-set.ts",
|
|
29
|
+
"bench:resizable-array-buffer": "tsx benches/resizable-array-buffer.ts",
|
|
30
30
|
"release": "standard-version"
|
|
31
31
|
},
|
|
32
32
|
"husky": {
|
|
33
33
|
"hooks": {
|
|
34
|
-
"pre-commit": "run-s
|
|
34
|
+
"pre-commit": "run-s lint build test",
|
|
35
35
|
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@commitlint/cli": "^
|
|
40
|
-
"@commitlint/config-conventional": "^
|
|
41
|
-
"@
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"extra-
|
|
47
|
-
"extra-generator": "^0.5.4",
|
|
48
|
-
"extra-promise": "^6.2.0",
|
|
39
|
+
"@commitlint/cli": "^21.2.3",
|
|
40
|
+
"@commitlint/config-conventional": "^21.2.3",
|
|
41
|
+
"@eslint/js": "^10.0.1",
|
|
42
|
+
"cross-env": "^10.1.0",
|
|
43
|
+
"eslint": "^10.12.0",
|
|
44
|
+
"extra-benchmark": "^0.3.1",
|
|
45
|
+
"extra-generator": "^0.7.1",
|
|
46
|
+
"extra-promise": "^7.1.1",
|
|
49
47
|
"husky": "^4.3.8",
|
|
50
48
|
"npm-run-all": "^4.1.5",
|
|
51
|
-
"return-style": "^
|
|
52
|
-
"rimraf": "^
|
|
49
|
+
"return-style": "^4.0.0",
|
|
50
|
+
"rimraf": "^6.1.3",
|
|
53
51
|
"standard-version": "^9.5.0",
|
|
54
|
-
"
|
|
55
|
-
"tslib": "^2.
|
|
56
|
-
"tsx": "^4.
|
|
57
|
-
"typescript": "
|
|
58
|
-
"typescript-
|
|
59
|
-
"vite": "^
|
|
60
|
-
"
|
|
61
|
-
"vitest": "^2.0.5"
|
|
52
|
+
"tsc-alias": "^1.9.7",
|
|
53
|
+
"tslib": "^2.8.1",
|
|
54
|
+
"tsx": "^4.23.15",
|
|
55
|
+
"typescript": "6",
|
|
56
|
+
"typescript-eslint": "^8.71.0",
|
|
57
|
+
"vite": "^8.3.2",
|
|
58
|
+
"vitest": "^5.0.3"
|
|
62
59
|
},
|
|
63
60
|
"dependencies": {
|
|
64
|
-
"@blackglory/errors": "^3.0
|
|
61
|
+
"@blackglory/errors": "^3.1.0",
|
|
65
62
|
"@blackglory/go": "^2.0.0",
|
|
66
|
-
"extra-timers": "^0.
|
|
67
|
-
"extra-utils": "^
|
|
68
|
-
"iterable-operator": "^
|
|
69
|
-
"justypes": "^4.
|
|
63
|
+
"extra-timers": "^0.3.1",
|
|
64
|
+
"extra-utils": "^6.2.0",
|
|
65
|
+
"iterable-operator": "^6.0.0",
|
|
66
|
+
"justypes": "^4.5.0"
|
|
70
67
|
}
|
|
71
68
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { assert } from '@blackglory/errors'
|
|
2
2
|
import { trailingZeros } from '@utils/trailing-zeros.js'
|
|
3
3
|
|
|
4
|
-
export class BitSet {
|
|
5
|
-
private array: number
|
|
4
|
+
export class BitSet implements Iterable<number> {
|
|
5
|
+
private array: Array<number | undefined> = []
|
|
6
6
|
private length = 0
|
|
7
|
-
|
|
7
|
+
#size = 0
|
|
8
|
+
|
|
9
|
+
private isBitsPerElementPowerOfTwo: boolean = false
|
|
10
|
+
private quotientShift = 0
|
|
11
|
+
private remainderMask = 0
|
|
8
12
|
|
|
9
13
|
constructor(private bitsPerElement: number = 8) {
|
|
10
14
|
assert(
|
|
@@ -15,11 +19,19 @@ export class BitSet {
|
|
|
15
19
|
bitsPerElement > 0
|
|
16
20
|
, 'The parameter bitsPerElement must be greater than 0'
|
|
17
21
|
)
|
|
18
|
-
// `31`是该数据结构中能够处理的最大值
|
|
19
22
|
assert(
|
|
20
|
-
bitsPerElement <=
|
|
21
|
-
, 'The
|
|
23
|
+
bitsPerElement <= 32
|
|
24
|
+
, 'The parameter bitsPerElement must be less than or equal to 32'
|
|
22
25
|
)
|
|
26
|
+
|
|
27
|
+
// bitsPerElement为2的幂时, 进行性能优化.
|
|
28
|
+
this.isBitsPerElementPowerOfTwo = (
|
|
29
|
+
bitsPerElement & (bitsPerElement - 1)
|
|
30
|
+
) === 0
|
|
31
|
+
if (this.isBitsPerElementPowerOfTwo) {
|
|
32
|
+
this.quotientShift = Math.log2(bitsPerElement)
|
|
33
|
+
this.remainderMask = bitsPerElement - 1
|
|
34
|
+
}
|
|
23
35
|
}
|
|
24
36
|
|
|
25
37
|
get [Symbol.toStringTag](): string {
|
|
@@ -27,7 +39,7 @@ export class BitSet {
|
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
get size(): number {
|
|
30
|
-
return this
|
|
42
|
+
return this.#size
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
[Symbol.iterator](): IterableIterator<number> {
|
|
@@ -40,13 +52,12 @@ export class BitSet {
|
|
|
40
52
|
const maxArrayLength = ~~(this.length / this.bitsPerElement) + 1
|
|
41
53
|
|
|
42
54
|
for (let index = 0; index < maxArrayLength; index++) {
|
|
43
|
-
let element = this.array[index]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
element >>= indexOfBit + 1
|
|
55
|
+
let element = this.array[index] ?? 0
|
|
56
|
+
while (element !== 0) {
|
|
57
|
+
const indexOfBit = trailingZeros(element)
|
|
58
|
+
yield index * this.bitsPerElement + indexOfBit
|
|
59
|
+
// 移除最低位置的1, 以推进下一个indexOfBit的获取.
|
|
60
|
+
element &= element - 1
|
|
50
61
|
}
|
|
51
62
|
}
|
|
52
63
|
}
|
|
@@ -55,7 +66,7 @@ export class BitSet {
|
|
|
55
66
|
_dumpBinaryStrings(): string[] {
|
|
56
67
|
const result: string[] = []
|
|
57
68
|
for (let i = 0; i < this.array.length; i++) {
|
|
58
|
-
const binary = this.array[i].toString(2)
|
|
69
|
+
const binary = ((this.array[i] ?? 0) >>> 0).toString(2)
|
|
59
70
|
if (binary.length < this.bitsPerElement) {
|
|
60
71
|
result.push('0'.repeat(this.bitsPerElement - binary.length) + binary)
|
|
61
72
|
} else {
|
|
@@ -72,39 +83,34 @@ export class BitSet {
|
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
add(value: number): boolean {
|
|
75
|
-
assert(value >= 0, 'value must be greater than or equal to 0')
|
|
76
|
-
if (value >= this.length) {
|
|
77
|
-
this.length = value + 1
|
|
78
|
-
}
|
|
79
|
-
|
|
80
86
|
const [index, mask] = this.getPosition(value)
|
|
81
87
|
|
|
82
88
|
const element = this.array[index] ?? 0
|
|
83
89
|
this.array[index] = element | mask
|
|
84
90
|
|
|
85
91
|
const added = (element & mask) !== mask
|
|
86
|
-
if (added)
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
if (added) this.#size++
|
|
93
|
+
|
|
94
|
+
if (value >= this.length) this.length = value + 1
|
|
95
|
+
|
|
89
96
|
return added
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
delete(value: number): boolean {
|
|
93
100
|
const [index, mask] = this.getPosition(value)
|
|
94
101
|
|
|
95
|
-
const element =
|
|
102
|
+
const element = this.array[index] ?? 0
|
|
96
103
|
this.array[index] = element & ~mask
|
|
97
104
|
|
|
98
105
|
const deleted = (element & mask) === mask
|
|
99
|
-
if (deleted)
|
|
100
|
-
this._size--
|
|
101
|
-
}
|
|
106
|
+
if (deleted) this.#size--
|
|
102
107
|
|
|
103
108
|
return deleted
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
clear(): void {
|
|
107
|
-
this
|
|
112
|
+
this.#size = 0
|
|
113
|
+
this.length = 0
|
|
108
114
|
this.array.length = 0
|
|
109
115
|
}
|
|
110
116
|
|
|
@@ -113,16 +119,26 @@ export class BitSet {
|
|
|
113
119
|
|
|
114
120
|
clone.array = [...this.array]
|
|
115
121
|
clone.length = this.length
|
|
116
|
-
clone
|
|
122
|
+
clone.#size = this.#size
|
|
117
123
|
|
|
118
124
|
return clone
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
private getPosition(value: number): [index: number, mask: number] {
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
let quotient: number
|
|
129
|
+
let remainder: number
|
|
130
|
+
if (this.isBitsPerElementPowerOfTwo) {
|
|
131
|
+
// 当bitsPerElement是2的幂时, 使用位运算版本.
|
|
132
|
+
remainder = value & this.remainderMask
|
|
133
|
+
quotient = value >>> this.quotientShift
|
|
134
|
+
} else {
|
|
135
|
+
remainder = value % this.bitsPerElement
|
|
136
|
+
quotient = (value - remainder) / this.bitsPerElement
|
|
137
|
+
}
|
|
138
|
+
|
|
124
139
|
const index = quotient
|
|
125
140
|
const mask = this.getMask(remainder)
|
|
141
|
+
|
|
126
142
|
return [index, mask]
|
|
127
143
|
}
|
|
128
144
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { UnsignedTypedArrayConstructor } from 'justypes'
|
|
2
|
+
import { assert } from '@blackglory/errors'
|
|
3
|
+
import { DynamicTypedArray } from '@src/dynamic-typed-array.js'
|
|
4
|
+
import { trailingZeros } from '@utils/trailing-zeros.js'
|
|
5
|
+
|
|
6
|
+
export class DynamicTypedBitSet implements Iterable<number> {
|
|
7
|
+
private bitsPerElement: number
|
|
8
|
+
private length = 0
|
|
9
|
+
#size = 0
|
|
10
|
+
|
|
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: DynamicTypedArray<UnsignedTypedArrayConstructor>) {
|
|
23
|
+
const bitsPerElement = array.BYTES_PER_ELEMENT * 8
|
|
24
|
+
|
|
25
|
+
assert(
|
|
26
|
+
Number.isInteger(bitsPerElement)
|
|
27
|
+
, 'The bitsPerElement must be an integer'
|
|
28
|
+
)
|
|
29
|
+
assert(
|
|
30
|
+
bitsPerElement > 0
|
|
31
|
+
, 'The bitsPerElement must be greater than 0'
|
|
32
|
+
)
|
|
33
|
+
assert(
|
|
34
|
+
bitsPerElement <= 32
|
|
35
|
+
, 'The bitsPerElement must be less than or equal to 31'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
this.bitsPerElement = bitsPerElement
|
|
39
|
+
this.quotientShift = Math.log2(bitsPerElement)
|
|
40
|
+
this.remainderMask = bitsPerElement - 1
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[Symbol.iterator](): IterableIterator<number> {
|
|
44
|
+
return this.values()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
* values(): IterableIterator<number> {
|
|
48
|
+
if (this.length > 0) {
|
|
49
|
+
// maxArrayLength = Math.ceil(this.length / this.bitsPerElement)
|
|
50
|
+
const maxArrayLength = ~~(this.length / this.bitsPerElement) + 1
|
|
51
|
+
|
|
52
|
+
for (let index = 0; index < maxArrayLength; index++) {
|
|
53
|
+
let element = this.array.get(index) ?? 0
|
|
54
|
+
while (element !== 0) {
|
|
55
|
+
const indexOfBit = trailingZeros(element)
|
|
56
|
+
yield index * this.bitsPerElement + indexOfBit
|
|
57
|
+
// 移除最低位置的1, 以推进下一个indexOfBit的获取.
|
|
58
|
+
element &= element - 1
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_dumpBinaryStrings(): string[] {
|
|
65
|
+
const result: string[] = []
|
|
66
|
+
for (let i = 0; i < this.array.length; i++) {
|
|
67
|
+
const binary = ((this.array.get(i) ?? 0) >>> 0).toString(2)
|
|
68
|
+
if (binary.length < this.bitsPerElement) {
|
|
69
|
+
result.push('0'.repeat(this.bitsPerElement - binary.length) + binary)
|
|
70
|
+
} else {
|
|
71
|
+
result.push(binary)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
has(value: number): boolean {
|
|
78
|
+
const [index, mask] = this.getPosition(value)
|
|
79
|
+
|
|
80
|
+
return ((this.array.get(index) ?? 0) & mask) === mask
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
add(value: number): boolean {
|
|
84
|
+
assert(value >= 0, 'value must be greater than or equal to 0')
|
|
85
|
+
|
|
86
|
+
const [index, mask] = this.getPosition(value)
|
|
87
|
+
|
|
88
|
+
const element = this.array.get(index) ?? 0
|
|
89
|
+
this.array.set(index, element | mask)
|
|
90
|
+
|
|
91
|
+
const added = (element & mask) !== mask
|
|
92
|
+
if (added) this.#size++
|
|
93
|
+
|
|
94
|
+
if (value >= this.length) this.length = value + 1
|
|
95
|
+
|
|
96
|
+
return added
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
delete(value: number): boolean {
|
|
100
|
+
const [index, mask] = this.getPosition(value)
|
|
101
|
+
|
|
102
|
+
const element = (this.array.get(index) ?? 0)
|
|
103
|
+
this.array.set(index, element & ~mask)
|
|
104
|
+
|
|
105
|
+
const deleted = (element & mask) === mask
|
|
106
|
+
if (deleted) this.#size--
|
|
107
|
+
|
|
108
|
+
return deleted
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
clear(): void {
|
|
112
|
+
this.#size = 0
|
|
113
|
+
this.array.clear()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private getPosition(value: number): [index: number, mask: number] {
|
|
117
|
+
const remainder = value & this.remainderMask
|
|
118
|
+
const quotient = value >>> this.quotientShift
|
|
119
|
+
|
|
120
|
+
const index = quotient
|
|
121
|
+
const mask = this.getMask(remainder)
|
|
122
|
+
|
|
123
|
+
return [index, mask]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 输入一定是一个小于bitsPerElement的值, 取值范围是[0, bitsPerElement)
|
|
127
|
+
private getMask(value: number): number {
|
|
128
|
+
// return 2 ** value
|
|
129
|
+
return 1 << value
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { UnsignedTypedArrayConstructor } from 'justypes'
|
|
2
2
|
import { assert } from '@blackglory/errors'
|
|
3
|
-
import {
|
|
3
|
+
import { ResizableTypedArray } from '@src/resizable-typed-array.js'
|
|
4
4
|
import { trailingZeros } from '@utils/trailing-zeros.js'
|
|
5
5
|
|
|
6
|
-
export class
|
|
6
|
+
export class ResizableTypedBitSet implements Iterable<number> {
|
|
7
7
|
private bitsPerElement: number
|
|
8
8
|
private length = 0
|
|
9
|
-
|
|
9
|
+
#size = 0
|
|
10
10
|
|
|
11
|
-
|
|
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 <=
|
|
25
|
-
, 'The
|
|
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.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
107
|
-
}
|
|
105
|
+
if (deleted) this.#size--
|
|
106
|
+
|
|
108
107
|
return deleted
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
clear(): void {
|
|
112
|
-
this
|
|
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
|
|
118
|
-
const quotient =
|
|
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
|
+
}
|