Skip to content

Commit beb2ad6

Browse files
authored
Merge pull request #346 from cppalliance/logb
2 parents 153d4ad + 85c3952 commit beb2ad6

File tree

7 files changed

+93
-3
lines changed

7 files changed

+93
-3
lines changed

include/boost/decimal/cmath.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <boost/decimal/detail/cmath/tgamma.hpp>
5454
#include <boost/decimal/detail/cmath/trunc.hpp>
5555
#include <boost/decimal/detail/cmath/nan.hpp>
56+
#include <boost/decimal/detail/cmath/logb.hpp>
5657
#include <boost/decimal/numbers.hpp>
5758

5859
// Macros from 3.6.2

include/boost/decimal/decimal128.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ class decimal128 final
214214

215215
friend constexpr auto d128_mod_impl(decimal128 lhs, decimal128 rhs, const decimal128& q, decimal128& r) noexcept -> void;
216216

217+
template <typename T>
218+
friend constexpr auto ilogb(T d) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, int>;
219+
220+
template <typename T>
221+
friend constexpr auto logb(T num) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, T>;
222+
217223
public:
218224
// 3.2.4.1 construct/copy/destroy
219225
constexpr decimal128() noexcept = default;

include/boost/decimal/decimal32.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ class decimal32 final // NOLINT(cppcoreguidelines-special-member-functions,hicpp
165165
template <typename T>
166166
friend constexpr auto ilogb(T d) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, int>;
167167

168+
template <typename T>
169+
friend constexpr auto logb(T num) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, T>;
170+
168171
// Debug bit pattern
169172
friend constexpr auto from_bits(std::uint32_t bits) noexcept -> decimal32;
170173
friend BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bits(decimal32 rhs) noexcept -> std::uint32_t;

include/boost/decimal/decimal64.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ class decimal64 final
208208
template <typename T>
209209
friend constexpr auto ilogb(T d) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, int>;
210210

211+
template <typename T>
212+
friend constexpr auto logb(T num) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, T>;
213+
211214
public:
212215
// 3.2.3.1 construct/copy/destroy
213216
constexpr decimal64() noexcept = default;

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
#include <boost/decimal/fwd.hpp> // NOLINT(llvm-include-order)
1212
#include <boost/decimal/detail/type_traits.hpp>
1313

14-
namespace boost { namespace decimal {
15-
16-
// TODO(mborland): Allow conversion between decimal types via a promotion system
14+
namespace boost {
15+
namespace decimal {
1716

1817
template <typename T>
1918
constexpr auto ilogb(T d) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, int>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2023 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#ifndef BOOST_DECIMAL_DETAIL_CMATH_LOGB_HPP
6+
#define BOOST_DECIMAL_DETAIL_CMATH_LOGB_HPP
7+
8+
#include <cmath>
9+
#include <type_traits>
10+
11+
#include <boost/decimal/fwd.hpp> // NOLINT(llvm-include-order)
12+
#include <boost/decimal/detail/type_traits.hpp>
13+
14+
namespace boost {
15+
namespace decimal {
16+
17+
template <typename T>
18+
constexpr auto logb(T num) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<T>, T>
19+
{
20+
const auto fpc {fpclassify(num)};
21+
22+
if (fpc == FP_ZERO)
23+
{
24+
return -std::numeric_limits<T>::infinity();
25+
}
26+
else if (fpc == FP_INFINITE)
27+
{
28+
return std::numeric_limits<T>::infinity();
29+
}
30+
else if (fpc == FP_NAN)
31+
{
32+
return num;
33+
}
34+
35+
const auto offset = detail::num_digits(num.full_significand()) - 1;
36+
const auto expval = static_cast<int>(static_cast<int>(num.unbiased_exponent()) + offset);
37+
38+
return static_cast<T>(expval);
39+
}
40+
41+
}
42+
}
43+
44+
#endif //BOOST_DECIMAL_DETAIL_CMATH_LOGB_HPP

test/test_cmath.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,12 +610,41 @@ void test_ilogb()
610610
BOOST_TEST_EQ(ilogb(Dec(1, 0)), 398);
611611
BOOST_TEST_EQ(ilogb(Dec(10, 0)), 399);
612612
}
613+
else
614+
{
615+
BOOST_TEST_EQ(ilogb(Dec(1, 0)), 6176);
616+
BOOST_TEST_EQ(ilogb(Dec(10, 0)), 6177);
617+
}
613618

614619
BOOST_TEST_EQ(ilogb(Dec(0)), FP_ILOGB0);
615620
BOOST_TEST_EQ(ilogb(std::numeric_limits<Dec>::infinity()), INT_MAX);
616621
BOOST_TEST_EQ(ilogb(std::numeric_limits<Dec>::quiet_NaN()), FP_ILOGBNAN);
617622
}
618623

624+
template <typename Dec>
625+
void test_logb()
626+
{
627+
BOOST_DECIMAL_IF_CONSTEXPR (std::is_same<Dec, decimal32>::value)
628+
{
629+
BOOST_TEST_EQ(ilogb(Dec(1, 0)), Dec(101));
630+
BOOST_TEST_EQ(ilogb(Dec(10, 0)), Dec(102));
631+
}
632+
else BOOST_DECIMAL_IF_CONSTEXPR (std::is_same<Dec, decimal64>::value)
633+
{
634+
BOOST_TEST_EQ(ilogb(Dec(1, 0)), Dec(398));
635+
BOOST_TEST_EQ(ilogb(Dec(10, 0)), Dec(399));
636+
}
637+
else
638+
{
639+
BOOST_TEST_EQ(ilogb(Dec(1, 0)), 6176);
640+
BOOST_TEST_EQ(ilogb(Dec(10, 0)), 6177);
641+
}
642+
643+
BOOST_TEST_EQ(logb(Dec(0)), -std::numeric_limits<Dec>::infinity());
644+
BOOST_TEST_EQ(logb(std::numeric_limits<Dec>::infinity()), std::numeric_limits<Dec>::infinity());
645+
BOOST_TEST(isnan(logb(std::numeric_limits<Dec>::quiet_NaN())));
646+
}
647+
619648
template <typename Dec>
620649
void test_sqrt()
621650
{
@@ -1422,6 +1451,11 @@ int main()
14221451

14231452
test_ilogb<decimal32>();
14241453
test_ilogb<decimal64>();
1454+
test_ilogb<decimal128>();
1455+
1456+
test_logb<decimal32>();
1457+
test_logb<decimal64>();
1458+
test_logb<decimal128>();
14251459

14261460
test_sqrt<decimal32>();
14271461
test_sqrt<decimal64>();

0 commit comments

Comments
 (0)