-
-
Save afabri/acc723427888dc49c60099bdb6220c53 to your computer and use it in GitHub Desktop.
#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; | |
} |
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
@sloriot had suggested to git bisect on boost::mp
@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 :<
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!).
I added these specializations in CGAL/config.h
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