/ concept-collection / timeseries-compressibility
Sign in
concept-collection / timeseries-compressibility
timeseries-compressibility / src / worker / entropyWorker.ts
38 lines · 1.5 KBBlameHistoryRaw
1/**
2 * The entropy-rate estimator off the main thread: one message starts an
3 * endless refinement loop that posts one unbiased value per completed past
4 * (with per-rep progress in between). Stopping is worker termination — the
5 * loop never yields, but outgoing messages still flow, and per-past values
6 * already delivered survive on the main thread, so a later run resumes at
7 * startPast with the same derived seeds as an uninterrupted one.
8 */
9import { estimateOnePast, pastSeed, REPS_PER_PAST } from '../entropy'
11export interface EntropyRequest {
12 kernel: Float64Array
13 sigma: number
14 /** Conditioning window M. */
15 past: number
16 seed: number
17 /** Index of the first past to compute (count already done). */
18 startPast: number
21export type EntropyUpdate =
22 | { type: 'progress'; pastIndex: number; repsDone: number; reps: number }
23 | { type: 'past'; pastIndex: number; value: number }
25const post = self.postMessage as (message: EntropyUpdate) => void
27self.onmessage = (e: MessageEvent<EntropyRequest>) => {
28 const { kernel, sigma, past, seed, startPast } = e.data
29 for (let i = startPast; ; i++) {
30 // The rep count is only known once the past's mixing probe resolves the
31 // thinning; until the first onRep, report the thin=1 budget.
32 post({ type: 'progress', pastIndex: i, repsDone: 0, reps: REPS_PER_PAST })
33 const value = estimateOnePast(kernel, sigma, past, pastSeed(seed, i), (repsDone, reps) =>
34 post({ type: 'progress', pastIndex: i, repsDone, reps }),
35 )
36 post({ type: 'past', pastIndex: i, value })
37 }
moveopenescclose