distillate 0.6.0 → 0.7.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/dist/blocked/index.cjs +2 -0
- package/dist/blocked/index.d.cts +16 -1
- package/dist/blocked/index.d.ts +16 -1
- package/dist/blocked/index.js +1 -1
- package/dist/bloom/index.cjs +3 -2
- package/dist/bloom/index.d.cts +12 -1
- package/dist/bloom/index.d.ts +12 -1
- package/dist/bloom/index.js +3 -3
- package/dist/fuse/index.cjs +14 -0
- package/dist/fuse/index.d.cts +11 -1
- package/dist/fuse/index.d.ts +11 -1
- package/dist/fuse/index.js +14 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
package/dist/blocked/index.cjs
CHANGED
|
@@ -267,3 +267,5 @@ function fillBlock(key, numBlocks, seed, outWords, outBits) {
|
|
|
267
267
|
exports.BlockedBloomFilter = BlockedBloomFilter;
|
|
268
268
|
exports.BlockedBloomParamMismatchError = BlockedBloomParamMismatchError;
|
|
269
269
|
exports.ParamError = require_params.ParamError;
|
|
270
|
+
exports.blockedBitsPerKey = blockedBitsPerKey;
|
|
271
|
+
exports.blockedFprAt = blockedFprAt;
|
package/dist/blocked/index.d.cts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { n as BytesLike, t as FilterJSON } from "../serialize-DRKh6QOr.cjs";
|
|
2
2
|
import { t as ParamError } from "../params-DnqJBqLS.cjs";
|
|
3
3
|
//#region src/blocked/blocked.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Modeled false-positive rate of a split-block filter at `bitsPerKey`. A block
|
|
6
|
+
* holding `j` keys has FPR `(1 - (1 - 1/32)^j)^8` (8 lanes of 32 bits, one probe
|
|
7
|
+
* each); the filter's rate averages that over the Poisson block load
|
|
8
|
+
* `lambda = 256 / bitsPerKey`. This clustering average is why the blocked curve
|
|
9
|
+
* is not linear in `log10(1/epsilon)`.
|
|
10
|
+
*/
|
|
11
|
+
declare function blockedFprAt(bitsPerKey: number): number;
|
|
12
|
+
/**
|
|
13
|
+
* Minimal integer bits-per-key whose modeled split-block FPR is at or below
|
|
14
|
+
* `epsilon`. Throws {@link ParamError} when even the densest supported filter
|
|
15
|
+
* cannot reach the target, so callers get a typed rejection instead of a
|
|
16
|
+
* silently under-provisioned filter.
|
|
17
|
+
*/
|
|
18
|
+
declare function blockedBitsPerKey(epsilon: number): number;
|
|
4
19
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
5
20
|
declare class BlockedBloomParamMismatchError extends Error {
|
|
6
21
|
/** Discriminates this error from other `Error`s. */
|
|
@@ -127,4 +142,4 @@ declare class BlockedBloomFilter {
|
|
|
127
142
|
has(key: BytesLike): boolean;
|
|
128
143
|
}
|
|
129
144
|
//#endregion
|
|
130
|
-
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams, type FilterJSON, ParamError };
|
|
145
|
+
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams, type FilterJSON, ParamError, blockedBitsPerKey, blockedFprAt };
|
package/dist/blocked/index.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { n as BytesLike, t as FilterJSON } from "../serialize-DRKh6QOr.js";
|
|
2
2
|
import { t as ParamError } from "../params-DnqJBqLS.js";
|
|
3
3
|
//#region src/blocked/blocked.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Modeled false-positive rate of a split-block filter at `bitsPerKey`. A block
|
|
6
|
+
* holding `j` keys has FPR `(1 - (1 - 1/32)^j)^8` (8 lanes of 32 bits, one probe
|
|
7
|
+
* each); the filter's rate averages that over the Poisson block load
|
|
8
|
+
* `lambda = 256 / bitsPerKey`. This clustering average is why the blocked curve
|
|
9
|
+
* is not linear in `log10(1/epsilon)`.
|
|
10
|
+
*/
|
|
11
|
+
declare function blockedFprAt(bitsPerKey: number): number;
|
|
12
|
+
/**
|
|
13
|
+
* Minimal integer bits-per-key whose modeled split-block FPR is at or below
|
|
14
|
+
* `epsilon`. Throws {@link ParamError} when even the densest supported filter
|
|
15
|
+
* cannot reach the target, so callers get a typed rejection instead of a
|
|
16
|
+
* silently under-provisioned filter.
|
|
17
|
+
*/
|
|
18
|
+
declare function blockedBitsPerKey(epsilon: number): number;
|
|
4
19
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
5
20
|
declare class BlockedBloomParamMismatchError extends Error {
|
|
6
21
|
/** Discriminates this error from other `Error`s. */
|
|
@@ -127,4 +142,4 @@ declare class BlockedBloomFilter {
|
|
|
127
142
|
has(key: BytesLike): boolean;
|
|
128
143
|
}
|
|
129
144
|
//#endregion
|
|
130
|
-
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams, type FilterJSON, ParamError };
|
|
145
|
+
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams, type FilterJSON, ParamError, blockedBitsPerKey, blockedFprAt };
|
package/dist/blocked/index.js
CHANGED
|
@@ -263,4 +263,4 @@ function fillBlock(key, numBlocks, seed, outWords, outBits) {
|
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
//#endregion
|
|
266
|
-
export { BlockedBloomFilter, BlockedBloomParamMismatchError, ParamError };
|
|
266
|
+
export { BlockedBloomFilter, BlockedBloomParamMismatchError, ParamError, blockedBitsPerKey, blockedFprAt };
|
package/dist/bloom/index.cjs
CHANGED
|
@@ -34,7 +34,7 @@ var BitSet = class {
|
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region src/core/sizing.ts
|
|
36
36
|
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
37
|
-
function
|
|
37
|
+
function bloomSizing(n, epsilon) {
|
|
38
38
|
const m = Math.ceil(-n * Math.log(epsilon) / (Math.LN2 * Math.LN2));
|
|
39
39
|
return {
|
|
40
40
|
m,
|
|
@@ -79,7 +79,7 @@ var BloomFilter = class BloomFilter {
|
|
|
79
79
|
require_params.assertPositiveInt(n, "n");
|
|
80
80
|
require_params.assertUint32(n, "n");
|
|
81
81
|
require_params.assertProbability(epsilon, "epsilon");
|
|
82
|
-
return BloomFilter.#withN(
|
|
82
|
+
return BloomFilter.#withN(bloomSizing(n, epsilon), n);
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Builds a filter from `keys`, sized for their count at the target
|
|
@@ -266,3 +266,4 @@ var BloomFilter = class BloomFilter {
|
|
|
266
266
|
exports.BloomFilter = BloomFilter;
|
|
267
267
|
exports.BloomParamMismatchError = BloomParamMismatchError;
|
|
268
268
|
exports.ParamError = require_params.ParamError;
|
|
269
|
+
exports.bloomSizing = bloomSizing;
|
package/dist/bloom/index.d.cts
CHANGED
|
@@ -128,4 +128,15 @@ declare class BloomFilter {
|
|
|
128
128
|
has(key: BytesLike): boolean;
|
|
129
129
|
}
|
|
130
130
|
//#endregion
|
|
131
|
-
|
|
131
|
+
//#region src/core/sizing.d.ts
|
|
132
|
+
/** Bloom filter geometry: the `BloomParams` fields a sizing solve determines. */
|
|
133
|
+
interface BloomSizing {
|
|
134
|
+
/** Number of bits in the filter. */
|
|
135
|
+
m: number;
|
|
136
|
+
/** Number of hash probes per key. */
|
|
137
|
+
k: number;
|
|
138
|
+
}
|
|
139
|
+
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
140
|
+
declare function bloomSizing(n: number, epsilon: number): BloomSizing;
|
|
141
|
+
//#endregion
|
|
142
|
+
export { BloomFilter, BloomParamMismatchError, type BloomParams, type BloomSizing, type FilterJSON, ParamError, bloomSizing };
|
package/dist/bloom/index.d.ts
CHANGED
|
@@ -128,4 +128,15 @@ declare class BloomFilter {
|
|
|
128
128
|
has(key: BytesLike): boolean;
|
|
129
129
|
}
|
|
130
130
|
//#endregion
|
|
131
|
-
|
|
131
|
+
//#region src/core/sizing.d.ts
|
|
132
|
+
/** Bloom filter geometry: the `BloomParams` fields a sizing solve determines. */
|
|
133
|
+
interface BloomSizing {
|
|
134
|
+
/** Number of bits in the filter. */
|
|
135
|
+
m: number;
|
|
136
|
+
/** Number of hash probes per key. */
|
|
137
|
+
k: number;
|
|
138
|
+
}
|
|
139
|
+
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
140
|
+
declare function bloomSizing(n: number, epsilon: number): BloomSizing;
|
|
141
|
+
//#endregion
|
|
142
|
+
export { BloomFilter, BloomParamMismatchError, type BloomParams, type BloomSizing, type FilterJSON, ParamError, bloomSizing };
|
package/dist/bloom/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var BitSet = class {
|
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/core/sizing.ts
|
|
35
35
|
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
36
|
-
function
|
|
36
|
+
function bloomSizing(n, epsilon) {
|
|
37
37
|
const m = Math.ceil(-n * Math.log(epsilon) / (Math.LN2 * Math.LN2));
|
|
38
38
|
return {
|
|
39
39
|
m,
|
|
@@ -78,7 +78,7 @@ var BloomFilter = class BloomFilter {
|
|
|
78
78
|
assertPositiveInt(n, "n");
|
|
79
79
|
assertUint32(n, "n");
|
|
80
80
|
assertProbability(epsilon, "epsilon");
|
|
81
|
-
return BloomFilter.#withN(
|
|
81
|
+
return BloomFilter.#withN(bloomSizing(n, epsilon), n);
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
84
|
* Builds a filter from `keys`, sized for their count at the target
|
|
@@ -262,4 +262,4 @@ var BloomFilter = class BloomFilter {
|
|
|
262
262
|
}
|
|
263
263
|
};
|
|
264
264
|
//#endregion
|
|
265
|
-
export { BloomFilter, BloomParamMismatchError, ParamError };
|
|
265
|
+
export { BloomFilter, BloomParamMismatchError, ParamError, bloomSizing };
|
package/dist/fuse/index.cjs
CHANGED
|
@@ -60,6 +60,19 @@ function computeParams(size) {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
64
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
65
|
+
* filter sizes on its deduped hash count.
|
|
66
|
+
*
|
|
67
|
+
* @param n - Number of distinct keys.
|
|
68
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
69
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
70
|
+
*/
|
|
71
|
+
function fuseBitsPerKey(n, width) {
|
|
72
|
+
if (n === 0) return 0;
|
|
73
|
+
return computeParams(n).arrayLength * width / n;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
63
76
|
* Peel the 3-hypergraph and assign fingerprints so every key's XOR of its 3
|
|
64
77
|
* lanes equals its fingerprint. Retries with a bumped seed on a stall; returns
|
|
65
78
|
* the seed that succeeded.
|
|
@@ -367,3 +380,4 @@ var BinaryFuse16 = class BinaryFuse16 extends BinaryFuse {
|
|
|
367
380
|
exports.BinaryFuse16 = BinaryFuse16;
|
|
368
381
|
exports.BinaryFuse8 = BinaryFuse8;
|
|
369
382
|
exports.BinaryFuseBuildError = BinaryFuseBuildError;
|
|
383
|
+
exports.fuseBitsPerKey = fuseBitsPerKey;
|
package/dist/fuse/index.d.cts
CHANGED
|
@@ -11,6 +11,16 @@ interface FuseParams {
|
|
|
11
11
|
segCountLen: number;
|
|
12
12
|
arrayLength: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
16
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
17
|
+
* filter sizes on its deduped hash count.
|
|
18
|
+
*
|
|
19
|
+
* @param n - Number of distinct keys.
|
|
20
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
21
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
22
|
+
*/
|
|
23
|
+
declare function fuseBitsPerKey(n: number, width: 8 | 16): number;
|
|
14
24
|
interface FuseState {
|
|
15
25
|
fp: Uint8Array | Uint16Array;
|
|
16
26
|
seed: number;
|
|
@@ -130,4 +140,4 @@ declare class BinaryFuse16 extends BinaryFuse {
|
|
|
130
140
|
static fromJSON(value: unknown): BinaryFuse16;
|
|
131
141
|
}
|
|
132
142
|
//#endregion
|
|
133
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON };
|
|
143
|
+
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON, fuseBitsPerKey };
|
package/dist/fuse/index.d.ts
CHANGED
|
@@ -11,6 +11,16 @@ interface FuseParams {
|
|
|
11
11
|
segCountLen: number;
|
|
12
12
|
arrayLength: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
16
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
17
|
+
* filter sizes on its deduped hash count.
|
|
18
|
+
*
|
|
19
|
+
* @param n - Number of distinct keys.
|
|
20
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
21
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
22
|
+
*/
|
|
23
|
+
declare function fuseBitsPerKey(n: number, width: 8 | 16): number;
|
|
14
24
|
interface FuseState {
|
|
15
25
|
fp: Uint8Array | Uint16Array;
|
|
16
26
|
seed: number;
|
|
@@ -130,4 +140,4 @@ declare class BinaryFuse16 extends BinaryFuse {
|
|
|
130
140
|
static fromJSON(value: unknown): BinaryFuse16;
|
|
131
141
|
}
|
|
132
142
|
//#endregion
|
|
133
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON };
|
|
143
|
+
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON, fuseBitsPerKey };
|
package/dist/fuse/index.js
CHANGED
|
@@ -59,6 +59,19 @@ function computeParams(size) {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
63
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
64
|
+
* filter sizes on its deduped hash count.
|
|
65
|
+
*
|
|
66
|
+
* @param n - Number of distinct keys.
|
|
67
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
68
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
69
|
+
*/
|
|
70
|
+
function fuseBitsPerKey(n, width) {
|
|
71
|
+
if (n === 0) return 0;
|
|
72
|
+
return computeParams(n).arrayLength * width / n;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
62
75
|
* Peel the 3-hypergraph and assign fingerprints so every key's XOR of its 3
|
|
63
76
|
* lanes equals its fingerprint. Retries with a bumped seed on a stall; returns
|
|
64
77
|
* the seed that succeeded.
|
|
@@ -363,4 +376,4 @@ var BinaryFuse16 = class BinaryFuse16 extends BinaryFuse {
|
|
|
363
376
|
}
|
|
364
377
|
};
|
|
365
378
|
//#endregion
|
|
366
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError };
|
|
379
|
+
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, fuseBitsPerKey };
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "distillate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Probabilistic data structures for JavaScript. Space-efficient, approximate-membership filters (Bloom, Blocked Bloom, Binary Fuse) with tunable error and a portable binary format; zero dependencies, universal.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bloom-filter",
|
|
@@ -66,13 +66,13 @@
|
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
68
68
|
"@microsoft/api-extractor": "^7.58.12",
|
|
69
|
-
"@types/node": "^
|
|
69
|
+
"@types/node": "^22.0.0",
|
|
70
70
|
"@vitest/coverage-v8": "^4.1.10",
|
|
71
71
|
"fast-check": "^4.9.0",
|
|
72
72
|
"mitata": "^1.0.34",
|
|
73
|
-
"publint": "^0.3.
|
|
73
|
+
"publint": "^0.3.23",
|
|
74
74
|
"tsdown": "^0.22.14",
|
|
75
|
-
"tsx": "^4.23.
|
|
75
|
+
"tsx": "^4.23.12",
|
|
76
76
|
"typedoc": "^0.28.20",
|
|
77
77
|
"typedoc-plugin-markdown": "^4.12.0",
|
|
78
78
|
"typescript": "^5.9.3",
|