[Boost.polygon.voronoi] [Boost.multiprecision] higher precision voronoi
I'm attempting to following the http://www.boost.org/doc/libs/1_53_0_beta1/libs/polygon/doc/voronoi_advanced... to compile boost::polygon::voronoi using 64 bit integer input. I'm using the boost::multiprecision library to do so. Using boost version 1.53 and Microsoft Visual Studio 2012. The error message is: 1>d:\workspace\movingboundary\boost_1_53_0\boost\polygon\detail\voronoi_robust_fpt.hpp(60): error C2665: 'sqrt' : none of the 3 overloads could convert all the argument types 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(588): could be 'long double sqrt(long double)' 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(540): or 'float sqrt(float)' 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(127): or 'double sqrt(double)' 1> while trying to match the argument list '(const boost::multiprecision::detail::expression<tag,Arg1,Arg2,Arg3,Arg4>)' 1> with 1> [ 1> tag=boost::multiprecision::detail::multiplies, 1> Arg1=boost::multiprecision::detail::expression<boost::multiprecision::detail::multiplies,boost::multiprecision::detail::expression<boost::multiprecision::detail::plus,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::plus,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,void,void>,void,void>, 1> Arg2=boost::multiprecision::detail::expression<boost::multiprecision::detail::plus,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,void,void>, 1> Arg3=void, 1> Arg4=void == reference line is template <typename T> T get_sqrt(const T& that) { return (std::sqrt)(that); //<-- line 60 } == code == #pragma warning (disable: 4996 4267) #include <cmath> #include <boost/multiprecision/cpp_int.hpp> #include <boost/multiprecision/cpp_dec_float.hpp> #include <boost/polygon/voronoi.hpp> #include <limits> #include <gtest/gtest.h> #include <iostream> using namespace boost::polygon; namespace vcellVoronoiImpl { typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<48>> floatingType; struct FloatingConverter { template <typename T> floatingType operator( )(T x) const { return static_cast<floatingType>(x); } }; struct compareFloatingType { enum Result { LESS = -1, EQUAL = 0, MORE = 1 }; Result operator()(floatingType a, floatingType b, unsigned int maxUlps) const { if (a > b) { return a - b <= maxUlps ? EQUAL : LESS; } return b - a <= maxUlps ? EQUAL : MORE; } }; struct voronoi_ctype_traits { typedef boost::int64_t int_type; typedef boost::multiprecision::int128_t int_x2_type; typedef boost::multiprecision::uint128_t uint_x2_type; typedef boost::multiprecision::int512_t big_int_type; typedef floatingType fpt_type; typedef floatingType efpt_type; typedef compareFloatingType ulp_cmp_type; typedef FloatingConverter to_fpt_converter_type; typedef FloatingConverter to_efpt_converter_type; }; struct vcell_vd_traits{ typedef voronoi_ctype_traits::fpt_type coordinate_type; typedef voronoi_cell<coordinate_type> cell_type; typedef voronoi_vertex<coordinate_type> vertex_type; typedef voronoi_edge<coordinate_type> edge_type; typedef struct { public: enum { ULPS = 128 }; bool operator()(const vertex_type &v1, const vertex_type &v2) const { return (ulp_cmp(v1.x(), v2.x(), ULPS) == compareFloatingType::EQUAL && ulp_cmp(v1.y(), v2.y(), ULPS) == compareFloatingType::EQUAL); } private: compareFloatingType ulp_cmp; } vertex_equality_predicate_type; }; } using namespace vcellVoronoiImpl; TEST(highv,build) { voronoi_builder<boost::int64_t, vcellVoronoiImpl::voronoi_ctype_traits> vb; voronoi_diagram<boost::int64_t,vcell_vd_traits> vd; vb.construct(&vd); } Gerard Weatherby Appllication Architect Virtual Cell, Center for Cell Analysis and Modeling (CCAM) University of Connecticut Health Center 860-679-2065
I'm attempting to following the http://www.boost.org/doc/libs/1_53_0_beta1/libs/polygon/doc/voronoi_advanced... to compile boost::polygon::voronoi using 64 bit integer input. I'm using the boost::multiprecision library to do so. Using boost version 1.53 and Microsoft Visual Studio 2012.
The error message is: 1>d:\workspace\movingboundary\boost_1_53_0\boost\polygon\detail\voronoi_robust_fpt.hpp(60): error C2665: 'sqrt' : none of the 3 overloads could convert all the argument types 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(588): could be 'long double sqrt(long double)' 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(540): or 'float sqrt(float)' 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(127): or 'double sqrt(double)' 1> while trying to match the argument list '(const boost::multiprecision::detail::expression<tag,Arg1,Arg2,Arg3,Arg4>)' 1> with 1> [ 1> tag=boost::multiprecision::detail::multiplies, 1> Arg1=boost::multiprecision::detail::expression<boost::multiprecision::detail::multiplies,boost::multiprecision::detail::expression<boost::multiprecision::detail::plus,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::plus,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multi precision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,void,void>,void,void>, 1> Arg2=boost::multiprecision::detail::expression<boost::multiprecision::detail::plus,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<48>>,void,void>,void,void>, 1> Arg3=void, 1> Arg4=void
== reference line is template <typename T> T get_sqrt(const T& that) { return (std::sqrt)(that); //<-- line 60 }
It's a conceptual issue: polynomial is calling std::sqrt, but there is no overload of sqrt for multiprecision types in that namespace: to place them there would actually be mal-formed according to the std. Had polygon been coded like this: template <typename T> T get_sqrt(const T& that) { using std::sqrt; return (sqrt)(that); // ADL is now active } Then the correct overload would have been found. One possible workaround would be to provide an overload of get_sqrt but that would be hard to do in the presence of expression templates :-( Turning them off in the number type you're using would make life much easier, or else I can help with providing expression-template aware overloads. I'd be interested to hear from polygon's authors as to why the library was coded that way, and whether there's any reason not to move to ADL-aware code. HTH, John.
-----Original Message----- From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of It's a conceptual issue: polynomial is calling std::sqrt, but there is no overload of sqrt for multiprecision types in that namespace: to place them there would actually be mal-formed according to the std.
Had polygon been coded like this:
template <typename T> T get_sqrt(const T& that) { using std::sqrt; return (sqrt)(that); // ADL is now active }
Then the correct overload would have been found.
One possible workaround would be to provide an overload of get_sqrt but that would be hard to do in the presence of expression templates :-( Turning them off in the number type you're using would make life much easier, or else I can help with providing expression-template aware overloads.
I tried both suggestions as best I understood them; changing the boost::polygon::voronoi get_sqrt implementation and changing my code as follows. (Aside: I realized I actually wanted 80, not 48 floating point bits). namespace bmulti = boost::multiprecision; using bmulti::et_off; typedef bmulti::number<bmulti::cpp_dec_float<80>,et_off> floatingType; using bmulti::cpp_int_backend; using bmulti::signed_magnitude; using bmulti::unsigned_magnitude; using bmulti::unchecked; typedef bmulti::number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void>,et_off > int128; typedef bmulti::number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void>,et_off > uint128; typedef bmulti::number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void>,et_off > int512; struct voronoi_ctype_traits { typedef boost::int64_t int_type; typedef int128 int_x2_type; typedef uint128 uint_x2_type; typedef int512 big_int_type; typedef floatingType fpt_type; typedef floatingType efpt_type; typedef compareFloatingType ulp_cmp_type; typedef FloatingConverter to_fpt_converter_type; typedef FloatingConverter to_efpt_converter_type; ... But still got: 1>d:\workspace\movingboundary\boost_1_53_0\boost\polygon\detail\voronoi_robust_fpt.hpp(61): error C2665: 'sqrt' : none of the 3 overloads could convert all the argument types 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(127): could be 'double sqrt(double)' 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(540): or 'float sqrt(float)' 1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\math.h(588): or 'long double sqrt(long double)' 1> while trying to match the argument list '(const boost::multiprecision::number<Backend,ExpressionTemplates>)' 1> with 1> [ 1> Backend=boost::multiprecision::backends::cpp_dec_float<80>, 1> ExpressionTemplates=et_off 1> ] 1> What does seem to work for MSVC compiling is adding (somewhat inelegant) definition: namespace std { boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80> > sqrt(const boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80> >& in) { boost::multiprecision::backends::cpp_dec_float<80> v = in.canonical_value(in); return v.calculate_sqrt( ); } } But gcc 4.8.2 compiling produces: In file included from /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/detail/voronoi_predicates.hpp:15:0, from /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/voronoi_builder.hpp:20, from /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/voronoi.hpp:17, from /state/partition1/MovingBoundary/Tests/v64.cpp:6: /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/detail/voronoi_robust_fpt.hpp: In instantiation of 'T boost::polygon::detail::get_sqrt(const T&) [with T = boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u>]': /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/detail/voronoi_predicates.hpp:1042:46: required from 'void boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::lazy_circle_formation_functor<Site, Circle>::ppp(const site_type&, const site_type&, const site_type&, boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::lazy_circle_formation_functor<Site, Circle>::circle_type&) [with Site = boost::polygon::detail::site_event<long int>; Circle = boost::polygon::detail::circle_event<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u> >; CTYPE_TRAITS = vcellVoronoiImpl::voronoi_ctype_traits; boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::lazy_circle_formation_functor<Site, Circle>::site_type = boost::polygon::detail::site_event<long int>; boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::lazy_circle_formation_functor<Site, Circle>::circle_type = boost::polygon::detail::circle_event<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u> >]' /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/detail/voronoi_predicates.hpp:1467:13: required from 'bool boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::circle_formation_predicate<Site, Circle, CEP, CFF>::operator()(const site_type&, const site_type&, const site_type&, boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::circle_formation_predicate<Site, Circle, CEP, CFF>::circle_type&) [with Site = boost::polygon::detail::site_event<long int>; Circle = boost::polygon::detail::circle_event<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u> >; CEP = boost::polygon::detail::voronoi_predicates<vcellVoronoiImpl::voronoi_ctype_traits>::circle_existence_predicate<boost::polygon::detail::site_event<long int> >; CFF = boost::polygon::detail::voronoi_predicates<vcellVoronoiImpl::voronoi_ctype_traits>::lazy_circle_formation_functor<boost::polygon::detail::site_event<long int>, boost::polygon::detail::circle_event<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u> > >; CTYPE_TRAITS = vcellVoronoiImpl::voronoi_ctype_traits; boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::circle_formation_predicate<Site, Circle, CEP, CFF>::site_type = boost::polygon::detail::site_event<long int>; boost::polygon::detail::voronoi_predicates<CTYPE_TRAITS>::circle_formation_predicate<Site, Circle, CEP, CFF>::circle_type = boost::polygon::detail::circle_event<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u> >]' /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/voronoi_builder.hpp:478:5: required from 'void boost::polygon::voronoi_builder<T, CTT, VP>::activate_circle_event(const site_event_type&, const site_event_type&, const site_event_type&, boost::polygon::voronoi_builder<T, CTT, VP>::beach_line_iterator) [with T = long int; CTT = vcellVoronoiImpl::voronoi_ctype_traits; VP = boost::polygon::detail::voronoi_predicates<vcellVoronoiImpl::voronoi_ctype_traits>; boost::polygon::voronoi_builder<T, CTT, VP>::site_event_type = boost::polygon::detail::site_event<long int>; typename CTT::int_type = long int; boost::polygon::voronoi_builder<T, CTT, VP>::beach_line_iterator = std::_Rb_tree_iterator<std::pair<const boost::polygon::detail::beach_line_node_key<boost::polygon::detail::site_event<long int> >, boost::polygon::detail::beach_line_node_data<void, boost::polygon::detail::circle_event<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u> > > > >]' /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/voronoi_builder.hpp:309:51: required from 'void boost::polygon::voronoi_builder<T, CTT, VP>::process_site_event(OUTPUT*) [with OUTPUT = boost::polygon::voronoi_diagram<long int, vcellVoronoiImpl::vcell_vd_traits>; T = long int; CTT = vcellVoronoiImpl::voronoi_ctype_traits; VP = boost::polygon::detail::voronoi_predicates<vcellVoronoiImpl::voronoi_ctype_traits>]' /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/voronoi_builder.hpp:106:34: required from 'void boost::polygon::voronoi_builder<T, CTT, VP>::construct(OUTPUT*) [with OUTPUT = boost::polygon::voronoi_diagram<long int, vcellVoronoiImpl::vcell_vd_traits>; T = long int; CTT = vcellVoronoiImpl::voronoi_ctype_traits; VP = boost::polygon::detail::voronoi_predicates<vcellVoronoiImpl::voronoi_ctype_traits>]' /state/partition1/MovingBoundary/Tests/v64.cpp:93:20: required from here /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/detail/voronoi_robust_fpt.hpp:61:21: error: no matching function for call to 'sqrt(const boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u>&)' return (sqrt)(that); ^ /state/partition1/MovingBoundary/boost_1_53_0/boost/polygon/detail/voronoi_robust_fpt.hpp:61:21: note: candidates are: In file included from /usr/include/features.h:361:0, from /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/x86_64-unknown-linux-gnu/bits/os_defines.h:39, from /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/x86_64-unknown-linux-gnu/bits/c++config.h:426, from /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/cmath:41, from /state/partition1/MovingBoundary/Tests/v64.cpp:3: /usr/include/bits/mathcalls.h:157:1: note: double sqrt(double) __MATHCALL (sqrt,, (_Mdouble_ __x)); ^ /usr/include/bits/mathcalls.h:157:1: note: no known conversion for argument 1 from 'const boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u>' to 'double' In file included from /state/partition1/MovingBoundary/Tests/v64.cpp:3:0: /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/cmath:482:3: note: constexpr float std::sqrt(float) sqrt(float __x) ^ /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/cmath:482:3: note: no known conversion for argument 1 from 'const boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u>' to 'float' /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/cmath:486:3: note: constexpr long double std::sqrt(long double) sqrt(long double __x) ^ /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/cmath:486:3: note: no known conversion for argument 1 from 'const boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80u>, (boost::multiprecision::expression_template_option)0u>' to 'long double' /home/CAM/gweatherby/.local/easybuild/software/GCC/4.8.2/include/c++/4.8.2/cmath:494:5: note: template<class _Tp> constexpr typename __gnu_cxx::__enable_if<std::__is_integer<_Tp>::__value, double>::__type std::sqrt(_Tp) sqrt(_Tp __x) ....
AMDG On 03/17/2014 08:57 AM, Weatherby,Gerard wrote:
Had polygon been coded like this:
template <typename T> T get_sqrt(const T& that) { using std::sqrt; return (sqrt)(that); // ADL is now active }
Then the correct overload would have been found.
Not quite true. The parentheses disable ADL, just as much as using a qualified name. To prevent macro expansion of sqrt while enabling ADL, you need to use: sqrt BOOST_PREVENT_MACRO_SUBSTITUTION (that)
<snip>
I tried both suggestions as best I understood them; changing the boost::polygon::voronoi get_sqrt implementation and changing my code as follows. (Aside: I realized I actually wanted 80, not 48 floating point bits).
namespace bmulti = boost::multiprecision; using bmulti::et_off; typedef bmulti::number<bmulti::cpp_dec_float<80>,et_off> floatingType;
Note: cpp_dec_float<80> has 80 /decimal/ digits, not 80 bits.
But still got: 1>d:\workspace\movingboundary\boost_1_53_0\boost\polygon\detail\voronoi_robust_fpt.hpp(61): error C2665: 'sqrt' : none of the 3 overloads could convert all the argument types
In Christ, Steven Watanabe
What does seem to work for MSVC compiling is adding (somewhat inelegant) definition: namespace std { boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80> > sqrt(const boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<80> >& in) { boost::multiprecision::backends::cpp_dec_float<80> v = in.canonical_value(in); return v.calculate_sqrt( ); } }
But gcc 4.8.2 compiling produces:
If you do that, then you need to define the std::sqrt overload *before* any polygon library include, otherwise GCC is correct in not considering the overload as a candidate, and MSVC is wrong in finding it. John.
participants (3)
-
John Maddock
-
Steven Watanabe
-
Weatherby,Gerard