mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-01-19 04:22:11 +00:00
Update Eigen NumTraits code.
Eigen's requirements have changed in version 3.4. Also improve testing and better support variable precision types.
This commit is contained in:
@@ -13,14 +13,18 @@
|
||||
// Generic Eigen support code:
|
||||
//
|
||||
namespace Eigen {
|
||||
template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
||||
struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
||||
|
||||
template <class B1, class B2>
|
||||
struct NumTraitsImp;
|
||||
|
||||
template <class B1>
|
||||
struct NumTraitsImp<B1, B1>
|
||||
{
|
||||
using self_type = boost::multiprecision::number<Backend, ExpressionTemplates> ;
|
||||
using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
|
||||
using NonInteger = self_type ; // Not correct but we can't do much better??
|
||||
using Literal = double ;
|
||||
using Nested = self_type ;
|
||||
using self_type = B1;
|
||||
using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
|
||||
using NonInteger = self_type; // Not correct but we can't do much better??
|
||||
using Literal = double;
|
||||
using Nested = self_type;
|
||||
enum
|
||||
{
|
||||
IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
|
||||
@@ -33,6 +37,7 @@ struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
||||
};
|
||||
static Real epsilon()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::epsilon();
|
||||
}
|
||||
static Real dummy_precision()
|
||||
@@ -41,14 +46,17 @@ struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
||||
}
|
||||
static Real highest()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return (std::numeric_limits<Real>::max)();
|
||||
}
|
||||
static Real lowest()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return (std::numeric_limits<Real>::min)();
|
||||
}
|
||||
static int digits10_imp(const std::integral_constant<bool, true>&)
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::digits10;
|
||||
}
|
||||
template <bool B>
|
||||
@@ -58,13 +66,107 @@ struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
||||
}
|
||||
static int digits10()
|
||||
{
|
||||
return digits10_imp(std::integral_constant<bool, std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ());
|
||||
return digits10_imp(std::integral_constant < bool, std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ());
|
||||
}
|
||||
static int digits()
|
||||
{
|
||||
// return the number of digits in the component type in case Real is complex
|
||||
// and we have no numeric_limits specialization.
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::digits;
|
||||
}
|
||||
static int min_exponent()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::min_exponent;
|
||||
}
|
||||
static int max_exponent()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::max_exponent;
|
||||
}
|
||||
static Real infinity()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::infinity();
|
||||
}
|
||||
static Real quiet_NaN()
|
||||
{
|
||||
static_assert(std::numeric_limits<Real>::is_specialized, "Eigen's NumTraits instantiated on a type with no numeric_limits support. Are you using a variable precision type?");
|
||||
return std::numeric_limits<Real>::quiet_NaN();
|
||||
}
|
||||
};
|
||||
|
||||
template <class B1, class B2>
|
||||
struct NumTraitsImp : public NumTraitsImp<B2, B2>
|
||||
{
|
||||
//
|
||||
// This version is instantiated when B1 and B2 are different types, this happens for rational/complex/interval
|
||||
// types, in which case many methods defer to those of the "component type" B2.
|
||||
//
|
||||
using self_type = B1;
|
||||
using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
|
||||
using NonInteger = self_type; // Not correct but we can't do much better??
|
||||
using Literal = double;
|
||||
using Nested = self_type;
|
||||
enum
|
||||
{
|
||||
IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
|
||||
IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
|
||||
ReadCost = 1,
|
||||
AddCost = 4,
|
||||
MulCost = 8,
|
||||
IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
|
||||
RequireInitialization = 1,
|
||||
};
|
||||
static B2 epsilon()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::epsilon();
|
||||
}
|
||||
static B2 dummy_precision()
|
||||
{
|
||||
return 1000 * epsilon();
|
||||
}
|
||||
static B2 highest()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::highest();
|
||||
}
|
||||
static B2 lowest()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::lowest();
|
||||
}
|
||||
static int digits10()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::digits10();
|
||||
}
|
||||
static int digits()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::digits();
|
||||
}
|
||||
static int min_exponent()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::min_exponent();
|
||||
}
|
||||
static int max_exponent()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::max_exponent();
|
||||
}
|
||||
static B2 infinity()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::infinity();
|
||||
}
|
||||
static B2 quiet_NaN()
|
||||
{
|
||||
return NumTraitsImp<B2, B2>::quiet_NaN();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
||||
struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> > : public NumTraitsImp<boost::multiprecision::number<Backend, ExpressionTemplates>, typename boost::multiprecision::number<Backend, ExpressionTemplates>::value_type>
|
||||
{};
|
||||
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
|
||||
struct NumTraits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public NumTraits<typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>
|
||||
{
|
||||
};
|
||||
{};
|
||||
|
||||
#define BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(A) \
|
||||
template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
|
||||
|
||||
@@ -3609,4 +3609,73 @@ constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace Eigen
|
||||
{
|
||||
|
||||
template <class B1, class B2>
|
||||
struct NumTraitsImp;
|
||||
|
||||
template <boost::multiprecision::expression_template_option ExpressionTemplates>
|
||||
struct NumTraitsImp<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>, boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
|
||||
{
|
||||
using self_type = boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>;
|
||||
using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
|
||||
using NonInteger = self_type; // Not correct but we can't do much better??
|
||||
using Literal = double;
|
||||
using Nested = self_type;
|
||||
enum
|
||||
{
|
||||
IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
|
||||
IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
|
||||
ReadCost = 1,
|
||||
AddCost = 4,
|
||||
MulCost = 8,
|
||||
IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
|
||||
RequireInitialization = 1,
|
||||
};
|
||||
static Real epsilon()
|
||||
{
|
||||
return boost::math::tools::epsilon<Real>();
|
||||
}
|
||||
static Real dummy_precision()
|
||||
{
|
||||
return 1000 * epsilon();
|
||||
}
|
||||
static Real highest()
|
||||
{
|
||||
return boost::math::tools::max_value<Real>();
|
||||
}
|
||||
static Real lowest()
|
||||
{
|
||||
return boost::math::tools::min_value<Real>();
|
||||
}
|
||||
static int digits10()
|
||||
{
|
||||
return Real::thread_default_precision();
|
||||
}
|
||||
static int digits()
|
||||
{
|
||||
return boost::math::tools::digits<Real>();
|
||||
}
|
||||
static int min_exponent()
|
||||
{
|
||||
return LONG_MIN;
|
||||
}
|
||||
static int max_exponent()
|
||||
{
|
||||
return LONG_MAX;
|
||||
}
|
||||
static Real infinity()
|
||||
{
|
||||
return Real();
|
||||
}
|
||||
static Real quiet_NaN()
|
||||
{
|
||||
return Real();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3078,6 +3078,74 @@ inline boost::multiprecision::number<boost::multiprecision::backends::logged_ada
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace Eigen
|
||||
{
|
||||
|
||||
template <class B1, class B2>
|
||||
struct NumTraitsImp;
|
||||
|
||||
template <boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
|
||||
struct NumTraitsImp<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>, boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>
|
||||
{
|
||||
using self_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>;
|
||||
using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
|
||||
using NonInteger = self_type; // Not correct but we can't do much better??
|
||||
using Literal = double;
|
||||
using Nested = self_type;
|
||||
enum
|
||||
{
|
||||
IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
|
||||
IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
|
||||
ReadCost = 1,
|
||||
AddCost = 4,
|
||||
MulCost = 8,
|
||||
IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
|
||||
RequireInitialization = 1,
|
||||
};
|
||||
static Real epsilon()
|
||||
{
|
||||
return boost::math::tools::epsilon< boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
|
||||
}
|
||||
static Real dummy_precision()
|
||||
{
|
||||
return 1000 * epsilon();
|
||||
}
|
||||
static Real highest()
|
||||
{
|
||||
return boost::math::tools::max_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
|
||||
}
|
||||
static Real lowest()
|
||||
{
|
||||
return boost::math::tools::min_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
|
||||
}
|
||||
static int digits10()
|
||||
{
|
||||
return Real::thread_default_precision();
|
||||
}
|
||||
static int digits()
|
||||
{
|
||||
return boost::math::tools::digits<Real>();
|
||||
}
|
||||
static int min_exponent()
|
||||
{
|
||||
return mpfr_get_emin();
|
||||
}
|
||||
static int max_exponent()
|
||||
{
|
||||
return mpfr_get_emax();
|
||||
}
|
||||
static Real infinity()
|
||||
{
|
||||
return std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<50, AllocateType>, ExpressionTemplates>>::infinity();
|
||||
}
|
||||
static Real quiet_NaN()
|
||||
{
|
||||
return std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<50, AllocateType>, ExpressionTemplates>>::quiet_NaN();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
//
|
||||
|
||||
@@ -1171,11 +1171,20 @@ test-suite misc :
|
||||
[ run test_eigen_interop_mpfr_1.cpp mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpfr : : <build>no ] ]
|
||||
[ run test_eigen_interop_mpfr_2.cpp mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpfr : : <build>no ] ]
|
||||
[ run test_eigen_interop_mpfr_3.cpp mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpfr : : <build>no ] ]
|
||||
[ run test_eigen_interop_mpfr_4.cpp mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpfr : : <build>no ] ]
|
||||
[ run test_eigen_interop_mpfr_5.cpp mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpfr : : <build>no ] ]
|
||||
[ run test_eigen_interop_mpfr_6.cpp mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpfr : : <build>no ] ]
|
||||
[ run test_eigen_interop_gmp.cpp gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_gmp : : <build>no ] ]
|
||||
[ run test_eigen_interop_gmp_2.cpp gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_gmp : : <build>no ] ]
|
||||
[ run test_eigen_interop_mpc.cpp mpc mpfr gmp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] [ check-target-builds ../config//has_mpc : : <build>no ] ]
|
||||
[ run git_issue_393.cpp : : : release [ check-target-builds ../config//has_eigen : : <build>no ] ]
|
||||
[ compile git_issue_393.cpp : release [ check-target-builds ../config//has_eigen : : <build>no ] ]
|
||||
;
|
||||
|
||||
alias eigen_tests : test_eigen_interop_cpp_int test_eigen_interop_cpp_dec_float test_eigen_interop_cpp_dec_float_2 test_eigen_interop_cpp_dec_float_3
|
||||
test_eigen_interop_cpp_bin_float_1 test_eigen_interop_cpp_bin_float_2 test_eigen_interop_cpp_bin_float_3 test_eigen_interop_mpfr_1
|
||||
test_eigen_interop_mpfr_2 test_eigen_interop_mpfr_3 test_eigen_interop_mpfr_4 test_eigen_interop_mpfr_5 test_eigen_interop_mpfr_6
|
||||
test_eigen_interop_gmp test_eigen_interop_gmp_2 test_eigen_interop_mpc git_issue_393 ;
|
||||
|
||||
|
||||
#
|
||||
# This take too long to run as a regular part of the tests:
|
||||
|
||||
@@ -549,15 +549,6 @@ void test_float_type()
|
||||
example15<Num>();
|
||||
example16<Num>();
|
||||
example17<Num>();
|
||||
/*
|
||||
example18<Num>();
|
||||
example19<Num>();
|
||||
example20<Num>();
|
||||
example21<Num>();
|
||||
example22<Num>();
|
||||
example23<Num>();
|
||||
example24<Num>();
|
||||
*/
|
||||
}
|
||||
|
||||
template <class Num>
|
||||
@@ -573,10 +564,6 @@ void test_float_type_2()
|
||||
example19<Num>();
|
||||
example20<Num>();
|
||||
example21<Num>();
|
||||
|
||||
//example22<Num>();
|
||||
//example23<Num>();
|
||||
//example24<Num>();
|
||||
}
|
||||
|
||||
template <class Num>
|
||||
|
||||
@@ -12,5 +12,6 @@ int main()
|
||||
using namespace boost::multiprecision;
|
||||
test_integer_type<boost::multiprecision::mpz_int>();
|
||||
test_integer_type<boost::multiprecision::mpq_rational>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
15
test/test_eigen_interop_gmp_2.cpp
Normal file
15
test/test_eigen_interop_gmp_2.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2018 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/multiprecision/gmp.hpp>
|
||||
|
||||
#include "eigen.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
test_float_type<boost::multiprecision::mpf_float_50>();
|
||||
test_float_type<boost::multiprecision::mpf_float>();
|
||||
return 0;
|
||||
}
|
||||
@@ -11,5 +11,6 @@ int main()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
test_complex_type<mpc_complex>();
|
||||
test_complex_type<mpc_complex_50>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
15
test/test_eigen_interop_mpfr_4.cpp
Normal file
15
test/test_eigen_interop_mpfr_4.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2018 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/multiprecision/mpfr.hpp>
|
||||
|
||||
#include "eigen.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
test_float_type<boost::multiprecision::mpfr_float_50>();
|
||||
return 0;
|
||||
}
|
||||
15
test/test_eigen_interop_mpfr_5.cpp
Normal file
15
test/test_eigen_interop_mpfr_5.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2018 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/multiprecision/mpfr.hpp>
|
||||
|
||||
#include "eigen.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
test_float_type_2<boost::multiprecision::mpfr_float_50>();
|
||||
return 0;
|
||||
}
|
||||
15
test/test_eigen_interop_mpfr_6.cpp
Normal file
15
test/test_eigen_interop_mpfr_6.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2018 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/multiprecision/mpfr.hpp>
|
||||
|
||||
#include "eigen.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
test_float_type_3<boost::multiprecision::mpfr_float_50>();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user