random_geometric.hpp

Back to Geometrically-distributed random numbers

pastel/sys/random/

#ifndef PASTELSYS_RANDOM_GEOMETRIC_HPP
#define PASTELSYS_RANDOM_GEOMETRIC_HPP

#include "pastel/sys/random/random_geometric.h"
#include "pastel/sys/random/random_uniform.h"

#include <cmath>

namespace Pastel
{

    template <typename Real>
    integer randomGeometric(
        const NoDeduction<Real>& success)
    {
        PENSURE(success > 0);
        PENSURE(success < 1);

        // Generates an exponentially distributed
        // random number, and rounds it down.
        return std::log(randomOpen0<Real>()) / 
            std::log(1 - success);
    }

    template <typename Real>
    Real geometricPdf(
        const NoDeduction<Real>& k,
        const NoDeduction<Real>& success)
    {
        PENSURE(k >= 0);
        PENSURE(success > 0);
        PENSURE(success < 1);

        // The probability of having a k consecutive
        // failures before the first success in a
        // Bernoulli process is 
        //
        //     P(X = k) = (1 - p)^k p.

        // Note that when success is either 0 or 1,
        // P is not a probability mass function.

        return std::pow(1 - success, k) * success;
    }

    template <typename Real>
    Real geometricCdf(
        const NoDeduction<Real>& k,
        const NoDeduction<Real>& success)
    {
        PENSURE(k >= 0);
        PENSURE(success > 0);
        PENSURE(success < 1);

        // The probability of having at most k
        // consecutive failures before the first
        // success in a Bernoulli process is
        //
        //   P(X <= k)
        //   = sum_{i = 0}^k P(X = i)
        //   = sum_{i = 0}^k (1 - p)^i p
        //   = p sum_{i = 0}^k (1 - p)^i
        //   = p (1 - (1 - p)^{k + 1}) / (1 - (1 - p))
        //   = 1 - (1 - p)^{k + 1}.

        return 1 - std::pow(1 - success, k + 1);
    }

}

#endif