BlockNumber
BlockSampler_Next(BlockSampler bs)
{
BlockNumber K = bs->N - bs->t; /* remaining blocks */ int k = bs->n - bs->m; /* blocks still to sample */ double p; /* probability to skip block */ double V; /* random */
Assert(BlockSampler_HasMore(bs)); /* hence K > 0 and k > 0 */
if ((BlockNumber) k >= K)
{ /* need all the rest */
bs->m++; return bs->t++;
}
/*---------- *ItisnotobviousthatthiscodematchesKnuth'sAlgorithmS. *Knuthsaystoskipthecurrentblockwithprobability1-k/K. *Ifwearetoskip,weshouldadvancet(hencedecreaseK),and *repeatthesameprobabilistictestforthenextblock.Thenaive *implementationthusrequiresasampler_random_fract()callforeach *blocknumber.Butwecanreducethistoonesampler_random_fract() *callperselectedblock,bynotingthateachtimethewhile-test *succeeds,wecanreinterpretVasauniformrandomnumberintherange *0top.Therefore,insteadofchoosinganewV,wejustadjustptobe *theappropriatefractionofitsformervalue,andournextloop *makestheappropriateprobabilistictest. * *WehaveinitiallyK>k>0.IftheloopreducesKtoequalk, *thenextwhile-testmustfailsincepwillbecomeexactlyzero *(weassumetherewillnotberoundofferrorinthedivision). *(Note:Knuthsuggestsa"<="loopcondition,butweuse"<"just *tobedoublysureaboutroundofferror.)ThereforeKcannotbecome *lessthank,whichmeansthatwecannotfailtoselectenoughblocks. *----------
*/
V = sampler_random_fract(&bs->randstate);
p = 1.0 - (double) k / (double) K; while (V < p)
{ /* skip */
bs->t++;
K--; /* keep K == N - t */
/* adjust p to be new cutoff point in reduced range */
p *= 1.0 - (double) k / (double) K;
}
/* Initial value of W (for use when Algorithm Z is first applied) */
rs->W = exp(-log(sampler_random_fract(&rs->randstate)) / n);
}
double
reservoir_get_next_S(ReservoirState rs, double t, int n)
{ double S;
/* The magic constant here is T from Vitter's paper */ if (t <= (22.0 * n))
{ /* Process records using Algorithm X until t is large enough */ double V,
quot;
V = sampler_random_fract(&rs->randstate); /* Generate V */
S = 0;
t += 1; /* Note: "num" in Vitter's code is always equal to t - n */
quot = (t - (double) n) / t; /* Find min S satisfying (4.1) */ while (quot > V)
{
S += 1;
t += 1;
quot *= (t - (double) n) / t;
}
} else
{ /* Now apply Algorithm Z */ double W = rs->W; double term = t - (double) n + 1;
for (;;)
{ double numer,
numer_lim,
denom; double U,
X,
lhs,
rhs,
y,
tmp;
/* Generate U and X */
U = sampler_random_fract(&rs->randstate);
X = t * (W - 1.0);
S = floor(X); /* S is tentatively set to floor(X) */ /* Test if U <= h(S)/cg(X) in the manner of (6.3) */
tmp = (t + 1) / term;
lhs = exp(log(((U * tmp * tmp) * (term + S)) / (t + X)) / n);
rhs = (((t + X) / (term + S)) * term) / t; if (lhs <= rhs)
{
W = rhs / lhs; break;
} /* Test if U <= f(S)/cg(X) */
y = (((U * (t + 1)) / term) * (t + S + 1)) / (t + X); if ((double) n < S)
{
denom = t;
numer_lim = term + S;
} else
{
denom = t - (double) n + S;
numer_lim = t + 1;
} for (numer = t + S; numer >= numer_lim; numer -= 1)
{
y *= numer / denom;
denom -= 1;
}
W = exp(-log(sampler_random_fract(&rs->randstate)) / n); /* Generate W in advance */ if (exp(log(y) / n) <= (t + X) / t) break;
}
rs->W = W;
} return S;
}
/* Select a random value R uniformly distributed in (0 - 1) */ double
sampler_random_fract(pg_prng_state *randstate)
{ double res;
/* pg_prng_double returns a value in [0.0 - 1.0), so we must reject 0.0 */ do
{
res = pg_prng_double(randstate);
} while (unlikely(res == 0.0)); return res;
}
double
anl_random_fract(void)
{ /* initialize if first time through */ if (unlikely(!oldrs_initialized))
{
sampler_random_init_state(pg_prng_uint32(&pg_global_prng_state),
&oldrs.randstate);
oldrs_initialized = true;
}
/* and compute a random fraction */ return sampler_random_fract(&oldrs.randstate);
}
double
anl_init_selection_state(int n)
{ /* initialize if first time through */ if (unlikely(!oldrs_initialized))
{
sampler_random_init_state(pg_prng_uint32(&pg_global_prng_state),
&oldrs.randstate);
oldrs_initialized = true;
}
/* Initial value of W (for use when Algorithm Z is first applied) */ return exp(-log(sampler_random_fract(&oldrs.randstate)) / n);
}
double
anl_get_next_S(double t, int n, double *stateptr)
{ double result;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.