eigen.hpp 10 KB

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