|
23 | 23 | unsigned set_crossover_locations(const Seq& aj, const Seq& bj, const Real& z, unsigned int* crossover_locations) |
24 | 24 | { |
25 | 25 | BOOST_MATH_STD_USING |
| 26 | + using nothrow_policy = typename boost::math::policies::normalise<boost::math::policies::policy<>, boost::math::policies::rounding_error<boost::math::policies::ignore_error>>::type; |
26 | 27 | unsigned N_terms = 0; |
27 | 28 |
|
28 | 29 | if(aj.size() == 1 && bj.size() == 1) |
|
55 | 56 | Real t = (-sqrt(sq) - b + z) / 2; |
56 | 57 | if (t >= 0) |
57 | 58 | { |
58 | | - crossover_locations[N_terms] = itrunc(t); |
| 59 | + crossover_locations[N_terms] = itrunc(t, nothrow_policy()); |
59 | 60 | ++N_terms; |
60 | 61 | } |
61 | 62 | t = (sqrt(sq) - b + z) / 2; |
62 | 63 | if (t >= 0) |
63 | 64 | { |
64 | | - crossover_locations[N_terms] = itrunc(t); |
| 65 | + crossover_locations[N_terms] = itrunc(t, nothrow_policy()); |
65 | 66 | ++N_terms; |
66 | 67 | } |
67 | 68 | } |
|
71 | 72 | Real t = (-sqrt(sq) - b - z) / 2; |
72 | 73 | if (t >= 0) |
73 | 74 | { |
74 | | - crossover_locations[N_terms] = itrunc(t); |
| 75 | + crossover_locations[N_terms] = itrunc(t, nothrow_policy()); |
75 | 76 | ++N_terms; |
76 | 77 | } |
77 | 78 | t = (sqrt(sq) - b - z) / 2; |
78 | 79 | if (t >= 0) |
79 | 80 | { |
80 | | - crossover_locations[N_terms] = itrunc(t); |
| 81 | + crossover_locations[N_terms] = itrunc(t, nothrow_policy()); |
81 | 82 | ++N_terms; |
82 | 83 | } |
83 | 84 | } |
|
110 | 111 | unsigned n = 0; |
111 | 112 | for (auto bi = bj.begin(); bi != bj.end(); ++bi, ++n) |
112 | 113 | { |
113 | | - crossover_locations[n] = *bi >= 0 ? 0 : itrunc(-*bi) + 1; |
| 114 | + crossover_locations[n] = *bi >= 0 ? 0 : itrunc(-*bi, nothrow_policy()) + 1; |
114 | 115 | } |
115 | 116 | std::sort(crossover_locations, crossover_locations + bj.size(), std::less<Real>()); |
116 | 117 | N_terms = (unsigned)bj.size(); |
|
122 | 123 | std::pair<Real, Real> hypergeometric_pFq_checked_series_impl(const Seq& aj, const Seq& bj, const Real& z, const Policy& pol, const Terminal& termination, long long& log_scale) |
123 | 124 | { |
124 | 125 | BOOST_MATH_STD_USING |
| 126 | + using nothrow_policy = typename boost::math::policies::normalise<Policy, boost::math::policies::rounding_error<boost::math::policies::ignore_error>>::type; |
125 | 127 | Real result = 1; |
126 | 128 | Real abs_result = 1; |
127 | 129 | Real term = 1; |
128 | 130 | Real term0 = 0; |
129 | 131 | Real tol = boost::math::policies::get_epsilon<Real, Policy>(); |
130 | 132 | std::uintmax_t k = 0; |
131 | 133 | Real upper_limit(sqrt(boost::math::tools::max_value<Real>())), diff; |
| 134 | + if ((tools::max_value<Real>() / fabs(z) < upper_limit)) |
| 135 | + { |
| 136 | + upper_limit = tools::max_value<Real>() / fabs(z); |
| 137 | + } |
| 138 | + for (auto pa = aj.begin(); pa != aj.end(); ++pa) |
| 139 | + { |
| 140 | + if (tools::max_value<Real>() / fabs(*pa) < upper_limit) |
| 141 | + { |
| 142 | + upper_limit = tools::max_value<Real>() / fabs(*pa); |
| 143 | + } |
| 144 | + } |
132 | 145 | Real lower_limit(1 / upper_limit); |
133 | | - long long log_scaling_factor = lltrunc(boost::math::tools::log_max_value<Real>()) - 2; |
| 146 | + long long log_scaling_factor = lltrunc(boost::math::tools::log_max_value<Real>(), nothrow_policy()) - 2; |
134 | 147 | Real scaling_factor = exp(Real(log_scaling_factor)); |
135 | 148 | Real term_m1; |
136 | 149 | long long local_scaling = 0; |
|
234 | 247 | log_scale += log_scaling_factor; |
235 | 248 | local_scaling += log_scaling_factor; |
236 | 249 | } |
237 | | - if (fabs(abs_result) < lower_limit) |
| 250 | + /* |
| 251 | + * rescaling to avoid underflow is pointless here, given that the first term is 1. |
| 252 | + * |
| 253 | + else if ((fabs(abs_result) < lower_limit) && (fabs(abs_result) * scaling_factor < upper_limit)) |
238 | 254 | { |
239 | 255 | abs_result *= scaling_factor; |
240 | 256 | result *= scaling_factor; |
241 | 257 | term *= scaling_factor; |
242 | 258 | log_scale -= log_scaling_factor; |
243 | 259 | local_scaling -= log_scaling_factor; |
244 | 260 | } |
245 | | - |
| 261 | + */ |
246 | 262 | if ((abs(result * tol) > abs(term)) && (abs(term0) > abs(term))) |
247 | 263 | break; |
248 | 264 | if (abs_result * tol > abs(result)) |
|
321 | 337 | else |
322 | 338 | { |
323 | 339 | int ls = 1; |
324 | | - Real p = log_pochhammer(*ai, s, pol, &ls); |
| 340 | + Real p = log_pochhammer(static_cast<Real>(*ai), s, pol, &ls); |
325 | 341 | s1 *= ls; |
326 | 342 | term += p; |
327 | 343 | loop_error_scale = (std::max)(p, loop_error_scale); |
|
334 | 350 | for (auto bi = bj.begin(); bi != bj.end(); ++bi) |
335 | 351 | { |
336 | 352 | int ls = 1; |
337 | | - Real p = log_pochhammer(*bi, s, pol, &ls); |
| 353 | + Real p = log_pochhammer(static_cast<Real>(*bi), s, pol, &ls); |
338 | 354 | s2 *= ls; |
339 | 355 | term -= p; |
340 | 356 | loop_error_scale = (std::max)(p, loop_error_scale); |
|
371 | 387 | if (term <= tools::log_min_value<Real>()) |
372 | 388 | { |
373 | 389 | // rescale if we can: |
374 | | - long long scale = lltrunc(floor(term - tools::log_min_value<Real>()) - 2); |
| 390 | + long long scale = lltrunc(floor(term - tools::log_min_value<Real>()) - 2, nothrow_policy()); |
375 | 391 | term -= scale; |
376 | 392 | loop_scale += scale; |
377 | 393 | } |
378 | 394 | if (term > 10) |
379 | 395 | { |
380 | | - int scale = itrunc(floor(term)); |
| 396 | + long long scale = lltrunc(floor(term), nothrow_policy()); |
381 | 397 | term -= scale; |
382 | 398 | loop_scale += scale; |
383 | 399 | } |
|
402 | 418 | term /= scaling_factor; |
403 | 419 | loop_scale += log_scaling_factor; |
404 | 420 | } |
405 | | - if (fabs(loop_result) < lower_limit) |
| 421 | + else if ((fabs(loop_result) < lower_limit) && (fabs(loop_result) * scaling_factor < upper_limit)) |
406 | 422 | { |
407 | 423 | loop_result *= scaling_factor; |
408 | 424 | loop_abs_result *= scaling_factor; |
|
0 commit comments