pinocchio  2.4.5
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
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 #ifndef PINOCCHIO_WITH_CXX11_SUPPORT
11  #error C++11 compiler required.
12 #endif
13 
14 #include <boost/multiprecision/number.hpp>
15 #include <Eigen/Dense>
16 
17 namespace Eigen
18 {
19  namespace internal
20  {
21  template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename Scalar>
22  struct cast_impl<boost::multiprecision::number<Backend, ExpressionTemplates>,Scalar>
23  {
24 #if EIGEN_VERSION_AT_LEAST(3,2,90)
25  EIGEN_DEVICE_FUNC
26 #endif
27  static inline Scalar run(const boost::multiprecision::number<Backend, ExpressionTemplates> & x)
28  {
29  return x.template convert_to<Scalar>();
30  }
31  };
32  }
33 } //namespace Eigen
34 
35 #ifndef BOOST_MP_EIGEN_HPP
36 
37 // Code adapted from <boost/multiprecision/eigen.hpp>
38 // Copyright 2018 John Maddock. Distributed under the Boost
39 // Software License, Version 1.0. (See accompanying file
40 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
41 namespace Eigen
42 {
43  template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
44  struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> >
45  {
46  typedef boost::multiprecision::number<Backend, ExpressionTemplates> self_type;
47 #if BOOST_VERSION / 100 % 1000 >= 68
48  typedef typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type Real;
49 #else
50  typedef self_type Real;
51 #endif
52  typedef self_type NonInteger; // Not correct but we can't do much better??
53  typedef double Literal;
54  typedef self_type Nested;
55  enum
56  {
57 #if BOOST_VERSION / 100 % 1000 >= 68
58  IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
59 #else
60  IsComplex = 0,
61 #endif
62  IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
63  ReadCost = 1,
64  AddCost = 4,
65  MulCost = 8,
66  IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
67  RequireInitialization = 1
68  };
69  static Real epsilon()
70  {
71  return std::numeric_limits<Real>::epsilon();
72  }
73  static Real dummy_precision()
74  {
75  return 1000 * epsilon();
76  }
77  static Real highest()
78  {
79  return (std::numeric_limits<Real>::max)();
80  }
81  static Real lowest()
82  {
83  return (std::numeric_limits<Real>::min)();
84  }
85  static int digits10_imp(const boost::mpl::true_&)
86  {
87  return std::numeric_limits<Real>::digits10;
88  }
89  template <bool B>
90  static int digits10_imp(const boost::mpl::bool_<B>&)
91  {
92  return Real::default_precision();
93  }
94  static int digits10()
95  {
96  return digits10_imp(boost::mpl::bool_ < std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ());
97  }
98  };
99 
100  template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
101  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>
102  {
103  };
104 
105 #if EIGEN_VERSION_AT_LEAST(3,2,93)
106 #define BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(A) \
107  template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
108  struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, A, BinaryOp> \
109  { \
110  /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \
111  typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType; \
112  }; \
113  template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
114  struct ScalarBinaryOpTraits<A, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> \
115  { \
116  /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \
117  typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType; \
118  };
119 
120  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(float)
121  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(double)
122  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long double)
123  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(char)
124  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned char)
125  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(signed char)
126  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(short)
127  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned short)
128  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(int)
129  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned int)
130  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long)
131  BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned long)
132 
133  template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4, typename BinaryOp>
134  struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, 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  template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp>
141  struct ScalarBinaryOpTraits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp>
142  {
143  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.");
144  typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
145  };
146 #endif
147 
148  namespace internal
149  {
150 
151  template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
152  struct scalar_product_traits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
153  {
154  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.");
155  typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
156  };
157 
158  template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
159  struct scalar_product_traits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::number<Backend, ExpressionTemplates> >
160  {
161  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.");
162  typedef boost::multiprecision::number<Backend, ExpressionTemplates> ReturnType;
163  };
164 
165  template <typename Scalar>
166  struct conj_retval;
167 
168  template <typename Scalar, bool IsComplex>
169  struct conj_impl;
170 
171  template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
172  struct conj_retval<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
173  {
174  typedef typename boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type type;
175  };
176 
177  template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
178  struct conj_impl<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, true>
179  {
180 #if EIGEN_VERSION_AT_LEAST(3,2,90)
181  EIGEN_DEVICE_FUNC
182 #endif
183  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)
184  {
185  return conj(x);
186  }
187  };
188 
189  } // namespace internal
190 
191 } // namespace Eigen
192 
193 #endif // ifndef BOOST_MP_EIGEN_HPP
194 
195 #endif // ifndef __pinocchio_math_mutliprecision_hpp__