in Standard/src/Emulation/Math.cs [115:230]
private long SampleUsingBTPE()
{
// The following code is ported from NumPy's binomial
// sampling implementation.
double r,q,fm,p1,xm,xl,xr,c,laml,lamr,p2,p3,p4;
double a,u,v,s,F,rho,t,A,nrq,x1,x2,f1,f2,z,z2,w,w2,x;
long m,y,k,i;
/* initialize */
r = Min(SuccessProbability, FailureProbability);
q = 1.0 - r;
fm = NSamples * r + r;
m = (long)Floor(fm);
p1 = Floor(2.195 * Sqrt(NSamples * r * q) - 4.6 * q) + 0.5;
xm = m + 0.5;
xl = xm - p1;
xr = xm + p1;
c = 0.134 + 20.5/(15.3 + m);
a = (fm - xl)/(fm-xl*r);
laml = a*(1.0 + a/2.0);
a = (xr - fm)/(xr*q);
lamr = a*(1.0 + a/2.0);
p2 = p1*(1.0 + 2.0*c);
p3 = p2 + c/laml;
p4 = p3 + c/lamr;
/* sigh ... */
Step10:
nrq = NSamples * r * q;
u = RandomState.NextDouble() * p4;
v = RandomState.NextDouble();
if (u > p1) goto Step20;
y = (long)Floor(xm - p1*v + u);
goto Step60;
Step20:
if (u > p2) goto Step30;
x = xl + (u - p1)/c;
v = v*c + 1.0 - Abs(m - x + 0.5)/p1;
if (v > 1.0) goto Step10;
y = (long)Floor(x);
goto Step50;
Step30:
if (u > p3) goto Step40;
y = (long)Floor(xl + Log(v)/laml);
/* Reject if v == 0.0 since cast of inf not well defined */
if ((y < 0) || (v == 0.0)) goto Step10;
v = v*(u-p2)*laml;
goto Step50;
Step40:
y = (long)Floor(xr - Log(v)/lamr);
/* Reject if v == 0.0 since cast of inf not well defined */
if ((y > NSamples) || (v == 0.0)) goto Step10;
v = v*(u-p3)*lamr;
Step50:
k = Abs(y - m);
if ((k > 20) && (k < ((nrq)/2.0 - 1))) goto Step52;
s = r/q;
a = s*(NSamples+1);
F = 1.0;
if (m < y)
{
for (i=m+1; i<=y; i++)
{
F *= (a/i - s);
}
}
else if (m > y)
{
for (i=y+1; i<=m; i++)
{
F /= (a/i - s);
}
}
if (v > F) goto Step10;
goto Step60;
Step52:
rho = (k/(nrq))*((k*(k/3.0 + 0.625) + 0.16666666666666666)/nrq + 0.5);
t = -k*k/(2*nrq); // lgtm [cs/loss-of-precision]
A = Log(v);
if (A < (t - rho)) goto Step60;
if (A > (t + rho)) goto Step10;
x1 = y+1;
f1 = m+1;
z = NSamples + 1-m;
w = NSamples - y+1;
x2 = x1*x1;
f2 = f1*f1;
z2 = z*z;
w2 = w*w;
if (A > (xm*Log(f1/x1)
+ (NSamples - m+0.5)*Log(z/w)
+ (y-m)*Log(w*r/(x1*q))
+ (13680.0-(462.0-(132.0-(99.0-140.0/f2)/f2)/f2)/f2)/f1/166320.0
+ (13680.0-(462.0-(132.0-(99.0-140.0/z2)/z2)/z2)/z2)/z/166320.0
+ (13680.0-(462.0-(132.0-(99.0-140.0/x2)/x2)/x2)/x2)/x1/166320.0
+ (13680.0-(462.0-(132.0-(99.0-140.0/w2)/w2)/w2)/w2)/w/166320.0))
{
goto Step10;
}
Step60:
if (SuccessProbability > 0.5)
{
y = NSamples - y;
}
return y;
}