1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright 2018 John Maddock. Distributed under the Boost 3 // Software License, Version 1.0. (See accompanying file 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_MP_EIGEN_HPP 7 #define BOOST_MP_EIGEN_HPP 8 9 #include <boost/multiprecision/number.hpp> 10 #include <Eigen/Core> 11 12 // 13 // Generic Eigen support code: 14 // 15 namespace Eigen { 16 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates> 17 struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> > 18 { 19 using self_type = boost::multiprecision::number<Backend, ExpressionTemplates> ; 20 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type; 21 using NonInteger = self_type ; // Not correct but we can't do much better?? 22 using Literal = double ; 23 using Nested = self_type ; 24 enum 25 { 26 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex, 27 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer, 28 ReadCost = 1, 29 AddCost = 4, 30 MulCost = 8, 31 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true, 32 RequireInitialization = 1, 33 }; epsilonEigen::NumTraits34 static Real epsilon() 35 { 36 return std::numeric_limits<Real>::epsilon(); 37 } dummy_precisionEigen::NumTraits38 static Real dummy_precision() 39 { 40 return 1000 * epsilon(); 41 } highestEigen::NumTraits42 static Real highest() 43 { 44 return (std::numeric_limits<Real>::max)(); 45 } lowestEigen::NumTraits46 static Real lowest() 47 { 48 return (std::numeric_limits<Real>::min)(); 49 } digits10_impEigen::NumTraits50 static int digits10_imp(const std::integral_constant<bool, true>&) 51 { 52 return std::numeric_limits<Real>::digits10; 53 } 54 template <bool B> digits10_impEigen::NumTraits55 static int digits10_imp(const std::integral_constant<bool, B>&) 56 { 57 return Real::thread_default_precision(); 58 } digits10Eigen::NumTraits59 static int digits10() 60 { 61 return digits10_imp(std::integral_constant<bool, std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ()); 62 } 63 }; 64 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4> 65 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> 66 { 67 }; 68 69 #define BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(A) \ 70 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \ 71 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, A, BinaryOp> \ 72 { \ 73 /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \ 74 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; \ 75 }; \ 76 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \ 77 struct ScalarBinaryOpTraits<A, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> \ 78 { \ 79 /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \ 80 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; \ 81 }; 82 83 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(float) 84 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(double) 85 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long double) 86 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(char) 87 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned char) 88 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(signed char) 89 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(short) 90 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned short) 91 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(int) 92 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned int) 93 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long) 94 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned long) 95 96 #if 0 97 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Backend2, boost::multiprecision::expression_template_option ExpressionTemplates2, typename BinaryOp> 98 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2>, BinaryOp> 99 { 100 static_assert( 101 boost::multiprecision::is_compatible_arithmetic_type<boost::multiprecision::number<Backend2, ExpressionTemplates2>, boost::multiprecision::number<Backend, ExpressionTemplates> >::value 102 || boost::multiprecision::is_compatible_arithmetic_type<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2> >::value, "Interoperability with this arithmetic type is not supported."); 103 using ReturnType = typename std::conditional<std::is_convertible<boost::multiprecision::number<Backend2, ExpressionTemplates2>, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, 104 boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2> >::type; 105 }; 106 107 template<unsigned D, typename BinaryOp> 108 struct ScalarBinaryOpTraits<boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>, boost::multiprecision::mpfr_float, BinaryOp> 109 { 110 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>; 111 }; 112 113 template<typename BinaryOp> 114 struct ScalarBinaryOpTraits<boost::multiprecision::mpfr_float, boost::multiprecision::mpc_complex, BinaryOp> 115 { 116 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<0>, boost::multiprecision::et_on>; 117 }; 118 119 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> 120 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> 121 { 122 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; 123 }; 124 #endif 125 126 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4, typename BinaryOp> 127 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, BinaryOp> 128 { 129 static_assert(std::is_convertible<typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported."); 130 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; 131 }; 132 133 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> 134 struct ScalarBinaryOpTraits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> 135 { 136 static_assert(std::is_convertible<typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported."); 137 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; 138 }; 139 140 namespace internal { 141 template <typename Scalar> 142 struct conj_retval; 143 144 template <typename Scalar, bool IsComplex> 145 struct conj_impl; 146 147 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4> 148 struct conj_retval<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > 149 { 150 using type = typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type; 151 }; 152 153 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4> 154 struct conj_impl<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, true> 155 { 156 EIGEN_DEVICE_FUNC runEigen::internal::conj_impl157 static inline typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type run(const typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& x) 158 { 159 return conj(x); 160 } 161 }; 162 163 } // namespace internal 164 165 } // namespace Eigen 166 167 #endif 168