Back to Exponential-distributed random numbers
#ifndef PASTELSYS_RANDOM_EXPONENTIAL_HPP
#define PASTELSYS_RANDOM_EXPONENTIAL_HPP
#include "pastel/sys/random/random_exponential.h"
#include "pastel/sys/random/random_uniform.h"
#include <cmath>
namespace Pastel
{
template <typename Real>
Real randomExponential()
{
/*
The probability density distribution of the
exponential distribution is
p(x) = a e^(-ax), for x >= 0
0 , for x < 0
where a > 0.
Its cumulative distribution is easy to derive:
for x < 0:
c(x) = 0
for x >= 0:
c(x) = int[t = 0..x] p(t) dt
= int[t = 0..x] a e^(-at) dt
= -[t = 0..x] e^(-at) dt
= -(e^(-ax) - 1)
= 1 - e^(-ax)
(For a check, c(oo) = 1)
Thus, the inverse of the cdf (for x >= 0) is
derived by:
t = 1 - e^(-ax)
<=>
1 - t = e^(-ax)
<=>
ln(1 - t) = -ax
<=>
x = -ln(1 - t) / a
So if we pick t a uniform random number in [0, 1[,
then -ln(1 - t) / a is exponentially distributed.
We simplify this further as follows. First, if t is
uniformly distributed in [0, 1[, then 1 - t is
uniformly distributed in ]0, 1].
Second, we can assume a = 1 without loss of
generality and let the user do the scaling
if needed. This improves performance.
*/
return -std::log(randomOpen0<Real>());
}
template <typename Real>
Real randomExponential(
const NoDeduction<Real>& mean)
{
PENSURE_OP(mean, >, 0);
return Pastel::randomExponential<Real>() / mean;
}
template <typename Real, integer N>
Vector<Real, N> randomExponentialVector()
{
PASTEL_STATIC_ASSERT(N != Dynamic);
return Pastel::randomExponentialVector<Real, N>(N);
}
template <typename Real, integer N>
Vector<Real, N> randomExponentialVector(
integer dimension)
{
PENSURE_OP(dimension, >=, 0);
Vector<Real, N> result(ofDimension(dimension));
for (integer i = 0;i < dimension;++i)
{
result[i] = randomExponential<Real>();
}
return result;
}
template <typename Real>
Real exponentialPdf(
const NoDeduction<Real>& x)
{
if (x < 0)
{
return 0;
}
return std::exp(-x);
}
template <typename Real>
Real exponentialPdf(
const NoDeduction<Real>& x,
const NoDeduction<Real>& mean)
{
PENSURE_OP(mean, >, 0);
if (x < 0)
{
return 0;
}
return mean * std::exp(-mean * x);
}
}
#endif