Program Listing for File callbacks.hpp

Return to documentation for file (fwdpp/extensions/callbacks.hpp)

#ifndef __FWDPP_EXTENSIONS_CALLBACKS_HPP__
#define __FWDPP_EXTENSIONS_CALLBACKS_HPP__

#include <gsl/gsl_randist.h>
#include <functional>
#include <stdexcept>
#include <cmath>

namespace fwdpp
{

    namespace extensions
    {

        struct shmodel
        {
            std::function<double(const gsl_rng *)> s, h;
            shmodel() = default;
            shmodel(std::function<double(const gsl_rng *)> sfxn,
                    std::function<double(const gsl_rng *)> hfxn)
                : s(std::move(sfxn)), h(std::move(hfxn))
            {
            }
        };

        struct constant
        {
            const double x;
            constant(const double &__x) : x(__x)
            {
                if (!std::isfinite(x))
                    {
                        throw std::invalid_argument("value must be finite");
                    }
            }
            inline double
            operator()(const gsl_rng *) const
            {
                return x;
            }
        };

        struct exponential
        {
            const double mean;
            exponential(const double &m) : mean(m)
            {
                if (!std::isfinite(mean))
                    {
                        throw std::invalid_argument("mean must be finite");
                    }
                if (mean == 0.)
                    {
                        throw std::invalid_argument("mean must not equal 0");
                    }
            }
            inline double
            operator()(const gsl_rng *r) const
            {
                return gsl_ran_exponential(r, mean);
            }
        };

        struct uniform
        {
            const double mn, mx;
            uniform(const double &__mn, const double &__mx)
                : mn(__mn), mx(__mx)
            {
                if (!std::isfinite(mn) || !std::isfinite(mx))
                    {
                        throw std::invalid_argument(
                            "min and max of range must both be finite");
                    }
                if (mn > mx)
                    {
                        throw std::invalid_argument("min must be <= max");
                    }
            }
            inline double
            operator()(const gsl_rng *r) const
            {
                return gsl_ran_flat(r, mn, mx);
            }
        };

        struct beta
        {
            const double a, b, factor;
            beta(const double &__a, const double &__b, const double &__f = 1)
                : a(__a), b(__b), factor(__f)
            {
                if (!std::isfinite(a) || a <= 0.)
                    {
                        throw std::invalid_argument("a must be > 0.");
                    }
                if (!std::isfinite(b) || b <= 0.)
                    {
                        throw std::invalid_argument("b must be > 0.");
                    }
                if (!std::isfinite(factor) || !(factor > 0.))
                    {
                        throw std::invalid_argument(
                            "scaling factor must be finite and > 0");
                    }
            }
            inline double
            operator()(const gsl_rng *r) const
            {
                return factor * gsl_ran_beta(r, a, b);
            }
        };

        struct gaussian
        {
            const double sd;
            gaussian(const double &__sd) : sd(__sd)
            {
                if (!(sd > 0.))
                    throw std::invalid_argument("sd must be > 0");
                if (!std::isfinite(sd))
                    throw std::invalid_argument("sd must be finite");
            }
            inline double
            operator()(const gsl_rng *r) const
            {
                return gsl_ran_gaussian_ziggurat(r, sd);
            }
        };

        struct gamma
        {
            const double mean, shape;
            gamma(const double &__m, const double &__s) : mean(__m), shape(__s)
            {
                if (!std::isfinite(mean) || !std::isfinite(shape))
                    {
                        throw std::invalid_argument(
                            "mean and shape must both be finite");
                    }
                if (!(shape > 0))
                    {
                        throw std::invalid_argument("shape must be > 0");
                    }
            }
            inline double
            operator()(const gsl_rng *r) const
            {
                return gsl_ran_gamma(r, shape, mean / shape);
            }
        };
    }
}
#endif