@@ -82,6 +82,58 @@ constexpr auto d32_fma_impl(T x, T y, T z) noexcept -> T
8282 abs_lhs_bigger);
8383}
8484
85+ template <bool checked, BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
86+ constexpr auto d64_fma_impl (T x, T y, T z) noexcept -> T
87+ {
88+ using T_components_type = components_type<T>;
89+ using exp_type = typename T::biased_exponent_type;
90+
91+ // Apply the add
92+ #ifndef BOOST_DECIMAL_FAST_MATH
93+ BOOST_DECIMAL_IF_CONSTEXPR (checked)
94+ {
95+ if (!isfinite (x) || !isfinite (y))
96+ {
97+ return detail::check_non_finite (x, y);
98+ }
99+ }
100+ #endif
101+
102+ int exp_lhs {};
103+ auto sig_lhs = frexp10 (x, &exp_lhs);
104+
105+ int exp_rhs {};
106+ auto sig_rhs = frexp10 (y, &exp_rhs);
107+
108+ auto first_res = detail::d64_mul_impl<T_components_type>(sig_lhs, static_cast <exp_type>(exp_lhs), x < 0 ,
109+ sig_rhs, static_cast <exp_type>(exp_rhs), y < 0 );
110+
111+ // Apply the mul on the carried components
112+ // We still create the result as a decimal type to check for non-finite values and comparisons,
113+ // but we do not use it for the resultant calculation
114+ const T complete_lhs {first_res.sig , first_res.exp , first_res.sign };
115+
116+ #ifndef BOOST_DECIMAL_FAST_MATH
117+ BOOST_DECIMAL_IF_CONSTEXPR (checked)
118+ {
119+ if (!isfinite (complete_lhs) || !isfinite (z))
120+ {
121+ return detail::check_non_finite (complete_lhs, z);
122+ }
123+ }
124+ #endif
125+
126+ const bool abs_lhs_bigger {abs (complete_lhs) > abs (z)};
127+
128+ int exp_z {};
129+ auto sig_z = frexp10 (z, &exp_z);
130+ detail::normalize<T>(first_res.sig , first_res.exp );
131+
132+ return detail::d64_add_impl<T>(first_res.sig , first_res.exp , first_res.sign ,
133+ sig_z, static_cast <exp_type>(exp_z), z < 0 ,
134+ abs_lhs_bigger);
135+ }
136+
85137#ifdef _MSC_VER
86138#pragma warning(pop)
87139#endif
@@ -96,6 +148,16 @@ constexpr auto unchecked_fma(decimal32_fast x, decimal32_fast y, decimal32_fast
96148 return detail::d32_fma_impl<false >(x, y, z);
97149}
98150
151+ constexpr auto unchecked_fma (decimal64 x, decimal64 y, decimal64 z) noexcept -> decimal64
152+ {
153+ return detail::d64_fma_impl<false >(x, y, z);
154+ }
155+
156+ constexpr auto unchecked_fma (decimal64_fast x, decimal64_fast y, decimal64_fast z) noexcept -> decimal64_fast
157+ {
158+ return detail::d64_fma_impl<false >(x, y, z);
159+ }
160+
99161} // Namespace detail
100162
101163BOOST_DECIMAL_EXPORT constexpr auto fma (decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal32
@@ -105,7 +167,7 @@ BOOST_DECIMAL_EXPORT constexpr auto fma(decimal32 x, decimal32 y, decimal32 z) n
105167
106168BOOST_DECIMAL_EXPORT constexpr auto fma (decimal64 x, decimal64 y, decimal64 z) noexcept -> decimal64
107169{
108- return x * y + z ;
170+ return detail::d64_fma_impl< true >(x, y, z) ;
109171}
110172
111173BOOST_DECIMAL_EXPORT constexpr auto fma (decimal128 x, decimal128 y, decimal128 z) noexcept -> decimal128
@@ -120,7 +182,7 @@ BOOST_DECIMAL_EXPORT constexpr auto fma(decimal32_fast x, decimal32_fast y, deci
120182
121183BOOST_DECIMAL_EXPORT constexpr auto fma (decimal64_fast x, decimal64_fast y, decimal64_fast z) noexcept -> decimal64_fast
122184{
123- return x * y + z ;
185+ return detail::d64_fma_impl< true >(x, y, z) ;
124186}
125187
126188BOOST_DECIMAL_EXPORT constexpr auto fma (decimal128_fast x, decimal128_fast y, decimal128_fast z) noexcept -> decimal128_fast
0 commit comments