33 #if !(defined TRNG_NORMAL_DIST_HPP)
35 #define TRNG_NORMAL_DIST_HPP
37 #include <trng/cuda.hpp>
38 #include <trng/constants.hpp>
39 #include <trng/limits.hpp>
40 #include <trng/utility.hpp>
41 #include <trng/math.hpp>
42 #include <trng/special_functions.hpp>
51 template<
typename float_t =
double>
54 using result_type = float_t;
58 result_type mu_{0}, sigma_{1};
62 result_type mu()
const {
return mu_; }
64 void mu(result_type mu_new) { mu_ = mu_new; }
66 result_type sigma()
const {
return sigma_; }
68 void sigma(result_type sigma_new) { sigma_ = sigma_new; }
72 explicit param_type(result_type mu, result_type sigma) : mu_{mu}, sigma_{sigma} {}
77 friend TRNG_CUDA_ENABLE
inline bool operator==(
const param_type &P1,
79 return P1.mu_ == P2.mu_ and P1.sigma_ == P2.sigma_;
82 friend TRNG_CUDA_ENABLE
inline bool operator!=(
const param_type &P1,
90 template<
typename char_t,
typename traits_t>
91 friend std::basic_ostream<char_t, traits_t> &operator<<(
92 std::basic_ostream<char_t, traits_t> &out,
const param_type &P) {
93 std::ios_base::fmtflags flags(out.flags());
94 out.flags(std::ios_base::dec | std::ios_base::fixed | std::ios_base::left);
95 out <<
'(' << std::setprecision(math::numeric_limits<float_t>::digits10 + 1) << P.mu()
96 <<
' ' << P.sigma() <<
')';
101 template<
typename char_t,
typename traits_t>
102 friend std::basic_istream<char_t, traits_t> &operator>>(
103 std::basic_istream<char_t, traits_t> &in,
param_type &P) {
105 std::ios_base::fmtflags flags(in.flags());
106 in.flags(std::ios_base::dec | std::ios_base::fixed | std::ios_base::left);
107 in >> utility::delim(
'(') >> mu >> utility::delim(
' ') >> sigma >> utility::delim(
')');
121 explicit normal_dist(result_type mu, result_type sigma) : P{mu, sigma} {}
123 explicit normal_dist(
const param_type &P) : P{P} {}
129 TRNG_CUDA_ENABLE result_type operator()(R &r) {
130 return icdf(utility::uniformoo<result_type>(r));
133 TRNG_CUDA_ENABLE result_type operator()(R &r,
const param_type &P) {
139 result_type min()
const {
return -math::numeric_limits<result_type>::infinity(); }
141 result_type max()
const {
return math::numeric_limits<result_type>::infinity(); }
143 const param_type ¶m()
const {
return P; }
145 void param(
const param_type &P_new) { P = P_new; }
147 result_type mu()
const {
return P.mu(); }
149 void mu(result_type mu_new) { P.mu(mu_new); }
151 result_type sigma()
const {
return P.sigma(); }
153 void sigma(result_type sigma_new) { P.sigma(sigma_new); }
156 result_type pdf(result_type x)
const {
157 const result_type t{x - P.mu()};
158 return math::constants<result_type>::one_over_sqrt_2pi / P.sigma() *
159 math::exp(t * t / (-2 * P.sigma() * P.sigma()));
163 result_type cdf(result_type x)
const {
170 result_type icdf(result_type x)
const {
return math::inv_Phi(x) * P.sigma() + P.mu(); }
176 template<
typename float_t>
177 TRNG_CUDA_ENABLE
inline bool operator==(
const normal_dist<float_t> &g1,
178 const normal_dist<float_t> &g2) {
179 return g1.param() == g2.param();
182 template<
typename float_t>
183 TRNG_CUDA_ENABLE
inline bool operator!=(
const normal_dist<float_t> &g1,
184 const normal_dist<float_t> &g2) {
185 return g1.param() != g2.param();
189 template<
typename char_t,
typename traits_t,
typename float_t>
190 std::basic_ostream<char_t, traits_t> &operator<<(std::basic_ostream<char_t, traits_t> &out,
191 const normal_dist<float_t> &g) {
192 std::ios_base::fmtflags flags(out.flags());
193 out.flags(std::ios_base::dec | std::ios_base::fixed | std::ios_base::left);
194 out <<
"[normal " << g.param() <<
']';
199 template<
typename char_t,
typename traits_t,
typename float_t>
200 std::basic_istream<char_t, traits_t> &operator>>(std::basic_istream<char_t, traits_t> &in,
201 normal_dist<float_t> &g) {
202 typename normal_dist<float_t>::param_type p;
203 std::ios_base::fmtflags flags(in.flags());
204 in.flags(std::ios_base::dec | std::ios_base::fixed | std::ios_base::left);
205 in >> utility::ignore_spaces() >> utility::delim(
"[normal ") >> p >> utility::delim(
']');
Definition: normal_dist.hpp:56
Definition: normal_dist.hpp:52