From a5d89b1f33639f61fe6140bc3c9799745ef40ec4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 22 Jan 2019 14:20:43 +0100 Subject: [PATCH] Specialize conversion of mpq_rational to interval copy-paste of the code for Gmpq/mpq_class --- Number_types/include/CGAL/boost_mp.h | 110 +++++++++++++++++---------- 1 file changed, 69 insertions(+), 41 deletions(-) diff --git a/Number_types/include/CGAL/boost_mp.h b/Number_types/include/CGAL/boost_mp.h index cae81077612..38ff8b20ddb 100644 --- a/Number_types/include/CGAL/boost_mp.h +++ b/Number_types/include/CGAL/boost_mp.h @@ -57,6 +57,9 @@ # include #endif +#ifdef CGAL_USE_MPFR +# include +#endif // TODO: work on the coercions (end of the file) @@ -136,6 +139,13 @@ struct AST_boost_mp +struct Algebraic_structure_traits > +: AST_boost_mp > {}; +template +struct Algebraic_structure_traits > +: Algebraic_structure_traits::result_type > {}; + // Real_embeddable_traits template @@ -211,26 +221,58 @@ struct RET_boost_mp struct RET_boost_mp > - : RET_boost_mp_base { -#if BOOST_VERSION < 105700 - typedef NT Type; + : RET_boost_mp_base {}; + +#ifdef CGAL_USE_MPFR +// Because of this full specialization, things get instantiated more eagerly. Make it artificially partial if necessary. +template <> +struct RET_boost_mp > + : RET_boost_mp_base { + typedef boost::multiprecision::mpq_rational Type; struct To_interval : public CGAL::cpp98::unary_function< Type, std::pair< double, double > > { std::pair operator()(const Type& x) const { - std::pair p_num = CGAL::to_interval (numerator (x)); - std::pair p_den = CGAL::to_interval (denominator (x)); - typedef Interval_nt IA; - IA::Protector P; - // assume the conversion is within 1 ulp for integers, but the conversion from rational may be unsafe, see boost trac #10085 - IA i_num (p_num.first, p_num.second); - IA i_den (p_den.first, p_den.second); - IA i = i_num / i_den; - return std::pair(i.inf(), i.sup()); +# if MPFR_VERSION_MAJOR >= 3 + mpfr_exp_t emin = mpfr_get_emin(); + mpfr_set_emin(-1073); + MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */ + int r = mpfr_set_q (y, x.backend().data(), MPFR_RNDA); + r = mpfr_subnormalize (y, r, MPFR_RNDA); /* Round subnormals */ + double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */ + mpfr_set_emin(emin); /* Restore old value, users may care */ + // With mpfr_set_emax(1024) we could drop the is_finite test + if (r == 0 && is_finite (i)) + return std::pair(i, i); + else + { + double s = nextafter (i, 0); + if (i < 0) + return std::pair(i, s); + else + return std::pair(s, i); + } +# else + mpfr_t y; + mpfr_init2 (y, 53); /* Assume IEEE-754 */ + mpfr_set_q (y, x.backend().data(), GMP_RNDD); + double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */ + mpfr_set_q (y, x.backend().data(), GMP_RNDU); + double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */ + mpfr_clear (y); + return std::pair(i, s); +# endif } }; -#endif }; +#endif + +template +struct Real_embeddable_traits > +: RET_boost_mp > {}; +template +struct Real_embeddable_traits > +: Real_embeddable_traits::result_type > {}; // Modular_traits @@ -262,6 +304,13 @@ struct MT_boost_mp +struct Modular_traits > +: MT_boost_mp > {}; +template +struct Modular_traits > +: Modular_traits::result_type > {}; + // Split_double template ::value> > @@ -284,6 +333,13 @@ struct SD_boost_mp +struct Split_double > +: SD_boost_mp > {}; +template +struct Split_double > +: Split_double::result_type > {}; + // Fraction_traits @@ -335,27 +391,6 @@ struct FT_boost_mp -struct Algebraic_structure_traits > -: AST_boost_mp > {}; -template -struct Algebraic_structure_traits > -: Algebraic_structure_traits::result_type > {}; - -template -struct Real_embeddable_traits > -: RET_boost_mp > {}; -template -struct Real_embeddable_traits > -: Real_embeddable_traits::result_type > {}; - -template -struct Modular_traits > -: MT_boost_mp > {}; -template -struct Modular_traits > -: Modular_traits::result_type > {}; - template struct Fraction_traits > : FT_boost_mp > {}; @@ -363,13 +398,6 @@ template struct Fraction_traits > : Fraction_traits::result_type > {}; -template -struct Split_double > -: SD_boost_mp > {}; -template -struct Split_double > -: Split_double::result_type > {}; - // Coercions