Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / multiprecision / eigen.hpp
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    typedef boost::multiprecision::number<Backend, ExpressionTemplates>                          self_type;
20    typedef typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type Real;
21    typedef self_type                                                                            NonInteger; // Not correct but we can't do much better??
22    typedef double                                                                               Literal;
23    typedef self_type                                                                            Nested;
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    };
34    static Real epsilon()
35    {
36       return std::numeric_limits<Real>::epsilon();
37    }
38    static Real dummy_precision()
39    {
40       return 1000 * epsilon();
41    }
42    static Real highest()
43    {
44       return (std::numeric_limits<Real>::max)();
45    }
46    static Real lowest()
47    {
48       return (std::numeric_limits<Real>::min)();
49    }
50    static int digits10_imp(const boost::mpl::true_&)
51    {
52       return std::numeric_limits<Real>::digits10;
53    }
54    template <bool B>
55    static int digits10_imp(const boost::mpl::bool_<B>&)
56    {
57       return Real::default_precision();
58    }
59    static int digits10()
60    {
61       return digits10_imp(boost::mpl::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       typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;                                                                                                                                  \
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       typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;                                                                                                                                  \
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       typedef typename boost::mpl::if_c<boost::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 ReturnType;
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       typedef boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on> ReturnType;
111    };
112
113    template<typename BinaryOp>
114    struct ScalarBinaryOpTraits<boost::multiprecision::mpfr_float, boost::multiprecision::mpc_complex, BinaryOp>
115    {
116       typedef boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<0>, boost::multiprecision::et_on> ReturnType;
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       typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
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(boost::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    typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
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(boost::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    typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
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    typedef typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type 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
157    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