Subject: Re: [Boost-bugs] [Boost C++ Libraries] #11149: boost::multiprecision compilation fail with std::max
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-02-17 16:41:17
#11149: boost::multiprecision compilation fail with std::max
-------------------------------+----------------------------
Reporter: minorlogic@⦠| Owner: johnmaddock
Type: Bugs | Status: closed
Milestone: To Be Determined | Component: multiprecision
Version: Boost 1.57.0 | Severity: Showstopper
Resolution: wontfix | Keywords:
-------------------------------+----------------------------
Comment (by dbrake@â¦):
Replying to [comment:11 johnmaddock]:
I have prepared a minimal working example, demonstrating your comment 11,
as well as the ongoing problem with Eigen.
{{{
// this file is intended to be compiled against boost multiprecision and
eigen.
// it demonstrates how eigen fails to find the correct overload of
min/max.
// example compile command
// g++ -std=c++11 -I/usr/local/Cellar/eigen/3.2.7/include/eigen3/
-I/usr/local/Cellar/boost/1.58.0/include/ mwe_eigen_mpfr_max.cpp -lmpfr
// this example fails to compile under clang on osx 10.11
// Configured with:
--prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-
include-dir=/usr/include/c++/4.2.1
// Apple LLVM version 7.0.2 (clang-700.1.81)
// Target: x86_64-apple-darwin15.3.0
// Thread model: posix
// prepared by Daniel Brake
// University of Notre Dame
// dbrake_at_[hidden]
// Feb 2016
#include <algorithm>
#include <cmath>
#include <boost/multiprecision/mpfr.hpp>
using mpfr_float =
boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>,
boost::multiprecision::et_on>;
// changing et_on to et_off allows this code to compile.
// the problem with min/max is with expression templates.
// from John Maddock, a boost multiprecision author, via email 2016.02.16
and
// https://svn.boost.org/trac/boost/ticket/11149
namespace boost { namespace multiprecision {
template <class Backend, class tag, class A1, class A2, class A3, class
A4>
inline number<Backend, et_on> min(const number<Backend, et_on>&
arg, const detail::expression<tag, A1, A2, A3, A4>& a)
{
number<Backend, et_on> t(a);
return (std::min)(arg, t);
}
template <class tag, class A1, class A2, class A3, class A4, class
Backend>
inline number<Backend, et_on> min(const detail::expression<tag,
A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)
{
number<Backend, et_on> t(arg);
return (std::min)(arg, a);
}
template <class tag, class A1, class A2, class A3, class A4, class tagb,
class A1b, class A2b, class A3b, class A4b>
inline typename detail::expression<tag, A1, A2, A3,
A4>::result_type min(const detail::expression<tag, A1, A2, A3, A4>& arg,
const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)
{
using N = typename detail::expression<tag, A1, A2, A3,
A4>::result_type;
N t1(arg), t2(a);
return (std::min)(arg, a);
}
template <class Backend, class tag, class A1, class A2, class A3, class
A4>
inline number<Backend, et_on> max(const number<Backend, et_on>&
arg, const detail::expression<tag, A1, A2, A3, A4>& a)
{
number<Backend, et_on> t(a);
return (std::max)(arg, t);
}
template <class tag, class A1, class A2, class A3, class A4, class
Backend>
inline number<Backend, et_on> max(const detail::expression<tag,
A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)
{
number<Backend, et_on> t(arg);
return (std::max)(arg, a);
}
template <class tag, class A1, class A2, class A3, class A4, class tagb,
class A1b, class A2b, class A3b, class A4b>
inline typename detail::expression<tag, A1, A2, A3,
A4>::result_type max(const detail::expression<tag, A1, A2, A3, A4>& arg,
const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)
{
using N = typename detail::expression<tag, A1, A2, A3,
A4>::result_type;
N t1(arg), t2(a);
return (std::max)(arg, a);
}
} }
// include AFTER the above templates
#include <Eigen/Dense>
// reopen the Eigen namespace to provide NumTraits for mpfr_float.
namespace Eigen {
// describe mpfr_float to Eigen
// permits to get the epsilon, dummy_precision, lowest, highest
functions
template<> struct NumTraits<mpfr_float> :
GenericNumTraits<mpfr_float>
{
typedef mpfr_float Real;
typedef mpfr_float NonInteger;
typedef mpfr_float Nested;
enum {
IsComplex = 0,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1, // yes, require
initialization, otherwise get crashes
ReadCost = 20,
AddCost = 30,
MulCost = 40
};
inline static Real highest() {
return (mpfr_float(1) - epsilon()) *
pow(mpfr_float(2),mpfr_get_emax()-1);
}
inline static Real lowest() {
return -highest();
}
inline static Real dummy_precision()
{
return pow(
mpfr_float(10),-int(mpfr_float::default_precision()-3));
}
inline static Real epsilon()
{
return
pow(mpfr_float(10),-int(mpfr_float::default_precision()));
}
//http://www.manpagez.com/info/mpfr/mpfr-2.3.2/mpfr_31.php
};
}
int main()
{
mpfr_float a(1), b(2), c(3);
using std::max;
// this line works because of the 6 above templates providing
min/max.
auto r = max(a,b*b+c);
// this line will fail, not finding the call to max. this is
syntactically similar to the failing eigen call from version 3.2.7.
auto s = (max)(a,b*b+c);
// make a 2x2 dynamic matrix
Eigen::Matrix<mpfr_float, Eigen::Dynamic, Eigen::Dynamic> A(2,2);
A << 2, 1, 1, 2; // populate it
// this is the offending line. Eigen attempts to call max, but
cannot see the above templates.
Eigen::JacobiSVD<Eigen::Matrix<mpfr_float, Eigen::Dynamic,
Eigen::Dynamic>> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
// In file included from mwe_eigen_mpfr_max.cpp:68:
// In file included from
/usr/local/Cellar/eigen/3.2.7/include/eigen3/Eigen/Dense:5:
// In file included from
/usr/local/Cellar/eigen/3.2.7/include/eigen3/Eigen/SVD:24:
//
/usr/local/Cellar/eigen/3.2.7/include/eigen3/Eigen/src/SVD/JacobiSVD.h:876:32:
error: no matching function for call to 'max'
return 0;
}
}}}
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/11149#comment:13> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:19 UTC