Skip to content

Commit 43a9bf1

Browse files
authored
Merge pull request #546 from cppalliance/pow10_in_pow
Fix #205 via powers of 10 in pow() function
2 parents 9c92a7e + dcdf379 commit 43a9bf1

File tree

13 files changed

+134
-31
lines changed

13 files changed

+134
-31
lines changed

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

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,28 +123,53 @@ constexpr auto pow(T b, IntegralType p) noexcept
123123
{
124124
result = one;
125125
}
126-
else BOOST_DECIMAL_IF_CONSTEXPR (std::is_signed<local_integral_type>::value)
126+
else
127127
{
128-
if(p < static_cast<local_integral_type>(UINT8_C(0)))
128+
int exp10val { };
129+
130+
const auto bn { frexp10(b, &exp10val) };
131+
132+
const auto
133+
zeros_removal
134+
{
135+
detail::remove_trailing_zeros(bn)
136+
};
137+
138+
const bool is_pure { static_cast<int>(zeros_removal.trimmed_number) == 1 };
139+
140+
if(is_pure)
129141
{
130-
const auto up =
131-
static_cast<local_unsigned_integral_type>
132-
(
133-
static_cast<local_unsigned_integral_type>(~p)
134-
+ static_cast<local_unsigned_integral_type>(UINT8_C(1))
135-
);
142+
// Here, a pure power-of-10 argument (b) gets a pure integral result.
143+
const int log10_val { exp10val + static_cast<int>(zeros_removal.number_of_removed_zeros) };
136144

137-
result = one / detail::pow_n_impl(b, up);
145+
result = T { 1, static_cast<int>(log10_val * static_cast<int>(p)) };
138146
}
139147
else
140148
{
141-
result = detail::pow_n_impl(b, static_cast<local_unsigned_integral_type>(p));
149+
BOOST_DECIMAL_IF_CONSTEXPR (std::is_signed<local_integral_type>::value)
150+
{
151+
if(p < static_cast<local_integral_type>(UINT8_C(0)))
152+
{
153+
const auto up =
154+
static_cast<local_unsigned_integral_type>
155+
(
156+
static_cast<local_unsigned_integral_type>(~p)
157+
+ static_cast<local_unsigned_integral_type>(UINT8_C(1))
158+
);
159+
160+
result = one / detail::pow_n_impl(b, up);
161+
}
162+
else
163+
{
164+
result = detail::pow_n_impl(b, static_cast<local_unsigned_integral_type>(p));
165+
}
166+
}
167+
else
168+
{
169+
result = detail::pow_n_impl(b, static_cast<local_unsigned_integral_type>(p));
170+
}
142171
}
143172
}
144-
else
145-
{
146-
result = detail::pow_n_impl(b, static_cast<local_unsigned_integral_type>(p));
147-
}
148173
}
149174

150175
return result;

test/link_1.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
void test_odr_use(const boost::decimal::rounding_mode*);
88

9+
// LCOV_EXCL_START
910
template <typename T>
1011
void test()
1112
{
@@ -18,3 +19,4 @@ void f1()
1819
test<boost::decimal::decimal64>();
1920
test<boost::decimal::decimal128>();
2021
}
22+
// LCOV_EXCL_STOP

test/link_2.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
void test_odr_use(const boost::decimal::rounding_mode*);
88

9+
// LCOV_EXCL_START
910
template <typename T>
1011
void test()
1112
{
@@ -18,3 +19,4 @@ void f2()
1819
test<boost::decimal::decimal64>();
1920
test<boost::decimal::decimal128>();
2021
}
22+
// LCOV_EXCL_STOP

test/link_3.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <boost/decimal.hpp>
66

7+
// LCOV_EXCL_START
78
void f1();
89
void f2();
910

@@ -16,3 +17,4 @@ int main()
1617
void test_odr_use(const boost::decimal::rounding_mode*)
1718
{
1819
}
20+
// LCOV_EXCL_STOP

test/test_acosh.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace local
5656

5757
if(b == static_cast<NumericType>(0))
5858
{
59-
result_is_ok = (fabs(a - b) < tol);
59+
result_is_ok = (fabs(a - b) < tol); // LCOV_EXCL_LINE
6060
}
6161
else
6262
{

test/test_asinh.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <boost/core/lightweight_test.hpp>
2323

2424
auto my_zero() -> boost::decimal::decimal32&;
25-
auto my_one () -> boost::decimal::decimal32&;
2625

2726
namespace local
2827
{
@@ -56,7 +55,7 @@ namespace local
5655

5756
if(b == static_cast<NumericType>(0))
5857
{
59-
result_is_ok = (fabs(a - b) < tol);
58+
result_is_ok = (fabs(a - b) < tol); // LCOV_EXCL_LINE
6059
}
6160
else
6261
{
@@ -268,4 +267,3 @@ auto main() -> int
268267
}
269268

270269
auto my_zero() -> boost::decimal::decimal32& { static boost::decimal::decimal32 val_zero { 0, 0 }; return val_zero; }
271-
auto my_one () -> boost::decimal::decimal32& { static boost::decimal::decimal32 val_one { 1, 0 }; return val_one; }

test/test_atanh.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace local
5656

5757
if(b == static_cast<NumericType>(0))
5858
{
59-
result_is_ok = (fabs(a - b) < tol);
59+
result_is_ok = (fabs(a - b) < tol); // LCOV_EXCL_LINE
6060
}
6161
else
6262
{

test/test_edges_and_behave.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ namespace local
6262

6363
if(b == static_cast<NumericType>(0))
6464
{
65-
result_is_ok = (fabs(a - b) < tol);
65+
result_is_ok = (fabs(a - b) < tol); // LCOV_EXCL_LINE
6666
}
6767
else
6868
{

test/test_expm1.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ namespace local
5555

5656
if(b == static_cast<NumericType>(0))
5757
{
58-
result_is_ok = (fabs(a - b) < tol);
58+
result_is_ok = (fabs(a - b) < tol); // LCOV_EXCL_LINE
5959
}
6060
else
6161
{

test/test_frexp_ldexp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace local
5353

5454
if(b == static_cast<NumericType>(0))
5555
{
56-
result_is_ok = (fabs(a - b) < tol);
56+
result_is_ok = (fabs(a - b) < tol); // LCOV_EXCL_LINE
5757
}
5858
else
5959
{

0 commit comments

Comments
 (0)