real pickdist(real eta, real sigma) { static real eta0 = -1.0, sigcorr; int niter; real x, y, q; if (eta != eta0) { sigcorr = rsqrt(8 * eta / (bessel_K(0.75, 1/(32*eta)) / bessel_K(0.25, 1/(32*eta)) - 1)); eprintf("[%s: sigma correction factor = %f]\n", getargv0(), sigcorr); eta0 = eta; } niter = 0; do { x = xrandom(-1.0, 1.0); y = xrandom(0.0, YMAX); q = rexp(- 0.5 * rsqr(fmap(x)) - eta * rsqr(rsqr(fmap(x)))) * (1 + x*x) / rsqr(1 - x*x); if (q > YMAX) /* should not ever happen */ error("%s: guess out of bounds\n x = %f q = %f > %f\n", getargv0(), x, q, YMAX); niter++; if (niter > 1000) error("%s: 1000 iterations without success\n", getargv0()); } while (y > q || x*x == 1); /* 2nd test prevents infty */ return (sigcorr * sigma * fmap(x)); }
double bessel_Knu(double alpha, double x) { long nb, ncalc, ize; double *bk; ize = (long) 1; if (alpha < 0) alpha = -alpha; nb = 1 + (long) floor(alpha); /* nb-1 <= |alpha| < nb */ alpha -= (nb - 1); bk = (double *) calloc(nb, sizeof(double)); bessel_K(&x, &alpha, &nb, &ize, bk, &ncalc); x = bk[nb - 1]; free(bk); return x; }