Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:48:43

0001 ///////////////////////////////////////////////////////////////////////////////
0002 //  Copyright 2018 John Maddock. Distributed under the Boost
0003 //  Software License, Version 1.0. (See accompanying file
0004 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // Generic Eigen support code:
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; // Not correct but we can't do much better??
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       // return the number of digits in the component type in case Real is complex
0074       // and we have no numeric_limits specialization.
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    // This version is instantiated when B1 and B2 are different types, this happens for rational/complex/interval
0105    // types, in which case many methods defer to those of the "component type" B2.
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; // Not correct but we can't do much better??
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       /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \
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       /*static_assert(boost::multiprecision::is_compatible_arithmetic_type<A, boost::multiprecision::number<Backend, ExpressionTemplates> >::value, "Interoperability with this arithmetic type is not supported.");*/ \
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 } // namespace Eigen
0247 
0248 #endif