Skip to content

Commit db1d409

Browse files
authored
Merge pull request #878 from cppalliance/798_2
Fix next after part 2
2 parents e28e801 + c5bfec8 commit db1d409

File tree

8 files changed

+64
-13
lines changed

8 files changed

+64
-13
lines changed

include/boost/decimal/decimal128.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <boost/decimal/detail/sub_impl.hpp>
3838
#include <boost/decimal/detail/mul_impl.hpp>
3939
#include <boost/decimal/detail/div_impl.hpp>
40+
#include <boost/decimal/detail/cmath/next.hpp>
4041

4142
#ifndef BOOST_DECIMAL_BUILD_MODULE
4243

@@ -228,6 +229,9 @@ BOOST_DECIMAL_EXPORT class decimal128 final
228229
friend constexpr auto to_dpd_d128(DecimalType val) noexcept
229230
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, detail::uint128);
230231

232+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
233+
friend constexpr auto detail::nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType;
234+
231235
public:
232236
// 3.2.4.1 construct/copy/destroy
233237
constexpr decimal128() noexcept = default;

include/boost/decimal/decimal128_fast.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <boost/decimal/detail/div_impl.hpp>
1818
#include <boost/decimal/detail/emulated128.hpp>
1919
#include <boost/decimal/detail/ryu/ryu_generic_128.hpp>
20+
#include <boost/decimal/detail/cmath/next.hpp>
2021

2122
#ifndef BOOST_DECIMAL_BUILD_MODULE
2223

@@ -131,6 +132,9 @@ BOOST_DECIMAL_EXPORT class decimal128_fast final
131132
template <BOOST_DECIMAL_FAST_DECIMAL_FLOATING_TYPE DecimalType>
132133
BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool;
133134

135+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
136+
friend constexpr auto detail::nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType;
137+
134138
public:
135139
constexpr decimal128_fast() noexcept = default;
136140

include/boost/decimal/decimal32.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <boost/decimal/detail/div_impl.hpp>
3939
#include <boost/decimal/detail/promote_significand.hpp>
4040
#include <boost/decimal/detail/components.hpp>
41+
#include <boost/decimal/detail/cmath/next.hpp>
4142

4243
#ifndef BOOST_DECIMAL_BUILD_MODULE
4344

@@ -220,6 +221,9 @@ BOOST_DECIMAL_EXPORT class decimal32 final // NOLINT(cppcoreguidelines-special-m
220221
friend constexpr auto to_dpd_d32(DecimalType val) noexcept
221222
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, std::uint32_t);
222223

224+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
225+
friend constexpr auto detail::nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType;
226+
223227
public:
224228
// 3.2.2.1 construct/copy/destroy:
225229
constexpr decimal32() noexcept = default;

include/boost/decimal/decimal32_fast.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <boost/decimal/detail/ryu/ryu_generic_128.hpp>
1818
#include <boost/decimal/detail/promotion.hpp>
1919
#include <boost/decimal/detail/comparison.hpp>
20+
#include <boost/decimal/detail/cmath/next.hpp>
2021

2122
#ifndef BOOST_DECIMAL_BUILD_MODULE
2223
#include <limits>
@@ -126,6 +127,9 @@ BOOST_DECIMAL_EXPORT class decimal32_fast final
126127

127128
friend constexpr auto not_finite(const decimal32_fast& val) noexcept -> bool;
128129

130+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
131+
friend constexpr auto detail::nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType;
132+
129133
public:
130134
constexpr decimal32_fast() noexcept = default;
131135

include/boost/decimal/decimal64.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <boost/decimal/detail/div_impl.hpp>
4141
#include <boost/decimal/detail/promote_significand.hpp>
4242
#include <boost/decimal/detail/components.hpp>
43+
#include <boost/decimal/detail/cmath/next.hpp>
4344

4445
#ifndef BOOST_DECIMAL_BUILD_MODULE
4546

@@ -226,6 +227,9 @@ BOOST_DECIMAL_EXPORT class decimal64 final
226227
friend constexpr auto to_dpd_d64(DecimalType val) noexcept
227228
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, std::uint64_t);
228229

230+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
231+
friend constexpr auto detail::nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType;
232+
229233
public:
230234
// 3.2.3.1 construct/copy/destroy
231235
constexpr decimal64() noexcept = default;

include/boost/decimal/decimal64_fast.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <boost/decimal/detail/promote_significand.hpp>
1919
#include <boost/decimal/detail/ryu/ryu_generic_128.hpp>
2020
#include <boost/decimal/detail/promotion.hpp>
21+
#include <boost/decimal/detail/cmath/next.hpp>
2122

