Skip to content
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
37 changes: 15 additions & 22 deletions include/boost/decimal/detail/cmath/pow.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2023 Matt Borland
// Copyright 2023 Christopher Kormanyos
// Copyright 2023 - 2026 Matt Borland
// Copyright 2023 - 2026 Christopher Kormanyos
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

Expand Down Expand Up @@ -151,27 +151,32 @@ constexpr auto pow(const T x, const T a) noexcept
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
{
constexpr T zero { 0, 0 };
constexpr T one { 1, 0 };

auto result = zero;

const auto fpc_a = fpclassify(a);

const auto na = static_cast<int>(a);

if ((na == a) || ((na == 0) && (na == abs(a))))
if (fpc_a == FP_ZERO)
{
// pow(base, +/-0) returns 1 for any base, even when base is NaN.

result = one;
}
else if (na == a)
{
result = pow(x, na);
}
else
{
constexpr T one { 1, 0 };

const auto fpc_x = fpclassify(x);
const auto fpc_a = fpclassify(a);

if (fpc_a == FP_ZERO)
if ((fpc_x == FP_NAN) || (fpc_a == FP_NAN))
{
// pow(base, +/-0) returns 1 for any base, even when base is NaN.

result = one;
// This line is known to be covered by tests.
result = std::numeric_limits<T>::quiet_NaN(); // LCOV_EXCL_LINE
}
else if (fpc_x == FP_ZERO)
{
Expand All @@ -186,10 +191,6 @@ constexpr auto pow(const T x, const T a) noexcept

result = (signbit(a) ? std::numeric_limits<T>::infinity() : zero);
}
else if (fpc_a == FP_NAN)
{
result = std::numeric_limits<T>::quiet_NaN();
}
#else
if (fpc_a == FP_NORMAL)
{
Expand All @@ -207,14 +208,6 @@ constexpr auto pow(const T x, const T a) noexcept

result = (signbit(a) ? zero : std::numeric_limits<T>::infinity());
}
else if (fpc_a == FP_NAN)
{
result = std::numeric_limits<T>::quiet_NaN();
}
}
else if (fpc_x != FP_NORMAL)
{
result = x;
}
#endif
else
Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ project : requirements
#<toolset>gcc:<cxxflags>-Wduplicated-branches
<toolset>gcc:<cxxflags>-Wfloat-equal
<toolset>gcc:<cxxflags>-Wshadow
<toolset>gcc:<cxxflags>-Wno-psabi
# https://github.com/boostorg/decimal/issues/1291
# GCC-7 does not support extra-semi, just pick one to try
<toolset>gcc-13:<cxxflags>-Wextra-semi
Expand Down
59 changes: 55 additions & 4 deletions test/test_asin.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2024 - 2025 Matt Borland
// Copyright 2024 - 2025 Christopher Kormanyos
// Copyright 2024 - 2026 Matt Borland
// Copyright 2024 - 2026 Christopher Kormanyos
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

Expand Down Expand Up @@ -32,6 +32,7 @@
#include <boost/math/special_functions/next.hpp>
#include <boost/core/lightweight_test.hpp>

#include <chrono>
#include <cmath>
#include <random>

Expand All @@ -48,6 +49,28 @@ using namespace boost::decimal;
template<typename T> auto my_zero() -> T;
template<typename T> auto my_one () -> T;

namespace local
{
template<typename IntegralTimePointType,
typename ClockType = std::chrono::high_resolution_clock>
auto time_point() noexcept -> IntegralTimePointType
{
using local_integral_time_point_type = IntegralTimePointType;
using local_clock_type = ClockType;

const auto current_now =
static_cast<std::uintmax_t>
(
std::chrono::duration_cast<std::chrono::nanoseconds>
(
local_clock_type::now().time_since_epoch()
).count()
);

return static_cast<local_integral_time_point_type>(current_now);
}
} // namespace local

template <typename Dec>
void test_asin()
{
Expand Down Expand Up @@ -178,8 +201,36 @@ auto test_asin_edge() -> void

constexpr T half_pi { numbers::pi_v<T> / 2 };

BOOST_TEST_EQ(asin(my_zero<T>() + my_one<T>()), half_pi);
BOOST_TEST_EQ(asin(my_zero<T>() - my_one<T>()), -half_pi);
std::random_device rd;
std::mt19937_64 gen(rd());

gen.seed(local::time_point<typename std::mt19937_64::result_type>());

auto dis =
std::uniform_real_distribution<float>
{
static_cast<float>(1.01F),
static_cast<float>(1.04F)
};

BOOST_TEST_EQ(asin((my_zero<T>() * static_cast<T>(dis(gen))) + my_one<T>()), half_pi);
BOOST_TEST_EQ(asin((my_zero<T>() * static_cast<T>(dis(gen))) - my_one<T>()), -half_pi);

for(auto i = static_cast<unsigned>(UINT8_C(0)); i < static_cast<unsigned>(UINT8_C(4)); ++i)
{
static_cast<void>(i);

const T near_one { my_one<T>() * static_cast<T>(dis(gen)) };

const T arg_one { T { static_cast<int>(near_one) } };

const auto val_one_pos = asin(+arg_one);
const auto val_one_neg = asin(-arg_one);

BOOST_TEST_EQ(val_one_pos, +half_pi);
BOOST_TEST_EQ(val_one_neg, -half_pi);
}

}

template<typename T>
Expand Down
6 changes: 4 additions & 2 deletions test/test_asinh.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2023 Matt Borland
// Copyright 2023 Christopher Kormanyos
// Copyright 2023 - 2026 Christopher Kormanyos
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

Expand Down Expand Up @@ -236,14 +236,16 @@ auto main() -> int
);

