]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/multiprecision/eigen.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / 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
17 template <class B1, class B2>
18 struct NumTraitsImp;
19
20 template <class B1>
21 struct NumTraitsImp<B1, B1>
22 {
23 using self_type = 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;
28 enum
29 {
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,
32 ReadCost = 1,
33 AddCost = 4,
34 MulCost = 8,
35 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
36 RequireInitialization = 1,
37 };
38 static Real epsilon()
39 {
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();
42 }
43 static Real dummy_precision()
44 {
45 return 1000 * epsilon();
46 }
47 static Real highest()
48 {
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)();
51 }
52 static Real lowest()
53 {
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)();
56 }
57 static int digits10_imp(const std::integral_constant<bool, true>&)
58 {
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;
61 }
62 template <bool B>
63 static int digits10_imp(const std::integral_constant<bool, B>&)
64 {
65 return Real::thread_default_precision();
66 }
67 static int digits10()
68 {
69 return digits10_imp(std::integral_constant < bool, std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ());
70 }
71 static int digits()
72 {
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;
77 }
78 static int min_exponent()
79 {
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;
82 }
83 static int max_exponent()
84 {
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;
87 }
88 static Real infinity()
89 {
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();
92 }
93 static Real quiet_NaN()
94 {
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();
97 }
98 };
99
100 template <class B1, class B2>
101 struct NumTraitsImp : public NumTraitsImp<B2, B2>
102 {
103 //
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.
106 //
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;
112 enum
113 {
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,
116 ReadCost = 1,
117 AddCost = 4,
118 MulCost = 8,
119 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
120 RequireInitialization = 1,
121 };
122 static B2 epsilon()
123 {
124 return NumTraitsImp<B2, B2>::epsilon();
125 }
126 static B2 dummy_precision()
127 {
128 return 1000 * epsilon();
129 }
130 static B2 highest()
131 {
132 return NumTraitsImp<B2, B2>::highest();
133 }
134 static B2 lowest()
135 {
136 return NumTraitsImp<B2, B2>::lowest();
137 }
138 static int digits10()
139 {
140 return NumTraitsImp<B2, B2>::digits10();
141 }
142 static int digits()
143 {
144 return NumTraitsImp<B2, B2>::digits();
145 }
146 static int min_exponent()
147 {
148 return NumTraitsImp<B2, B2>::min_exponent();
149 }
150 static int max_exponent()
151 {
152 return NumTraitsImp<B2, B2>::max_exponent();
153 }
154 static B2 infinity()
155 {
156 return NumTraitsImp<B2, B2>::infinity();
157 }
158 static B2 quiet_NaN()
159 {
160 return NumTraitsImp<B2, B2>::quiet_NaN();
161 }
162 };
163
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>
166 {};
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>
169 {};
170
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> \
174 { \
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>; \
177 }; \
178 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
179 struct ScalarBinaryOpTraits<A, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> \
180 { \
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>; \
183 };
184
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)
197
198 #if 0
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>
201 {
202 static_assert(
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;
207 };
208
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>
211 {
212 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>;
213 };
214
215 template<typename BinaryOp>
216 struct ScalarBinaryOpTraits<boost::multiprecision::mpfr_float, boost::multiprecision::mpc_complex, BinaryOp>
217 {
218 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<0>, boost::multiprecision::et_on>;
219 };
220
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>
223 {
224 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
225 };
226 #endif
227
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>
230 {
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>;
233 };
234
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>
237 {
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>;
240 };
241
242 namespace internal {
243 template <typename Scalar>
244 struct conj_retval;
245
246 template <typename Scalar, bool IsComplex>
247 struct conj_impl;
248
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> >
251 {
252 using type = typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type;
253 };
254
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>
257 {
258 EIGEN_DEVICE_FUNC
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)
260 {
261 return conj(x);
262 }
263 };
264
265 } // namespace internal
266
267 } // namespace Eigen
268
269 #endif