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 20:29:07
#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@â¦):
thanks very much for continuing to troubleshoot this with me!
i had to change the third and sixth templates, replacing `number<Backend,
et_on>` with `typename detail::expression<tag, A1, A2, A3,
A4>::result_type`.
without the
{{{
namespace std{ using boost::multiprecision::min; using
boost::multiprecision::max;
}}}
i still get `error: no matching function for call to 'max'`.
with it, `error: call to 'max' is ambiguous`.
{{{
/usr/local/Cellar/eigen/3.2.7/include/eigen3/Eigen/src/SVD/JacobiSVD.h:876:66:
error: call to 'max' is ambiguous
RealScalar threshold = (max)(considerAsZero, precision *
(max)(abs(m_workMatrix.coeff(p,p)),
^~~~~
/usr/local/Cellar/eigen/3.2.7/include/eigen3/Eigen/src/SVD/JacobiSVD.h:578:7:
note: in instantiation of member function
'Eigen::JacobiSVD<Eigen::Matrix<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0,
allocate_dynamic>,
boost::multiprecision::expression_template_option::et_on>, -1, -1,
0, -1, -1>, 2>::compute' requested here
compute(matrix, computationOptions);
^
mwe_eigen_mpfr_max.cpp:161:78: note: in instantiation of member function
'Eigen::JacobiSVD<Eigen::Matrix<boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0,
allocate_dynamic>,
boost::multiprecision::expression_template_option::et_on>, -1, -1,
0, -1, -1>, 2>::JacobiSVD' requested here
Eigen::JacobiSVD<Eigen::Matrix<mpfr_float, Eigen::Dynamic,
Eigen::Dynamic>> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:2662:1:
note: candidate function [with
_Tp =
boost::multiprecision::detail::expression<boost::multiprecision::detail::function,
boost::multiprecision::detail::abs_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>]
max(const _Tp& __a, const _Tp& __b)
^
mwe_eigen_mpfr_max.cpp:89:2: note: candidate function [with tag =
boost::multiprecision::detail::function, A1 =
boost::multiprecision::detail::abs_funct<boost::multiprecision::backends::mpfr_float_backend<0,
allocate_dynamic> >, A2 =
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0,
allocate_dynamic>,
boost::multiprecision::expression_template_option::et_on>, A3 =
void, A4 = void, tagb = boost::multiprecision::detail::function, A1b =
boost::multiprecision::detail::abs_funct<boost::multiprecision::backends::mpfr_float_backend<0,
allocate_dynamic> >, A2b =
boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0,
allocate_dynamic>,
boost::multiprecision::expression_template_option::et_on>, A3b =
void, A4b = void]
max(const detail::expression<tag, A1, A2, A3, A4>& arg, const
^
}}}
the code i tested is below for reference.
{{{
#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.
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>& a, const
detail::expression<tag, A1, A2, A3, A4>& b)
{
number<Backend, et_on> t(b);
if(a < t)
return a;
return BOOST_MP_MOVE(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>& a, const number<Backend, et_on>& b)
{
number<Backend, et_on> t(a);
if(t < b)
return BOOST_MP_MOVE(t);
return b;
}
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)
{
// number<Backend, et_on> t1(a), t2(b);
typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(arg),
t2(a);
if(t1 < t2)
return BOOST_MP_MOVE(t1);
return BOOST_MP_MOVE(t2);
}
template <class Backend, class tag, class A1, class A2, class A3, class
A4>
inline number<Backend, et_on> max(const number<Backend, et_on>& a, const
detail::expression<tag, A1, A2, A3, A4>& b)
{
number<Backend, et_on> t(b);
if(a > t)
return a;
return BOOST_MP_MOVE(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>& a, const number<Backend, et_on>& b)
{
number<Backend, et_on> t(a);
if(t > b)
return BOOST_MP_MOVE(t);
return b;
}
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)
{
// number<Backend, et_on> t1(a), t2(b);
typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(arg),
t2(a);
if(t1 > t2)
return BOOST_MP_MOVE(t1);
return BOOST_MP_MOVE(t2);
}
}}
namespace std{ using boost::multiprecision::min; using
boost::multiprecision::max;
}
// 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()));
}
};
}
#include <iostream> // so i can print the V result of the SVD. not
strictly necessary for this MWE
int main()
{
// 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, or has ambiguous call to max, depending on
the presence of the using directives in namespace std.
Eigen::JacobiSVD<Eigen::Matrix<mpfr_float, Eigen::Dynamic,
Eigen::Dynamic>> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
std::cout << svd.matrixV();
return 0;
}
}}}
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/11149#comment:17> 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