Skip to content

Commit 84b94fe

Browse files
committed
Revamp impl
1 parent 760d6d6 commit 84b94fe

File tree

1 file changed

+34
-19
lines changed
  • include/boost/decimal/detail/cmath

1 file changed

+34
-19
lines changed

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

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ constexpr auto nextafter_impl(const DecimalType val, const bool direction) noexc
3434
{
3535
constexpr DecimalType zero {0};
3636

37-
// Val < direction = +
38-
// Val > direction = -
37+
const bool is_neg {val < 0};
3938
const auto abs_val {abs(val)};
4039

4140
if (val == zero)
@@ -44,32 +43,48 @@ constexpr auto nextafter_impl(const DecimalType val, const bool direction) noexc
4443
-std::numeric_limits<DecimalType>::denorm_min()};
4544
return min_val;
4645
}
47-
else if (abs_val > zero && abs_val < std::numeric_limits<DecimalType>::epsilon())
48-
{
49-
auto exp {val.biased_exponent()};
50-
auto significand {val.full_significand()};
51-
direction ? ++significand : --significand;
5246

53-
return {significand, exp, val.isneg()};
54-
}
47+
const auto components {val.to_components()};
48+
auto sig {components.sig};
49+
auto exp {components.exp};
50+
const auto removed_zeros {remove_trailing_zeros(sig)};
51+
const auto sig_dig {num_digits(sig)};
5552

56-
const auto val_eps {direction ? val + std::numeric_limits<DecimalType>::epsilon() :
57-
val - std::numeric_limits<DecimalType>::epsilon()};
53+
// Our two boundaries
54+
const bool is_pow_10 {removed_zeros.trimmed_number == 1U};
55+
const bool is_max_sig {sig == detail::max_significand_v<DecimalType>};
5856

59-
// If adding epsilon does nothing, then we need to manipulate the representation
60-
if (val == val_eps)
57+
if (sig_dig < detail::precision_v<DecimalType>)
6158
{
62-
int exp {} ;
63-
auto significand {frexp10(val, &exp)};
64-
65-
direction ? ++significand : --significand;
59+
const auto offset{detail::precision_v<DecimalType> - sig_dig};
60+
sig *= pow10(static_cast<decltype(sig)>(detail::precision_v<DecimalType> - sig_dig));
61+
exp -= offset;
62+
}
6663

67-
return DecimalType{significand, exp};
64+
if (direction)
65+
{
66+
// Val < direction = +
67+
++sig;
68+
if (is_max_sig)
69+
{
70+
sig /= 10u;
71+
++exp;
72+
}
6873
}
6974
else
7075
{
71-
return val_eps;
76+
// Val > direction = -
77+
--sig;
78+
if (is_pow_10)
79+
{
80+
// 1000 becomes 999 but needs to be 9999
81+
sig *= 10u;
82+
sig += 9u;
83+
--exp;
84+
}
7285
}
86+
87+
return DecimalType{sig, exp, is_neg};
7388
}
7489

7590
} // namespace detail

0 commit comments

Comments
 (0)