1/**
2 * The reference-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
19}
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 post({ type: 'progress', pastIndex: i, repsDone: 0, reps: REPS_PER_PAST })
31 const value = estimateOnePast(kernel, sigma, past, pastSeed(seed, i), repsDone =>
32 post({ type: 'progress', pastIndex: i, repsDone, reps: REPS_PER_PAST }),
33 )
34 post({ type: 'past', pastIndex: i, value })
35 }
36}