Warning, file /include/celeritas/random/distribution/GammaDistribution.hh was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include <cmath>
0011
0012 #include "corecel/Assert.hh"
0013 #include "corecel/Macros.hh"
0014 #include "corecel/Types.hh"
0015 #include "corecel/math/Algorithms.hh"
0016 #include "celeritas/Constants.hh"
0017
0018 #include "NormalDistribution.hh"
0019
0020 namespace celeritas
0021 {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template<class RealType = ::celeritas::real_type>
0047 class GammaDistribution
0048 {
0049 public:
0050
0051
0052 using real_type = RealType;
0053 using result_type = real_type;
0054
0055
0056 public:
0057
0058 explicit inline CELER_FUNCTION
0059 GammaDistribution(real_type alpha = 1, real_type beta = 1);
0060
0061
0062 template<class Generator>
0063 inline CELER_FUNCTION result_type operator()(Generator& rng);
0064
0065 private:
0066 real_type const alpha_;
0067 real_type const beta_;
0068 real_type const alpha_p_;
0069 real_type const d_;
0070 real_type const c_;
0071 NormalDistribution<real_type> sample_normal_;
0072 };
0073
0074
0075
0076
0077
0078
0079
0080 template<class RealType>
0081 CELER_FUNCTION
0082 GammaDistribution<RealType>::GammaDistribution(real_type alpha, real_type beta)
0083 : alpha_(alpha)
0084 , beta_(beta)
0085 , alpha_p_(alpha < 1 ? alpha + 1 : alpha)
0086 , d_(alpha_p_ - real_type(1) / 3)
0087 , c_(celeritas::rsqrt(9 * d_))
0088 {
0089 CELER_EXPECT(alpha_ > 0);
0090 CELER_EXPECT(beta_ > 0);
0091 }
0092
0093
0094
0095
0096
0097 template<class RealType>
0098 template<class Generator>
0099 CELER_FUNCTION auto
0100 GammaDistribution<RealType>::operator()(Generator& rng) -> result_type
0101 {
0102 real_type u, v, z;
0103 do
0104 {
0105 do
0106 {
0107 z = sample_normal_(rng);
0108 v = 1 + c_ * z;
0109 } while (v <= 0);
0110 v = ipow<3>(v);
0111 u = generate_canonical<real_type>(rng);
0112 } while (u > 1 - real_type(0.0331) * ipow<4>(z)
0113 && std::log(u) > real_type(0.5) * ipow<2>(z)
0114 + d_ * (1 - v + std::log(v)));
0115
0116 result_type result = d_ * v * beta_;
0117 if (alpha_ != alpha_p_)
0118 result *= fastpow(generate_canonical<real_type>(rng), 1 / alpha_);
0119 return result;
0120 }
0121
0122
0123 }