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

Add cmath support to decimal128_fast #638

Merged
merged 29 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6208bde
Add friend cmath functions
mborland Jun 6, 2024
afcc199
Add asin overload
mborland Jun 6, 2024
49a98ed
Add compound arithmetic operators
mborland Jun 6, 2024
ca045a9
Fix narrowing warning
mborland Jun 6, 2024
7082d08
Implement assoc legendre lookup table for decimal128_fast
mborland Jun 6, 2024
75d59fa
Add atan overloads
mborland Jun 6, 2024
bf5899e
Add numeric constants overloads
mborland Jun 6, 2024
9add61c
Add attribute overloads
mborland Jun 6, 2024
fe9b048
Add cos overload
mborland Jun 6, 2024
c257006
Add cosh overload
mborland Jun 6, 2024
4917c54
Add expm1 overload
mborland Jun 6, 2024
bab79fb
Add lgamma overload
mborland Jun 6, 2024
0d72262
Add log1p overload
mborland Jun 6, 2024
c925bd0
Add log overload
mborland Jun 6, 2024
6388eb7
Add riemann zeta overload
mborland Jun 6, 2024
6bb259c
Add sin overload
mborland Jun 6, 2024
41330c2
Add sinh overload
mborland Jun 6, 2024
14361e8
Add tanh overload
mborland Jun 6, 2024
15186a7
Add tgamma overload
mborland Jun 6, 2024
dfb4c1a
Add promotion value with testing
mborland Jun 6, 2024
f314269
Add logb and ilogb friends
mborland Jun 6, 2024
488a2ae
Add cmath testing
mborland Jun 6, 2024
6b438ed
Reduce test sets and add assertion for high word
mborland Jun 7, 2024
7c335c0
Enable sqrt testing
mborland Jun 7, 2024
19fb872
Add remquo handling
mborland Jun 7, 2024
0a9c5cc
Remove temporary operator<<
mborland Jun 7, 2024
8483c80
Fix ADL error
mborland Jun 10, 2024
6b127ff
Fix rounding for decimal128_fast
mborland Jun 10, 2024
7172da4
Increase GHA timeout
mborland Jun 11, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ jobs:
cxxstd: "03,11,14,17,20,2b"
os: macos-14

timeout-minutes: 120
timeout-minutes: 180
runs-on: ${{matrix.os}}
container: ${{matrix.container}}

Expand Down
33 changes: 30 additions & 3 deletions include/boost/decimal/charconv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@
return detail::from_chars_general_impl(first, last, value, fmt);
}

BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal128_fast& value, chars_format fmt = chars_format::general) noexcept
{
return detail::from_chars_general_impl(first, last, value, fmt);
}

// ---------------------------------------------------------------------------------------------------------------------
// to_chars and implementation
// ---------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -242,7 +247,7 @@
int exp {};
auto significand {frexp10(value, &exp)};

using uint_type = std::conditional_t<std::is_same<TargetDecimalType, decimal128>::value, uint128, std::uint64_t>;
using uint_type = std::conditional_t<std::is_same<TargetDecimalType, decimal128>::value || std::is_same<TargetDecimalType, decimal128_fast>::value, uint128, std::uint64_t>;
auto significand_digits = num_digits(significand);
exp += significand_digits - 1;
bool append_zeros = false;
Expand Down Expand Up @@ -473,7 +478,8 @@
}
}

using uint_type = std::conditional_t<std::is_same<TargetDecimalType, decimal128>::value, uint128, std::uint64_t>;
using uint_type = std::conditional_t<std::is_same<TargetDecimalType, decimal128>::value ||
std::is_same<TargetDecimalType, decimal128_fast>::value, uint128, std::uint64_t>;
auto r = to_chars_integer_impl<uint_type, uint_type>(first, last, significand, 10);

if (BOOST_DECIMAL_UNLIKELY(!r))
Expand Down Expand Up @@ -579,7 +585,8 @@
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE TargetDecimalType>
BOOST_DECIMAL_CONSTEXPR auto to_chars_hex_impl(char* first, char* last, const TargetDecimalType& value, int precision = -1) noexcept -> to_chars_result
{
using Unsigned_Integer = std::conditional_t<!std::is_same<TargetDecimalType, decimal128>::value, std::uint64_t, uint128>;
using Unsigned_Integer = std::conditional_t<std::is_same<TargetDecimalType, decimal128>::value ||
std::is_same<TargetDecimalType, decimal128_fast>::value, uint128, std::uint64_t>;

if (signbit(value))
{
Expand Down Expand Up @@ -868,6 +875,26 @@
return detail::to_chars_impl(first, last, value, fmt, precision);
}

BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* last, decimal128_fast value) noexcept -> to_chars_result
{
return detail::to_chars_impl(first, last, value);
}

BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* last, decimal128_fast value, chars_format fmt) noexcept -> to_chars_result
{
return detail::to_chars_impl(first, last, value, fmt);
}

BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* last, decimal128_fast value, chars_format fmt, int precision) noexcept -> to_chars_result
{
if (precision < 0)

Check warning on line 890 in include/boost/decimal/charconv.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/decimal/charconv.hpp#L890

Added line #L890 was not covered by tests
{
precision = 6;
}

return detail::to_chars_impl(first, last, value, fmt, precision);

Check warning on line 895 in include/boost/decimal/charconv.hpp

View check run for this annotation

Codecov / codecov/patch

include/boost/decimal/charconv.hpp#L895

Added line #L895 was not covered by tests
}

template <typename T>
struct limits
{
Expand Down
150 changes: 121 additions & 29 deletions include/boost/decimal/decimal128_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ class decimal128_fast final
-> std::enable_if_t<(detail::is_decimal_floating_point_v<Decimal1> &&
detail::is_decimal_floating_point_v<Decimal2>), bool>;

template <typename T>
friend constexpr auto ilogb(T d) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, int);

template <typename T>
friend constexpr auto logb(T num) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T);

public:
constexpr decimal128_fast() noexcept = default;

Expand Down Expand Up @@ -253,6 +261,31 @@ class decimal128_fast final
friend constexpr auto operator/(Integer lhs, decimal128_fast rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast);

// Compound Arithmetic Operators
constexpr auto operator+=(decimal128_fast rhs) noexcept -> decimal128_fast&;

template <typename Integer>
constexpr auto operator+=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&);

constexpr auto operator-=(decimal128_fast rhs) noexcept -> decimal128_fast&;

template <typename Integer>
constexpr auto operator-=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&);

constexpr auto operator*=(decimal128_fast rhs) noexcept -> decimal128_fast&;

template <typename Integer>
constexpr auto operator*=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&);

constexpr auto operator/=(decimal128_fast rhs) noexcept -> decimal128_fast&;

template <typename Integer>
constexpr auto operator/=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&);

// Conversions
explicit constexpr operator bool() const noexcept;
explicit constexpr operator int() const noexcept;
Expand Down Expand Up @@ -295,35 +328,10 @@ class decimal128_fast final
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
friend constexpr auto frexp10(T num, int* expptr) noexcept -> typename T::significand_type;

#if !defined(BOOST_DECIMAL_DISABLE_CLIB)

// LCOV_EXCL_START
// TODO(mborland): Fix with STL bindings and delete
template <typename charT, typename traits>
friend auto operator<<(std::basic_ostream<charT, traits>& os, const decimal128_fast& d) -> std::basic_ostream<charT, traits>&
{
if (d.sign_)
{
os << "-";
}
else
{
os << "+";
}

os << d.significand_ << "e";
const auto biased_exp {d.biased_exponent()};
if (biased_exp > 0)
{
os << '+';
}
os << biased_exp;

return os;
}
// LCOV_EXCL_STOP

#endif
friend constexpr auto copysignd128f(decimal128_fast mag, decimal128_fast sgn) noexcept -> decimal128_fast;
friend constexpr auto scalblnd128f(decimal128_fast num, long exp) noexcept -> decimal128_fast;
friend constexpr auto scalbnd128f(decimal128_fast num, int exp) noexcept -> decimal128_fast;
friend constexpr auto fmad128f(decimal128_fast x, decimal128_fast y, decimal128 z) noexcept -> decimal128;
};

#ifdef BOOST_DECIMAL_HAS_CONCEPTS
Expand Down Expand Up @@ -986,6 +994,7 @@ constexpr auto operator*(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
}
#endif

// TODO(mborland): Is trimming the zeros really necessary? Doesn't seem like it
auto lhs_sig {lhs.full_significand()};
auto lhs_exp {lhs.biased_exponent()};
const auto lhs_zeros {detail::remove_trailing_zeros(lhs_sig)};
Expand Down Expand Up @@ -1238,6 +1247,62 @@ constexpr auto operator%(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
return r;
};

constexpr auto decimal128_fast::operator+=(decimal128_fast rhs) noexcept -> decimal128_fast&
{
*this = *this + rhs;
return *this;
}

template <typename Integer>
constexpr auto decimal128_fast::operator+=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&)
{
*this = *this + rhs;
return *this;
}

constexpr auto decimal128_fast::operator-=(decimal128_fast rhs) noexcept -> decimal128_fast&
{
*this = *this - rhs;
return *this;
}

template <typename Integer>
constexpr auto decimal128_fast::operator-=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&)
{
*this = *this - rhs;
return *this;
}

constexpr auto decimal128_fast::operator*=(decimal128_fast rhs) noexcept -> decimal128_fast&
{
*this = *this * rhs;
return *this;
}

template <typename Integer>
constexpr auto decimal128_fast::operator*=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&)
{
*this = *this * rhs;
return *this;
}

