Skip to content

Commit d901dd4

Browse files
authored
Merge pull request #584 from cppalliance/d64FMA
2 parents 4bbb42f + 9f688c4 commit d901dd4

File tree

3 files changed

+84
-134
lines changed

3 files changed

+84
-134
lines changed

include/boost/decimal/decimal128.hpp

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,75 +2414,6 @@ constexpr auto scalbnd128(decimal128 num, int expval) noexcept -> decimal128
24142414
return scalblnd128(num, static_cast<long>(expval));
24152415
}
24162416

2417-
constexpr auto fmad128(decimal128 x, decimal128 y, decimal128 z) noexcept -> decimal128
2418-
{
2419-
// First calculate x * y without rounding
2420-
constexpr decimal128 zero {0, 0};
2421-
2422-
const auto res {detail::check_non_finite(x, y)};
2423-
if (res != zero)
2424-
{
2425-
return res;
2426-
}
2427-
2428-
auto sig_lhs {x.full_significand()};
2429-
auto exp_lhs {x.biased_exponent()};
2430-
detail::normalize<decimal128>(sig_lhs, exp_lhs);
2431-
2432-
auto sig_rhs {y.full_significand()};
2433-
auto exp_rhs {y.biased_exponent()};
2434-
detail::normalize<decimal128>(sig_rhs, exp_rhs);
2435-
2436-
auto mul_result {d128_mul_impl(sig_lhs, exp_lhs, x.isneg(), sig_rhs, exp_rhs, y.isneg())};
2437-
const decimal128 dec_result {mul_result.sig, mul_result.exp, mul_result.sign};
2438-
2439-
return dec_result + z;
2440-
2441-
/*
2442-
const auto res_add {detail::check_non_finite(dec_result, z)};
2443-
if (res_add != zero)
2444-
{
2445-
return res_add;
2446-
}
2447-
2448-
bool lhs_bigger {dec_result > z};
2449-
if (dec_result.isneg() && z.isneg())
2450-
{
2451-
lhs_bigger = !lhs_bigger;
2452-
}
2453-
bool abs_lhs_bigger {abs(dec_result) > abs(z)};
2454-
2455-
detail::normalize<decimal128>(mul_result.sig, mul_result.exp);
2456-
2457-
auto sig_z {z.full_significand()};
2458-
auto exp_z {z.biased_exponent()};
2459-
detail::normalize<decimal128>(sig_z, exp_z);
2460-
detail::decimal128_components z_components {sig_z, exp_z, z.isneg()};
2461-
2462-
if (!lhs_bigger)
2463-
{
2464-
detail::swap(mul_result, z_components);
2465-
abs_lhs_bigger = !abs_lhs_bigger;
2466-
}
2467-
2468-
detail::decimal128_components result {};
2469-
2470-
if (!mul_result.sign && z_components.sign)
2471-
{
2472-
result = d128_sub_impl(mul_result.sig, mul_result.exp, mul_result.sign,
2473-
z_components.sig, z_components.exp, z_components.sign,
2474-
abs_lhs_bigger);
2475-
}
2476-
else
2477-
{
2478-
result = d128_add_impl(mul_result.sig, mul_result.exp, mul_result.sign,
2479-
z_components.sig, z_components.exp, z_components.sign);
2480-
}
2481-
2482-
return {result.sig, result.exp, result.sign};
2483-
*/
2484-
}
2485-
24862417
} //namespace decimal
24872418
} //namespace boost
24882419

include/boost/decimal/decimal64.hpp

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2347,71 +2347,6 @@ constexpr auto copysignd64(decimal64 mag, decimal64 sgn) noexcept -> decimal64
23472347
return mag;
23482348
}
23492349

2350-
constexpr auto fmad64(decimal64 x, decimal64 y, decimal64 z) noexcept -> decimal64
2351-
{
2352-
// First calculate x * y without rounding
2353-
constexpr decimal64 zero {0, 0};
2354-
2355-
const auto res {detail::check_non_finite(x, y)};
2356-
if (res != zero)
2357-
{
2358-
return res;
2359-
}
2360-
2361-
auto sig_lhs {x.full_significand()};
2362-
auto exp_lhs {x.biased_exponent()};
2363-
detail::normalize<decimal64>(sig_lhs, exp_lhs);
2364-
2365-
auto sig_rhs {y.full_significand()};
2366-
auto exp_rhs {y.biased_exponent()};
2367-
detail::normalize<decimal64>(sig_rhs, exp_rhs);
2368-
2369-
auto mul_result {d64_mul_impl(sig_lhs, exp_lhs, x.isneg(), sig_rhs, exp_rhs, y.isneg())};
2370-
const decimal64 dec_result {mul_result.sig, mul_result.exp, mul_result.sign};
2371-
2372-
const auto res_add {detail::check_non_finite(dec_result, z)};
2373-
if (res_add != zero)
2374-
{
2375-
return res_add;
2376-
}
2377-
2378-
bool lhs_bigger {dec_result > z};
2379-
if (dec_result.isneg() && z.isneg())
2380-
{
2381-
lhs_bigger = !lhs_bigger;
2382-
}
2383-
bool abs_lhs_bigger {abs(dec_result) > abs(z)};
2384-
2385-
detail::normalize<decimal64>(mul_result.sig, mul_result.exp);
2386-
2387-
auto sig_z {z.full_significand()};
2388-
auto exp_z {z.biased_exponent()};
2389-
detail::normalize<decimal64>(sig_z, exp_z);
2390-
detail::decimal64_components z_components {sig_z, exp_z, z.isneg()};
2391-
2392-
if (!lhs_bigger)
2393-
{
2394-
detail::swap(mul_result, z_components);
2395-
abs_lhs_bigger = !abs_lhs_bigger;
2396-
}
2397-
2398-
detail::decimal64_components result {};
2399-
2400-
if (!mul_result.sign && z_components.sign)
2401-
{
2402-
result = d64_sub_impl(mul_result.sig, mul_result.exp, mul_result.sign,
2403-
z_components.sig, z_components.exp, z_components.sign,
2404-
abs_lhs_bigger);
2405-
}
2406-
else
2407-
{
2408-
result = d64_add_impl(mul_result.sig, mul_result.exp, mul_result.sign,
2409-
z_components.sig, z_components.exp, z_components.sign);
2410-
}
2411-
2412-
return {result.sig, result.exp, result.sign};
2413-
}
2414-
24152350
} //namespace decimal
24162351
} //namespace boost
24172352

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,85 @@ constexpr auto fmad32(decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal
8383
return {result.sig, result.exp, result.sign};
8484
}
8585

