distillate 0.8.2 → 0.9.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 +34 -6
- package/dist/blocked/index.cjs +3 -3
- package/dist/blocked/index.d.cts +1 -1
- package/dist/blocked/index.d.ts +1 -1
- package/dist/blocked/index.js +3 -3
- package/dist/bloom/index.cjs +23 -27
- package/dist/bloom/index.d.cts +18 -14
- package/dist/bloom/index.d.ts +18 -14
- package/dist/bloom/index.js +22 -26
- package/dist/fuse/index.cjs +3 -3
- package/dist/fuse/index.d.cts +1 -1
- package/dist/fuse/index.d.ts +1 -1
- package/dist/fuse/index.js +3 -3
- package/dist/hll/index.cjs +362 -0
- package/dist/hll/index.d.cts +119 -0
- package/dist/hll/index.d.ts +119 -0
- package/dist/hll/index.js +353 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{serialize-ChyWpB9F.d.cts → serialize-Bv1zWzrh.d.cts} +10 -7
- package/dist/{serialize-ChyWpB9F.d.ts → serialize-Bv1zWzrh.d.ts} +10 -7
- package/dist/{serialize-BqIcsR2J.js → serialize-D59Ri81a.js} +17 -13
- package/dist/{serialize-CXnRWItH.cjs → serialize-Ul2LKFJU.cjs} +17 -13
- package/dist/sizing-BLzZk2zr.cjs +28 -0
- package/dist/sizing-BtUrtvF_.js +17 -0
- package/dist/sizing-wYOW27eY.d.cts +22 -0
- package/dist/sizing-wYOW27eY.d.ts +22 -0
- package/package.json +10 -2
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_serialize = require("../serialize-Ul2LKFJU.cjs");
|
|
3
|
+
const require_params = require("../params-UTZbJ22c.cjs");
|
|
4
|
+
const require_sizing = require("../sizing-BLzZk2zr.cjs");
|
|
5
|
+
//#region src/hll/estimate.ts
|
|
6
|
+
const ALPHA_INF = .5 / Math.LN2;
|
|
7
|
+
function sigma(x) {
|
|
8
|
+
if (x === 1) return Infinity;
|
|
9
|
+
let y = 1;
|
|
10
|
+
let z = x;
|
|
11
|
+
let previous;
|
|
12
|
+
do {
|
|
13
|
+
x *= x;
|
|
14
|
+
previous = z;
|
|
15
|
+
z += x * y;
|
|
16
|
+
y += y;
|
|
17
|
+
} while (z !== previous);
|
|
18
|
+
return z;
|
|
19
|
+
}
|
|
20
|
+
function tau(x) {
|
|
21
|
+
if (x === 0 || x === 1) return 0;
|
|
22
|
+
let y = 1;
|
|
23
|
+
let z = 1 - x;
|
|
24
|
+
let previous;
|
|
25
|
+
do {
|
|
26
|
+
x = Math.sqrt(x);
|
|
27
|
+
previous = z;
|
|
28
|
+
y *= .5;
|
|
29
|
+
const gap = 1 - x;
|
|
30
|
+
z -= gap * gap * y;
|
|
31
|
+
} while (z !== previous);
|
|
32
|
+
return z / 3;
|
|
33
|
+
}
|
|
34
|
+
function estimate(hist, p) {
|
|
35
|
+
const m = 2 ** p;
|
|
36
|
+
const q = 64 - p;
|
|
37
|
+
let z = m * tau((m - (hist[q + 1] ?? 0)) / m);
|
|
38
|
+
for (let k = q; k >= 1; k--) z = .5 * (z + (hist[k] ?? 0));
|
|
39
|
+
z += m * sigma((hist[0] ?? 0) / m);
|
|
40
|
+
return ALPHA_INF * m * m / z;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/hll/fold.ts
|
|
44
|
+
function foldRho(index, rho, d) {
|
|
45
|
+
const mid = index & (1 << d) - 1;
|
|
46
|
+
if (mid === 0) return d + rho;
|
|
47
|
+
return Math.clz32(mid) - 32 + d + 1;
|
|
48
|
+
}
|
|
49
|
+
function foldDense(src, srcP, dst, dstP) {
|
|
50
|
+
const d = srcP - dstP;
|
|
51
|
+
for (let i = 0; i < 2 ** srcP; i++) {
|
|
52
|
+
const rho = src.get(i);
|
|
53
|
+
if (rho === 0) continue;
|
|
54
|
+
dst.raise(i >>> d, foldRho(i, rho, d));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/hll/registers.ts
|
|
59
|
+
const WIDTH = 6;
|
|
60
|
+
const MASK = 63;
|
|
61
|
+
var Registers = class {
|
|
62
|
+
#bytes;
|
|
63
|
+
constructor(p) {
|
|
64
|
+
this.#bytes = new Uint8Array(WIDTH * 2 ** p / 8);
|
|
65
|
+
}
|
|
66
|
+
get bytes() {
|
|
67
|
+
return this.#bytes;
|
|
68
|
+
}
|
|
69
|
+
max() {
|
|
70
|
+
const bytes = this.#bytes;
|
|
71
|
+
let max = 0;
|
|
72
|
+
for (let at = 0; at < bytes.length; at += 3) {
|
|
73
|
+
const word = (bytes[at] ?? 0) | (bytes[at + 1] ?? 0) << 8 | (bytes[at + 2] ?? 0) << 16;
|
|
74
|
+
const a = word & MASK;
|
|
75
|
+
const b = word >>> 6 & MASK;
|
|
76
|
+
const c = word >>> 12 & MASK;
|
|
77
|
+
const d = word >>> 18 & MASK;
|
|
78
|
+
if (a > max) max = a;
|
|
79
|
+
if (b > max) max = b;
|
|
80
|
+
if (c > max) max = c;
|
|
81
|
+
if (d > max) max = d;
|
|
82
|
+
}
|
|
83
|
+
return max;
|
|
84
|
+
}
|
|
85
|
+
get(i) {
|
|
86
|
+
const bit = i * WIDTH;
|
|
87
|
+
const at = bit >>> 3;
|
|
88
|
+
return ((this.#bytes[at] ?? 0) | (this.#bytes[at + 1] ?? 0) << 8) >>> (bit & 7) & MASK;
|
|
89
|
+
}
|
|
90
|
+
raise(i, v) {
|
|
91
|
+
if (v > this.get(i)) this.set(i, v);
|
|
92
|
+
}
|
|
93
|
+
set(i, v) {
|
|
94
|
+
const bit = i * WIDTH;
|
|
95
|
+
const at = bit >>> 3;
|
|
96
|
+
const off = bit & 7;
|
|
97
|
+
const word = ((this.#bytes[at] ?? 0) | (this.#bytes[at + 1] ?? 0) << 8) & ~(MASK << off) | (v & MASK) << off;
|
|
98
|
+
this.#bytes[at] = word & 255;
|
|
99
|
+
if (at + 1 < this.#bytes.length) this.#bytes[at + 1] = word >>> 8 & 255;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const RHO_BITS = 6;
|
|
103
|
+
const RHO_MASK = (1 << RHO_BITS) - 1;
|
|
104
|
+
function encodeSparse(index, rho) {
|
|
105
|
+
return index << RHO_BITS | rho;
|
|
106
|
+
}
|
|
107
|
+
function sparseIndex(entry) {
|
|
108
|
+
return entry >>> RHO_BITS;
|
|
109
|
+
}
|
|
110
|
+
function sparseRho(entry) {
|
|
111
|
+
return entry & RHO_MASK;
|
|
112
|
+
}
|
|
113
|
+
function foldSparse(buf, len, fromP, registers, toP) {
|
|
114
|
+
const d = fromP - toP;
|
|
115
|
+
for (let i = 0; i < len; i++) {
|
|
116
|
+
const entry = buf[i] ?? 0;
|
|
117
|
+
const at = sparseIndex(entry) >>> 25 - fromP;
|
|
118
|
+
registers.raise(at >>> d, foldRho(at, sparseRho(entry), d));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function refoldSparse(entry, fromP, toP) {
|
|
122
|
+
const index = sparseIndex(entry);
|
|
123
|
+
return encodeSparse(index, foldRho(index >>> 25 - fromP, sparseRho(entry), fromP - toP));
|
|
124
|
+
}
|
|
125
|
+
function compact(buf, len) {
|
|
126
|
+
if (len === 0) return 0;
|
|
127
|
+
buf.subarray(0, len).sort();
|
|
128
|
+
let out = 0;
|
|
129
|
+
for (let i = 0; i < len; i++) {
|
|
130
|
+
const entry = buf[i] ?? 0;
|
|
131
|
+
const next = buf[i + 1] ?? 0;
|
|
132
|
+
if (i + 1 < len && sparseIndex(next) === sparseIndex(entry)) continue;
|
|
133
|
+
buf[out++] = entry;
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/hll/hll.ts
|
|
139
|
+
const ERROR_CONSTANT = 1.04;
|
|
140
|
+
const TYPE = 5;
|
|
141
|
+
const PARAMS_SIZE = 6;
|
|
142
|
+
const DENSE = 0;
|
|
143
|
+
const SPARSE = 1;
|
|
144
|
+
const ENTRY_SIZE = 4;
|
|
145
|
+
function assertPrecision(p) {
|
|
146
|
+
if (!Number.isInteger(p) || p < 4 || p > 18) throw new require_params.ParamError(`p must be an integer in [${String(4)}, ${String(18)}], got ${String(p)}`);
|
|
147
|
+
}
|
|
148
|
+
function sparseCapacity(registers) {
|
|
149
|
+
return registers.bytes.length >> 2;
|
|
150
|
+
}
|
|
151
|
+
var HyperLogLog = class HyperLogLog {
|
|
152
|
+
#registers;
|
|
153
|
+
#p;
|
|
154
|
+
#seed;
|
|
155
|
+
#scratch = {
|
|
156
|
+
w0: 0,
|
|
157
|
+
w1: 0,
|
|
158
|
+
w2: 0,
|
|
159
|
+
w3: 0
|
|
160
|
+
};
|
|
161
|
+
#sparse;
|
|
162
|
+
#len = 0;
|
|
163
|
+
constructor({ p, seed = 0 }) {
|
|
164
|
+
assertPrecision(p);
|
|
165
|
+
require_params.assertUint32(seed, "seed");
|
|
166
|
+
this.#registers = new Registers(p);
|
|
167
|
+
this.#p = p;
|
|
168
|
+
this.#seed = seed;
|
|
169
|
+
this.#sparse = new Int32Array(sparseCapacity(this.#registers));
|
|
170
|
+
}
|
|
171
|
+
static create(relativeError) {
|
|
172
|
+
return new HyperLogLog(require_sizing.hllSizing(relativeError));
|
|
173
|
+
}
|
|
174
|
+
static from(keys, relativeError) {
|
|
175
|
+
const sketch = HyperLogLog.create(relativeError);
|
|
176
|
+
for (const key of keys) sketch.add(key);
|
|
177
|
+
return sketch;
|
|
178
|
+
}
|
|
179
|
+
static fromBytes(bytes) {
|
|
180
|
+
const { type, flags, body } = require_serialize.readHeader(bytes);
|
|
181
|
+
if (type !== TYPE) throw new require_serialize.SerializationError(`expected DSTL type ${String(TYPE)}, got ${String(type)}`);
|
|
182
|
+
if ((flags & 15) !== 0) throw new require_serialize.UnknownHashVariantError(`unsupported hash variant ${String(flags & 15)}`);
|
|
183
|
+
require_serialize.assertMinBodyLength(body.length, PARAMS_SIZE, "hll");
|
|
184
|
+
const dv = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
185
|
+
const p = body[0] ?? 0;
|
|
186
|
+
const encoding = body[1] ?? 0;
|
|
187
|
+
const seed = dv.getUint32(2, true);
|
|
188
|
+
if (encoding !== DENSE && encoding !== SPARSE) throw new require_serialize.SerializationError(`unknown hll encoding ${String(encoding)}`);
|
|
189
|
+
const sketch = new HyperLogLog({
|
|
190
|
+
p,
|
|
191
|
+
seed
|
|
192
|
+
});
|
|
193
|
+
const payload = body.length - PARAMS_SIZE;
|
|
194
|
+
const maxRho = 65 - p;
|
|
195
|
+
if (encoding === DENSE) {
|
|
196
|
+
require_serialize.assertBodyLength(body.length, PARAMS_SIZE + sketch.#registers.bytes.length, "hll");
|
|
197
|
+
sketch.#goDense();
|
|
198
|
+
sketch.#registers.bytes.set(body.subarray(PARAMS_SIZE));
|
|
199
|
+
const largest = sketch.#registers.max();
|
|
200
|
+
if (largest > maxRho) throw new require_serialize.SerializationError(`hll: register holds ${String(largest)}, above the maximum ${String(maxRho)} at p ${String(p)}`);
|
|
201
|
+
return sketch;
|
|
202
|
+
}
|
|
203
|
+
const capacity = sparseCapacity(sketch.#registers);
|
|
204
|
+
if (payload % ENTRY_SIZE !== 0 || payload / ENTRY_SIZE > capacity) throw new require_serialize.TruncatedError(`hll: sparse payload of ${String(payload)} bytes is not up to ${String(capacity)} whole entries`);
|
|
205
|
+
const entries = payload / ENTRY_SIZE;
|
|
206
|
+
const buffer = new Int32Array(capacity);
|
|
207
|
+
for (let i = 0; i < entries; i++) {
|
|
208
|
+
const entry = dv.getUint32(PARAMS_SIZE + i * ENTRY_SIZE, true);
|
|
209
|
+
if (entry > 2147483647) throw new require_serialize.SerializationError(`hll: sparse entry ${String(entry)} does not fit the 31-bit encoding`);
|
|
210
|
+
const rho = sparseRho(entry);
|
|
211
|
+
if (rho > maxRho) throw new require_serialize.SerializationError(`hll: sparse entry holds rho ${String(rho)}, above the maximum ${String(maxRho)} at p ${String(p)}`);
|
|
212
|
+
buffer[i] = entry;
|
|
213
|
+
}
|
|
214
|
+
sketch.#sparse = buffer;
|
|
215
|
+
sketch.#len = entries;
|
|
216
|
+
return sketch;
|
|
217
|
+
}
|
|
218
|
+
toBytes() {
|
|
219
|
+
const sparse = this.#sparse;
|
|
220
|
+
if (sparse !== null) {
|
|
221
|
+
const entries = compact(sparse, this.#len);
|
|
222
|
+
this.#len = entries;
|
|
223
|
+
return require_serialize.writeFrame({
|
|
224
|
+
version: 4,
|
|
225
|
+
type: TYPE,
|
|
226
|
+
flags: 0
|
|
227
|
+
}, PARAMS_SIZE + entries * ENTRY_SIZE, (body, dv) => {
|
|
228
|
+
body[0] = this.#p;
|
|
229
|
+
body[1] = SPARSE;
|
|
230
|
+
dv.setUint32(2, this.#seed, true);
|
|
231
|
+
for (let i = 0; i < entries; i++) dv.setUint32(PARAMS_SIZE + i * ENTRY_SIZE, sparse[i] ?? 0, true);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const payload = this.#registers.bytes;
|
|
235
|
+
return require_serialize.writeFrame({
|
|
236
|
+
version: 4,
|
|
237
|
+
type: TYPE,
|
|
238
|
+
flags: 0
|
|
239
|
+
}, PARAMS_SIZE + payload.length, (body, dv) => {
|
|
240
|
+
body[0] = this.#p;
|
|
241
|
+
body[1] = DENSE;
|
|
242
|
+
dv.setUint32(2, this.#seed, true);
|
|
243
|
+
body.set(payload, PARAMS_SIZE);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
toJSON() {
|
|
247
|
+
return require_serialize.toJSONEnvelope(this.toBytes());
|
|
248
|
+
}
|
|
249
|
+
static fromJSON(value) {
|
|
250
|
+
return HyperLogLog.fromBytes(require_serialize.fromJSONEnvelope(value));
|
|
251
|
+
}
|
|
252
|
+
get p() {
|
|
253
|
+
return this.#p;
|
|
254
|
+
}
|
|
255
|
+
get seed() {
|
|
256
|
+
return this.#seed;
|
|
257
|
+
}
|
|
258
|
+
get standardError() {
|
|
259
|
+
return ERROR_CONSTANT / Math.sqrt(2 ** this.#p);
|
|
260
|
+
}
|
|
261
|
+
add(key) {
|
|
262
|
+
const s = this.#scratch;
|
|
263
|
+
require_serialize.hash128KeyInto(key, this.#seed, s);
|
|
264
|
+
const p = this.#p;
|
|
265
|
+
const tail = s.w0 << p >>> 0;
|
|
266
|
+
const rho = tail !== 0 ? Math.clz32(tail) + 1 : 32 - p + Math.clz32(s.w1) + 1;
|
|
267
|
+
const sparse = this.#sparse;
|
|
268
|
+
if (sparse === null) {
|
|
269
|
+
this.#registers.raise(s.w0 >>> 32 - p, rho);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
sparse[this.#len++] = encodeSparse(s.w0 >>> 7, rho);
|
|
273
|
+
if (this.#len === sparse.length) this.#collapse(sparse);
|
|
274
|
+
}
|
|
275
|
+
#collapse(sparse) {
|
|
276
|
+
const distinct = compact(sparse, this.#len);
|
|
277
|
+
this.#len = distinct;
|
|
278
|
+
const slack = Math.max(1, sparse.length >> 2);
|
|
279
|
+
if (distinct > sparse.length - slack) this.#goDense();
|
|
280
|
+
}
|
|
281
|
+
union(other) {
|
|
282
|
+
if (other.#seed !== this.#seed) throw new require_params.ParamError(`cannot merge sketches with different seeds, got ${String(this.#seed)} and ${String(other.#seed)}`);
|
|
283
|
+
const p = Math.min(this.#p, other.#p);
|
|
284
|
+
const merged = new HyperLogLog({
|
|
285
|
+
p,
|
|
286
|
+
seed: this.#seed
|
|
287
|
+
});
|
|
288
|
+
merged.#drain(this);
|
|
289
|
+
merged.#drain(other);
|
|
290
|
+
return merged;
|
|
291
|
+
}
|
|
292
|
+
#drain(src) {
|
|
293
|
+
const sparse = src.#sparse;
|
|
294
|
+
if (sparse === null) {
|
|
295
|
+
this.#goDense();
|
|
296
|
+
foldDense(src.#registers, src.#p, this.#registers, this.#p);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const distinct = compact(sparse, src.#len);
|
|
300
|
+
src.#len = distinct;
|
|
301
|
+
for (let i = 0; i < distinct; i++) this.#absorb(refoldSparse(sparse[i] ?? 0, src.#p, this.#p));
|
|
302
|
+
}
|
|
303
|
+
#absorb(entry) {
|
|
304
|
+
const sparse = this.#sparse;
|
|
305
|
+
if (sparse === null) {
|
|
306
|
+
const index = sparseIndex(entry) >>> 25 - this.#p;
|
|
307
|
+
this.#registers.raise(index, sparseRho(entry));
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
sparse[this.#len++] = entry;
|
|
311
|
+
if (this.#len === sparse.length) this.#collapse(sparse);
|
|
312
|
+
}
|
|
313
|
+
#goDense() {
|
|
314
|
+
const sparse = this.#sparse;
|
|
315
|
+
if (sparse === null) return;
|
|
316
|
+
foldSparse(sparse, this.#len, this.#p, this.#registers, this.#p);
|
|
317
|
+
this.#sparse = null;
|
|
318
|
+
this.#len = 0;
|
|
319
|
+
}
|
|
320
|
+
#dense() {
|
|
321
|
+
const sparse = this.#sparse;
|
|
322
|
+
if (sparse === null) return this.#registers;
|
|
323
|
+
const out = new Registers(this.#p);
|
|
324
|
+
foldSparse(sparse, this.#len, this.#p, out, this.#p);
|
|
325
|
+
return out;
|
|
326
|
+
}
|
|
327
|
+
equals(other) {
|
|
328
|
+
if (other.#p !== this.#p || other.#seed !== this.#seed) return false;
|
|
329
|
+
const mine = this.#dense().bytes;
|
|
330
|
+
const theirs = other.#dense().bytes;
|
|
331
|
+
for (let i = 0; i < mine.length; i++) if (mine[i] !== theirs[i]) return false;
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
count() {
|
|
335
|
+
const sparse = this.#sparse;
|
|
336
|
+
if (sparse !== null) {
|
|
337
|
+
const distinct = compact(sparse, this.#len);
|
|
338
|
+
this.#len = distinct;
|
|
339
|
+
const buckets = 2 ** 25;
|
|
340
|
+
return Math.round(buckets * Math.log(buckets / (buckets - distinct)));
|
|
341
|
+
}
|
|
342
|
+
const p = this.#p;
|
|
343
|
+
const q = 64 - p;
|
|
344
|
+
const m = 2 ** p;
|
|
345
|
+
const hist = new Int32Array(q + 2);
|
|
346
|
+
for (let i = 0; i < m; i++) {
|
|
347
|
+
const value = this.#registers.get(i);
|
|
348
|
+
hist[value] = (hist[value] ?? 0) + 1;
|
|
349
|
+
}
|
|
350
|
+
return Math.round(estimate(hist, p));
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
//#endregion
|
|
354
|
+
exports.BadMagicError = require_serialize.BadMagicError;
|
|
355
|
+
exports.ChecksumError = require_serialize.ChecksumError;
|
|
356
|
+
exports.HyperLogLog = HyperLogLog;
|
|
357
|
+
exports.ParamError = require_params.ParamError;
|
|
358
|
+
exports.SerializationError = require_serialize.SerializationError;
|
|
359
|
+
exports.TruncatedError = require_serialize.TruncatedError;
|
|
360
|
+
exports.UnknownHashVariantError = require_serialize.UnknownHashVariantError;
|
|
361
|
+
exports.UnknownVersionError = require_serialize.UnknownVersionError;
|
|
362
|
+
exports.hllSizing = require_sizing.hllSizing;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { a as TruncatedError, c as BytesLike, i as SerializationError, n as ChecksumError, o as UnknownHashVariantError, r as FilterJSON, s as UnknownVersionError, t as BadMagicError } from "../serialize-Bv1zWzrh.cjs";
|
|
2
|
+
import { t as ParamError } from "../params-DnqJBqLS.cjs";
|
|
3
|
+
import { i as hllSizing, n as HllSizing } from "../sizing-wYOW27eY.cjs";
|
|
4
|
+
//#region src/hll/hll.d.ts
|
|
5
|
+
/** Construction parameters for a {@link HyperLogLog} sketch. */
|
|
6
|
+
interface HllParams {
|
|
7
|
+
/** Precision: the sketch holds `2 ** p` registers. */
|
|
8
|
+
p: number;
|
|
9
|
+
/** Hash seed; defaults to `0`. */
|
|
10
|
+
seed?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A HyperLogLog sketch: estimates how many distinct keys it has seen, in space
|
|
14
|
+
* fixed by `p` rather than by the cardinality.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const sketch = HyperLogLog.create(0.01);
|
|
19
|
+
* sketch.add("alice");
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare class HyperLogLog {
|
|
23
|
+
#private;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a sketch at an explicit precision.
|
|
26
|
+
*
|
|
27
|
+
* @param params - Precision and optional hash seed.
|
|
28
|
+
*/
|
|
29
|
+
constructor({ p, seed }: HllParams);
|
|
30
|
+
/**
|
|
31
|
+
* Creates a sketch whose standard error meets `relativeError`.
|
|
32
|
+
*
|
|
33
|
+
* @param relativeError - Target relative error, e.g. `0.01` for 1%.
|
|
34
|
+
* @returns A new, empty sketch.
|
|
35
|
+
*/
|
|
36
|
+
static create(relativeError: number): HyperLogLog;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a sketch counting `keys`, sized to meet `relativeError`. The
|
|
39
|
+
* ergonomic entry point when the key set is already in hand.
|
|
40
|
+
*
|
|
41
|
+
* Needs no count of the keys first, unlike the filters: a sketch is sized by
|
|
42
|
+
* the error it targets, not by how many keys it will see.
|
|
43
|
+
*
|
|
44
|
+
* @param keys - The keys to record.
|
|
45
|
+
* @param relativeError - Target relative error, e.g. `0.01` for 1%.
|
|
46
|
+
* @returns A new sketch holding every key.
|
|
47
|
+
*/
|
|
48
|
+
static from(keys: Iterable<BytesLike>, relativeError: number): HyperLogLog;
|
|
49
|
+
/**
|
|
50
|
+
* Restores a sketch from its {@link HyperLogLog.toBytes} serialization.
|
|
51
|
+
*
|
|
52
|
+
* @param bytes - The serialized sketch.
|
|
53
|
+
* @returns The reconstructed sketch.
|
|
54
|
+
*/
|
|
55
|
+
static fromBytes(bytes: Uint8Array): HyperLogLog;
|
|
56
|
+
/**
|
|
57
|
+
* Serializes the sketch to a portable little-endian byte layout.
|
|
58
|
+
*
|
|
59
|
+
* @returns The serialized sketch, readable by
|
|
60
|
+
* {@link HyperLogLog.fromBytes}.
|
|
61
|
+
*/
|
|
62
|
+
toBytes(): Uint8Array;
|
|
63
|
+
/**
|
|
64
|
+
* Serializes the sketch to a JSON-safe envelope wrapping
|
|
65
|
+
* {@link HyperLogLog.toBytes}.
|
|
66
|
+
*
|
|
67
|
+
* @returns The envelope, readable by {@link HyperLogLog.fromJSON}.
|
|
68
|
+
*/
|
|
69
|
+
toJSON(): FilterJSON;
|
|
70
|
+
/**
|
|
71
|
+
* Restores a sketch from its {@link HyperLogLog.toJSON} envelope.
|
|
72
|
+
*
|
|
73
|
+
* @param value - The parsed envelope.
|
|
74
|
+
* @returns The reconstructed sketch.
|
|
75
|
+
*/
|
|
76
|
+
static fromJSON(value: unknown): HyperLogLog;
|
|
77
|
+
/** Precision: the sketch holds `2 ** p` registers. */
|
|
78
|
+
get p(): number;
|
|
79
|
+
/** Hash seed the sketch was built with. */
|
|
80
|
+
get seed(): number;
|
|
81
|
+
/** Analytic relative standard error, `1.04 / sqrt(2 ** p)`. */
|
|
82
|
+
get standardError(): number;
|
|
83
|
+
/**
|
|
84
|
+
* Records a key. Adding a key already seen leaves the sketch unchanged, which
|
|
85
|
+
* is what lets it count distinct values without storing them.
|
|
86
|
+
*
|
|
87
|
+
* @param key - The key to record.
|
|
88
|
+
*/
|
|
89
|
+
add(key: BytesLike): void;
|
|
90
|
+
/**
|
|
91
|
+
* Merges two sketches, giving a sketch that counts the keys either has seen.
|
|
92
|
+
*
|
|
93
|
+
* Both operands are left untouched.
|
|
94
|
+
*
|
|
95
|
+
* @param other - The sketch to merge with; must share this one's seed.
|
|
96
|
+
* @returns A new sketch holding both key sets.
|
|
97
|
+
* @throws {@link ParamError} if the seeds differ, since the two would have
|
|
98
|
+
* sent the same key to different registers and the merge would mean nothing.
|
|
99
|
+
*/
|
|
100
|
+
union(other: HyperLogLog): HyperLogLog;
|
|
101
|
+
/**
|
|
102
|
+
* Whether two sketches hold the same registers at the same precision and
|
|
103
|
+
* seed. Which representation each is in does not enter into it.
|
|
104
|
+
*
|
|
105
|
+
* @param other - The sketch to compare against.
|
|
106
|
+
* @returns `true` if the two would answer every query identically.
|
|
107
|
+
*/
|
|
108
|
+
equals(other: HyperLogLog): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Counts how many distinct keys have been added. Below a few thousand
|
|
111
|
+
* distinct keys the answer is exact; above that, and once the sketch has
|
|
112
|
+
* gone dense, it estimates within {@link standardError}.
|
|
113
|
+
*
|
|
114
|
+
* @returns The cardinality, a whole number; `0` for an empty sketch.
|
|
115
|
+
*/
|
|
116
|
+
count(): number;
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { BadMagicError, ChecksumError, type FilterJSON, type HllParams, type HllSizing, HyperLogLog, ParamError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, hllSizing };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { a as TruncatedError, c as BytesLike, i as SerializationError, n as ChecksumError, o as UnknownHashVariantError, r as FilterJSON, s as UnknownVersionError, t as BadMagicError } from "../serialize-Bv1zWzrh.js";
|
|
2
|
+
import { t as ParamError } from "../params-DnqJBqLS.js";
|
|
3
|
+
import { i as hllSizing, n as HllSizing } from "../sizing-wYOW27eY.js";
|
|
4
|
+
//#region src/hll/hll.d.ts
|
|
5
|
+
/** Construction parameters for a {@link HyperLogLog} sketch. */
|
|
6
|
+
interface HllParams {
|
|
7
|
+
/** Precision: the sketch holds `2 ** p` registers. */
|
|
8
|
+
p: number;
|
|
9
|
+
/** Hash seed; defaults to `0`. */
|
|
10
|
+
seed?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A HyperLogLog sketch: estimates how many distinct keys it has seen, in space
|
|
14
|
+
* fixed by `p` rather than by the cardinality.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const sketch = HyperLogLog.create(0.01);
|
|
19
|
+
* sketch.add("alice");
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare class HyperLogLog {
|
|
23
|
+
#private;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a sketch at an explicit precision.
|
|
26
|
+
*
|
|
27
|
+
* @param params - Precision and optional hash seed.
|
|
28
|
+
*/
|
|
29
|
+
constructor({ p, seed }: HllParams);
|
|
30
|
+
/**
|
|
31
|
+
* Creates a sketch whose standard error meets `relativeError`.
|
|
32
|
+
*
|
|
33
|
+
* @param relativeError - Target relative error, e.g. `0.01` for 1%.
|
|
34
|
+
* @returns A new, empty sketch.
|
|
35
|
+
*/
|
|
36
|
+
static create(relativeError: number): HyperLogLog;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a sketch counting `keys`, sized to meet `relativeError`. The
|
|
39
|
+
* ergonomic entry point when the key set is already in hand.
|
|
40
|
+
*
|
|
41
|
+
* Needs no count of the keys first, unlike the filters: a sketch is sized by
|
|
42
|
+
* the error it targets, not by how many keys it will see.
|
|
43
|
+
*
|
|
44
|
+
* @param keys - The keys to record.
|
|
45
|
+
* @param relativeError - Target relative error, e.g. `0.01` for 1%.
|
|
46
|
+
* @returns A new sketch holding every key.
|
|
47
|
+
*/
|
|
48
|
+
static from(keys: Iterable<BytesLike>, relativeError: number): HyperLogLog;
|
|
49
|
+
/**
|
|
50
|
+
* Restores a sketch from its {@link HyperLogLog.toBytes} serialization.
|
|
51
|
+
*
|
|
52
|
+
* @param bytes - The serialized sketch.
|
|
53
|
+
* @returns The reconstructed sketch.
|
|
54
|
+
*/
|
|
55
|
+
static fromBytes(bytes: Uint8Array): HyperLogLog;
|
|
56
|
+
/**
|
|
57
|
+
* Serializes the sketch to a portable little-endian byte layout.
|
|
58
|
+
*
|
|
59
|
+
* @returns The serialized sketch, readable by
|
|
60
|
+
* {@link HyperLogLog.fromBytes}.
|
|
61
|
+
*/
|
|
62
|
+
toBytes(): Uint8Array;
|
|
63
|
+
/**
|
|
64
|
+
* Serializes the sketch to a JSON-safe envelope wrapping
|
|
65
|
+
* {@link HyperLogLog.toBytes}.
|
|
66
|
+
*
|
|
67
|
+
* @returns The envelope, readable by {@link HyperLogLog.fromJSON}.
|
|
68
|
+
*/
|
|
69
|
+
toJSON(): FilterJSON;
|
|
70
|
+
/**
|
|
71
|
+
* Restores a sketch from its {@link HyperLogLog.toJSON} envelope.
|
|
72
|
+
*
|
|
73
|
+
* @param value - The parsed envelope.
|
|
74
|
+
* @returns The reconstructed sketch.
|
|
75
|
+
*/
|
|
76
|
+
static fromJSON(value: unknown): HyperLogLog;
|
|
77
|
+
/** Precision: the sketch holds `2 ** p` registers. */
|
|
78
|
+
get p(): number;
|
|
79
|
+
/** Hash seed the sketch was built with. */
|
|
80
|
+
get seed(): number;
|
|
81
|
+
/** Analytic relative standard error, `1.04 / sqrt(2 ** p)`. */
|
|
82
|
+
get standardError(): number;
|
|
83
|
+
/**
|
|
84
|
+
* Records a key. Adding a key already seen leaves the sketch unchanged, which
|
|
85
|
+
* is what lets it count distinct values without storing them.
|
|
86
|
+
*
|
|
87
|
+
* @param key - The key to record.
|
|
88
|
+
*/
|
|
89
|
+
add(key: BytesLike): void;
|
|
90
|
+
/**
|
|
91
|
+
* Merges two sketches, giving a sketch that counts the keys either has seen.
|
|
92
|
+
*
|
|
93
|
+
* Both operands are left untouched.
|
|
94
|
+
*
|
|
95
|
+
* @param other - The sketch to merge with; must share this one's seed.
|
|
96
|
+
* @returns A new sketch holding both key sets.
|
|
97
|
+
* @throws {@link ParamError} if the seeds differ, since the two would have
|
|
98
|
+
* sent the same key to different registers and the merge would mean nothing.
|
|
99
|
+
*/
|
|
100
|
+
union(other: HyperLogLog): HyperLogLog;
|
|
101
|
+
/**
|
|
102
|
+
* Whether two sketches hold the same registers at the same precision and
|
|
103
|
+
* seed. Which representation each is in does not enter into it.
|
|
104
|
+
*
|
|
105
|
+
* @param other - The sketch to compare against.
|
|
106
|
+
* @returns `true` if the two would answer every query identically.
|
|
107
|
+
*/
|
|
108
|
+
equals(other: HyperLogLog): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Counts how many distinct keys have been added. Below a few thousand
|
|
111
|
+
* distinct keys the answer is exact; above that, and once the sketch has
|
|
112
|
+
* gone dense, it estimates within {@link standardError}.
|
|
113
|
+
*
|
|
114
|
+
* @returns The cardinality, a whole number; `0` for an empty sketch.
|
|
115
|
+
*/
|
|
116
|
+
count(): number;
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { BadMagicError, ChecksumError, type FilterJSON, type HllParams, type HllSizing, HyperLogLog, ParamError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, hllSizing };
|