constexpr auto decimal128_fast::operator/=(decimal128_fast rhs) noexcept -> decimal128_fast&
{
*this = *this / rhs;
return *this;
}

template <typename Integer>
constexpr auto decimal128_fast::operator/=(Integer rhs) noexcept
BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&)
{
*this = *this / rhs;
return *this;
}

constexpr decimal128_fast::operator bool() const noexcept
{
constexpr decimal128_fast zero {0, 0};
Expand Down Expand Up @@ -1354,6 +1419,33 @@ constexpr decimal128_fast::operator Decimal() const noexcept
return to_decimal<Decimal>(*this);
}

constexpr auto copysignd128f(decimal128_fast mag, decimal128_fast sgn) noexcept -> decimal128_fast
{
mag.sign_ = sgn.sign_;
return mag;
}

constexpr auto scalblnd128f(decimal128_fast num, long exp) noexcept -> decimal128_fast
{
#ifndef BOOST_DECIMAL_FAST_MATH
constexpr decimal128_fast zero {0, 0};

if (num == zero || exp == 0 || isinf(num) || isnan(num))
{
return num;
}
#endif

num.exponent_ = static_cast<decimal128_fast::exponent_type>(static_cast<long>(num.biased_exponent()) + exp);

return num;
}

constexpr auto scalbnd128f(decimal128_fast num, int exp) noexcept -> decimal128_fast
{
return scalblnd128f(num, static_cast<long>(exp));
}

} // namespace decimal
} // namespace boost

Expand Down
31 changes: 31 additions & 0 deletions include/boost/decimal/detail/attributes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,54 @@ BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto storage_wid
template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto storage_width_v<decimal128> = 128;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto storage_width_v<decimal128_fast> = 128;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto precision_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 7 : 16;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto precision_v<decimal128> = 34;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto precision_v<decimal128_fast> = 34;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto bias_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 101 : 398;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto bias_v<decimal128> = 6176;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto bias_v<decimal128_fast> = 6176;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_biased_exp_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 191 : 767;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_biased_exp_v<decimal128> = 12287;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_biased_exp_v<decimal128_fast> = 12287;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto emax_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 96 : 384;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emax_v<decimal128> = 6144;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emax_v<decimal128_fast> = 6144;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto emin_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? -95 : -383;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emin_v<decimal128> = -6143;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emin_v<decimal128_fast> = -6143;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto etiny_v = -bias_v<Dec>;

Expand All @@ -65,26 +83,39 @@ BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto combination
template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto combination_field_width_v<decimal128> = 17;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto combination_field_width_v<decimal128_fast> = 17;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto trailing_significand_field_width_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 20 : 50;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto trailing_significand_field_width_v<decimal128> = 110;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto trailing_significand_field_width_v<decimal128_fast> = 110;

template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_significand_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 9'999'999 : 9'999'999'999'999'999;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_significand_v<decimal128> =
uint128{UINT64_C(0b1111111111'1111111111'1111111111'1111111111'111111), UINT64_MAX};

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_significand_v<decimal128_fast> =
uint128{UINT64_C(0b1111111111'1111111111'1111111111'1111111111'111111), UINT64_MAX};

// sign + decimal digits + '.' + 'e' + '+/-' + max digits of exponent + null term
template <typename Dec, std::enable_if_t<detail::is_decimal_floating_point_v<Dec>, bool> = true>
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_string_length_v = std::is_same<Dec, decimal32>::value || std::is_same<Dec, decimal32_fast>::value ? 15 : 25;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_string_length_v<decimal128> = 41;

template <>
BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_string_length_v<decimal128_fast> = 41;

BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto storage_width {storage_width_v<decimal32>};
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto precision {precision_v<decimal32>};
BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto bias {bias_v<decimal32>};
Expand Down
10 changes: 10 additions & 0 deletions include/boost/decimal/detail/cmath/fma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,11 @@ constexpr auto fmad64f(decimal64_fast x, decimal64_fast y, decimal64_fast z) noe
return {result.sig, result.exp, result.sign};
}

constexpr auto fmad128f(decimal128_fast x, decimal128_fast y, decimal128_fast z) noexcept -> decimal128_fast
{
return x * y + z;
}

BOOST_DECIMAL_EXPORT constexpr auto fma(decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal32
{
return fmad32(x, y, z);
Expand All @@ -325,6 +330,11 @@ BOOST_DECIMAL_EXPORT constexpr auto fma(decimal64_fast x, decimal64_fast y, deci
return fmad64f(x, y, z);
}

BOOST_DECIMAL_EXPORT constexpr auto fma(decimal128_fast x, decimal128_fast y, decimal128_fast z) noexcept -> decimal128_fast
{
return fmad128f(x, y, z);
}

} //namespace decimal
} //namespace boost

Expand Down
Loading
Loading