distillate 0.1.2 → 0.3.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 +28 -1
- package/dist/blocked/index.d.cts +13 -1
- package/dist/blocked/index.d.ts +13 -1
- package/dist/blocked/index.js +28 -2
- package/dist/bloom/index.cjs +33 -0
- package/dist/bloom/index.d.cts +18 -1
- package/dist/bloom/index.d.ts +18 -1
- package/dist/bloom/index.js +33 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/params-ChTRNxM9.js +24 -0
- package/dist/params-DnqJBqLS.d.cts +8 -0
- package/dist/params-DnqJBqLS.d.ts +8 -0
- package/dist/params-J8p3bKq5.cjs +53 -0
- package/package.json +1 -1
package/dist/blocked/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_serialize = require("../serialize-CHHDM4TQ.cjs");
|
|
3
|
+
const require_params = require("../params-J8p3bKq5.cjs");
|
|
3
4
|
//#region src/blocked/blocked.ts
|
|
4
5
|
const TYPE = 2;
|
|
5
6
|
const SALT = Uint32Array.of(1203114875, 1150766481, 2284105051, 2729912477, 1884591559, 770785867, 2667333959, 1550580529);
|
|
@@ -45,6 +46,8 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
45
46
|
* @returns A new, empty filter.
|
|
46
47
|
*/
|
|
47
48
|
static create(n, epsilon) {
|
|
49
|
+
require_params.assertPositiveInt(n, "n");
|
|
50
|
+
require_params.assertProbability(epsilon, "epsilon");
|
|
48
51
|
const t = Math.log10(1 / epsilon);
|
|
49
52
|
const a = BlockedBloomFilter.#ANCHORS;
|
|
50
53
|
let seg = a.findIndex((p) => t <= p[0]);
|
|
@@ -53,7 +56,7 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
53
56
|
const [t1, b1] = a[seg] ?? [0, 0];
|
|
54
57
|
const bitsPerKey = b0 + (b1 - b0) / (t1 - t0) * (t - t0);
|
|
55
58
|
return new BlockedBloomFilter({
|
|
56
|
-
bitsPerKey: Math.ceil(bitsPerKey),
|
|
59
|
+
bitsPerKey: Math.max(1, Math.ceil(bitsPerKey)),
|
|
57
60
|
capacity: n
|
|
58
61
|
});
|
|
59
62
|
}
|
|
@@ -62,6 +65,9 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
62
65
|
* {@link BlockedBloomFilter.create} unless restoring a specific configuration.
|
|
63
66
|
*/
|
|
64
67
|
constructor({ bitsPerKey, capacity, seed = 0 }) {
|
|
68
|
+
require_params.assertPositiveFinite(bitsPerKey, "bitsPerKey");
|
|
69
|
+
require_params.assertPositiveInt(capacity, "capacity");
|
|
70
|
+
require_params.assertUint32(seed, "seed");
|
|
65
71
|
this.#numBlocks = Math.max(1, Math.ceil(bitsPerKey * capacity / 256));
|
|
66
72
|
this.#lanes = new Uint32Array(this.#numBlocks * 8);
|
|
67
73
|
this.#seed = seed;
|
|
@@ -71,6 +77,26 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
71
77
|
get bitsPerKey() {
|
|
72
78
|
return this.#numBlocks * 256 / this.#n;
|
|
73
79
|
}
|
|
80
|
+
/** Number of bits currently set across all lanes. */
|
|
81
|
+
get length() {
|
|
82
|
+
let bits = 0;
|
|
83
|
+
for (let w of this.#lanes) while (w) {
|
|
84
|
+
w &= w - 1;
|
|
85
|
+
bits++;
|
|
86
|
+
}
|
|
87
|
+
return bits;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
91
|
+
* `(length / totalBits) ** 8`. A split-block query checks exactly 8 lane-bits,
|
|
92
|
+
* so the exponent is 8 rather than a classic probe count `k`. This reflects
|
|
93
|
+
* how full the filter is right now, not the design target.
|
|
94
|
+
*
|
|
95
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
96
|
+
*/
|
|
97
|
+
rate() {
|
|
98
|
+
return (this.length / (this.#numBlocks * 256)) ** 8;
|
|
99
|
+
}
|
|
74
100
|
/**
|
|
75
101
|
* Restores a filter from its {@link BlockedBloomFilter.toBytes} serialization.
|
|
76
102
|
*
|
|
@@ -168,3 +194,4 @@ function fillBlock(key, numBlocks, seed, outWords, outBits) {
|
|
|
168
194
|
//#endregion
|
|
169
195
|
exports.BlockedBloomFilter = BlockedBloomFilter;
|
|
170
196
|
exports.BlockedBloomParamMismatchError = BlockedBloomParamMismatchError;
|
|
197
|
+
exports.ParamError = require_params.ParamError;
|
package/dist/blocked/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as BytesLike } from "../bytes-DCuYtUVS.cjs";
|
|
2
|
+
import { t as ParamError } from "../params-DnqJBqLS.cjs";
|
|
2
3
|
//#region src/blocked/blocked.d.ts
|
|
3
4
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
4
5
|
declare class BlockedBloomParamMismatchError extends Error {
|
|
@@ -42,6 +43,17 @@ declare class BlockedBloomFilter {
|
|
|
42
43
|
constructor({ bitsPerKey, capacity, seed }: BlockedBloomParams);
|
|
43
44
|
/** Actual bits allocated per key (`total bits / capacity`). */
|
|
44
45
|
get bitsPerKey(): number;
|
|
46
|
+
/** Number of bits currently set across all lanes. */
|
|
47
|
+
get length(): number;
|
|
48
|
+
/**
|
|
49
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
50
|
+
* `(length / totalBits) ** 8`. A split-block query checks exactly 8 lane-bits,
|
|
51
|
+
* so the exponent is 8 rather than a classic probe count `k`. This reflects
|
|
52
|
+
* how full the filter is right now, not the design target.
|
|
53
|
+
*
|
|
54
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
55
|
+
*/
|
|
56
|
+
rate(): number;
|
|
45
57
|
/**
|
|
46
58
|
* Restores a filter from its {@link BlockedBloomFilter.toBytes} serialization.
|
|
47
59
|
*
|
|
@@ -78,4 +90,4 @@ declare class BlockedBloomFilter {
|
|
|
78
90
|
has(key: BytesLike): boolean;
|
|
79
91
|
}
|
|
80
92
|
//#endregion
|
|
81
|
-
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams };
|
|
93
|
+
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams, ParamError };
|
package/dist/blocked/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as BytesLike } from "../bytes-DCuYtUVS.js";
|
|
2
|
+
import { t as ParamError } from "../params-DnqJBqLS.js";
|
|
2
3
|
//#region src/blocked/blocked.d.ts
|
|
3
4
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
4
5
|
declare class BlockedBloomParamMismatchError extends Error {
|
|
@@ -42,6 +43,17 @@ declare class BlockedBloomFilter {
|
|
|
42
43
|
constructor({ bitsPerKey, capacity, seed }: BlockedBloomParams);
|
|
43
44
|
/** Actual bits allocated per key (`total bits / capacity`). */
|
|
44
45
|
get bitsPerKey(): number;
|
|
46
|
+
/** Number of bits currently set across all lanes. */
|
|
47
|
+
get length(): number;
|
|
48
|
+
/**
|
|
49
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
50
|
+
* `(length / totalBits) ** 8`. A split-block query checks exactly 8 lane-bits,
|
|
51
|
+
* so the exponent is 8 rather than a classic probe count `k`. This reflects
|
|
52
|
+
* how full the filter is right now, not the design target.
|
|
53
|
+
*
|
|
54
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
55
|
+
*/
|
|
56
|
+
rate(): number;
|
|
45
57
|
/**
|
|
46
58
|
* Restores a filter from its {@link BlockedBloomFilter.toBytes} serialization.
|
|
47
59
|
*
|
|
@@ -78,4 +90,4 @@ declare class BlockedBloomFilter {
|
|
|
78
90
|
has(key: BytesLike): boolean;
|
|
79
91
|
}
|
|
80
92
|
//#endregion
|
|
81
|
-
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams };
|
|
93
|
+
export { BlockedBloomFilter, BlockedBloomParamMismatchError, type BlockedBloomParams, ParamError };
|
package/dist/blocked/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { i as hash128KeyInto, n as readHeader, o as reduce, r as writeHeader } from "../serialize-5XQ5y_R-.js";
|
|
2
|
+
import { a as assertUint32, i as assertProbability, n as assertPositiveFinite, r as assertPositiveInt, t as ParamError } from "../params-ChTRNxM9.js";
|
|
2
3
|
//#region src/blocked/blocked.ts
|
|
3
4
|
const TYPE = 2;
|
|
4
5
|
const SALT = Uint32Array.of(1203114875, 1150766481, 2284105051, 2729912477, 1884591559, 770785867, 2667333959, 1550580529);
|
|
@@ -44,6 +45,8 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
44
45
|
* @returns A new, empty filter.
|
|
45
46
|
*/
|
|
46
47
|
static create(n, epsilon) {
|
|
48
|
+
assertPositiveInt(n, "n");
|
|
49
|
+
assertProbability(epsilon, "epsilon");
|
|
47
50
|
const t = Math.log10(1 / epsilon);
|
|
48
51
|
const a = BlockedBloomFilter.#ANCHORS;
|
|
49
52
|
let seg = a.findIndex((p) => t <= p[0]);
|
|
@@ -52,7 +55,7 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
52
55
|
const [t1, b1] = a[seg] ?? [0, 0];
|
|
53
56
|
const bitsPerKey = b0 + (b1 - b0) / (t1 - t0) * (t - t0);
|
|
54
57
|
return new BlockedBloomFilter({
|
|
55
|
-
bitsPerKey: Math.ceil(bitsPerKey),
|
|
58
|
+
bitsPerKey: Math.max(1, Math.ceil(bitsPerKey)),
|
|
56
59
|
capacity: n
|
|
57
60
|
});
|
|
58
61
|
}
|
|
@@ -61,6 +64,9 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
61
64
|
* {@link BlockedBloomFilter.create} unless restoring a specific configuration.
|
|
62
65
|
*/
|
|
63
66
|
constructor({ bitsPerKey, capacity, seed = 0 }) {
|
|
67
|
+
assertPositiveFinite(bitsPerKey, "bitsPerKey");
|
|
68
|
+
assertPositiveInt(capacity, "capacity");
|
|
69
|
+
assertUint32(seed, "seed");
|
|
64
70
|
this.#numBlocks = Math.max(1, Math.ceil(bitsPerKey * capacity / 256));
|
|
65
71
|
this.#lanes = new Uint32Array(this.#numBlocks * 8);
|
|
66
72
|
this.#seed = seed;
|
|
@@ -70,6 +76,26 @@ var BlockedBloomFilter = class BlockedBloomFilter {
|
|
|
70
76
|
get bitsPerKey() {
|
|
71
77
|
return this.#numBlocks * 256 / this.#n;
|
|
72
78
|
}
|
|
79
|
+
/** Number of bits currently set across all lanes. */
|
|
80
|
+
get length() {
|
|
81
|
+
let bits = 0;
|
|
82
|
+
for (let w of this.#lanes) while (w) {
|
|
83
|
+
w &= w - 1;
|
|
84
|
+
bits++;
|
|
85
|
+
}
|
|
86
|
+
return bits;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
90
|
+
* `(length / totalBits) ** 8`. A split-block query checks exactly 8 lane-bits,
|
|
91
|
+
* so the exponent is 8 rather than a classic probe count `k`. This reflects
|
|
92
|
+
* how full the filter is right now, not the design target.
|
|
93
|
+
*
|
|
94
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
95
|
+
*/
|
|
96
|
+
rate() {
|
|
97
|
+
return (this.length / (this.#numBlocks * 256)) ** 8;
|
|
98
|
+
}
|
|
73
99
|
/**
|
|
74
100
|
* Restores a filter from its {@link BlockedBloomFilter.toBytes} serialization.
|
|
75
101
|
*
|
|
@@ -165,4 +191,4 @@ function fillBlock(key, numBlocks, seed, outWords, outBits) {
|
|
|
165
191
|
}
|
|
166
192
|
}
|
|
167
193
|
//#endregion
|
|
168
|
-
export { BlockedBloomFilter, BlockedBloomParamMismatchError };
|
|
194
|
+
export { BlockedBloomFilter, BlockedBloomParamMismatchError, ParamError };
|
package/dist/bloom/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_serialize = require("../serialize-CHHDM4TQ.cjs");
|
|
3
|
+
const require_params = require("../params-J8p3bKq5.cjs");
|
|
3
4
|
//#region src/core/bitset.ts
|
|
4
5
|
var BitSetRangeError = class extends RangeError {
|
|
5
6
|
name = "BitSetRangeError";
|
|
@@ -80,6 +81,8 @@ var BloomFilter = class BloomFilter {
|
|
|
80
81
|
* @returns A new, empty filter.
|
|
81
82
|
*/
|
|
82
83
|
static create(n, epsilon) {
|
|
84
|
+
require_params.assertPositiveInt(n, "n");
|
|
85
|
+
require_params.assertProbability(epsilon, "epsilon");
|
|
83
86
|
const f = new BloomFilter(optimal(n, epsilon));
|
|
84
87
|
f.#n = n;
|
|
85
88
|
return f;
|
|
@@ -109,6 +112,9 @@ var BloomFilter = class BloomFilter {
|
|
|
109
112
|
* {@link BloomFilter.create} unless restoring a specific configuration.
|
|
110
113
|
*/
|
|
111
114
|
constructor({ m, k, seed = 0 }) {
|
|
115
|
+
require_params.assertPositiveInt(m, "m");
|
|
116
|
+
require_params.assertPositiveInt(k, "k");
|
|
117
|
+
require_params.assertUint32(seed, "seed");
|
|
112
118
|
this.#bits = new BitSet(m);
|
|
113
119
|
this.#m = m;
|
|
114
120
|
this.#k = k;
|
|
@@ -116,11 +122,37 @@ var BloomFilter = class BloomFilter {
|
|
|
116
122
|
this.#scratch = new Uint32Array(k);
|
|
117
123
|
this.#n = Math.round(m * Math.LN2 / k);
|
|
118
124
|
}
|
|
125
|
+
/** Number of bits in the filter. */
|
|
126
|
+
get m() {
|
|
127
|
+
return this.#m;
|
|
128
|
+
}
|
|
129
|
+
/** Number of hash probes per key. */
|
|
130
|
+
get k() {
|
|
131
|
+
return this.#k;
|
|
132
|
+
}
|
|
133
|
+
/** Hash seed. */
|
|
134
|
+
get seed() {
|
|
135
|
+
return this.#seed;
|
|
136
|
+
}
|
|
137
|
+
/** Number of bits currently set. */
|
|
138
|
+
get length() {
|
|
139
|
+
return this.#bits.count();
|
|
140
|
+
}
|
|
119
141
|
/** Analytic design bits-per-key `m / n`. */
|
|
120
142
|
get bitsPerKey() {
|
|
121
143
|
return this.#m / this.#n;
|
|
122
144
|
}
|
|
123
145
|
/**
|
|
146
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
147
|
+
* `(length / m) ** k`. This reflects how full the filter is right now, not
|
|
148
|
+
* the design target; it rises as keys are added.
|
|
149
|
+
*
|
|
150
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
151
|
+
*/
|
|
152
|
+
rate() {
|
|
153
|
+
return (this.length / this.#m) ** this.#k;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
124
156
|
* Serializes the filter to a portable little-endian byte layout.
|
|
125
157
|
*
|
|
126
158
|
* @returns The serialized filter, readable by {@link BloomFilter.fromBytes}.
|
|
@@ -184,3 +216,4 @@ var BloomFilter = class BloomFilter {
|
|
|
184
216
|
//#endregion
|
|
185
217
|
exports.BloomFilter = BloomFilter;
|
|
186
218
|
exports.BloomParamMismatchError = BloomParamMismatchError;
|
|
219
|
+
exports.ParamError = require_params.ParamError;
|
package/dist/bloom/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as BytesLike } from "../bytes-DCuYtUVS.cjs";
|
|
2
|
+
import { t as ParamError } from "../params-DnqJBqLS.cjs";
|
|
2
3
|
//#region src/bloom/bloom.d.ts
|
|
3
4
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
4
5
|
declare class BloomParamMismatchError extends Error {
|
|
@@ -48,8 +49,24 @@ declare class BloomFilter {
|
|
|
48
49
|
* {@link BloomFilter.create} unless restoring a specific configuration.
|
|
49
50
|
*/
|
|
50
51
|
constructor({ m, k, seed }: BloomParams);
|
|
52
|
+
/** Number of bits in the filter. */
|
|
53
|
+
get m(): number;
|
|
54
|
+
/** Number of hash probes per key. */
|
|
55
|
+
get k(): number;
|
|
56
|
+
/** Hash seed. */
|
|
57
|
+
get seed(): number;
|
|
58
|
+
/** Number of bits currently set. */
|
|
59
|
+
get length(): number;
|
|
51
60
|
/** Analytic design bits-per-key `m / n`. */
|
|
52
61
|
get bitsPerKey(): number;
|
|
62
|
+
/**
|
|
63
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
64
|
+
* `(length / m) ** k`. This reflects how full the filter is right now, not
|
|
65
|
+
* the design target; it rises as keys are added.
|
|
66
|
+
*
|
|
67
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
68
|
+
*/
|
|
69
|
+
rate(): number;
|
|
53
70
|
/**
|
|
54
71
|
* Serializes the filter to a portable little-endian byte layout.
|
|
55
72
|
*
|
|
@@ -79,4 +96,4 @@ declare class BloomFilter {
|
|
|
79
96
|
has(key: BytesLike): boolean;
|
|
80
97
|
}
|
|
81
98
|
//#endregion
|
|
82
|
-
export { BloomFilter, BloomParamMismatchError, type BloomParams };
|
|
99
|
+
export { BloomFilter, BloomParamMismatchError, type BloomParams, ParamError };
|
package/dist/bloom/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as BytesLike } from "../bytes-DCuYtUVS.js";
|
|
2
|
+
import { t as ParamError } from "../params-DnqJBqLS.js";
|
|
2
3
|
//#region src/bloom/bloom.d.ts
|
|
3
4
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
4
5
|
declare class BloomParamMismatchError extends Error {
|
|
@@ -48,8 +49,24 @@ declare class BloomFilter {
|
|
|
48
49
|
* {@link BloomFilter.create} unless restoring a specific configuration.
|
|
49
50
|
*/
|
|
50
51
|
constructor({ m, k, seed }: BloomParams);
|
|
52
|
+
/** Number of bits in the filter. */
|
|
53
|
+
get m(): number;
|
|
54
|
+
/** Number of hash probes per key. */
|
|
55
|
+
get k(): number;
|
|
56
|
+
/** Hash seed. */
|
|
57
|
+
get seed(): number;
|
|
58
|
+
/** Number of bits currently set. */
|
|
59
|
+
get length(): number;
|
|
51
60
|
/** Analytic design bits-per-key `m / n`. */
|
|
52
61
|
get bitsPerKey(): number;
|
|
62
|
+
/**
|
|
63
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
64
|
+
* `(length / m) ** k`. This reflects how full the filter is right now, not
|
|
65
|
+
* the design target; it rises as keys are added.
|
|
66
|
+
*
|
|
67
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
68
|
+
*/
|
|
69
|
+
rate(): number;
|
|
53
70
|
/**
|
|
54
71
|
* Serializes the filter to a portable little-endian byte layout.
|
|
55
72
|
*
|
|
@@ -79,4 +96,4 @@ declare class BloomFilter {
|
|
|
79
96
|
has(key: BytesLike): boolean;
|
|
80
97
|
}
|
|
81
98
|
//#endregion
|
|
82
|
-
export { BloomFilter, BloomParamMismatchError, type BloomParams };
|
|
99
|
+
export { BloomFilter, BloomParamMismatchError, type BloomParams, ParamError };
|
package/dist/bloom/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { a as probeInto, n as readHeader, r as writeHeader } from "../serialize-5XQ5y_R-.js";
|
|
2
|
+
import { a as assertUint32, i as assertProbability, r as assertPositiveInt, t as ParamError } from "../params-ChTRNxM9.js";
|
|
2
3
|
//#region src/core/bitset.ts
|
|
3
4
|
var BitSetRangeError = class extends RangeError {
|
|
4
5
|
name = "BitSetRangeError";
|
|
@@ -79,6 +80,8 @@ var BloomFilter = class BloomFilter {
|
|
|
79
80
|
* @returns A new, empty filter.
|
|
80
81
|
*/
|
|
81
82
|
static create(n, epsilon) {
|
|
83
|
+
assertPositiveInt(n, "n");
|
|
84
|
+
assertProbability(epsilon, "epsilon");
|
|
82
85
|
const f = new BloomFilter(optimal(n, epsilon));
|
|
83
86
|
f.#n = n;
|
|
84
87
|
return f;
|
|
@@ -108,6 +111,9 @@ var BloomFilter = class BloomFilter {
|
|
|
108
111
|
* {@link BloomFilter.create} unless restoring a specific configuration.
|
|
109
112
|
*/
|
|
110
113
|
constructor({ m, k, seed = 0 }) {
|
|
114
|
+
assertPositiveInt(m, "m");
|
|
115
|
+
assertPositiveInt(k, "k");
|
|
116
|
+
assertUint32(seed, "seed");
|
|
111
117
|
this.#bits = new BitSet(m);
|
|
112
118
|
this.#m = m;
|
|
113
119
|
this.#k = k;
|
|
@@ -115,11 +121,37 @@ var BloomFilter = class BloomFilter {
|
|
|
115
121
|
this.#scratch = new Uint32Array(k);
|
|
116
122
|
this.#n = Math.round(m * Math.LN2 / k);
|
|
117
123
|
}
|
|
124
|
+
/** Number of bits in the filter. */
|
|
125
|
+
get m() {
|
|
126
|
+
return this.#m;
|
|
127
|
+
}
|
|
128
|
+
/** Number of hash probes per key. */
|
|
129
|
+
get k() {
|
|
130
|
+
return this.#k;
|
|
131
|
+
}
|
|
132
|
+
/** Hash seed. */
|
|
133
|
+
get seed() {
|
|
134
|
+
return this.#seed;
|
|
135
|
+
}
|
|
136
|
+
/** Number of bits currently set. */
|
|
137
|
+
get length() {
|
|
138
|
+
return this.#bits.count();
|
|
139
|
+
}
|
|
118
140
|
/** Analytic design bits-per-key `m / n`. */
|
|
119
141
|
get bitsPerKey() {
|
|
120
142
|
return this.#m / this.#n;
|
|
121
143
|
}
|
|
122
144
|
/**
|
|
145
|
+
* Estimates the current false-positive rate from the actual fill,
|
|
146
|
+
* `(length / m) ** k`. This reflects how full the filter is right now, not
|
|
147
|
+
* the design target; it rises as keys are added.
|
|
148
|
+
*
|
|
149
|
+
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
150
|
+
*/
|
|
151
|
+
rate() {
|
|
152
|
+
return (this.length / this.#m) ** this.#k;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
123
155
|
* Serializes the filter to a portable little-endian byte layout.
|
|
124
156
|
*
|
|
125
157
|
* @returns The serialized filter, readable by {@link BloomFilter.fromBytes}.
|
|
@@ -181,4 +213,4 @@ var BloomFilter = class BloomFilter {
|
|
|
181
213
|
}
|
|
182
214
|
};
|
|
183
215
|
//#endregion
|
|
184
|
-
export { BloomFilter, BloomParamMismatchError };
|
|
216
|
+
export { BloomFilter, BloomParamMismatchError, ParamError };
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/core/params.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
var ParamError = class extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
name = "ParamError";
|
|
6
|
+
};
|
|
7
|
+
/** Asserts `value` is an integer greater than or equal to 1. */
|
|
8
|
+
function assertPositiveInt(value, label) {
|
|
9
|
+
if (!Number.isInteger(value) || value < 1) throw new ParamError(`${label} must be a positive integer, got ${String(value)}`);
|
|
10
|
+
}
|
|
11
|
+
/** Asserts `value` is a finite number greater than 0 (a positive real). */
|
|
12
|
+
function assertPositiveFinite(value, label) {
|
|
13
|
+
if (!Number.isFinite(value) || value <= 0) throw new ParamError(`${label} must be a positive number, got ${String(value)}`);
|
|
14
|
+
}
|
|
15
|
+
/** Asserts `value` is an integer in the uint32 range `[0, 2^32 - 1]`. */
|
|
16
|
+
function assertUint32(value, label) {
|
|
17
|
+
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new ParamError(`${label} must be a uint32, got ${String(value)}`);
|
|
18
|
+
}
|
|
19
|
+
/** Asserts `value` is a finite number in the open interval `(0, 1)`. */
|
|
20
|
+
function assertProbability(value, label) {
|
|
21
|
+
if (!Number.isFinite(value) || value <= 0 || value >= 1) throw new ParamError(`${label} must be in the open interval (0, 1), got ${String(value)}`);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { assertUint32 as a, assertProbability as i, assertPositiveFinite as n, assertPositiveInt as r, ParamError as t };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/core/params.d.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
declare class ParamError extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
override readonly name = "ParamError";
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { ParamError as t };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/core/params.d.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
declare class ParamError extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
override readonly name = "ParamError";
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { ParamError as t };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/core/params.ts
|
|
2
|
+
/** Thrown when a structure is constructed with invalid parameters. */
|
|
3
|
+
var ParamError = class extends RangeError {
|
|
4
|
+
/** Discriminates this error from other `Error`s. */
|
|
5
|
+
name = "ParamError";
|
|
6
|
+
};
|
|
7
|
+
/** Asserts `value` is an integer greater than or equal to 1. */
|
|
8
|
+
function assertPositiveInt(value, label) {
|
|
9
|
+
if (!Number.isInteger(value) || value < 1) throw new ParamError(`${label} must be a positive integer, got ${String(value)}`);
|
|
10
|
+
}
|
|
11
|
+
/** Asserts `value` is a finite number greater than 0 (a positive real). */
|
|
12
|
+
function assertPositiveFinite(value, label) {
|
|
13
|
+
if (!Number.isFinite(value) || value <= 0) throw new ParamError(`${label} must be a positive number, got ${String(value)}`);
|
|
14
|
+
}
|
|
15
|
+
/** Asserts `value` is an integer in the uint32 range `[0, 2^32 - 1]`. */
|
|
16
|
+
function assertUint32(value, label) {
|
|
17
|
+
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new ParamError(`${label} must be a uint32, got ${String(value)}`);
|
|
18
|
+
}
|
|
19
|
+
/** Asserts `value` is a finite number in the open interval `(0, 1)`. */
|
|
20
|
+
function assertProbability(value, label) {
|
|
21
|
+
if (!Number.isFinite(value) || value <= 0 || value >= 1) throw new ParamError(`${label} must be in the open interval (0, 1), got ${String(value)}`);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
Object.defineProperty(exports, "ParamError", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function() {
|
|
27
|
+
return ParamError;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "assertPositiveFinite", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function() {
|
|
33
|
+
return assertPositiveFinite;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "assertPositiveInt", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function() {
|
|
39
|
+
return assertPositiveInt;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "assertProbability", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function() {
|
|
45
|
+
return assertProbability;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "assertUint32", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function() {
|
|
51
|
+
return assertUint32;
|
|
52
|
+
}
|
|
53
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "distillate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|