vardef normaldeviate = save u, v, xa; forever: u := 1 - uniformdeviate 63/64; v := sqrt(8/mexp(256)) * (-1/2 + uniformdeviate 1); xa := v / u; exitif (xa * xa <= -mlog(u)/64); endfor xa enddef; vardef exponentialdeviate expr mu = save u; u = 1 - uniformdeviate 1; % hence 0 < u <= 1 and so you avoid -mu * 1/256 mlog(u) % the danger of calling mlog(0) enddef; vardef tand(expr theta) = save x, y; (x, y) = dir theta; if abs(x) < eps: infinity else: y/x fi enddef; vardef exp(expr x) = mexp(256x) enddef; vardef log(expr x) = 1/256 mlog(x) enddef; % this is defined only for a > 1 vardef gammadeviate(expr a, b) = save y, x, v, s, accept; boolean accept; s = sqrt(2a - 1); forever: forever: y := tand(uniformdeviate 180); exitif abs(y) < 16; endfor x := s * y + a - 1; accept := false; if x > 0: v := uniformdeviate 1; if v <= (1 + y * y) * exp((a - 1) * log(x / (a - 1)) - s * y): accept := true; fi fi exitif accept; endfor x/b enddef;