diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index d73f3723b49..aff22a96c7e 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -144,6 +144,7 @@ struct Algebraic_structure_traits::digits-1 + // TODO: possibly return denormals sometimes... inline Interval_nt shift_positive_interval( const Interval_nt& intv, const int e ) { CGAL_assertion(intv.inf() > 0.0); @@ -157,6 +158,7 @@ namespace Boost_MP_internal { return CGAL::Interval_nt((limits::max)(), limits::infinity()); // intv is positive const double scale = std::ldexp(1.0, e); // ldexp call is exact + // TODO: multiply directly without using intervals return scale * intv; // cases that would require a rounding mode have been handled above } @@ -166,7 +168,7 @@ namespace Boost_MP_internal { typedef std::numeric_limits limits; const double inf = std::numeric_limits::infinity(); - if ( u!=l && (u==-inf || l==inf + if ( u!=l && (l==-inf || u==inf || (u==0 && l >= -(limits::min)()) || (l==0 && u <= (limits::min)())) ) { @@ -175,48 +177,30 @@ namespace Boost_MP_internal { (x > Type(-(limits::min)()) && x < Type((limits::min)())); } -// CGAL_assertion(u == l || u == std::nextafter(l, +inf)); - const bool are_bounds_tight = (u == l || u == std::nextafter(l, +inf)); + if (!(u == l || u == std::nextafter(l, +inf))) return false; + //TODO: Type(nextafter(l,inf))>x && Type(nextafter(u,-inf)) - std::pair get_0ulp_interval( const int64_t shift, const ET& p ) { + std::pair get_0ulp_interval( const int shift, const uint64_t p ) { - CGAL_assertion(p > 0); - CGAL_assertion(msb(p) == std::numeric_limits::digits); - const uint64_t pp = static_cast(p); - const double pp_dbl = static_cast(pp); + const double pp_dbl = static_cast(p); const Interval_nt intv(pp_dbl, pp_dbl); - return shift_positive_interval(intv, -static_cast(shift)).pair(); + return shift_positive_interval(intv, -shift).pair(); } // This one returns 1 unit length interval. - template - std::pair get_1ulp_interval( const int64_t shift, const ET& p ) { + std::pair get_1ulp_interval( const int shift, const uint64_t p ) { - CGAL_assertion(p > 0); - CGAL_assertion(msb(p) == std::numeric_limits::digits); - const uint64_t pp = static_cast(p); - CGAL_assertion(pp > 0); - const double pp_dbl = static_cast(pp); - const double qq_dbl = pp+1; + const double pp_dbl = static_cast(p); + const double qq_dbl = pp_dbl+1; const Interval_nt intv(pp_dbl, qq_dbl); - return shift_positive_interval(intv, -static_cast(shift)).pair(); + return shift_positive_interval(intv, -shift).pair(); } // This is a version of to_interval that converts a rational type into a @@ -253,7 +237,8 @@ namespace Boost_MP_internal { const int64_t msb_num = static_cast(boost::multiprecision::msb(xnum)); const int64_t msb_den = static_cast(boost::multiprecision::msb(xden)); const int64_t msb_diff = msb_num - msb_den; - int64_t shift = num_dbl_digits - msb_diff; + int shift = static_cast(num_dbl_digits - msb_diff); + CGAL_assertion(shift == num_dbl_digits - msb_diff); if (shift > 0) { CGAL_assertion(msb_diff < num_dbl_digits); @@ -269,9 +254,13 @@ namespace Boost_MP_internal { decltype(xnum) p, r; boost::multiprecision::divide_qr(xnum, xden, p, r); const int64_t p_bits = static_cast(boost::multiprecision::msb(p)); + //CGAL_assertion(p > 0); + //CGAL_assertion(msb(p) == std::numeric_limits::digits); + //const uint64_t pp = static_cast(p); if (r == 0) { - std::tie(l, u) = get_0ulp_interval(shift, p); + CGAL_assertion(msb(p) <= num_dbl_digits); + std::tie(l, u) = get_0ulp_interval(shift, static_cast(p)); } else { CGAL_assertion(r > 0); CGAL_assertion(r < xden); @@ -284,17 +273,15 @@ namespace Boost_MP_internal { CGAL_assertion(r > 0); const int cmp = r.compare(xden); if (cmp > 0) { - ++p; - std::tie(l, u) = get_1ulp_interval(shift, p); + std::tie(l, u) = get_1ulp_interval(shift, static_cast(p) + 1); } else if (cmp == 0) { - ++p; - std::tie(l, u) = get_0ulp_interval(shift, p); + std::tie(l, u) = get_0ulp_interval(shift, static_cast(p) + 1); } else { - std::tie(l, u) = get_1ulp_interval(shift, p); + std::tie(l, u) = get_1ulp_interval(shift, static_cast(p)); } } else { - std::tie(l, u) = get_1ulp_interval(shift, p); + std::tie(l, u) = get_1ulp_interval(shift, static_cast(p)); } } @@ -329,29 +316,17 @@ namespace Boost_MP_internal { } CGAL_assertion(CGAL::is_positive(x)); - int64_t e = 0; const int64_t n = static_cast(boost::multiprecision::msb(x)) + 1; const int64_t num_dbl_digits = std::numeric_limits::digits; if (n > num_dbl_digits) { - e = n - num_dbl_digits; + int e = static_cast(n - num_dbl_digits); x >>= e; - const uint64_t xx = static_cast(x); - const uint64_t yy = xx + 1; - CGAL_assertion(xx > 0 && yy > xx); - l = static_cast(xx); - u = static_cast(yy); + std::tie(l, u) = get_1ulp_interval(-e, static_cast(x)); } else { - const uint64_t xx = static_cast(x); - CGAL_assertion(xx > 0); - l = static_cast(xx); - u = l; + l = u = static_cast(static_cast(x)); } - const Interval_nt intv(l, u); - Protect_FPU_rounding P(CGAL_FE_UPWARD); - std::tie(l, u) = CGAL::ldexp(intv, static_cast(e)).pair(); - if (change_sign) { const double t = l; l = -u;