Skip to content

Commit a6ebf50

Browse files
committed
Add 64-bit FMA
1 parent 50b689c commit a6ebf50

File tree

1 file changed

+64
-2
lines changed
  • include/boost/decimal/detail/cmath

1 file changed

+64
-2
lines changed

include/boost/decimal/detail/cmath/fma.hpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

101163
BOOST_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

106168
BOOST_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

111173
BOOST_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

121183
BOOST_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

126188
BOOST_DECIMAL_EXPORT constexpr auto fma(decimal128_fast x, decimal128_fast y, decimal128_fast z) noexcept -> decimal128_fast

0 commit comments

Comments
 (0)