Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce language requirement for constexpr BID conversions #739

Merged
merged 7 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 36 additions & 9 deletions doc/decimal/conversions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,54 @@ struct uint128

// ----- BID Conversions -----

BOOST_DECIMAL_CXX20_CONSTEXPR std::uint32_t to_bid_d32(decimal32 val) noexcept;
constexpr std::uint32_t to_bid_d32(decimal32 val) noexcept;

BOOST_DECIMAL_CXX20_CONSTEXPR std::uint32_t to_bid_d32f(decimal32_fast val) noexcept;
constexpr decimal32 from_bid_d32(std::uint32_t bits) noexcept;

BOOST_DECIMAL_CXX20_CONSTEXPR std::uint64_t to_bid_d64(decimal64 val) noexcept;
constexpr std::uint32_t to_bid_d32f(decimal32_fast val) noexcept;

BOOST_DECIMAL_CXX20_CONSTEXPR std::uint64_t to_bid_d64f(decimal64_fast val) noexcept;
constexpr decimal32_fast from_bid_d32f(std::uint32_t bits) noexcept;

BOOST_DECIMAL_CXX20_CONSTEXPR detail::uint128 to_bid_d128(decimal128 val) noexcept;
constexpr std::uint64_t to_bid_d64(decimal64 val) noexcept;

constexpr decimal64 from_bid_d64(std::uint64_t bits) noexcept;

constexpr std::uint64_t to_bid_d64f(decimal64_fast val) noexcept;

constexpr decimal64_fast from_bid_d64f(std::uint64_t bits) noexcept;

constexpr detail::uint128 to_bid_d128(decimal128 val) noexcept;

constexpr decimal128 from_bid_d128(detail::uint128 bits) noexcept;

// Automatic detection if your platform has built-in unsigned __int128 or not to enable/disable the overload
#ifdef BOOST_DECIMAL_HAS_INT128

constexpr decimal128 from_bid_d128(unsigned __int128 bits) noexcept;

#endif // BOOST_DECIMAL_HAS_INT128

constexpr detail::uint128 to_bid_d128f(decimal128_fast val) noexcept;

constexpr decimal128 from_bid_d128f(detail::uint128 bits) noexcept;

#ifdef BOOST_DECIMAL_HAS_INT128

constexpr decimal128 from_bid_d128f(unsigned __int128 bits) noexcept;

#endif // BOOST_DECIMAL_HAS_INT128

template <typename T>
BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(T val) noexcept;
constexpr auto to_bid(T val) noexcept;

template <typename T = decimal32_fast>
BOOST_DECIMAL_CXX20_CONSTEXPR T from_bid(std::uint32_t bits) noexcept;
constexpr T from_bid(std::uint32_t bits) noexcept;

template <typename T = decimal64_fast>
BOOST_DECIMAL_CXX20_CONSTEXPR T from_bid(std::uint64_t bits) noexcept;
constexpr T from_bid(std::uint64_t bits) noexcept;

template <typename T = decimal128>
BOOST_DECIMAL_CXX20_CONSTEXPR T from_bid(detail::uint128 bits) noexcept;
constexpr T from_bid(detail::uint128 bits) noexcept;

// ----- DPD Conversions -----