const auto result_tiny_is_ok = local::test_asinh(INT32_C(4096), false, 1.001, 1.1);
const auto result_small_is_ok = local::test_asinh(INT32_C(96), false, 0.1, 1.59);
const auto result_small_is_ok = local::test_asinh(INT32_C(384), false, 0.1, 1.59);
const auto result_small_neg_is_ok = local::test_asinh(INT32_C(384), true, 0.1, 1.59);
const auto result_medium_is_ok = local::test_asinh(INT32_C(48), false, 1.59, 10.1);
const auto result_medium_neg_is_ok = local::test_asinh(INT32_C(48), true, 1.59, 10.1);
const auto result_large_is_ok = local::test_asinh(INT32_C(48), false, 1.0E+01, 1.0E+19);

BOOST_TEST(result_eps_is_ok);
BOOST_TEST(result_tiny_is_ok);
BOOST_TEST(result_small_is_ok);
BOOST_TEST(result_small_neg_is_ok);
BOOST_TEST(result_medium_is_ok);
BOOST_TEST(result_medium_neg_is_ok);
BOOST_TEST(result_large_is_ok);
Expand Down
20 changes: 9 additions & 11 deletions test/test_assoc_legendre.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
// Propogates up from boost.math
#define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING

#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4714) // Marked as forceinline but not inlined
#endif

#include "testing_config.hpp"
#include <boost/decimal.hpp>

Expand All @@ -28,22 +33,13 @@
# pragma GCC diagnostic ignored "-Wuseless-cast"
#endif

// Windows in Github actions has a broken chrono header
#if defined(_WIN32)

int main()
{
return 0;
}

#else

#include <boost/math/special_functions/next.hpp>
#include <boost/math/special_functions/legendre.hpp>
#include <boost/core/lightweight_test.hpp>

#include <cmath>
#include <iostream>
#include <random>
#include <cmath>

static constexpr std::size_t N {10};

Expand Down Expand Up @@ -245,4 +241,6 @@ int main()
return boost::report_errors();
}

#ifdef _MSC_VER
# pragma warning(pop)
#endif
Loading