/*
 * Copyright (C) 1994. James Darrell McCauley.  (darrell@mccauley-usa.com)
 *                                              http://mccauley-usa.com/
 *
 * This program is free software under the GPL (>=v2)
 * Read the file GPL.TXT coming with GRASS for details.
 */

#include <stdio.h>
#include <math.h>
#include "zufall.h"

/*-Poisson generator for distribution function of p's:
 * q(mu,p) = exp(-mu) mu**p/p!
 */

int fische(int n, double *mu, int *p)
{
    int left, indx[1024], i, k, nsegs, p0, ii, jj, nl0;
    double q[1024], u[1024], q0, pmu;

    --p;

    if (n <= 0)
        return 0;

    pmu = exp(-(*mu));
    p0 = 0;

    nsegs = (n - 1) / 1024;
    left = n - (nsegs << 10);
    ++nsegs;
    nl0 = left;

    for (k = 1; k <= nsegs; ++k) {
        for (i = 1; i <= left; ++i) {
            indx[i - 1] = i;
            p[p0 + i] = 0;
            q[i - 1] = 1.0;
        }

        do {                 /* Begin iterative loop on segment of p's */
            zufall(left, u); /* Get the needed uniforms */
            jj = 0;

            for (i = 1; i <= left; ++i) {
                ii = indx[i - 1];
                q0 = q[ii - 1] * u[i - 1];
                q[ii - 1] = q0;
                if (q0 > pmu) {
                    indx[jj++] = ii;
                    ++p[p0 + ii];
                }
            }
            left = jj; /* any left in this segment? */
        } while (left > 0);

        p0 += nl0;
        nl0 = left = 1024;
    }
    return 0;
} /* fische */
