Skip to content
5 changes: 5 additions & 0 deletions doc/decimal/decimal128.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ namespace decimal {

class decimal128 {

public:
using significand_type = detail::uint128;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.4.1 construct/copy/destroy
Expand Down
5 changes: 5 additions & 0 deletions doc/decimal/decimal128_fast.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ namespace decimal {

class decimal128_fast {

public:
using significand_type = detail::uint128;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.4.1 construct/copy/destroy
Expand Down
5 changes: 5 additions & 0 deletions doc/decimal/decimal32.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ namespace decimal {

class decimal32 {

public:
using significand_type = std::uint32_t;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.2.1 construct/copy/destroy
Expand Down
7 changes: 6 additions & 1 deletion doc/decimal/decimal32_fast.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ https://www.boost.org/LICENSE_1_0.txt
The performance changes by being non-IEEE 754 compliant so that the value does not have to be decoded from bits, but is instead directly represented internal to the type.
As is often the case this trades space for time by having greater storage width requirements.

- Storage width - At least 48bits (`std::uint_fast32_t` + `std::uint_fast8_t` + `bool`)
- Storage width - 48bits (`std::uint32_t` + `std::uint8_t` + `bool`)
- Precision - 7 decimal digits (not bits like binary)
- Max exponent - 96
- Max Value - 9.999999e96
Expand All @@ -30,6 +30,11 @@ namespace decimal {

class decimal32_fast {

public:
using significand_type = std::uint32_t;
using exponent_type = std::uint8_t;
using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.2.1 construct/copy/destroy
Expand Down
5 changes: 5 additions & 0 deletions doc/decimal/decimal64.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ namespace decimal {

class decimal64 {

public:
using significand_type = std::uint64_t;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.3.1 construct/copy/destroy
Expand Down
7 changes: 6 additions & 1 deletion doc/decimal/decimal64_fast.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ https://www.boost.org/LICENSE_1_0.txt
The performance changes by being non-IEEE 754 compliant so that the value does not have to be decoded from bits, but is instead directly represented internal to the type.
As is often the case this trades space for time by having greater storage width requirements.

- Storage width - At least 88 bits (`std::uint_fast64_t` + `std::uint_fast_16_t` + `bool`)
- Storage width - 88 bits (`std::uint64_t` + `std::uint16_t` + `bool`)
- Precision - 16 decimal digits (not bits like binary)
- Max exponent - 385
- Max Value - 9.999999999999999e385
Expand All @@ -30,6 +30,11 @@ namespace decimal {

class decimal64_fast {

public:
using significand_type = std::uint64_t;
using exponent_type = std::uint16_t;
using biased_exponent_type = std::int32_t;

// Paragraph numbers are from ISO/IEC DTR 24733

// 3.2.3.1 construct/copy/destroy
Expand Down
2 changes: 1 addition & 1 deletion include/boost/decimal/decimal128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ BOOST_DECIMAL_EXPORT class decimal128 final
{
public:
using significand_type = detail::uint128;
using exponent_type = std::uint64_t;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

private:
Expand Down
6 changes: 3 additions & 3 deletions include/boost/decimal/decimal128_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d128_fast_snan_high_bits = UINT64_MAX;
struct decimal128_fast_components
{
using significand_type = uint128;
using biased_exponent_type = std::int_fast32_t;
using biased_exponent_type = std::int32_t;

significand_type sig;
biased_exponent_type exp;
Expand All @@ -54,8 +54,8 @@ BOOST_DECIMAL_EXPORT class decimal128_fast final
{
public:
using significand_type = detail::uint128;
using exponent_type = std::uint_fast32_t;
using biased_exponent_type = std::int_fast32_t;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

private:
// Instead of having to encode and decode at every operation
Expand Down
34 changes: 18 additions & 16 deletions include/boost/decimal/decimal32_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ namespace decimal {

namespace detail {

BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d32_fast_inf = std::numeric_limits<std::uint_fast32_t>::max() - 3;
BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d32_fast_qnan = std::numeric_limits<std::uint_fast32_t>::max() - 2;
BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d32_fast_snan = std::numeric_limits<std::uint_fast32_t>::max() - 1;
BOOST_DECIMAL_CONSTEXPR_VARIABLE std::uint32_t d32_fast_inf = std::numeric_limits<std::uint32_t>::max() - 3;
BOOST_DECIMAL_CONSTEXPR_VARIABLE std::uint32_t d32_fast_qnan = std::numeric_limits<std::uint32_t>::max() - 2;
BOOST_DECIMAL_CONSTEXPR_VARIABLE std::uint32_t d32_fast_snan = std::numeric_limits<std::uint32_t>::max() - 1;

}

BOOST_DECIMAL_EXPORT class decimal32_fast final
{
public:
using significand_type = std::uint_fast32_t;
using exponent_type = std::uint_fast8_t;
using biased_exponent_type = std::int_fast32_t;
using significand_type = std::uint32_t;
using exponent_type = std::uint8_t;
using biased_exponent_type = std::int32_t;

private:
// In regular decimal32 we have to decode the 24 bits of the significand and the 8 bits of the exp
Expand Down Expand Up @@ -326,7 +326,7 @@ BOOST_DECIMAL_EXPORT class decimal32_fast final
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE Decimal, std::enable_if_t<detail::is_decimal_floating_point_v<Decimal> && (detail::impl::decimal_val_v<Decimal> <= detail::impl::decimal_val_v<decimal32_fast>), bool> = true>
explicit constexpr operator Decimal() const noexcept;

friend constexpr auto direct_init(std::uint_fast32_t significand, std::uint_fast8_t exponent, bool sign) noexcept -> decimal32_fast;
friend constexpr auto direct_init(significand_type significand, exponent_type exponent, bool sign) noexcept -> decimal32_fast;

// <cmath> or extensions that need to be friends
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
Expand Down Expand Up @@ -379,10 +379,10 @@ constexpr decimal32_fast::decimal32_fast(T1 coeff, T2 exp, bool sign) noexcept
exp = 0;
}

auto biased_exp {static_cast<std::uint_fast32_t>(exp + detail::bias)};
auto biased_exp {static_cast<std::int64_t>(exp + detail::bias)};

// Decimal32 exponent holds 8 bits
if (biased_exp > detail::max_biased_exp_v<decimal32_fast>)
if (biased_exp > detail::max_biased_exp_v<decimal32_fast> || exp > detail::max_biased_exp_v<decimal32_fast>)
{
significand_ = detail::d32_fast_inf;
}
Expand Down Expand Up @@ -431,7 +431,7 @@ BOOST_DECIMAL_CXX20_CONSTEXPR decimal32_fast::decimal32_fast(Float val) noexcept
# pragma GCC diagnostic pop
#endif

constexpr auto direct_init(std::uint_fast32_t significand, std::uint_fast8_t exponent, bool sign = false) noexcept -> decimal32_fast
constexpr auto direct_init(decimal32_fast::significand_type significand, decimal32_fast::exponent_type exponent, bool sign = false) noexcept -> decimal32_fast
{
decimal32_fast val;
val.significand_ = significand;
Expand Down Expand Up @@ -837,9 +837,9 @@ constexpr auto operator+(decimal32_fast lhs, Integer rhs) noexcept

exp_type exp_rhs {0};
detail::normalize(sig_rhs, exp_rhs);
const auto final_sig_rhs {static_cast<detail::decimal32_fast_components::significand_type>(detail::make_positive_unsigned(sig_rhs))};
const auto final_sig_rhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(sig_rhs))};

return detail::d32_add_impl<decimal32_fast>(lhs.significand_, lhs.biased_exponent(), lhs.sign_,
return detail::d32_add_impl<decimal32_fast>(static_cast<promoted_significand_type>(lhs.significand_), lhs.biased_exponent(), lhs.sign_,
final_sig_rhs, exp_rhs, (rhs < 0),
abs_lhs_bigger);
}
Expand Down Expand Up @@ -1028,11 +1028,13 @@ constexpr auto div_impl(decimal32_fast lhs, decimal32_fast rhs, decimal32_fast&
<< "\nexp rhs: " << exp_rhs << std::endl;
#endif

using promoted_type = std::uint64_t;

// We promote to uint64 since the significands are currently 32-bits
// By appending enough zeros to the LHS we end up finding what we need anyway
constexpr auto ten_pow_precision {detail::pow10(static_cast<std::uint_fast64_t>(detail::precision_v<decimal32>))};
const auto big_sig_lhs {static_cast<std::uint_fast64_t>(lhs.significand_) * ten_pow_precision};
const auto res_sig {big_sig_lhs / static_cast<std::uint_fast64_t>(rhs.significand_)};
constexpr auto ten_pow_precision {detail::pow10(static_cast<promoted_type>(detail::precision_v<decimal32>))};
const auto big_sig_lhs {static_cast<promoted_type>(lhs.significand_) * ten_pow_precision};
const auto res_sig {big_sig_lhs / static_cast<promoted_type>(rhs.significand_)};
const auto res_exp {(lhs.biased_exponent() - detail::precision_v<decimal32>) - rhs.biased_exponent()};

q = decimal32_fast(res_sig, res_exp, lhs.sign_ != rhs.sign_);
Expand Down Expand Up @@ -1500,7 +1502,7 @@ struct numeric_limits<boost::decimal::decimal32_fast>
static constexpr int min_exponent10 = min_exponent;
static constexpr int max_exponent = 96;
static constexpr int max_exponent10 = max_exponent;
static constexpr bool traps = numeric_limits<std::uint_fast32_t>::traps;
static constexpr bool traps = numeric_limits<std::uint32_t>::traps;
static constexpr bool tinyness_before = true;

// Member functions
Expand Down
4 changes: 2 additions & 2 deletions include/boost/decimal/decimal64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ BOOST_DECIMAL_EXPORT class decimal64 final
{
public:
using significand_type = std::uint64_t;
using exponent_type = std::uint64_t;
using exponent_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

private:
Expand Down Expand Up @@ -1018,7 +1018,7 @@ constexpr auto decimal64::unbiased_exponent() const noexcept -> exponent_type
break;
}

expval |= (bits_ & detail::d64_exponent_mask) >> detail::d64_significand_bits;
expval |= static_cast<exponent_type>((bits_ & detail::d64_exponent_mask) >> detail::d64_significand_bits);

return expval;
}
Expand Down
20 changes: 10 additions & 10 deletions include/boost/decimal/decimal64_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ namespace decimal {

namespace detail {

BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d64_fast_inf = std::numeric_limits<std::uint_fast64_t>::max() - 3;
BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d64_fast_qnan = std::numeric_limits<std::uint_fast64_t>::max() - 2;
BOOST_DECIMAL_CONSTEXPR_VARIABLE auto d64_fast_snan = std::numeric_limits<std::uint_fast64_t>::max() - 1;
BOOST_DECIMAL_CONSTEXPR_VARIABLE std::uint64_t d64_fast_inf = std::numeric_limits<std::uint64_t>::max() - 3;
BOOST_DECIMAL_CONSTEXPR_VARIABLE std::uint64_t d64_fast_qnan = std::numeric_limits<std::uint64_t>::max() - 2;
BOOST_DECIMAL_CONSTEXPR_VARIABLE std::uint64_t d64_fast_snan = std::numeric_limits<std::uint64_t>::max() - 1;

struct decimal64_fast_components
{
using significand_type = std::uint_fast64_t;
using biased_exponent_type = std::int_fast32_t;
using significand_type = std::uint64_t;
using biased_exponent_type = std::int32_t;

significand_type sig;
biased_exponent_type exp;
Expand All @@ -50,9 +50,9 @@ struct decimal64_fast_components
BOOST_DECIMAL_EXPORT class decimal64_fast final
{
public:
using significand_type = std::uint_fast64_t;
using exponent_type = std::uint_fast16_t;
using biased_exponent_type = std::int_fast32_t;
using significand_type = std::uint64_t;
using exponent_type = std::uint16_t;
using biased_exponent_type = std::int32_t;

private:
// In regular decimal64 we have to decode the significand end exponent
Expand Down Expand Up @@ -390,9 +390,9 @@ constexpr decimal64_fast::decimal64_fast(T1 coeff, T2 exp, bool sign) noexcept
exp = 0;
}

const auto biased_exp {static_cast<std::uint_fast32_t>(exp + detail::bias_v<decimal64>)};
const auto biased_exp {static_cast<exponent_type>(exp + detail::bias_v<decimal64>)};

if (biased_exp > detail::max_biased_exp_v<decimal64>)
if (biased_exp > detail::max_biased_exp_v<decimal64> || exp > detail::max_biased_exp_v<decimal64>)
{
significand_ = detail::d64_fast_inf;
}
Expand Down
4 changes: 2 additions & 2 deletions include/boost/decimal/detail/components.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ struct decimal32_components

struct decimal32_fast_components
{
using significand_type = std::uint_fast32_t;
using biased_exponent_type = std::int_fast32_t;
using significand_type = std::uint32_t;
using biased_exponent_type = std::int32_t;

significand_type sig;
biased_exponent_type exp;
Expand Down
2 changes: 1 addition & 1 deletion include/boost/decimal/detail/promote_significand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace impl {
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType, BOOST_DECIMAL_INTEGRAL Integer>
struct promote_significand
{
using type = std::conditional_t<std::numeric_limits<Integer>::digits10 < std::numeric_limits<typename DecimalType::significand_type>::digits10,
using type = std::conditional_t<std::numeric_limits<make_unsigned_t<Integer>>::digits10 < std::numeric_limits<typename DecimalType::significand_type>::digits10,
typename DecimalType::significand_type, detail::make_unsigned_t<Integer>>;
};

Expand Down
Loading