File indexing completed on 2025-01-30 09:48:43
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MP_EIGEN_HPP
0007 #define BOOST_MP_EIGEN_HPP
0008
0009 #include <boost/multiprecision/number.hpp>
0010 #include <Eigen/Core>
0011
0012
0013
0014
0015 namespace Eigen {
0016
0017 template <class B1, class B2>
0018 struct NumTraitsImp;
0019
0020 template <class B1>
0021 struct NumTraitsImp<B1, B1>
0022 {
0023 using self_type = B1;
0024 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
0025 using NonInteger = self_type;
0026 using Literal = double;
0027 using Nested = self_type;
0028 enum
0029 {
0030 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
0031 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
0032 ReadCost = 1,
0033 AddCost = 4,
0034 MulCost = 8,
0035 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
0036 RequireInitialization = 1,
0037 };
0038 static Real epsilon()
0039 {
0040 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?");
0041 return std::numeric_limits<Real>::epsilon();
0042 }
0043 static Real dummy_precision()
0044 {
0045 return 1000 * epsilon();
0046 }
0047 static Real highest()
0048 {
0049 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?");
0050 return (std::numeric_limits<Real>::max)();
0051 }
0052 static Real lowest()
0053 {
0054 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?");
0055 return (std::numeric_limits<Real>::min)();
0056 }
0057 static int digits10_imp(const std::integral_constant<bool, true>&)
0058 {
0059 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?");
0060 return std::numeric_limits<Real>::digits10;
0061 }
0062 template <bool B>
0063 static int digits10_imp(const std::integral_constant<bool, B>&)
0064 {
0065 return Real::thread_default_precision();
0066 }
0067 static int digits10()
0068 {
0069 return digits10_imp(std::integral_constant < bool, std::numeric_limits<Real>::digits10 && (std::numeric_limits<Real>::digits10 != INT_MAX) ? true : false > ());
0070 }
0071 static int digits()
0072 {
0073
0074
0075 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?");
0076 return std::numeric_limits<Real>::digits;
0077 }
0078 static int min_exponent()
0079 {
0080 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?");
0081 return std::numeric_limits<Real>::min_exponent;
0082 }
0083 static int max_exponent()
0084 {
0085 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?");
0086 return std::numeric_limits<Real>::max_exponent;
0087 }
0088 static Real infinity()
0089 {
0090 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?");
0091 return std::numeric_limits<Real>::infinity();
0092 }
0093 static Real quiet_NaN()
0094 {
0095 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?");
0096 return std::numeric_limits<Real>::quiet_NaN();
0097 }
0098 };
0099
0100 template <class B1, class B2>
0101 struct NumTraitsImp : public NumTraitsImp<B2, B2>
0102 {
0103
0104
0105
0106
0107 using self_type = B1;
0108 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
0109 using NonInteger = self_type;
0110 using Literal = double;
0111 using Nested = self_type;
0112 enum
0113 {
0114 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
0115 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
0116 ReadCost = 1,
0117 AddCost = 4,
0118 MulCost = 8,
0119 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
0120 RequireInitialization = 1,
0121 };
0122 static B2 epsilon()
0123 {
0124 return NumTraitsImp<B2, B2>::epsilon();
0125 }
0126 static B2 dummy_precision()
0127 {
0128 return 1000 * epsilon();
0129 }
0130 static B2 highest()
0131 {
0132 return NumTraitsImp<B2, B2>::highest();
0133 }
0134 static B2 lowest()
0135 {
0136 return NumTraitsImp<B2, B2>::lowest();
0137 }
0138 static int digits10()
0139 {
0140 return NumTraitsImp<B2, B2>::digits10();
0141 }
0142 static int digits()
0143 {
0144 return NumTraitsImp<B2, B2>::digits();
0145 }
0146 static int min_exponent()
0147 {
0148 return NumTraitsImp<B2, B2>::min_exponent();
0149 }
0150 static int max_exponent()
0151 {
0152 return NumTraitsImp<B2, B2>::max_exponent();
0153 }
0154 static B2 infinity()
0155 {
0156 return NumTraitsImp<B2, B2>::infinity();
0157 }
0158 static B2 quiet_NaN()
0159 {
0160 return NumTraitsImp<B2, B2>::quiet_NaN();
0161 }
0162 };
0163
0164 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
0165 struct NumTraits<boost::multiprecision::number<Backend, ExpressionTemplates> > : public NumTraitsImp<boost::multiprecision::number<Backend, ExpressionTemplates>, typename boost::multiprecision::number<Backend, ExpressionTemplates>::value_type>
0166 {};
0167 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
0168 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>
0169 {};
0170
0171 #define BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(A) \
0172 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
0173 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, A, BinaryOp> \
0174 { \
0175 \
0176 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; \
0177 }; \
0178 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp> \
0179 struct ScalarBinaryOpTraits<A, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp> \
0180 { \
0181 \
0182 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>; \
0183 };
0184
0185 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(float)
0186 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(double)
0187 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long double)
0188 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(char)
0189 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned char)
0190 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(signed char)
0191 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(short)
0192 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned short)
0193 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(int)
0194 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned int)
0195 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(long)
0196 BOOST_MP_EIGEN_SCALAR_TRAITS_DECL(unsigned long)
0197
0198 #if 0
0199 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Backend2, boost::multiprecision::expression_template_option ExpressionTemplates2, typename BinaryOp>
0200 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2>, BinaryOp>
0201 {
0202 static_assert(
0203 boost::multiprecision::is_compatible_arithmetic_type<boost::multiprecision::number<Backend2, ExpressionTemplates2>, boost::multiprecision::number<Backend, ExpressionTemplates> >::value
0204 || 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.");
0205 using ReturnType = typename std::conditional<std::is_convertible<boost::multiprecision::number<Backend2, ExpressionTemplates2>, boost::multiprecision::number<Backend, ExpressionTemplates> >::value,
0206 boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend2, ExpressionTemplates2> >::type;
0207 };
0208
0209 template<unsigned D, typename BinaryOp>
0210 struct ScalarBinaryOpTraits<boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>, boost::multiprecision::mpfr_float, BinaryOp>
0211 {
0212 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<D>, boost::multiprecision::et_on>;
0213 };
0214
0215 template<typename BinaryOp>
0216 struct ScalarBinaryOpTraits<boost::multiprecision::mpfr_float, boost::multiprecision::mpc_complex, BinaryOp>
0217 {
0218 using ReturnType = boost::multiprecision::number<boost::multiprecision::backends::mpc_complex_backend<0>, boost::multiprecision::et_on>;
0219 };
0220
0221 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp>
0222 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp>
0223 {
0224 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
0225 };
0226 #endif
0227
0228 template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4, typename BinaryOp>
0229 struct ScalarBinaryOpTraits<boost::multiprecision::number<Backend, ExpressionTemplates>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, BinaryOp>
0230 {
0231 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.");
0232 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
0233 };
0234
0235 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, typename BinaryOp>
0236 struct ScalarBinaryOpTraits<boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, boost::multiprecision::number<Backend, ExpressionTemplates>, BinaryOp>
0237 {
0238 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.");
0239 using ReturnType = boost::multiprecision::number<Backend, ExpressionTemplates>;
0240 };
0241
0242 namespace numext {
0243 using boost::multiprecision::conj;
0244 }
0245
0246 }
0247
0248 #endif