@@ -535,6 +535,7 @@ class decimal128 final
535
535
friend constexpr auto copysignd128 (decimal128 mag, decimal128 sgn) noexcept -> decimal128;
536
536
friend constexpr auto scalblnd128 (decimal128 num, long exp) noexcept -> decimal128;
537
537
friend constexpr auto scalbnd128 (decimal128 num, int exp) noexcept -> decimal128;
538
+ friend constexpr auto fmad128 (decimal128 x, decimal128 y, decimal128 z) noexcept -> decimal128;
538
539
};
539
540
540
541
#if !defined(BOOST_DECIMAL_DISABLE_IOSTREAM)
@@ -1802,11 +1803,21 @@ constexpr auto operator*(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
1802
1803
1803
1804
auto lhs_sig {lhs.full_significand ()};
1804
1805
auto lhs_exp {lhs.biased_exponent ()};
1805
- detail::normalize<decimal128>(lhs_sig, lhs_exp);
1806
+
1807
+ while (lhs_sig % 10 == 0 && lhs_sig != 0 )
1808
+ {
1809
+ lhs_sig /= 10 ;
1810
+ ++lhs_exp;
1811
+ }
1806
1812
1807
1813
auto rhs_sig {rhs.full_significand ()};
1808
1814
auto rhs_exp {rhs.biased_exponent ()};
1809
- detail::normalize<decimal128>(rhs_sig, rhs_exp);
1815
+
1816
+ while (rhs_sig % 10 == 0 && rhs_sig != 0 )
1817
+ {
1818
+ rhs_sig /= 10 ;
1819
+ ++rhs_exp;
1820
+ }
1810
1821
1811
1822
const auto result {d128_mul_impl (lhs_sig, lhs_exp, lhs.isneg (),
1812
1823
rhs_sig, rhs_exp, rhs.isneg ())};
@@ -1825,12 +1836,20 @@ constexpr auto operator*(decimal128 lhs, Integer rhs) noexcept
1825
1836
1826
1837
auto lhs_sig {lhs.full_significand ()};
1827
1838
auto lhs_exp {lhs.biased_exponent ()};
1828
- detail::normalize<decimal128>(lhs_sig, lhs_exp);
1839
+ while (lhs_sig % 10 == 0 && lhs_sig != 0 )
1840
+ {
1841
+ lhs_sig /= 10 ;
1842
+ ++lhs_exp;
1843
+ }
1829
1844
auto lhs_components {detail::decimal128_components{lhs_sig, lhs_exp, lhs.isneg ()}};
1830
1845
1831
1846
auto rhs_sig {static_cast <detail::uint128>(detail::make_positive_unsigned (rhs))};
1832
1847
std::int32_t rhs_exp {0 };
1833
- detail::normalize<decimal128>(rhs_sig, rhs_exp);
1848
+ while (rhs_sig % 10 == 0 && rhs_sig != 0 )
1849
+ {
1850
+ rhs_sig /= 10 ;
1851
+ ++rhs_exp;
1852
+ }
1834
1853
auto unsigned_sig_rhs {detail::make_positive_unsigned (rhs_sig)};
1835
1854
auto rhs_components {detail::decimal128_components{unsigned_sig_rhs, rhs_exp, (rhs < 0 )}};
1836
1855
@@ -2260,6 +2279,81 @@ constexpr auto scalbnd128(decimal128 num, int expval) noexcept -> decimal128
2260
2279
return scalblnd128 (num, static_cast <long >(expval));
2261
2280
}
2262
2281
2282
+ constexpr auto fmad128 (decimal128 x, decimal128 y, decimal128 z) noexcept -> decimal128
2283
+ {
2284
+ // First calculate x * y without rounding
2285
+ constexpr decimal128 zero {0 , 0 };
2286
+
2287
+ const auto res {detail::check_non_finite (x, y)};
2288
+ if (res != zero)
2289
+ {
2290
+ return res;
2291
+ }
2292
+
2293
+ auto sig_lhs {x.full_significand ()};
2294
+ auto exp_lhs {x.biased_exponent ()};
2295
+
2296
+ while (sig_lhs % 10 == 0 && sig_lhs != 0 )
2297
+ {
2298
+ sig_lhs /= 10 ;
2299
+ ++exp_lhs;
2300
+ }
2301
+
2302
+ auto sig_rhs {y.full_significand ()};
2303
+ auto exp_rhs {y.biased_exponent ()};
2304
+
2305
+ while (sig_rhs % 10 == 0 && sig_rhs != 0 )
2306
+ {
2307
+ sig_rhs /= 10 ;
2308
+ ++exp_rhs;
2309
+ }
2310
+
2311
+ auto mul_result {d128_mul_impl (sig_lhs, exp_lhs, x.isneg (), sig_rhs, exp_rhs, y.isneg ())};
2312
+ const decimal128 dec_result {mul_result.sig , mul_result.exp , mul_result.sign };
2313
+
2314
+ const auto res_add {detail::check_non_finite (dec_result, z)};
2315
+ if (res_add != zero)
2316
+ {
2317
+ return res_add;
2318
+ }
2319
+
2320
+ bool lhs_bigger {dec_result > z};
2321
+ if (dec_result.isneg () && z.isneg ())
2322
+ {
2323
+ lhs_bigger = !lhs_bigger;
2324
+ }
2325
+ bool abs_lhs_bigger {abs (dec_result) > abs (z)};
2326
+
2327
+ detail::normalize<decimal128>(mul_result.sig , mul_result.exp );
2328
+
2329
+ auto sig_z {z.full_significand ()};
2330
+ auto exp_z {z.biased_exponent ()};
2331
+ detail::normalize<decimal128>(sig_z, exp_z);
2332
+ detail::decimal128_components z_components {sig_z, exp_z, z.isneg ()};
2333
+
2334
+ if (!lhs_bigger)
2335
+ {
2336
+ detail::swap (mul_result, z_components);
2337
+ abs_lhs_bigger = !abs_lhs_bigger;
2338
+ }
2339
+
2340
+ detail::decimal128_components result {};
2341
+
2342
+ if (!mul_result.sign && z_components.sign )
2343
+ {
2344
+ result = d128_sub_impl (mul_result.sig , mul_result.exp , mul_result.sign ,
2345
+ z_components.sig , z_components.exp , z_components.sign ,
2346
+ abs_lhs_bigger);
2347
+ }
2348
+ else
2349
+ {
2350
+ result = d128_add_impl (mul_result.sig , mul_result.exp , mul_result.sign ,
2351
+ z_components.sig , z_components.exp , z_components.sign );
2352
+ }
2353
+
2354
+ return {result.sig , result.exp , result.sign };
2355
+ }
2356
+
2263
2357
} // namespace decimal
2264
2358
} // namespace boost
2265
2359
0 commit comments