@wtasnorg/node-lib 0.0.11 → 0.0.12
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/docs/README.md +5 -0
- package/docs/docs.json +1022 -514
- package/docs/functions/countOnes.md +31 -0
- package/docs/functions/countZeroes.md +32 -0
- package/docs/functions/countZeroesWithWidth.md +37 -0
- package/docs/functions/createFindDirectories.md +3 -3
- package/docs/functions/decode.md +3 -3
- package/docs/functions/decode32.md +3 -3
- package/docs/functions/decode58.md +3 -3
- package/docs/functions/decode85.md +3 -3
- package/docs/functions/encode.md +3 -3
- package/docs/functions/encode32.md +3 -3
- package/docs/functions/encode58.md +3 -3
- package/docs/functions/encode85.md +3 -3
- package/docs/functions/hello.md +1 -1
- package/docs/functions/parseUserAgent.md +1 -1
- package/docs/functions/pojo.md +1 -1
- package/docs/functions/popcount32.md +27 -0
- package/docs/functions/popcount64.md +31 -0
- package/docs/interfaces/FileSystemDependencies.md +3 -3
- package/docs/interfaces/FindDirectoriesOptions.md +5 -5
- package/docs/interfaces/UserAgentInfo.md +6 -6
- package/docs/type-aliases/Base32CharsetType.md +1 -1
- package/docs/type-aliases/Base58CharsetType.md +1 -1
- package/docs/type-aliases/Base64CharsetType.md +1 -1
- package/docs/type-aliases/Base85CharsetType.md +1 -1
- package/docs/variables/Base32Charset.md +1 -1
- package/docs/variables/Base58Charset.md +1 -1
- package/docs/variables/Base64Charset.md +1 -1
- package/docs/variables/Base85Charset.md +1 -1
- package/package.json +12 -8
- package/readme.txt +24 -10
- package/src/bits.d.ts +43 -0
- package/src/bits.js +117 -0
- package/src/bits.test.d.ts +2 -0
- package/src/bits.test.js +62 -0
- package/src/bits.test.ts +77 -0
- package/src/bits.ts +135 -0
- package/src/index.d.ts +2 -1
- package/src/index.js +2 -1
- package/src/index.ts +7 -1
- package/.github/workflows/npm-publish.yml +0 -36
- package/.github/workflows/npm-test-on-pr.yml +0 -30
package/readme.txt
CHANGED
|
@@ -15,6 +15,7 @@ A library project for nodejs. #nodejs #typescript #library
|
|
|
15
15
|
6. `encode58` / `decode58` for Base58 encoding/decoding with charset variants (`bitcoin`, `flickr`, `ripple`).
|
|
16
16
|
7. `encode85` / `decode85` for Base85 encoding/decoding with charset variants (`ascii85`, `z85`, `rfc1924`).
|
|
17
17
|
8. `encode32` / `decode32` for Base32 encoding/decoding with charset variants (`rfc4648`, `hex`, `crockford`).
|
|
18
|
+
9. `popcount32`, `popcount64`, `countOnes`, `countZeroesWithWidth`, `countZeroes` for integer bit counting helpers.
|
|
18
19
|
|
|
19
20
|
## Develop
|
|
20
21
|
|
|
@@ -33,23 +34,36 @@ We are using `node --test` for testing.
|
|
|
33
34
|
npm install @wtasnorg/node-lib
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
# check if you can run code
|
|
38
|
-
import {hello} from "@wtasnorg/node-lib";
|
|
37
|
+
**Recommended:** Use subpath imports for maximum efficiency (enables tree shaking):
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
```typescript
|
|
40
|
+
import { encode, decode } from "@wtasnorg/node-lib/base64";
|
|
41
|
+
import { encode58 } from "@wtasnorg/node-lib/base58";
|
|
42
|
+
import { encode32 } from "@wtasnorg/node-lib/base32";
|
|
43
|
+
import { parseUserAgent } from "@wtasnorg/node-lib/user-agent";
|
|
44
|
+
import { popcount32, countZeroes } from "@wtasnorg/node-lib/bits";
|
|
42
45
|
```
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Import only what you need for smaller bundles:
|
|
47
|
+
Alternatively, import from the main entry point (includes all modules):
|
|
47
48
|
|
|
48
49
|
```typescript
|
|
49
|
-
import { encode58 } from "@wtasnorg/node-lib
|
|
50
|
-
import { encode32 } from "@wtasnorg/node-lib/base32";
|
|
50
|
+
import { hello, encode, encode58 } from "@wtasnorg/node-lib";
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
## Available Subpath Imports
|
|
54
|
+
|
|
55
|
+
| Module | Import Path |
|
|
56
|
+
|--------|-------------|
|
|
57
|
+
| Base64 | `@wtasnorg/node-lib/base64` |
|
|
58
|
+
| Base58 | `@wtasnorg/node-lib/base58` |
|
|
59
|
+
| Base85 | `@wtasnorg/node-lib/base85` |
|
|
60
|
+
| Base32 | `@wtasnorg/node-lib/base32` |
|
|
61
|
+
| User-Agent | `@wtasnorg/node-lib/user-agent` |
|
|
62
|
+
| Find | `@wtasnorg/node-lib/find` |
|
|
63
|
+
| POJO | `@wtasnorg/node-lib/pojo` |
|
|
64
|
+
| Hello | `@wtasnorg/node-lib/hello` |
|
|
65
|
+
| Bits | `@wtasnorg/node-lib/bits` |
|
|
66
|
+
|
|
53
67
|
## License: MIT
|
|
54
68
|
|
|
55
69
|
[MIT License file](LICENSE)
|
package/src/bits.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count set bits in an unsigned 32-bit representation of a number.
|
|
3
|
+
*
|
|
4
|
+
* @param {number} value - Number interpreted as uint32.
|
|
5
|
+
* @returns {number} Number of set bits (0-32).
|
|
6
|
+
*/
|
|
7
|
+
declare function popcount32(value: number): number;
|
|
8
|
+
/**
|
|
9
|
+
* Count set bits in the low 64 bits of a number or bigint.
|
|
10
|
+
*
|
|
11
|
+
* @param {number | bigint} value - Input value. For `number`, it must be a non-negative safe integer.
|
|
12
|
+
* @returns {number} Number of set bits (0-64).
|
|
13
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
14
|
+
*/
|
|
15
|
+
declare function popcount64(value: number | bigint): number;
|
|
16
|
+
/**
|
|
17
|
+
* Count set bits in a non-negative integer.
|
|
18
|
+
*
|
|
19
|
+
* @param {number | bigint} value - Input value.
|
|
20
|
+
* @returns {number} Number of set bits.
|
|
21
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
22
|
+
*/
|
|
23
|
+
declare function countOnes(value: number | bigint): number;
|
|
24
|
+
/**
|
|
25
|
+
* Count zero bits within a fixed width, considering only low-order `width` bits.
|
|
26
|
+
*
|
|
27
|
+
* @param {number | bigint} value - Input value.
|
|
28
|
+
* @param {number} width - Bit width to inspect.
|
|
29
|
+
* @returns {number} Number of zero bits in the selected width.
|
|
30
|
+
* @throws {RangeError} If `value` is negative/unsafe or `width` is negative/unsafe.
|
|
31
|
+
*/
|
|
32
|
+
declare function countZeroesWithWidth(value: number | bigint, width: number): number;
|
|
33
|
+
/**
|
|
34
|
+
* Count zero bits from LSB up to and including the highest set bit.
|
|
35
|
+
* For zero input, returns 0.
|
|
36
|
+
*
|
|
37
|
+
* @param {number | bigint} value - Input value.
|
|
38
|
+
* @returns {number} Zero count up to the left-most set bit.
|
|
39
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
40
|
+
*/
|
|
41
|
+
declare function countZeroes(value: number | bigint): number;
|
|
42
|
+
export { popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes };
|
|
43
|
+
//# sourceMappingURL=bits.d.ts.map
|
package/src/bits.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const UINT64_MASK = (1n << 64n) - 1n;
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {number | bigint} value
|
|
5
|
+
* @param {string} fnName
|
|
6
|
+
* @returns {bigint}
|
|
7
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
8
|
+
* @example
|
|
9
|
+
* toNonNegativeBigInt(42, "exampleFunction"); // returns 42n
|
|
10
|
+
* toNonNegativeBigInt(-1, "exampleFunction"); // throws RangeError
|
|
11
|
+
*/
|
|
12
|
+
function toNonNegativeBigInt(value, fnName) {
|
|
13
|
+
if (typeof value === "bigint") {
|
|
14
|
+
if (value < 0n) {
|
|
15
|
+
throw new RangeError(`${fnName}: value must be non-negative`);
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
20
|
+
throw new RangeError(`${fnName}: value must be a non-negative safe integer`);
|
|
21
|
+
}
|
|
22
|
+
return BigInt(value);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Count set bits in a bigint.
|
|
26
|
+
*
|
|
27
|
+
* @param {bigint} value - Input value.
|
|
28
|
+
* @returns {number} Number of set bits.
|
|
29
|
+
* @example
|
|
30
|
+
* popcountBigInt(0b1011n); // returns 3
|
|
31
|
+
*/
|
|
32
|
+
function popcountBigInt(value) {
|
|
33
|
+
let count = 0;
|
|
34
|
+
let bits = value;
|
|
35
|
+
while (bits !== 0n) {
|
|
36
|
+
bits &= bits - 1n;
|
|
37
|
+
count += 1;
|
|
38
|
+
}
|
|
39
|
+
return count;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Count set bits in an unsigned 32-bit representation of a number.
|
|
43
|
+
*
|
|
44
|
+
* @param {number} value - Number interpreted as uint32.
|
|
45
|
+
* @returns {number} Number of set bits (0-32).
|
|
46
|
+
*/
|
|
47
|
+
function popcount32(value) {
|
|
48
|
+
let bits = value >>> 0;
|
|
49
|
+
bits -= (bits >>> 1) & 0x55555555;
|
|
50
|
+
bits = (bits & 0x33333333) + ((bits >>> 2) & 0x33333333);
|
|
51
|
+
bits = (bits + (bits >>> 4)) & 0x0f0f0f0f;
|
|
52
|
+
bits += bits >>> 8;
|
|
53
|
+
bits += bits >>> 16;
|
|
54
|
+
return bits & 0x3f;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Count set bits in the low 64 bits of a number or bigint.
|
|
58
|
+
*
|
|
59
|
+
* @param {number | bigint} value - Input value. For `number`, it must be a non-negative safe integer.
|
|
60
|
+
* @returns {number} Number of set bits (0-64).
|
|
61
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
62
|
+
*/
|
|
63
|
+
function popcount64(value) {
|
|
64
|
+
const bits64 = toNonNegativeBigInt(value, "popcount64") & UINT64_MASK;
|
|
65
|
+
return popcountBigInt(bits64);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Count set bits in a non-negative integer.
|
|
69
|
+
*
|
|
70
|
+
* @param {number | bigint} value - Input value.
|
|
71
|
+
* @returns {number} Number of set bits.
|
|
72
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
73
|
+
*/
|
|
74
|
+
function countOnes(value) {
|
|
75
|
+
const bits = toNonNegativeBigInt(value, "countOnes");
|
|
76
|
+
return popcountBigInt(bits);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Count zero bits within a fixed width, considering only low-order `width` bits.
|
|
80
|
+
*
|
|
81
|
+
* @param {number | bigint} value - Input value.
|
|
82
|
+
* @param {number} width - Bit width to inspect.
|
|
83
|
+
* @returns {number} Number of zero bits in the selected width.
|
|
84
|
+
* @throws {RangeError} If `value` is negative/unsafe or `width` is negative/unsafe.
|
|
85
|
+
*/
|
|
86
|
+
function countZeroesWithWidth(value, width) {
|
|
87
|
+
if (!Number.isSafeInteger(width) || width < 0) {
|
|
88
|
+
throw new RangeError("countZeroesWithWidth: width must be a non-negative safe integer");
|
|
89
|
+
}
|
|
90
|
+
if (width === 0) {
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
const bits = toNonNegativeBigInt(value, "countZeroesWithWidth");
|
|
94
|
+
const widthBigInt = BigInt(width);
|
|
95
|
+
const mask = (1n << widthBigInt) - 1n;
|
|
96
|
+
const ones = popcountBigInt(bits & mask);
|
|
97
|
+
return width - ones;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Count zero bits from LSB up to and including the highest set bit.
|
|
101
|
+
* For zero input, returns 0.
|
|
102
|
+
*
|
|
103
|
+
* @param {number | bigint} value - Input value.
|
|
104
|
+
* @returns {number} Zero count up to the left-most set bit.
|
|
105
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
106
|
+
*/
|
|
107
|
+
function countZeroes(value) {
|
|
108
|
+
const bits = toNonNegativeBigInt(value, "countZeroes");
|
|
109
|
+
if (bits === 0n) {
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
const width = bits.toString(2).length;
|
|
113
|
+
const ones = popcountBigInt(bits);
|
|
114
|
+
return width - ones;
|
|
115
|
+
}
|
|
116
|
+
export { popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes };
|
|
117
|
+
//# sourceMappingURL=bits.js.map
|
package/src/bits.test.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import { strictEqual, throws } from "node:assert";
|
|
3
|
+
import { popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes } from "./bits.js";
|
|
4
|
+
describe("popcount32", () => {
|
|
5
|
+
it("counts set bits for simple values", () => {
|
|
6
|
+
strictEqual(popcount32(0), 0);
|
|
7
|
+
strictEqual(popcount32(1), 1);
|
|
8
|
+
strictEqual(popcount32(0b10110100), 4);
|
|
9
|
+
});
|
|
10
|
+
it("uses uint32 semantics", () => {
|
|
11
|
+
strictEqual(popcount32(-1), 32);
|
|
12
|
+
strictEqual(popcount32(0xffffffff), 32);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe("popcount64", () => {
|
|
16
|
+
it("counts set bits for bigint values", () => {
|
|
17
|
+
strictEqual(popcount64(0n), 0);
|
|
18
|
+
strictEqual(popcount64((1n << 64n) - 1n), 64);
|
|
19
|
+
strictEqual(popcount64(41n), 3);
|
|
20
|
+
});
|
|
21
|
+
it("counts only low 64 bits", () => {
|
|
22
|
+
const value = (1n << 65n) | 1n;
|
|
23
|
+
strictEqual(popcount64(value), 1);
|
|
24
|
+
});
|
|
25
|
+
it("throws for invalid number input", () => {
|
|
26
|
+
throws(() => popcount64(-1), /must be a non-negative safe integer/);
|
|
27
|
+
throws(() => popcount64(Number.MAX_SAFE_INTEGER + 1), /must be a non-negative safe integer/);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe("countOnes", () => {
|
|
31
|
+
it("counts set bits for number and bigint", () => {
|
|
32
|
+
strictEqual(countOnes(0), 0);
|
|
33
|
+
strictEqual(countOnes(255), 8);
|
|
34
|
+
strictEqual(countOnes(65537n), 2);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe("countZeroesWithWidth", () => {
|
|
38
|
+
it("counts zero bits for a chosen width", () => {
|
|
39
|
+
strictEqual(countZeroesWithWidth(0b10100, 5), 3);
|
|
40
|
+
strictEqual(countZeroesWithWidth(0b10100, 8), 6);
|
|
41
|
+
strictEqual(countZeroesWithWidth(0, 8), 8);
|
|
42
|
+
strictEqual(countZeroesWithWidth(123, 0), 0);
|
|
43
|
+
});
|
|
44
|
+
it("throws for invalid width", () => {
|
|
45
|
+
throws(() => countZeroesWithWidth(1, -1), /width must be a non-negative safe integer/);
|
|
46
|
+
throws(() => countZeroesWithWidth(1, Number.MAX_SAFE_INTEGER + 1), /width must be a non-negative safe integer/);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("countZeroes", () => {
|
|
50
|
+
it("counts zero bits only up to highest set bit", () => {
|
|
51
|
+
strictEqual(countZeroes(0), 0);
|
|
52
|
+
strictEqual(countZeroes(1), 0);
|
|
53
|
+
strictEqual(countZeroes(0b10100), 3);
|
|
54
|
+
strictEqual(countZeroes(0b1000), 3);
|
|
55
|
+
strictEqual(countZeroes(0b1111), 0);
|
|
56
|
+
});
|
|
57
|
+
it("throws for invalid inputs", () => {
|
|
58
|
+
throws(() => countZeroes(-1), /must be a non-negative safe integer/);
|
|
59
|
+
throws(() => countOnes(-1n), /must be non-negative/);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=bits.test.js.map
|
package/src/bits.test.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import { strictEqual, throws } from "node:assert";
|
|
3
|
+
import {
|
|
4
|
+
popcount32,
|
|
5
|
+
popcount64,
|
|
6
|
+
countOnes,
|
|
7
|
+
countZeroesWithWidth,
|
|
8
|
+
countZeroes
|
|
9
|
+
} from "./bits.js";
|
|
10
|
+
|
|
11
|
+
describe("popcount32", () => {
|
|
12
|
+
it("counts set bits for simple values", () => {
|
|
13
|
+
strictEqual(popcount32(0), 0);
|
|
14
|
+
strictEqual(popcount32(1), 1);
|
|
15
|
+
strictEqual(popcount32(0b10110100), 4);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("uses uint32 semantics", () => {
|
|
19
|
+
strictEqual(popcount32(-1), 32);
|
|
20
|
+
strictEqual(popcount32(0xffffffff), 32);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("popcount64", () => {
|
|
25
|
+
it("counts set bits for bigint values", () => {
|
|
26
|
+
strictEqual(popcount64(0n), 0);
|
|
27
|
+
strictEqual(popcount64((1n << 64n) - 1n), 64);
|
|
28
|
+
strictEqual(popcount64(0b101001n), 3);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("counts only low 64 bits", () => {
|
|
32
|
+
const value = (1n << 65n) | 1n;
|
|
33
|
+
strictEqual(popcount64(value), 1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("throws for invalid number input", () => {
|
|
37
|
+
throws(() => popcount64(-1), /must be a non-negative safe integer/);
|
|
38
|
+
throws(() => popcount64(Number.MAX_SAFE_INTEGER + 1), /must be a non-negative safe integer/);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("countOnes", () => {
|
|
43
|
+
it("counts set bits for number and bigint", () => {
|
|
44
|
+
strictEqual(countOnes(0), 0);
|
|
45
|
+
strictEqual(countOnes(255), 8);
|
|
46
|
+
strictEqual(countOnes(0b10000000000000001n), 2);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("countZeroesWithWidth", () => {
|
|
51
|
+
it("counts zero bits for a chosen width", () => {
|
|
52
|
+
strictEqual(countZeroesWithWidth(0b10100, 5), 3);
|
|
53
|
+
strictEqual(countZeroesWithWidth(0b10100, 8), 6);
|
|
54
|
+
strictEqual(countZeroesWithWidth(0, 8), 8);
|
|
55
|
+
strictEqual(countZeroesWithWidth(123, 0), 0);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("throws for invalid width", () => {
|
|
59
|
+
throws(() => countZeroesWithWidth(1, -1), /width must be a non-negative safe integer/);
|
|
60
|
+
throws(() => countZeroesWithWidth(1, Number.MAX_SAFE_INTEGER + 1), /width must be a non-negative safe integer/);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("countZeroes", () => {
|
|
65
|
+
it("counts zero bits only up to highest set bit", () => {
|
|
66
|
+
strictEqual(countZeroes(0), 0);
|
|
67
|
+
strictEqual(countZeroes(1), 0);
|
|
68
|
+
strictEqual(countZeroes(0b10100), 3);
|
|
69
|
+
strictEqual(countZeroes(0b1000), 3);
|
|
70
|
+
strictEqual(countZeroes(0b1111), 0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("throws for invalid inputs", () => {
|
|
74
|
+
throws(() => countZeroes(-1), /must be a non-negative safe integer/);
|
|
75
|
+
throws(() => countOnes(-1n), /must be non-negative/);
|
|
76
|
+
});
|
|
77
|
+
});
|
package/src/bits.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const UINT64_MASK = (1n << 64n) - 1n;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number | bigint} value
|
|
6
|
+
* @param {string} fnName
|
|
7
|
+
* @returns {bigint}
|
|
8
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
9
|
+
* @example
|
|
10
|
+
* toNonNegativeBigInt(42, "exampleFunction"); // returns 42n
|
|
11
|
+
* toNonNegativeBigInt(-1, "exampleFunction"); // throws RangeError
|
|
12
|
+
*/
|
|
13
|
+
function toNonNegativeBigInt(value: number | bigint, fnName: string): bigint {
|
|
14
|
+
if (typeof value === "bigint") {
|
|
15
|
+
if (value < 0n) {
|
|
16
|
+
throw new RangeError(`${fnName}: value must be non-negative`);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
22
|
+
throw new RangeError(`${fnName}: value must be a non-negative safe integer`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return BigInt(value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Count set bits in a bigint.
|
|
30
|
+
*
|
|
31
|
+
* @param {bigint} value - Input value.
|
|
32
|
+
* @returns {number} Number of set bits.
|
|
33
|
+
* @example
|
|
34
|
+
* popcountBigInt(0b1011n); // returns 3
|
|
35
|
+
*/
|
|
36
|
+
function popcountBigInt(value: bigint): number {
|
|
37
|
+
let count = 0;
|
|
38
|
+
let bits = value;
|
|
39
|
+
while (bits !== 0n) {
|
|
40
|
+
bits &= bits - 1n;
|
|
41
|
+
count += 1;
|
|
42
|
+
}
|
|
43
|
+
return count;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Count set bits in an unsigned 32-bit representation of a number.
|
|
48
|
+
*
|
|
49
|
+
* @param {number} value - Number interpreted as uint32.
|
|
50
|
+
* @returns {number} Number of set bits (0-32).
|
|
51
|
+
*/
|
|
52
|
+
function popcount32(value: number): number {
|
|
53
|
+
let bits = value >>> 0;
|
|
54
|
+
bits -= (bits >>> 1) & 0x55555555;
|
|
55
|
+
bits = (bits & 0x33333333) + ((bits >>> 2) & 0x33333333);
|
|
56
|
+
bits = (bits + (bits >>> 4)) & 0x0f0f0f0f;
|
|
57
|
+
bits += bits >>> 8;
|
|
58
|
+
bits += bits >>> 16;
|
|
59
|
+
return bits & 0x3f;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Count set bits in the low 64 bits of a number or bigint.
|
|
64
|
+
*
|
|
65
|
+
* @param {number | bigint} value - Input value. For `number`, it must be a non-negative safe integer.
|
|
66
|
+
* @returns {number} Number of set bits (0-64).
|
|
67
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
68
|
+
*/
|
|
69
|
+
function popcount64(value: number | bigint): number {
|
|
70
|
+
const bits64 = toNonNegativeBigInt(value, "popcount64") & UINT64_MASK;
|
|
71
|
+
return popcountBigInt(bits64);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Count set bits in a non-negative integer.
|
|
76
|
+
*
|
|
77
|
+
* @param {number | bigint} value - Input value.
|
|
78
|
+
* @returns {number} Number of set bits.
|
|
79
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
80
|
+
*/
|
|
81
|
+
function countOnes(value: number | bigint): number {
|
|
82
|
+
const bits = toNonNegativeBigInt(value, "countOnes");
|
|
83
|
+
return popcountBigInt(bits);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Count zero bits within a fixed width, considering only low-order `width` bits.
|
|
88
|
+
*
|
|
89
|
+
* @param {number | bigint} value - Input value.
|
|
90
|
+
* @param {number} width - Bit width to inspect.
|
|
91
|
+
* @returns {number} Number of zero bits in the selected width.
|
|
92
|
+
* @throws {RangeError} If `value` is negative/unsafe or `width` is negative/unsafe.
|
|
93
|
+
*/
|
|
94
|
+
function countZeroesWithWidth(value: number | bigint, width: number): number {
|
|
95
|
+
if (!Number.isSafeInteger(width) || width < 0) {
|
|
96
|
+
throw new RangeError("countZeroesWithWidth: width must be a non-negative safe integer");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (width === 0) {
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const bits = toNonNegativeBigInt(value, "countZeroesWithWidth");
|
|
104
|
+
const widthBigInt = BigInt(width);
|
|
105
|
+
const mask = (1n << widthBigInt) - 1n;
|
|
106
|
+
const ones = popcountBigInt(bits & mask);
|
|
107
|
+
return width - ones;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Count zero bits from LSB up to and including the highest set bit.
|
|
112
|
+
* For zero input, returns 0.
|
|
113
|
+
*
|
|
114
|
+
* @param {number | bigint} value - Input value.
|
|
115
|
+
* @returns {number} Zero count up to the left-most set bit.
|
|
116
|
+
* @throws {RangeError} If `value` is negative or an unsafe integer.
|
|
117
|
+
*/
|
|
118
|
+
function countZeroes(value: number | bigint): number {
|
|
119
|
+
const bits = toNonNegativeBigInt(value, "countZeroes");
|
|
120
|
+
if (bits === 0n) {
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const width = bits.toString(2).length;
|
|
125
|
+
const ones = popcountBigInt(bits);
|
|
126
|
+
return width - ones;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
popcount32,
|
|
131
|
+
popcount64,
|
|
132
|
+
countOnes,
|
|
133
|
+
countZeroesWithWidth,
|
|
134
|
+
countZeroes
|
|
135
|
+
};
|
package/src/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { Base85CharsetType } from "./base85.js";
|
|
|
12
12
|
import { encode85, decode85, Base85Charset } from "./base85.js";
|
|
13
13
|
import type { Base32CharsetType } from "./base32.js";
|
|
14
14
|
import { encode32, decode32, Base32Charset } from "./base32.js";
|
|
15
|
-
|
|
15
|
+
import { popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes } from "./bits.js";
|
|
16
|
+
export { hello, pojo, createFindDirectories, parseUserAgent, encode, decode, Base64Charset, encode58, decode58, Base58Charset, encode85, decode85, Base85Charset, encode32, decode32, Base32Charset, popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes };
|
|
16
17
|
export type { FindDirectoriesOptions, FileSystemDependencies, UserAgentInfo, Base64CharsetType, Base58CharsetType, Base85CharsetType, Base32CharsetType };
|
|
17
18
|
//# sourceMappingURL=index.d.ts.map
|
package/src/index.js
CHANGED
|
@@ -6,5 +6,6 @@ import { encode, decode, Base64Charset } from "./base64.js";
|
|
|
6
6
|
import { encode58, decode58, Base58Charset } from "./base58.js";
|
|
7
7
|
import { encode85, decode85, Base85Charset } from "./base85.js";
|
|
8
8
|
import { encode32, decode32, Base32Charset } from "./base32.js";
|
|
9
|
-
|
|
9
|
+
import { popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes } from "./bits.js";
|
|
10
|
+
export { hello, pojo, createFindDirectories, parseUserAgent, encode, decode, Base64Charset, encode58, decode58, Base58Charset, encode85, decode85, Base85Charset, encode32, decode32, Base32Charset, popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes };
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { Base85CharsetType } from "./base85.js";
|
|
|
12
12
|
import { encode85, decode85, Base85Charset } from "./base85.js";
|
|
13
13
|
import type { Base32CharsetType } from "./base32.js";
|
|
14
14
|
import { encode32, decode32, Base32Charset } from "./base32.js";
|
|
15
|
+
import { popcount32, popcount64, countOnes, countZeroesWithWidth, countZeroes } from "./bits.js";
|
|
15
16
|
|
|
16
17
|
export {
|
|
17
18
|
hello,
|
|
@@ -29,7 +30,12 @@ export {
|
|
|
29
30
|
Base85Charset,
|
|
30
31
|
encode32,
|
|
31
32
|
decode32,
|
|
32
|
-
Base32Charset
|
|
33
|
+
Base32Charset,
|
|
34
|
+
popcount32,
|
|
35
|
+
popcount64,
|
|
36
|
+
countOnes,
|
|
37
|
+
countZeroesWithWidth,
|
|
38
|
+
countZeroes
|
|
33
39
|
};
|
|
34
40
|
|
|
35
41
|
export type {
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
-
|
|
4
|
-
name: Node.js Package
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
release:
|
|
8
|
-
types: [created]
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
build:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
- uses: actions/setup-node@v4
|
|
16
|
-
with:
|
|
17
|
-
node-version: 20
|
|
18
|
-
- run: npm clean-install
|
|
19
|
-
- run: npm run build
|
|
20
|
-
- run: npm run test
|
|
21
|
-
- run: npm run docs
|
|
22
|
-
- run: npm run docs:json
|
|
23
|
-
|
|
24
|
-
publish-npm:
|
|
25
|
-
needs: build
|
|
26
|
-
runs-on: ubuntu-latest
|
|
27
|
-
steps:
|
|
28
|
-
- uses: actions/checkout@v4
|
|
29
|
-
- uses: actions/setup-node@v4
|
|
30
|
-
with:
|
|
31
|
-
node-version: 20
|
|
32
|
-
registry-url: https://registry.npmjs.org/
|
|
33
|
-
- run: npm clean-install
|
|
34
|
-
- run: npm publish
|
|
35
|
-
env:
|
|
36
|
-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
name: Run tests on pull request
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
types: [opened, reopened, synchronize]
|
|
6
|
-
|
|
7
|
-
permissions:
|
|
8
|
-
contents: read
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
run-tests:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- name: Checkout repository
|
|
16
|
-
uses: actions/checkout@v4
|
|
17
|
-
with:
|
|
18
|
-
fetch-depth: 0
|
|
19
|
-
|
|
20
|
-
- name: Setup Node.js
|
|
21
|
-
uses: actions/setup-node@v4
|
|
22
|
-
with:
|
|
23
|
-
node-version: 20
|
|
24
|
-
cache: npm
|
|
25
|
-
|
|
26
|
-
- name: Install dependencies
|
|
27
|
-
run: npm ci
|
|
28
|
-
|
|
29
|
-
- name: Run tests
|
|
30
|
-
run: npm test
|