random_generalizedgaussian.hpp

Back to Generalized-Gaussian-distributed random numbers

pastel/sys/random/

#ifndef   PASTELSYS_RANDOM_GENERALIZEDGAUSSIAN_HPP
#define PASTELSYS_RANDOM_GENERALIZEDGAUSSIAN_HPP

#include "pastel/sys/random/random_generalizedgaussian.h"
#include "pastel/sys/random/random_uniform.h"
#include "pastel/sys/random/random_gamma.h"

#include <cmath>

namespace Pastel
{

    template <typename Real>
    Real randomGeneralizedGaussian(
        const NoDeduction<Real>& shape)
    {
        PENSURE_OP(shape, >, 0);

        // See "Computer generation of the exponential power
        // distributions", Johnson, M. E., 
        // Journal of Statistical Computation and Simulation, 9,
        // pp. 239--240, 1979

        Real invShape = inverse(shape);
        Real x = std::pow(
            randomGamma<Real>(invShape), invShape);

        if (random<Real>() < 0.5)
        {
            return -x;
        }

        return x;
    }

    template <typename Real>
    Real randomGeneralizedGaussian(
        const NoDeduction<Real>& shape,
        const NoDeduction<Real>& scale)
    {
        return Pastel::randomGeneralizedGaussian<Real>(shape) * scale;
    }

    template <typename Real>
    Real varianceToGeneralizedGaussianScale(
        const NoDeduction<Real>& shape,
        const NoDeduction<Real>& variance)
    {
        PENSURE_OP(shape, >, 0);
        PENSURE_OP(variance, >=, 0);

        Real invShape = inverse(shape);

        return std::sqrt(variance * gamma<Real>(invShape) / 
            gamma<Real>(invShape * 3));
    }

    template <typename Real, integer N>
    Vector<Real, N> randomGeneralizedGaussianVector(
        const NoDeduction<Real>& shape, 
        const NoDeduction<Real>& scale)
    {
        PASTEL_STATIC_ASSERT(N != Dynamic);

        return Pastel::randomGeneralizedGaussianVector<Real, N>(
            N, shape, scale);
    }

    template <typename Real, integer N>
    Vector<Real, N> randomGeneralizedGaussianVector(
        integer dimension,
        const NoDeduction<Real>& shape, 
        const NoDeduction<Real>& scale)
    {
        PENSURE_OP(dimension, >=, 0);

        Vector<Real, N> result(ofDimension(dimension));
        for (integer i = 0;i < dimension;++i)
        {
            result[i] = randomGeneralizedGaussian<Real>(shape, scale);
        }

        return result;
    }

    template <typename Real>
    Real generalizedGaussianPdf(
        const NoDeduction<Real>& x,
        const NoDeduction<Real>& shape,
        const NoDeduction<Real>& scale)
    {
        PENSURE_OP(shape, >, 0);
        PENSURE_OP(scale, >=, 0);

        return (shape / (2 * scale * gamma<Real>(inverse(shape)))) *
            std::exp(-std::pow((std::abs(x / scale)), shape));
    }

    template <typename Real>
    Real generalizedGaussianPdf(
        const NoDeduction<Real>& x,
        const NoDeduction<Real>& shape)
    {
        PENSURE_OP(shape, >, 0);

        return (shape / (2 * gamma<Real>(inverse(shape)))) *
            std::exp(-std::pow((std::abs(x)), shape));
    }

}

#endif