2223
#ifndef BOOST_DECIMAL_BUILD_MODULE
2324

@@ -144,6 +145,9 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final
144145
template <BOOST_DECIMAL_FAST_DECIMAL_FLOATING_TYPE DecimalType>
145146
BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_equal_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool;
146147

148+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
149+
friend constexpr auto detail::nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType;
150+
147151
public:
148152
constexpr decimal64_fast() noexcept = default;
149153

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,30 +29,32 @@ namespace decimal {
2929

3030
namespace detail {
3131

32-
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T1>
33-
constexpr auto nextafter_impl(T1 val, bool direction) noexcept -> T1
32+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
33+
constexpr auto nextafter_impl(DecimalType val, bool direction) noexcept -> DecimalType
3434
{
35-
constexpr T1 zero {0};
35+
constexpr DecimalType zero {0};
3636

3737
// Val < direction = +
3838
// Val > direction = -
3939
const auto abs_val {abs(val)};
4040

4141
if (val == zero)
4242
{
43-
const auto min_val {direction ? std::numeric_limits<T1>::denorm_min() :
44-
-std::numeric_limits<T1>::denorm_min()};
43+
const auto min_val {direction ? std::numeric_limits<DecimalType>::denorm_min() :
44+
-std::numeric_limits<DecimalType>::denorm_min()};
4545
return min_val;
4646
}
47-
if (abs_val > zero && abs_val < std::numeric_limits<T1>::epsilon())
47+
else if (abs_val > zero && abs_val < std::numeric_limits<DecimalType>::epsilon())
4848
{
49-
const auto min_val {direction ? val + std::numeric_limits<T1>::min() :
50-
val - std::numeric_limits<T1>::min()};
51-
return min_val;
49+
auto exp {val.biased_exponent()};
50+
auto sig {val.full_significand()};
51+
sig = direction ? sig + 1 : sig - 1;
52+
53+
return {sig, exp, val.isneg()};
5254
}
5355

54-
const auto val_eps {direction ? val + std::numeric_limits<T1>::epsilon() :
55-
val - std::numeric_limits<T1>::epsilon()};
56+
const auto val_eps {direction ? val + std::numeric_limits<DecimalType>::epsilon() :
57+
val - std::numeric_limits<DecimalType>::epsilon()};
5658

5759
// If adding epsilon does nothing then we need to manipulate the representation
5860
if (val == val_eps)
@@ -62,7 +64,7 @@ constexpr auto nextafter_impl(T1 val, bool direction) noexcept -> T1
6264

6365
direction ? significand++ : significand--;
6466

65-
return T1{significand, exp};
67+
return DecimalType{significand, exp};
6668
}
6769
else
6870
{

test/github_issue_798.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
#include <boost/decimal.hpp>
77
#include <boost/core/lightweight_test.hpp>
8-
#include <boost/decimal/detail/cmath/next.hpp>
98
#include <iomanip>
109
#include <limits>
1110
#include <random>
@@ -65,6 +64,25 @@ void test_onek()
6564
BOOST_TEST_LT(next_after_onek, twok);
6665
}
6766

67+
template <typename T>
68+
void test_min()
69+
{
70+
std::mt19937_64 rng(42);
71+
std::uniform_int_distribution<int> dist(1, 1);
72+
73+
const T min_val {std::numeric_limits<T>::denorm_min()};
74+
const T one {dist(rng)};
75+
76+
const auto next_after_min {boost::decimal::nextafter(min_val, one)};
77+
78+
BOOST_TEST_GT(next_after_min, min_val);
79+
BOOST_TEST_LT(next_after_min, min_val + 3*std::numeric_limits<T>::min());
80+
81+
const auto two_next_after_zero {boost::decimal::nextafter(next_after_min, one)};
82+
BOOST_TEST_GT(two_next_after_zero, next_after_min);
83+
BOOST_TEST_LT(two_next_after_zero, min_val + 4*std::numeric_limits<T>::min());
84+
}
85+
6886
int main()
6987
{
7088
using namespace boost::decimal;
@@ -97,5 +115,12 @@ int main()
97115
test_onek<decimal128>();
98116
test_onek<decimal128_fast>();
99117

118+
test_min<decimal32>();
119+
test_min<decimal32_fast>();
120+
test_min<decimal64>();
121+
test_min<decimal64_fast>();
122+
test_min<decimal128>();
123+
test_min<decimal128_fast>();
124+
100125
return boost::report_errors();
101126
}

0 commit comments

Comments
 (0)