Paul, Boost, Thanks for the quick reply! I haven’t looked into this in detail, but I think not,
but Boost.Math does
#include <boost/math/special_functions/modf.hpp>
You might also need to add this to your local function(s) to aid Argument Dependant Lookup (ADL).
BOOST_MATH_STD_USING
Boost.Math and the BOOST_MATH_STD_USING solved the modf problem, so long as I include and using before including Karma. Since the compiler got past that, it generated a new error, related to log10, floor, and int comparison. I've had errors related to log10, floor, and ceil in the context of Eigen before. /u/ggael resolved them by explicit casting in certain places, see e.g. https://forum.kde.org/viewtopic.php?f=74&t=133404&p=359710#p359710 Here's the new error message: In file included from test/generating/mpfr_float.cpp:27: In file included from ./include/bertini2/io/generators.hpp:44: In file included from /usr/local/include/boost/spirit/include/karma.hpp:16: In file included from /usr/local/include/boost/spirit/home/karma.hpp:15: In file included from /usr/local/include/boost/spirit/home/karma/numeric.hpp:16: In file included from /usr/local/include/boost/spirit/home/karma/numeric/real.hpp:32: /usr/local/include/boost/spirit/home/karma/numeric/real_policies.hpp:263:39: error: incompatible operand types ('int' and 'typename enable_if_c<number_category<detail::expression<function, log10_funct<mpfr_float_backend<0, allocate_dynamic> >, number<mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void>
::value == number_kind_floating_point, detail::expression<detail::function, detail::floor_funct<typename detail::backend_type<detail::expression<function, log10_funct<mpfr_float_backend<0, allocate_dynamic> >, number<mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void> >::type>, detail::expression<function, log10_funct<mpfr_float_backend<0, allocate_dynamic> >, number<mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void> > >::type' (aka 'boost::multiprecision::detail::expression<boost::multiprecision::detail::function,
boost::multiprecision::detail::floor_funct<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic> >, boost::multiprecision::detail::expression<boost::multiprecision::detail::function, boost::multiprecision::detail::log10_funct<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic> >, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void>, void, void>')) (traits::test_zero(n) ? 0 : floor(log10(n))) + 1; ^ ~ ~~~~~~~~~~~~~~~ /usr/local/include/boost/spirit/home/karma/numeric/detail/real_utils.hpp:170:24: note: in instantiation of function template specialization 'boost::spirit::karma::real_policies<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>
::fraction_part<boost::spirit::karma::detail::output_iterator<std::__1::back_insert_iterator<std::__1::basic_string<char> , mpl_::int_<0>, boost::spirit::unused_type> >' requested here r = r && p.fraction_part(sink, long_frac_part, prec, precision); ^ /usr/local/include/boost/spirit/home/karma/numeric/real_policies.hpp:94:30: note: in instantiation of function template specialization
'boost::spirit::karma::real_inserter<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, bertini::generators::BertiniNumPolicy<mpfr_float>, boost::spirit::unused_type, boost::spirit::unused_type>::call_n<boost::spirit::karma::detail::output_iterator<std::__1::back_insert_iterator<std::__1::basic_string<char>
, mpl_::int_<0>, boost::spirit::unused_type>, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> >' requested here return Inserter::call_n(sink, n, p); ^ /usr/local/include/boost/spirit/home/karma/numeric/detail/real_utils.hpp:56:31: note: in instantiation of function template specialization
'boost::spirit::karma::real_policies<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>
::call<boost::spirit::karma::real_inserter<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, bertini::generators::BertiniNumPolicy<mpfr_float>, boost::spirit::unused_type, boost::spirit::unused_type>, boost::spirit::karma::detail::output_iterator<std::__1::back_insert_iterator<std::__1::basic_string<char> , mpl_::int_<0>, boost::spirit::unused_type>, bertini::generators::BertiniNumPolicy<mpfr_float> >' requested here return p.template call<real_inserter>(sink, n, p); ^ /usr/local/include/boost/spirit/home/karma/numeric/real.hpp:192:35: note: in instantiation of function template specialization
'boost::spirit::karma::real_inserter<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, bertini::generators::BertiniNumPolicy<mpfr_float>, boost::spirit::unused_type, boost::spirit::unused_type>::call<boost::spirit::karma::detail::output_iterator<std::__1::back_insert_iterator<std::__1::basic_string<char>
, mpl_::int_<0>, boost::spirit::unused_type>, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> >' requested here return inserter_type::call(sink, traits::extract_from<T>(attr, context), p_) && ^ /usr/local/include/boost/spirit/home/karma/generate.hpp:69:45: note: in instantiation of function template specialization
'boost::spirit::karma::any_real_generator<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, bertini::generators::BertiniNumPolicy<mpfr_float>, boost::spirit::unused_type, boost::spirit::unused_type>::generate<boost::spirit::karma::detail::output_iterator<std::__1::back_insert_iterator<std::__1::basic_string<char>
, mpl_::int_<0>, boost::spirit::unused_type>, boost::spirit::context<boost::fusion::cons<const
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> &, boost::fusion::nil_>, boost::spirit::locals<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >, boost::spirit::unused_type, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> >' requested here return compile<karma::domain>(expr).generate(sink, context, unused, attr); ^ /usr/local/include/boost/spirit/home/karma/generate.hpp:91:23: note: in instantiation of function template specialization 'boost::spirit::karma::generate<std::__1::back_insert_iterator<std::__1::basic_string<char>
, mpl_::int_<0>,
boost::spirit::karma::real_generator<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, bertini::generators::BertiniNumPolicy<mpfr_float> >, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> >' requested here return karma::generate(sink, expr, attr); ^ ./include/bertini2/io/generators.hpp:153:21: note: in instantiation of function template specialization 'boost::spirit::karma::generate<std::__1::back_insert_iterator<std::__1::basic_string<char>
,
boost::spirit::karma::real_generator<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, bertini::generators::BertiniNumPolicy<mpfr_float> >, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> >' requested here return generate(sink, ^ test/generating/mpfr_float.cpp:53:47: note: in instantiation of function template specialization 'bertini::generators::Classic::generate<std::__1::back_insert_iterator<std::__1::basic_string<char>
' requested here BOOST_CHECK(bertini::generators::Classic::generate(sink, z));
Any help with this one would be greatly appreciated. It feels beyond my diagnosis. It feels to me like I might should feed mpfr_float into Fusion to adapt it, so I can use the type directly with Karma. Here's the generator code so far: template <typename Num> struct BertiniNumPolicy : public karma::real_policies<Num> { // we want the numbers always to be in scientific format static int floatfield(Num n) { return std::ios_base::scientific; } static unsigned int precision(Num) { return std::numeric_limits<Num>::max_digits10; } }; template<> struct BertiniNumPolicy<mpfr_float> : public karma::real_policies<mpfr_float> { // we want the numbers always to be in scientific format static int floatfield(mpfr_float n) { return std::ios_base::scientific; } static unsigned int precision(mpfr_float const& x) { return x.precision(); } }; template<typename Num> using FullPrec = boost::spirit::karma::real_generator<Num, BertiniNumPolicy<Num> >; FullPrec<double> const full_prec_d = FullPrec<double>(); FullPrec<mpfr_float> const full_prec_mp = FullPrec<mpfr_float>(); template <typename OutputIterator> static bool generate(OutputIterator sink, mpfr_float const& c) { using boost::spirit::karma::generate; return generate(sink, // Begin grammar ( full_prec_mp ), // End grammar c // Data to output ); } As a last question, I am unsure about the use of the a function parameter in my specialization BertiniNumPolicy<mpfr_float>, particularly the precision(mpfr_float) function. In the documentation and examples I have seen for specializations, this function doesn't use the argument. Is it ok that it does, that it checks the actual precision of x??? See above code. An alternate method for me might be to just use the str() method provided by the number<...> from Multiprecision, but it seems like since this type is numeric, I'd like to be able to generate using the numeric generators from Karma. Thanks again! Daniel Brake
---------- Forwarded message ---------- From: "Paul A. Bristow" <pbristow@hetp.u-net.com> To: <boost-users@lists.boost.org> Cc: Date: Wed, 3 Aug 2016 10:00:20 +0100 Subject: Re: [Boost-users] multiprecision modf
I haven’t looked into this in detail, but I think not,
but Boost.Math does
#include <boost/math/special_functions/modf.hpp>
You might also need to add this to your local function(s) to aid Argument Dependant Lookup (ADL).
BOOST_MATH_STD_USING
http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/config_...
*Table 11. Boost.Math Macros*
“Provides using statements for many std:: (abs to sqrt) and boost::math (rounds, modf) functions. This allows these functions to be called unqualified so that ifargument-dependent Argument Dependent Lookup <http://en.wikipedia.org/wiki/Argument-dependent_name_lookup> fails to find a suitable overload, then the std:: versions will also be considered.”
HTH
Paul
Here's the new error message:
In file included from test/generating/mpfr_float.cpp:27: In file included from ./include/bertini2/io/generators.hpp:44: In file included from /usr/local/include/boost/spirit/include/karma.hpp:16: In file included from /usr/local/include/boost/spirit/home/karma.hpp:15: In file included from /usr/local/include/boost/spirit/home/karma/numeric.hpp:16: In file included from /usr/local/include/boost/spirit/home/karma/numeric/real.hpp:32: /usr/local/include/boost/spirit/home/karma/numeric/real_policies.hpp:263:39: error: incompatible operand types ('int' and 'typename enable_if_c<number_category<detail::expression<function, log10_funct<mpfr_float_backend<0, allocate_dynamic> >, number<mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void>
::value == number_kind_floating_point, detail::expression<detail::function, detail::floor_funct<typename detail::backend_type<detail::expression<function, log10_funct<mpfr_float_backend<0, allocate_dynamic> >, number<mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void> ::type>, detail::expression<function, log10_funct<mpfr_float_backend<0, allocate_dynamic> >, number<mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void> > >::type' (aka 'boost::multiprecision::detail::expression<boost::multiprecision::detail::function, boost::multiprecision::detail::floor_funct<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic> >, boost::multiprecision::detail::expression<boost::multiprecision::detail::function, boost::multiprecision::detail::log10_funct<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic> >, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on>, void, void>, void, void>')) (traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
I'm afraid that code is incompatible with expression templates: the two halves of the conditional expression have different/unrelated types which aren't convertible to each other. An explicit cast is needed here to make the code expression-template compatible. Or else use a number type with expression templates turned off. Suggest you contact the spirit developers (they have their own mailing list I believe) and see what their intent is here.
As a last question, I am unsure about the use of the a function parameter in my specialization BertiniNumPolicy<mpfr_float>, particularly the precision(mpfr_float) function. In the documentation and examples I have seen for specializations, this function doesn't use the argument. Is it ok that it does, that it checks the actual precision of x??? See above code. An alternate method for me might be to just use the str() method provided by the number<...> from Multiprecision, but it seems like since this type is numeric, I'd like to be able to generate using the numeric generators from Karma.
That looks to be the intent yes. Note however, that it's a conceptual requirement of karma that the number have numeric_limits specialized - that's not true for type mpfr_float since most of the fields would have to vary at runtime which isn't possible for numeric_limits. Technically we could provide a specialization that defines the members that are constant and leaves the others as undefined/zero/infinity, but it's not clear what's the right thing to do here - numeric_limits wasn't designed for this kind of type it seems :( I'm changing the subject line to include spirit/karma in hopes that their developers will see this and chip in.... we should really find a way to make the libraries work better together. HTH, John.
participants (2)
-
Daniel Brake
-
John Maddock