Opened 6 years ago

Closed 6 years ago

#12234 closed Bugs (fixed)

boost::multiprecision x64 win32 hard compile errors on windows with mpir

Reported by: tlyons@… Owned by: John Maddock
Milestone: Boost 1.62.0 Component: multiprecision
Version: Boost 1.61.0 Severity: Showstopper
Keywords: mpir x64 Cc:

Description

I get a hard compile error in trying to get boost multprecision floating point examples working with mpir on windows x64.

The crux of the error is that some of the boost code uses functions whose signatures are long* but the code is used with arguments of type mpir_ui* etc.and of course this is a nasty for pointers!

1>C:\Program Files\boost\boost_1_61_0\boost/multiprecision/gmp.hpp(982): error C2664: 'double __gmpf_get_d_2exp(mpir_si *,mpf_srcptr)': cannot convert argument 1 from 'long *' to 'mpir_si *'
1> C:\Program Files\boost\boost_1_61_0\boost/multiprecision/gmp.hpp(982): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

One workaround that "works" is to define double gmpf_get_d_2exp(long * p, mpf_srcptr a) :

#include "stdafx.h"
#include <boost/multiprecision/gmp.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include "Safeint3.hpp"
#include <iostream>
namespace boost {
        namespace multiprecision {
                template <unsigned Digits10>
                struct gmp_float;
                typedef number<gmp_float<50> >    mpf_float_50;
                typedef number<gmp_float<100> >   mpf_float_100;
                typedef number<gmp_float<500> >   mpf_float_500;
                typedef number<gmp_float<1000> >  mpf_float_1000;
                typedef number<gmp_float<0> >     mpf_float;
        }
} // namespaces

//FIX - define a wrapper
double __gmpf_get_d_2exp(long * p, mpf_srcptr a) {
        mpir_si temp{ *p };
        double b = __gmpf_get_d_2exp(&temp, a);
        *p = SafeInt<long>(temp);
        return b;
}


But is this the answer? I find it difficult to get the sense of gmp.hpp well enough to figure out whether or not it knows when it can narrow a variable and when it cannot.

Clearly is intended to cope with the 64 32 divide on long; however I am puzzled by code like:

inline void eval_convert_to(long* result, const gmp_rational& val)
{
double r;
eval_convert_to(&r, val);
*result = static_cast<long>(r);
}

inline void eval_convert_to(unsigned long* result, const gmp_rational& val)
{
 double r;
 eval_convert_to(&r, val);
 *result = static_cast<long>(r);
}

Which to my amateur eye does not seem to be nice.

Suggestions welcome - mpir is the current version and working nicely; boost is 1.61.0 and working nicely.

I would really like to get them working together.

Environment - VS 2015-2008, Intel 16.0, windows 7.

Terry

Change History (4)

comment:1 by tlyons@…, 6 years ago

I should have given the code example that triggered the problem. Uncomment the relevant part and it runs successfully:

#include "stdafx.h"
#include <boost/multiprecision/gmp.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include "Safeint3.hpp" // for a safe fix: http://safeint.codeplex.com/
#include <iostream>

namespace boost {
	namespace multiprecision {

		template <unsigned Digits10>
		struct gmp_float;

		typedef number<gmp_float<100> >   mpf_float_100;
	}
} // namespaces

/*
// uncomment this block to fix the code

double __gmpf_get_d_2exp(long * p, mpf_srcptr a) {
	mpir_si temp{ *p };
	double b = __gmpf_get_d_2exp(&temp, a);
	*p = SafeInt<long>(temp);
	return b;
}
*/
using namespace boost::multiprecision;
int fourth() {
	mpf_float_100 b = 2;
	std::cout << std::numeric_limits<mpf_float_100>::digits << std::endl;
	// We can use any C++ std lib function:
	std::cout << log(b) << std::endl; // print log(2)// ERROR on this line
	// We can also use any function from Boost.Math:
	std::cout << boost::math::tgamma(b) << std::endl;
	// These even work when the argument is an expression template:
	std::cout << boost::math::tgamma(b * b) << std::endl;

	return 0;
}

comment:2 by John Maddock, 6 years ago

I need to check with latest MPIR, but my version has no such type as mpir_si, further the function call that's causing the issue (mpf_get_d_2exp) is documented as:

double mpf_get_d_2exp (signed long int *exp, const mpf_t op)

In the latest GMP documentation. Is this an incompatibility between GMP and MPIR by any chance?

comment:3 by John Maddock, 6 years ago

I believe this to be an MPIR bug: https://github.com/wbhart/mpir/commit/fb616eed78d0a32dc9e53b355b0c2d42c1209907#commitcomment-17775327

Will commit a workaround shortly.

comment:4 by John Maddock, 6 years ago

Milestone: To Be DeterminedBoost 1.62.0
Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.