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_macros.html#math_toolkit.config_macros.boost_math_macros

 

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 fails to find a suitable overload, then the std:: versions will also be considered.”

 

HTH

 

Paul