13 #if !defined(RANDOMLIB_MPFRNORMALR_HPP)
14 #define RANDOMLIB_MPFRNORMALR_HPP 1
20 #define HAVE_MPFR (MPFR_VERSION_MAJOR >= 3)
22 #if HAVE_MPFR || defined(DOXYGEN)
48 static const long chunk_ = 32;
49 static const unsigned long m = 3684067834;
58 mpfr_init2(_eps, chunk_);
59 mpfr_init2(_u, chunk_);
60 mpfr_init2(_v, chunk_);
61 mpfr_init2(_up, chunk_);
62 mpfr_init2(_vp, chunk_);
63 mpfr_init2(_vx, chunk_);
64 mpfr_init2(_x1, chunk_);
65 mpfr_init2(_x2, chunk_);
91 int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round)
const {
101 scale = std::pow(2.0, -chunk_);
104 mpz_urandomb(_vi, r, chunk_);
105 if (mpz_cmp_ui(_vi, m) >= 0)
continue;
106 double vf = (mpz_get_ui(_vi) + 0.5) * scale;
107 mpz_urandomb(_ui, r, chunk_);
108 double uf = (mpz_get_ui(_ui) + 0.5) * scale;
112 Q = x*x + y * (a*y - b*x);
113 if (Q >= r2)
continue;
114 mpfr_set_ui_2exp(_eps, 1u, -chunk_, MPFR_RNDN);
115 mpfr_prec_t prec = chunk_;
116 mpfr_set_prec(_u, prec);
117 mpfr_set_prec(_v, prec);
119 mpfr_set_z_2exp(_u, _ui, -prec, MPFR_RNDN);
120 mpfr_set_z_2exp(_v, _vi, -prec, MPFR_RNDN);
121 mpfr_set_prec(_up, prec);
122 mpfr_set_prec(_vp, prec);
124 mpfr_add(_up, _u, _eps, MPFR_RNDN);
125 mpfr_add(_vp, _v, _eps, MPFR_RNDN);
128 mpfr_prec_t prec_guard = 3 + chunk_ -
129 (std::max)(mpz_sizeinbase(_ui, 2), mpz_sizeinbase(_vi, 2));
139 reject = Reject(_u, _vp, prec, MPFR_RNDU);
141 reject = Reject(_up, _vp, prec, MPFR_RNDU);
143 mpfr_set_prec(_vx, prec);
144 mpfr_add(_vx, _vp, _eps, MPFR_RNDN);
145 reject = Reject(_u, _vx, prec, MPFR_RNDU);
147 if (reject < 0)
break;
151 reject = Reject(_up, _v, prec, MPFR_RNDD);
153 reject = Reject(_u, _v, prec, MPFR_RNDD);
155 mpfr_sub(_vx, _v, _eps, MPFR_RNDN);
156 reject = Reject(_u, _vx, prec, MPFR_RNDD);
158 if (reject > 0)
break;
160 prec = Refine(r, prec);
162 if (reject > 0)
continue;
165 mpfr_prec_t prec0 = mpfr_get_prec (val);
167 if (prec < prec0 + prec_guard)
168 prec = Refine(r, prec,
169 (prec0 + prec_guard - prec + chunk_ - 1) / chunk_);
170 mpfr_set_prec(_x1, prec0);
171 mpfr_set_prec(_x2, prec0);
175 f1 = mpfr_div(_x1, _v, _up, round),
176 f2 = mpfr_div(_x2, _vp, _u, round);
177 if (f1 == f2 && mpfr_equal_p(_x1, _x2)) {
181 prec = Refine(r, prec);
183 mpz_urandomb(_ui, r, 1);
184 if (mpz_tstbit(_ui, 0)) {
186 mpfr_neg(val, _x1, MPFR_RNDN);
188 mpfr_set(val, _x1, MPFR_RNDN);
198 mpfr_prec_t Refine(gmp_randstate_t r, mpfr_prec_t prec,
long num = 1)
200 if (num <= 0)
return prec;
202 prec += num * chunk_;
203 mpfr_div_2ui(_eps, _eps, num * chunk_, MPFR_RNDN);
205 mpz_urandomb(_ui, r, num * chunk_);
206 mpfr_set_prec(_up, prec);
207 mpfr_set_z_2exp(_up, _ui, -prec, MPFR_RNDN);
208 mpfr_set_prec(_vx, prec);
209 mpfr_add(_vx, _u, _up, MPFR_RNDN);
211 mpfr_add(_up, _u, _eps, MPFR_RNDN);
213 mpz_urandomb(_vi, r, num * chunk_);
214 mpfr_set_prec(_vp, prec);
215 mpfr_set_z_2exp(_vp, _vi, -prec, MPFR_RNDN);
216 mpfr_set_prec(_vx, prec);
217 mpfr_add(_vx, _v, _vp, MPFR_RNDN);
219 mpfr_add(_vp, _v, _eps, MPFR_RNDN);
224 int Reject(mpfr_t u, mpfr_t v, mpfr_prec_t prec, mpfr_rnd_t round)
const {
226 mpfr_set_prec(_x1, prec);
228 mpfr_log(_x1, u, round);
229 mpfr_mul(_x1, _x1, u, round);
230 mpfr_mul(_x1, _x1, u, round);
231 mpfr_mul_2ui(_x1, _x1, 2u, round);
233 mpfr_set_prec(_x2, prec);
234 mpfr_mul(_x2, v, v, round);
236 mpfr_add(_x1, _x1, _x2, round);
238 return mpfr_sgn(_x1);
255 #endif // RANDOMLIB_MPFRNORMALR_HPP
int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const
The normal distribution for MPFR (ratio method).