99#include < boost/decimal/decimal32_fast.hpp>
1010#include < boost/decimal/decimal64.hpp>
1111#include < boost/decimal/decimal128.hpp>
12+ #include < boost/decimal/decimal128_fast.hpp>
1213#include < boost/decimal/detail/config.hpp>
1314
1415namespace boost {
1516namespace decimal {
1617
18+ namespace detail {
19+
20+ #ifdef _MSC_VER
21+ #pragma warning(push)
22+ #pragma warning(disable : 4127)
23+ #endif
24+
25+ template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE Dec>
26+ using components_type = std::conditional_t <std::is_same<Dec, decimal32>::value, decimal32_components,
27+ std::conditional_t <std::is_same<Dec, decimal32_fast>::value, decimal32_fast_components,
28+ std::conditional_t <std::is_same<Dec, decimal64>::value, decimal64_components,
29+ std::conditional_t <std::is_same<Dec, decimal64_fast>::value, decimal64_fast_components,
30+ std::conditional_t <std::is_same<Dec, decimal128>::value, decimal128_components, decimal128_fast_components
31+ >>>>>;
32+
33+ template <bool checked, BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
34+ constexpr auto d32_fma_impl (T x, T y, T z) noexcept -> T
35+ {
36+ using T_components_type = components_type<T>;
37+ using exp_type = typename T::biased_exponent_type;
38+
39+ // Apply the add
40+ #ifndef BOOST_DECIMAL_FAST_MATH
41+ BOOST_DECIMAL_IF_CONSTEXPR (checked)
42+ {
43+ if (!isfinite (x) || !isfinite (y))
44+ {
45+ return detail::check_non_finite (x, y);
46+ }
47+ }
48+ #endif
49+
50+ int exp_lhs {};
51+ auto sig_lhs = frexp10 (x, &exp_lhs);
52+
53+ int exp_rhs {};
54+ auto sig_rhs = frexp10 (y, &exp_rhs);
55+
56+ auto first_res = detail::mul_impl<T_components_type>(sig_lhs, static_cast <exp_type>(exp_lhs), x < 0 ,
57+ sig_rhs, static_cast <exp_type>(exp_rhs), y < 0 );
58+
59+ // Apply the mul on the carried components
60+ // We still create the result as a decimal type to check for non-finite values and comparisons,
61+ // but we do not use it for the resultant calculation
62+ const T complete_lhs {first_res.sig , first_res.exp , first_res.sign };
63+
64+ #ifndef BOOST_DECIMAL_FAST_MATH
65+ BOOST_DECIMAL_IF_CONSTEXPR (checked)
66+ {
67+ if (!isfinite (complete_lhs) || !isfinite (z))
68+ {
69+ return detail::check_non_finite (complete_lhs, z);
70+ }
71+ }
72+ #endif
73+
74+ const bool abs_lhs_bigger {abs (complete_lhs) > abs (z)};
75+
76+ int exp_z {};
77+ auto sig_z = frexp10 (z, &exp_z);
78+ detail::normalize<T>(first_res.sig , first_res.exp );
79+
80+ return detail::d32_add_impl<T>(first_res.sig , first_res.exp , first_res.sign ,
81+ sig_z, static_cast <exp_type>(exp_z), z < 0 ,
82+ abs_lhs_bigger);
83+ }
84+
85+ #ifdef _MSC_VER
86+ #pragma warning(pop)
87+ #endif
88+
89+ constexpr auto unchecked_fma (decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal32
90+ {
91+ return detail::d32_fma_impl<false >(x, y, z);
92+ }
93+
94+ constexpr auto unchecked_fma (decimal32_fast x, decimal32_fast y, decimal32_fast z) noexcept -> decimal32_fast
95+ {
96+ return detail::d32_fma_impl<false >(x, y, z);
97+ }
98+
99+ } // Namespace detail
100+
17101BOOST_DECIMAL_EXPORT constexpr auto fma (decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal32
18102{
19- return x * y + z ;
103+ return detail::d32_fma_impl< true >(x, y, z) ;
20104}
21105
22106BOOST_DECIMAL_EXPORT constexpr auto fma (decimal64 x, decimal64 y, decimal64 z) noexcept -> decimal64
@@ -31,7 +115,7 @@ BOOST_DECIMAL_EXPORT constexpr auto fma(decimal128 x, decimal128 y, decimal128 z
31115
32116BOOST_DECIMAL_EXPORT constexpr auto fma (decimal32_fast x, decimal32_fast y, decimal32_fast z) noexcept -> decimal32_fast
33117{
34- return x * y + z ;
118+ return detail::d32_fma_impl< true >(x, y, z) ;
35119}
36120
37121BOOST_DECIMAL_EXPORT constexpr auto fma (decimal64_fast x, decimal64_fast y, decimal64_fast z) noexcept -> decimal64_fast
0 commit comments