Expand Down
103 changes: 58 additions & 45 deletions include/boost/decimal/bid_conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,149 +20,162 @@ namespace decimal {
# pragma GCC diagnostic ignored "-Wconversion"
#endif

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d32(decimal32 val) noexcept -> std::uint32_t
constexpr auto to_bid_d32(decimal32 val) noexcept -> std::uint32_t
{
const auto bits {detail::bit_cast<std::uint32_t>(val)};
return bits;
return val.bits_;
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d32(std::uint32_t bits) noexcept -> decimal32
constexpr auto from_bid_d32(std::uint32_t bits) noexcept -> decimal32
{
const auto val {detail::bit_cast<decimal32>(bits)};
return val;
return from_bits(bits);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d32f(decimal32_fast val) noexcept -> std::uint32_t
constexpr auto to_bid_d32f(decimal32_fast val) noexcept -> std::uint32_t
{
const decimal32 compliant_val {val};
const auto bits {detail::bit_cast<std::uint32_t>(compliant_val)};
return bits;
return to_bid_d32(compliant_val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d32f(std::uint32_t bits) noexcept -> decimal32_fast
constexpr auto from_bid_d32f(std::uint32_t bits) noexcept -> decimal32_fast
{
const auto compliant_val {detail::bit_cast<decimal32>(bits)};
const auto compliant_val {from_bid_d32(bits)};
const decimal32_fast val {compliant_val};
return val;
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d64(decimal64 val) noexcept -> std::uint64_t
constexpr auto to_bid_d64(decimal64 val) noexcept -> std::uint64_t
{
const auto bits {detail::bit_cast<std::uint64_t>(val)};
return bits;
return val.bits_;
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d64(std::uint64_t bits) noexcept -> decimal64
constexpr auto from_bid_d64(std::uint64_t bits) noexcept -> decimal64
{
const auto val {detail::bit_cast<decimal64>(bits)};
return val;
return from_bits(bits);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d64f(decimal64_fast val) noexcept -> std::uint64_t
constexpr auto to_bid_d64f(decimal64_fast val) noexcept -> std::uint64_t
{
const decimal64 compliant_val {val};
const auto bits {detail::bit_cast<std::uint64_t>(compliant_val)};
return bits;
return to_bid_d64(compliant_val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d64f(std::uint64_t bits) noexcept -> decimal64_fast
constexpr auto from_bid_d64f(std::uint64_t bits) noexcept -> decimal64_fast
{
const auto compliant_val {detail::bit_cast<decimal64>(bits)};
const auto compliant_val {from_bid_d64(bits)};
const decimal64_fast val {compliant_val};
return val;
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d128(decimal128 val) noexcept -> detail::uint128
constexpr auto to_bid_d128(decimal128 val) noexcept -> detail::uint128
{
const auto bits {detail::bit_cast<detail::uint128>(val)};
return bits;
return val.bits_;
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d128(detail::uint128 bits) noexcept -> decimal128
constexpr auto from_bid_d128(detail::uint128 bits) noexcept -> decimal128
{
const auto val {detail::bit_cast<decimal128>(bits)};
return val;
return from_bits(bits);
}

#ifdef BOOST_DECIMAL_HAS_INT128
constexpr auto from_bits_d128(detail::uint128_t bits) noexcept -> decimal128
{
return from_bits(bits);
}
#endif

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid_d128f(decimal128_fast val) noexcept -> detail::uint128
constexpr auto to_bid_d128f(decimal128_fast val) noexcept -> detail::uint128
{
const decimal128 compliant_val {val};
const auto bits {detail::bit_cast<detail::uint128>(compliant_val)};
return bits;
return to_bid_d128(compliant_val);
}

constexpr auto from_bid_d128f(detail::uint128 bits) noexcept -> decimal128_fast
{
const auto compliant_val {from_bid_d128(bits)};
const decimal128_fast val {compliant_val};
return val;
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid_d128f(detail::uint128 bits) noexcept -> decimal128_fast
#ifdef BOOST_DECIMAL_HAS_INT128
constexpr auto from_bid_d128f(detail::uint128_t bits) noexcept -> decimal128_fast
{
const auto compliant_val {detail::bit_cast<decimal128>(bits)};
const auto compliant_val {from_bid_d128(bits)};
const decimal128_fast val {compliant_val};
return val;
}
#endif

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal32 val) noexcept -> std::uint32_t
constexpr auto to_bid(decimal32 val) noexcept -> std::uint32_t
{
return to_bid_d32(val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal32_fast val) noexcept -> std::uint32_t
constexpr auto to_bid(decimal32_fast val) noexcept -> std::uint32_t
{
return to_bid_d32f(val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal64 val) noexcept -> std::uint64_t
constexpr auto to_bid(decimal64 val) noexcept -> std::uint64_t
{
return to_bid_d64(val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal64_fast val) noexcept -> std::uint64_t
constexpr auto to_bid(decimal64_fast val) noexcept -> std::uint64_t
{
return to_bid_d64f(val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal128 val) noexcept -> detail::uint128
constexpr auto to_bid(decimal128 val) noexcept -> detail::uint128
{
return to_bid_d128(val);
}

BOOST_DECIMAL_CXX20_CONSTEXPR auto to_bid(decimal128_fast val) noexcept -> detail::uint128
constexpr auto to_bid(decimal128_fast val) noexcept -> detail::uint128
{
return to_bid_d128f(val);
}

template <typename T>
constexpr auto to_bid(T val) noexcept
{
return to_bid(val);
}

template <typename T = decimal32_fast>
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid(std::uint32_t bits) noexcept
constexpr auto from_bid(std::uint32_t bits) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
{
return from_bid_d32f(bits);
}

template <>
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid<decimal32>(std::uint32_t bits) noexcept -> decimal32
constexpr auto from_bid<decimal32>(std::uint32_t bits) noexcept -> decimal32
{
return from_bid_d32(bits);
}

template <typename T = decimal64_fast>
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid(std::uint64_t bits) noexcept
constexpr auto from_bid(std::uint64_t bits) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
{
return from_bid_d64f(bits);
}

template <>
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid<decimal64>(std::uint64_t bits) noexcept -> decimal64
constexpr auto from_bid<decimal64>(std::uint64_t bits) noexcept -> decimal64
{
return from_bid_d64(bits);
}

template <typename T = decimal128_fast>
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid(detail::uint128 bits) noexcept
constexpr auto from_bid(detail::uint128 bits) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
{
return from_bid_d128f(bits);
}

template <>
BOOST_DECIMAL_CXX20_CONSTEXPR auto from_bid<decimal128>(detail::uint128 bits) noexcept -> decimal128
constexpr auto from_bid<decimal128>(detail::uint128 bits) noexcept -> decimal128
{
return from_bid_d128(bits);
}
Expand Down
8 changes: 8 additions & 0 deletions include/boost/decimal/decimal128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ BOOST_DECIMAL_EXPORT class decimal128 final

friend constexpr auto not_finite(decimal128 rhs) noexcept -> bool;

friend constexpr auto to_bid_d128(decimal128 val) noexcept -> detail::uint128;

friend constexpr auto from_bid_d128(detail::uint128 bits) noexcept -> decimal128;

#ifdef BOOST_DECIMAL_HAS_INT128
friend constexpr auto from_bid_d128(detail::uint128_t bits) noexcept -> decimal128;
#endif

public:
// 3.2.4.1 construct/copy/destroy
constexpr decimal128() noexcept = default;
Expand Down
4 changes: 4 additions & 0 deletions include/boost/decimal/decimal32.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ BOOST_DECIMAL_EXPORT class decimal32 final // NOLINT(cppcoreguidelines-special-m
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
friend constexpr auto sequential_less_impl(DecimalType lhs, DecimalType rhs) noexcept -> bool;

friend constexpr auto to_bid_d32(decimal32 val) noexcept -> std::uint32_t;

friend constexpr auto from_bid_d32(std::uint32_t bits) noexcept -> decimal32;

template <typename DecimalType>
friend constexpr auto to_dpd_d32(DecimalType val) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, std::uint32_t);
Expand Down
4 changes: 4 additions & 0 deletions include/boost/decimal/decimal64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ BOOST_DECIMAL_EXPORT class decimal64 final
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
friend constexpr auto sequential_less_impl(DecimalType lhs, DecimalType rhs) noexcept -> bool;

friend constexpr auto to_bid_d64(decimal64 val) noexcept -> std::uint64_t;

friend constexpr auto from_bid_d64(std::uint64_t bits) noexcept -> decimal64;

public:
// 3.2.3.1 construct/copy/destroy
constexpr decimal64() noexcept = default;
Expand Down
2 changes: 1 addition & 1 deletion test/test_bid_conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void test()
for (std::size_t i {}; i < 1024; ++i)
{
const T val {dist(rng)};
const auto bits {to_bid(val)};
const auto bits {to_bid<T>(val)};
const T return_val {from_bid<T>(bits)};
BOOST_TEST_EQ(val, return_val);
}
Expand Down
Loading