Skip to content

Commit a199bd0

Browse files
authored
Merge pull request #523 from cppalliance/FMA
2 parents 94c0413 + bdfa306 commit a199bd0

File tree

7 files changed

+82
-63
lines changed

7 files changed

+82
-63
lines changed

include/boost/decimal/decimal128.hpp

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,21 +1937,15 @@ constexpr auto operator*(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
19371937

19381938
auto lhs_sig {lhs.full_significand()};
19391939
auto lhs_exp {lhs.biased_exponent()};
1940-
1941-
while (lhs_sig % 10 == 0 && lhs_sig != 0)
1942-
{
1943-
lhs_sig /= 10;
1944-
++lhs_exp;
1945-
}
1940+
const auto lhs_zeros {detail::remove_trailing_zeros(lhs_sig)};
1941+
lhs_sig = lhs_zeros.trimmed_number;
1942+
lhs_exp += static_cast<std::int32_t>(lhs_zeros.number_of_removed_zeros);
19461943

19471944
auto rhs_sig {rhs.full_significand()};
19481945
auto rhs_exp {rhs.biased_exponent()};
1949-
1950-
while (rhs_sig % 10 == 0 && rhs_sig != 0)
1951-
{
1952-
rhs_sig /= 10;
1953-
++rhs_exp;
1954-
}
1946+
const auto rhs_zeros {detail::remove_trailing_zeros(rhs_sig)};
1947+
rhs_sig = rhs_zeros.trimmed_number;
1948+
rhs_exp += static_cast<std::int32_t>(rhs_zeros.number_of_removed_zeros);
19551949

19561950
const auto result {d128_mul_impl(lhs_sig, lhs_exp, lhs.isneg(),
19571951
rhs_sig, rhs_exp, rhs.isneg())};
@@ -1970,20 +1964,16 @@ constexpr auto operator*(decimal128 lhs, Integer rhs) noexcept
19701964

19711965
auto lhs_sig {lhs.full_significand()};
19721966
auto lhs_exp {lhs.biased_exponent()};
1973-
while (lhs_sig % 10 == 0 && lhs_sig != 0)
1974-
{
1975-
lhs_sig /= 10;
1976-
++lhs_exp;
1977-
}
1967+
const auto lhs_zeros {detail::remove_trailing_zeros(lhs_sig)};
1968+
lhs_sig = lhs_zeros.trimmed_number;
1969+
lhs_exp += static_cast<std::int32_t>(lhs_zeros.number_of_removed_zeros);
19781970
auto lhs_components {detail::decimal128_components{lhs_sig, lhs_exp, lhs.isneg()}};
19791971

19801972
auto rhs_sig {static_cast<detail::uint128>(detail::make_positive_unsigned(rhs))};
19811973
std::int32_t rhs_exp {0};
1982-
while (rhs_sig % 10 == 0 && rhs_sig != 0)
1983-
{
1984-
rhs_sig /= 10;
1985-
++rhs_exp;
1986-
}
1974+
const auto rhs_zeros {detail::remove_trailing_zeros(rhs_sig)};
1975+
rhs_sig = rhs_zeros.trimmed_number;
1976+
rhs_exp += static_cast<std::int32_t>(rhs_zeros.number_of_removed_zeros);
19871977
auto unsigned_sig_rhs {detail::make_positive_unsigned(rhs_sig)};
19881978
auto rhs_components {detail::decimal128_components{unsigned_sig_rhs, rhs_exp, (rhs < 0)}};
19891979

@@ -2433,25 +2423,18 @@ constexpr auto fmad128(decimal128 x, decimal128 y, decimal128 z) noexcept -> dec
24332423

24342424
auto sig_lhs {x.full_significand()};
24352425
auto exp_lhs {x.biased_exponent()};
2436-
2437-
while (sig_lhs % 10 == 0 && sig_lhs != 0)
2438-
{
2439-
sig_lhs /= 10;
2440-
++exp_lhs;
2441-
}
2426+
detail::normalize<decimal128>(sig_lhs, exp_lhs);
24422427

24432428
auto sig_rhs {y.full_significand()};
24442429
auto exp_rhs {y.biased_exponent()};
2445-
2446-
while (sig_rhs % 10 == 0 && sig_rhs != 0)
2447-
{
2448-
sig_rhs /= 10;
2449-
++exp_rhs;
2450-
}
2430+
detail::normalize<decimal128>(sig_rhs, exp_rhs);
24512431

24522432
auto mul_result {d128_mul_impl(sig_lhs, exp_lhs, x.isneg(), sig_rhs, exp_rhs, y.isneg())};
24532433
const decimal128 dec_result {mul_result.sig, mul_result.exp, mul_result.sign};
24542434

2435+
return dec_result + z;
2436+
2437+
/*
24552438
const auto res_add {detail::check_non_finite(dec_result, z)};
24562439
if (res_add != zero)
24572440
{
@@ -2493,6 +2476,7 @@ constexpr auto fmad128(decimal128 x, decimal128 y, decimal128 z) noexcept -> dec
24932476
}
24942477
24952478
return {result.sig, result.exp, result.sign};
2479+
*/
24962480
}
24972481

