|
20 | 20 | #include <cfloat> |
21 | 21 | #include <tuple> |
22 | 22 | #include <cstring> |
| 23 | +#include <complex> |
23 | 24 | #include <boost/multiprecision/detail/standalone_config.hpp> |
24 | 25 | #include <boost/multiprecision/number.hpp> |
25 | 26 | #include <boost/multiprecision/detail/hash.hpp> |
@@ -710,6 +711,29 @@ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> rsqr |
710 | 711 | return res; |
711 | 712 | } |
712 | 713 |
|
| 714 | +// The default std::abs(std::complex<>) implementation normalizes by max(|re|, |im|), |
| 715 | +// which yields NaN when an input is infinite (inf/inf). |
| 716 | +// Per IEEE 754, the result must be +infinity if either component is infinite, even if the other is NaN. |
| 717 | +template <boost::multiprecision::expression_template_option ExpressionTemplates> |
| 718 | +inline boost::multiprecision::number<float128_backend, ExpressionTemplates> |
| 719 | +abs BOOST_PREVENT_MACRO_SUBSTITUTION(const std::complex<boost::multiprecision::number<float128_backend, ExpressionTemplates>>& z) |
| 720 | +{ |
| 721 | + using number_type = boost::multiprecision::number<float128_backend, ExpressionTemplates>; |
| 722 | + const float128_type re_v = z.real().backend().value(); |
| 723 | + const float128_type im_v = z.imag().backend().value(); |
| 724 | +#ifdef BOOST_MP_USE_FLOAT128 |
| 725 | + return number_type(::hypotq(re_v, im_v)); |
| 726 | +#else |
| 727 | + if (isinfq(re_v) || isinfq(im_v)) |
| 728 | + { |
| 729 | + return std::numeric_limits<number_type>::infinity(); |
| 730 | + } |
| 731 | + const float128_type re_abs = re_v < 0 ? -re_v : re_v; |
| 732 | + const float128_type im_abs = im_v < 0 ? -im_v : im_v; |
| 733 | + return number_type(sqrtq(re_abs * re_abs + im_abs * im_abs)); |
| 734 | +#endif |
| 735 | +} |
| 736 | + |
713 | 737 | #ifndef BOOST_MP_USE_QUAD |
714 | 738 | template <multiprecision::expression_template_option ExpressionTemplates> |
715 | 739 | inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b) |
|
0 commit comments