86+
constexpr auto fmad64(decimal64 x, decimal64 y, decimal64 z) noexcept -> decimal64
87+
{
88+
// First calculate x * y without rounding
89+
constexpr decimal64 zero {0, 0};
90+
91+
const auto res {detail::check_non_finite(x, y)};
92+
if (res != zero)
93+
{
94+
return res;
95+
}
96+
97+
auto sig_lhs {x.full_significand()};
98+
auto exp_lhs {x.biased_exponent()};
99+
detail::normalize<decimal64>(sig_lhs, exp_lhs);
100+
101+
auto sig_rhs {y.full_significand()};
102+
auto exp_rhs {y.biased_exponent()};
103+
detail::normalize<decimal64>(sig_rhs, exp_rhs);
104+
105+
auto mul_result {d64_mul_impl(sig_lhs, exp_lhs, x.isneg(), sig_rhs, exp_rhs, y.isneg())};
106+
const decimal64 dec_result {mul_result.sig, mul_result.exp, mul_result.sign};
107+
108+
const auto res_add {detail::check_non_finite(dec_result, z)};
109+
if (res_add != zero)
110+
{
111+
return res_add;
112+
}
113+
114+
bool lhs_bigger {dec_result > z};
115+
if (dec_result.isneg() && z.isneg())
116+
{
117+
lhs_bigger = !lhs_bigger;
118+
}
119+
bool abs_lhs_bigger {abs(dec_result) > abs(z)};
120+
121+
// To avoid the rounding step we promote the constituent pieces to the next higher type
122+
detail::decimal128_components promoted_mul_result {static_cast<detail::uint128>(mul_result.sig),
123+
mul_result.exp, mul_result.sign};
124+
125+
detail::normalize<decimal128>(promoted_mul_result.sig, promoted_mul_result.exp);
126+
127+
auto sig_z {static_cast<detail::uint128>(z.full_significand())};
128+
auto exp_z {z.biased_exponent()};
129+
detail::normalize<decimal128>(sig_z, exp_z);
130+
detail::decimal128_components z_components {sig_z, exp_z, z.isneg()};
131+
132+
if (!lhs_bigger)
133+
{
134+
detail::swap(promoted_mul_result, z_components);
135+
abs_lhs_bigger = !abs_lhs_bigger;
136+
}
137+
138+
detail::decimal128_components result {};
139+
140+
if (!promoted_mul_result.sign && z_components.sign)
141+
{
142+
result = d128_sub_impl(promoted_mul_result.sig, promoted_mul_result.exp, promoted_mul_result.sign,
143+
z_components.sig, z_components.exp, z_components.sign,
144+
abs_lhs_bigger);
145+
}
146+
else
147+
{
148+
result = d128_add_impl(promoted_mul_result.sig, promoted_mul_result.exp, promoted_mul_result.sign,
149+
z_components.sig, z_components.exp, z_components.sign);
150+
}
151+
152+
return {result.sig, result.exp, result.sign};
153+
}
154+
155+
constexpr auto fmad128(decimal128 x, decimal128 y, decimal128 z) noexcept -> decimal128
156+
{
157+
return x * y + z;
158+
}
159+
160+
constexpr auto fmad32f(decimal32_fast x, decimal32_fast y, decimal32_fast z) noexcept -> decimal32_fast
161+
{
162+
return x * y + z;
163+
}
164+
86165
BOOST_DECIMAL_EXPORT constexpr auto fma(decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal32
87166
{
88167
return fmad32(x, y, z);
@@ -98,6 +177,11 @@ BOOST_DECIMAL_EXPORT constexpr auto fma(decimal128 x, decimal128 y, decimal128 z
98177
return fmad128(x, y, z);
99178
}
100179

180+
BOOST_DECIMAL_EXPORT constexpr auto fma(decimal32_fast x, decimal32_fast y, decimal32_fast z) noexcept -> decimal32_fast
181+
{
182+
return fmad32f(x, y, z);
183+
}
184+
101185
} //namespace decimal
102186
} //namespace boost
103187

0 commit comments

Comments
 (0)