24982482
} //namespace decimal

include/boost/decimal/detail/cmath/impl/taylor_series_result.hpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,6 @@ constexpr auto taylor_series_result(T x, const Array &coeffs) noexcept
2727
return result;
2828
}
2929

30-
template <typename Array>
31-
constexpr auto taylor_series_result(boost::decimal::decimal128 x, const Array &coeffs) noexcept
32-
{
33-
const std::size_t N = coeffs.size();
34-
35-
auto result = coeffs[N - 1];
36-
37-
auto my_own_fma =
38-
[](boost::decimal::decimal128 x, boost::decimal::decimal128 y, boost::decimal::decimal128 z)
39-
{
40-
return (x * y) + z;
41-
};
42-
43-
for (std::size_t i = N - 1; i-- > 0;)
44-
{
45-
result = my_own_fma(result, x, coeffs[i]);
46-
}
47-
48-
return result;
49-
}
50-
5130
} //namespace detail
5231
} //namespace decimal
5332
} //namespace boost

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,8 @@ constexpr auto tgamma_impl(T x) noexcept
9999
z = z - nx;
100100
}
101101

102-
auto my_own_fma =
103-
[](T x, T y, T z)
104-
{
105-
return (x * y) + z;
106-
};
107-
108102
result = detail::tgamma_series_expansion(z);
109-
result = one / (z * my_own_fma(result, z, one));
103+
result = one / (z * fma(result, z, one));
110104

111105
if (x_is_gt_one)
112106
{

include/boost/decimal/detail/remove_trailing_zeros.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,15 @@ constexpr auto remove_trailing_zeros(std::uint64_t n) noexcept -> remove_trailin
8585
return {n, s};
8686
}
8787

88-
// TODO(mborland): Make this better. Check lower word for equal to 0.
88+
// TODO(mborland): Make this better for the 2-word case
8989
constexpr auto remove_trailing_zeros(uint128 n) noexcept -> remove_trailing_zeros_return<uint128>
9090
{
91+
if (n.high == UINT64_C(0))
92+
{
93+
const auto temp {remove_trailing_zeros(n.low)};
94+
return {static_cast<uint128>(temp.trimmed_number), temp.number_of_removed_zeros};
95+
}
96+
9197
std::size_t s {};
9298

9399
while (n % 10 == 0)

test/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ run-fail benchmarks.cpp ;
4545
compile-fail concepts_test.cpp ;
4646
run github_issue_426.cpp ;
4747
run github_issue_448.cpp ;
48+
run-fail github_issue_519.cpp ;
4849
run ibm_abs.cpp ;
4950
run ibm_add.cpp ;
5051
run link_1.cpp link_2.cpp link_3.cpp ;

test/github_issue_519.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2024 Matt Borland
2+
// Copyright 2024 Christopher Kormanyos
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// https://www.boost.org/LICENSE_1_0.txt
5+
6+
#include <boost/decimal.hpp>
7+
8+
#include <iomanip>
9+
#include <iostream>
10+
#include <limits>
11+
#include <sstream>
12+
13+
auto main() -> int
14+
{
15+
using local_decimal_type = boost::decimal::decimal128;
16+
17+
// N[Gamma[456/100], 34]
18+
// 12.64819265438397922113369900828315
19+
//
20+
// For Decimal 128:
21+
// 4.56
22+
// 12.64819265438397922113369900828314
23+
24+
const local_decimal_type x = local_decimal_type { 456, -2 };
25+
26+
const auto tg = tgamma(x);
27+
28+
{
29+
std::stringstream strm;
30+
31+
strm << std::setprecision(std::numeric_limits<local_decimal_type>::digits10) << x;
32+
33+
std::cout << "Expected: 4.56" << std::endl;
34+
std::cout << " Got: " << strm.str() << std::endl;
35+
}
36+
37+
{
38+
std::stringstream strm;
39+
40+
strm << std::setprecision(std::numeric_limits<local_decimal_type>::digits10) << tg;
41+
42+
std::cout << "Expected: 12.64819265438397922113369900828314" << std::endl;
43+
std::cout << " Got: " << strm.str() << std::endl;
44+
}
45+
46+
return 1;
47+
}

test/test_tgamma.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ namespace local
6363
const auto delta = fabs(1 - (a / b));
6464

6565
result_is_ok = (delta < tol);
66+
67+
if (!result_is_ok)
68+
{
69+
std::cerr << std::setprecision(std::numeric_limits<NumericType>::digits10) << "a: " << a
70+
<< "\nb: " << b
71+
<< "\ndelta: " << delta
72+
<< "\ntol: " << tol << std::endl;
73+
}
6674
}
6775

6876
return result_is_ok;

0 commit comments

Comments
 (0)