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)
6 #ifndef BOOST_MP_EIGEN_HPP
7 #define BOOST_MP_EIGEN_HPP
9 #include <boost/multiprecision/number.hpp>
13 // Generic Eigen support code:
17 template <class B1, class B2>
21 struct NumTraitsImp<B1, B1>
24 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
25 using NonInteger = self_type; // Not correct but we can't do much better??
26 using Literal = double;
27 using Nested = self_type;
30 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
31 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
35 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
36 RequireInitialization = 1,
40 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?");
41 return std::numeric_limits<Real>::epsilon();
43 static Real dummy_precision()
45 return 1000 * epsilon();
49 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?");
50 return (std::numeric_limits<Real>::max)();
54 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?");
55 return (std::numeric_limits<Real>::min)();
57 static int digits10_imp(const std::integral_constant<bool, true>&)
59 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?");
60 return std::numeric_limits<Real>::digits10;
63 static int digits10_imp(const std::integral_constant<bool, B>&)
65 return Real::thread_default_precision();
69 return digits10_imp(std::integral_constant < bool, std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ());
73 // return the number of digits in the component type in case Real is complex
74 // and we have no numeric_limits specialization.
75 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?");
76 return std::numeric_limits<Real>::digits;
78 static int min_exponent()
80 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?");
81 return std::numeric_limits<Real>::min_exponent;
83 static int max_exponent()
85 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?");
86 return std::numeric_limits<Real>::max_exponent;
88 static Real infinity()
90 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?");
91 return std::numeric_limits<Real>::infinity();
93 static Real quiet_NaN()
95 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?");
96 return std::numeric_limits<Real>::quiet_NaN();
100 template <class B1, class B2>
101 struct NumTraitsImp : public NumTraitsImp<B2, B2>
104 // This version is instantiated when B1 and B2 are different types, this happens for rational/complex/interval
105 // types, in which case many methods defer to those of the "component type" B2.
107 using self_type = B1;
108 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
109 using NonInteger = self_type; // Not correct but we can't do much better??
110 using Literal = double;
111 using Nested = self_type;
114 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
115 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
119 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
120 RequireInitialization = 1,
124 return NumTraitsImp<B2, B2>::epsilon();
126 static B2 dummy_precision()
128 return 1000 * epsilon();
132 return NumTraitsImp<B2, B2>::highest();
136 return NumTraitsImp<B2, B2>::lowest();
138 static int digits10()
140 return NumTraitsImp<B2, B2>::digits10();
144 return NumTraitsImp<B2, B2>::digits();
146 static int min_exponent()
148 return NumTraitsImp<B2, B2>::min_exponent();
150 static int max_exponent()
152 return NumTraitsImp<B2, B2>::max_exponent();
156 return NumTraitsImp<B2, B2>::infinity();
158 static B2 quiet_NaN()
160 return NumTraitsImp<B2, B2>::quiet_NaN();
164 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
165 struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> > : public NumTraitsImp<boost::multiprecision::number<Backend, ExpressionTemplates>, typename boost::multiprecision::number<Backend, ExpressionTemplates>::value_type>
167 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
168 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>
171 #define BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(A) \
172 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
173 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, A, BinaryOp> \
175 /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \
176 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; \
178 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
179 struct ScalarBinaryOpTraits<A, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> \
181 /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \
182 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; \
185 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(float)
186 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(double)
187 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long double)
188 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(char)
189 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned char)
190 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(signed char)
191 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(short)
192 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned short)
193 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(int)
194 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned int)
195 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long)
196 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned long)
199 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Backend2, boost::multiprecision::expression_template_option ExpressionTemplates2, typename BinaryOp>
200 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2>, BinaryOp>
203 boost::multiprecision::is_compatible_arithmetic_type<boost::multiprecision::number<Backend2, ExpressionTemplates2>, boost::multiprecision::number<Backend, ExpressionTemplates> >::value
204 || 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.");
205 using ReturnType = typename std::conditional<std::is_convertible<boost::multiprecision::number<Backend2, ExpressionTemplates2>, boost::multiprecision::number<Backend, ExpressionTemplates> >::value,
206 boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2> >::type;
209 template<unsigned D, typename BinaryOp>
210 struct ScalarBinaryOpTraits<boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>, boost::multiprecision::mpfr_float, BinaryOp>
212 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>;
215 template<typename BinaryOp>
216 struct ScalarBinaryOpTraits<boost::multiprecision::mpfr_float, boost::multiprecision::mpc_complex, BinaryOp>
218 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<0>, boost::multiprecision::et_on>;
221 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp>
222 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp>
224 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
228 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4, typename BinaryOp>
229 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, BinaryOp>
231 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.");
232 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
235 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp>
236 struct ScalarBinaryOpTraits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp>
238 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.");
239 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
243 template <typename Scalar>
246 template <typename Scalar, bool IsComplex>
249 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
250 struct conj_retval<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
252 using type = typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
255 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
256 struct conj_impl<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, true>
259 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)
265 } // namespace internal