pinocchio  3.7.0
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
 
Loading...
Searching...
No Matches
multiprecision.hpp
1//
2// Copyright (c) 2020 INRIA
3//
4
5#ifndef __pinocchio_math_mutliprecision_hpp__
6#define __pinocchio_math_mutliprecision_hpp__
7
8#include "pinocchio/math/fwd.hpp"
9
10#include <boost/multiprecision/number.hpp>
11#include <boost/random.hpp>
12#include <Eigen/Dense>
13
14namespace pinocchio
15{
16 // We check std::numeric_limits<_>::has_infinity to exclude integral, rational
17 // and complex types
18 template<typename Backend, boost::multiprecision::expression_template_option ET>
20 : boost::integral_constant<
21 bool,
22 ((!std::numeric_limits<boost::multiprecision::number<Backend, ET>>::is_integer
23 && std::numeric_limits<boost::multiprecision::number<Backend, ET>>::has_infinity))>
24 {
25 };
26} // namespace pinocchio
27
28namespace Eigen
29{
30 namespace internal
31 {
32 template<
33 class Backend,
34 boost::multiprecision::expression_template_option ExpressionTemplates,
35 typename Scalar>
36 struct cast_impl<boost::multiprecision::number<Backend, ExpressionTemplates>, Scalar>
37 {
38#if EIGEN_VERSION_AT_LEAST(3, 2, 90)
39 EIGEN_DEVICE_FUNC
40#endif
41 static inline Scalar
42 run(const boost::multiprecision::number<Backend, ExpressionTemplates> & x)
43 {
44 return x.template convert_to<Scalar>();
45 }
46 };
47 } // namespace internal
48} // namespace Eigen
49
50#ifndef BOOST_MP_EIGEN_HPP
51
52// Code adapted from <boost/multiprecision/eigen.hpp>
53// Copyright 2018 John Maddock. Distributed under the Boost
54// Software License, Version 1.0. (See accompanying file
55// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
56namespace Eigen
57{
58 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
59 struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates>>
60 {
61 typedef boost::multiprecision::number<Backend, ExpressionTemplates> self_type;
62 #if BOOST_VERSION / 100 % 1000 >= 68
63 typedef
64 typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type Real;
65 #else
66 typedef self_type Real;
67 #endif
68 typedef self_type NonInteger; // Not correct but we can't do much better??
69 typedef double Literal;
70 typedef self_type Nested;
71 enum
72 {
73 #if BOOST_VERSION / 100 % 1000 >= 68
74 IsComplex = boost::multiprecision::number_category<self_type>::value
75 == boost::multiprecision::number_kind_complex,
76 #else
77 IsComplex = 0,
78 #endif
79 IsInteger = boost::multiprecision::number_category<self_type>::value
80 == boost::multiprecision::number_kind_integer,
81 ReadCost = 1,
82 AddCost = 4,
83 MulCost = 8,
84 IsSigned = std::numeric_limits<self_type>::is_specialized
85 ? std::numeric_limits<self_type>::is_signed
86 : true,
87 RequireInitialization = 1
88 };
89 static Real epsilon()
90 {
91 return std::numeric_limits<Real>::epsilon();
92 }
93 static Real dummy_precision()
94 {
95 return 1000 * epsilon();
96 }
97 static Real highest()
98 {
99 return (std::numeric_limits<Real>::max)();
100 }
101 static Real lowest()
102 {
103 return (std::numeric_limits<Real>::min)();
104 }
105 static int digits10_imp(const boost::mpl::true_ &)
106 {
107 return std::numeric_limits<Real>::digits10;
108 }
109 template<bool B>
110 static int digits10_imp(const boost::mpl::bool_<B> &)
111 {
112 return static_cast<int>(Real::default_precision());
113 }
114 static int digits10()
115 {
116 return digits10_imp(
117 boost::mpl::bool_<
118 std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX)
119 ? true
120 : false>());
121 }
122
123 constexpr static inline int digits()
124 {
125 return internal::default_digits_impl<self_type>::run();
126 }
127
128 #if EIGEN_VERSION_AT_LEAST(3, 4, 90)
129 constexpr static inline int max_digits10()
130 {
131 return internal::default_max_digits10_impl<Real>::run();
132 }
133 #endif
134 };
135
136 template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
137 struct NumTraits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>>
138 : public NumTraits<
139 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>
140 {
141 };
142
143 #if EIGEN_VERSION_AT_LEAST(3, 4, 90)
144 // Fix random generator number in 3.4.90. TODO(jcarpent): Yet, we should wait for Eigen 3.5.0 to
145 // the proper fix in Eigen/src/Core/MathFunctions.h.
146 namespace internal
147 {
148 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
149 struct random_default_impl<
150 boost::multiprecision::number<Backend, ExpressionTemplates>,
151 false,
152 false>
153 {
154 typedef boost::multiprecision::number<Backend, ExpressionTemplates> Scalar;
155
156 static inline Scalar run(const Scalar & x, const Scalar & y)
157 {
158 return x + (y - x) * Scalar(std::rand()) / Scalar(RAND_MAX);
159 }
160 static inline Scalar run()
161 {
162 return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1));
163 }
164 };
165 } // namespace internal
166 #endif
167
168 #if EIGEN_VERSION_AT_LEAST(3, 2, 93)
169 #define BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(A) \
170 template< \
171 class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, \
172 typename BinaryOp> \
173 struct ScalarBinaryOpTraits< \
174 boost::multiprecision::number<Backend, ExpressionTemplates>, A, BinaryOp> \
175 { \
176 /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, \
177 * boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability \
178 * with this arithmetic type is not supported.");*/ \
179 typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType; \
180 }; \
181 template< \
182 class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, \
183 typename BinaryOp> \
184 struct ScalarBinaryOpTraits< \
185 A, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> \
186 { \
187 /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, \
188 * boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability \
189 * with this arithmetic type is not supported.");*/ \
190 typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType; \
191 };
192
193 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(float)
194 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(double)
195 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long double)
196 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(char)
197 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned char)
198 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(signed char)
199 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(short)
200 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned short)
201 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(int)
202 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned int)
203 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long)
204 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned long)
205
206 template<
207 class Backend,
208 boost::multiprecision::expression_template_option ExpressionTemplates,
209 class tag,
210 class Arg1,
211 class Arg2,
212 class Arg3,
213 class Arg4,
214 typename BinaryOp>
215 struct ScalarBinaryOpTraits<
216 boost::multiprecision::number<Backend, ExpressionTemplates>,
217 boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>,
218 BinaryOp>
219 {
220 static_assert(
221 boost::is_convertible<
222 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::
223 result_type,
224 boost::multiprecision::number<Backend, ExpressionTemplates>>::value,
225 "Interoperability with this arithmetic type is not supported.");
226 typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
227 };
228
229 template<
230 class tag,
231 class Arg1,
232 class Arg2,
233 class Arg3,
234 class Arg4,
235 class Backend,
236 boost::multiprecision::expression_template_option ExpressionTemplates,
237 typename BinaryOp>
238 struct ScalarBinaryOpTraits<
239 boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>,
240 boost::multiprecision::number<Backend, ExpressionTemplates>,
241 BinaryOp>
242 {
243 static_assert(
244 boost::is_convertible<
245 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::
246 result_type,
247 boost::multiprecision::number<Backend, ExpressionTemplates>>::value,
248 "Interoperability with this arithmetic type is not supported.");
249 typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
250 };
251 #endif
252
253 namespace internal
254 {
255
256 template<
257 class Backend,
258 boost::multiprecision::expression_template_option ExpressionTemplates,
259 class tag,
260 class Arg1,
261 class Arg2,
262 class Arg3,
263 class Arg4>
264 struct scalar_product_traits<
265 boost::multiprecision::number<Backend, ExpressionTemplates>,
266 boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>>
267 {
268 static_assert(
269 boost::is_convertible<
270 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::
271 result_type,
272 boost::multiprecision::number<Backend, ExpressionTemplates>>::value,
273 "Interoperability with this arithmetic type is not supported.");
274 typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
275 };
276
277 template<
278 class tag,
279 class Arg1,
280 class Arg2,
281 class Arg3,
282 class Arg4,
283 class Backend,
284 boost::multiprecision::expression_template_option ExpressionTemplates>
285 struct scalar_product_traits<
286 boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>,
287 boost::multiprecision::number<Backend, ExpressionTemplates>>
288 {
289 static_assert(
290 boost::is_convertible<
291 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::
292 result_type,
293 boost::multiprecision::number<Backend, ExpressionTemplates>>::value,
294 "Interoperability with this arithmetic type is not supported.");
295 typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
296 };
297
298 template<typename Scalar>
299 struct conj_retval;
300
301 template<typename Scalar, bool IsComplex>
302 #if EIGEN_VERSION_AT_LEAST(3, 3, 9)
303 struct conj_default_impl;
304 #else
305 struct conj_impl;
306 #endif
307
308 template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
309 struct conj_retval<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>>
310 {
311 typedef
312 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type
313 type;
314 };
315
316 template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
317 #if EIGEN_VERSION_AT_LEAST(3, 3, 9)
318 struct conj_default_impl<
319 boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>,
320 true>
321 #else
322 struct conj_impl<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, true>
323 #endif
324 {
325 #if EIGEN_VERSION_AT_LEAST(3, 2, 90)
326 EIGEN_DEVICE_FUNC
327 #endif
328 static inline
329 typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type
330 run(
331 const typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> & x)
332 {
333 return conj(x);
334 }
335 };
336
337 } // namespace internal
338
339} // namespace Eigen
340
341#endif // ifndef BOOST_MP_EIGEN_HPP
342
343#endif // ifndef __pinocchio_math_mutliprecision_hpp__
Main pinocchio namespace.
Definition treeview.dox:11