Skip to content

Instantly share code, notes, and snippets.

@afabri
Created March 20, 2023 07:14
Show Gist options
  • Save afabri/acc723427888dc49c60099bdb6220c53 to your computer and use it in GitHub Desktop.
Save afabri/acc723427888dc49c60099bdb6220c53 to your computer and use it in GitHub Desktop.
Minimal code showing a compilation problem for boost multiprecision and operator, combined with Eigen on VC2017
#include <boost/operators.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <Eigen/Dense>
// Quotient
template <class NT_>
class Toto
: boost::additive2 < Toto<NT_>, NT_ >
{
public:
NT_ num, den;
Toto() {}
Toto(const NT_& a) {}
Toto(const NT_& a, const NT_&b) {}
template <class T>
Toto operator+=(const T&) { return *this; }
};
// Sqrt_extension:
template <class NT_>
class Toto2
: boost::additive2 < Toto2<NT_>, NT_ >
{
public:
NT_ num, den;
Toto2() {}
Toto2(const NT_& nt)
{}
template <class T>
Toto2 operator+=(const T&) { return *this; }
};
void toto(Toto<boost::multiprecision::cpp_int>& x)
{
x.den;
}
// No idea if needed
namespace Eigen {
template<class> struct NumTraits;
template<class NT> struct NumTraits<Toto<NT> >
{
typedef Toto<NT> Real;
typedef Toto<NT> NonInteger;
typedef Toto<NT> Nested;
typedef Toto<NT> Literal;
static inline Real epsilon() { return NumTraits<NT>::epsilon(); }
static inline Real dummy_precision() { return NumTraits<NT>::dummy_precision(); }
enum {
IsInteger = 0,
IsSigned = 1,
IsComplex = 0,
RequireInitialization = NumTraits<NT>::RequireInitialization,
ReadCost = 2 * NumTraits<NT>::ReadCost,
AddCost = 150,
MulCost = 100
};
};
template<class NT> struct NumTraits<Toto2<NT> >
{
typedef Toto2<NT> Real;
typedef Toto2<NT> NonInteger;
typedef Toto2<NT> Nested;
typedef Toto2<NT> Literal;
static inline Real epsilon() { return NumTraits<NT>::epsilon(); }
static inline Real dummy_precision() { return NumTraits<NT>::dummy_precision(); }
enum {
IsInteger = 0,
IsSigned = 1,
IsComplex = 0,
RequireInitialization = NumTraits<NT>::RequireInitialization,
ReadCost = 2 * NumTraits<NT>::ReadCost,
AddCost = 150,
MulCost = 100
};
};
}
int main() {
typedef Toto2<int> NT;
Eigen::Matrix<NT, 3, 3> m(3, 3);
m + m;
return 0;
}
@janetournois
Copy link

I can reproduce the same errors as @afabri with Boost 1.74, Eigen 3.4 and MSVC 2017.

For consitency of our tests, here is the CMakeLists I am using

cmake_minimum_required(VERSION 3.1...3.23)
project(Number_types_Tests)

find_package(Boost 1.74 REQUIRED)
find_package(Eigen3 3.2.0 REQUIRED)

add_executable(boost-mp-operator-eigen-VC2017bug "boost-mp-operator-eigen-VC2017bug.cpp" )

target_link_libraries(boost-mp-operator-eigen-VC2017bug PUBLIC Eigen3::Eigen)
target_link_libraries(boost-mp-operator-eigen-VC2017bug PUBLIC Boost::boost)

@janetournois
Copy link

In my tests, the example does not compile with

  • Eigen 3.4 and master version
  • MSVC 2017, 2019 and 2022 compilers
  • boost 1.74

It does compile when I switch to boost 1.80

@afabri
Copy link
Author

afabri commented Mar 21, 2023

@sloriot had suggested to git bisect on boost::mp

@afabri
Copy link
Author

afabri commented Mar 22, 2023

@jzmaddock could it be a hacky fix to add a specialization of is_byte_container for Eigen::Matrix ?

typedef Eigen::Matrix<NT, 3, 3>::const_iterator It;
std::cout << typeid(It).name() << std::endl;

The output is void.

Adding this solves my problem above:

namespace boost {
    namespace multiprecision {
        namespace detail {
            template <class A, int B, int C, int D, int E, int F>
            struct is_byte_container< Eigen::Matrix<A,B,C,D,E,F>> 
            {
                static const bool value = false;
            };

} } }

In the real code I would also need a specialization for Ref<Eigen::Matrix<..>,..>, and maybe even more :<

@jzmaddock
Copy link

could it be a hacky fix to add a specialization of is_byte_container for Eigen::Matrix ?

It that fixes things, then I don't see why not - it would have to be to your code as a workaround, and you could predicate it on BOOST_VERSION should you wish - that would also protect you from any future changes to is_byte_container given that it's an implementation detail (not that I'm planning to change it, but you know, 12 months from now I'll probably have forgotten this conversation!).

@afabri
Copy link
Author

afabri commented Mar 23, 2023

I added these specializations in CGAL/config.h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment