Skip to content

Commit fc669ff

Browse files
authored
Merge pull request #1333 from boostorg/tuning_tests
Test tuning and improvement
2 parents 0444beb + 087fb29 commit fc669ff

File tree

10 files changed

+206
-146
lines changed

10 files changed

+206
-146
lines changed

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

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Copyright 2023 Matt Borland
2-
// Copyright 2023 Christopher Kormanyos
1+
// Copyright 2023 - 2026 Matt Borland
2+
// Copyright 2023 - 2026 Christopher Kormanyos
33
// Distributed under the Boost Software License, Version 1.0.
44
// https://www.boost.org/LICENSE_1_0.txt
55

@@ -151,27 +151,32 @@ constexpr auto pow(const T x, const T a) noexcept
151151
BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T)
152152
{
153153
constexpr T zero { 0, 0 };
154+
constexpr T one { 1, 0 };
154155

155156
auto result = zero;
156157

158+
const auto fpc_a = fpclassify(a);
159+
157160
const auto na = static_cast<int>(a);
158161

159-
if ((na == a) || ((na == 0) && (na == abs(a))))
162+
if (fpc_a == FP_ZERO)
163+
{
164+
// pow(base, +/-0) returns 1 for any base, even when base is NaN.
165+
166+
result = one;
167+
}
168+
else if (na == a)
160169
{
161170
result = pow(x, na);
162171
}
163172
else
164173
{
165-
constexpr T one { 1, 0 };
166-
167174
const auto fpc_x = fpclassify(x);
168-
const auto fpc_a = fpclassify(a);
169175

170-
if (fpc_a == FP_ZERO)
176+
if ((fpc_x == FP_NAN) || (fpc_a == FP_NAN))
171177
{
172-
// pow(base, +/-0) returns 1 for any base, even when base is NaN.
173-
174-
result = one;
178+
// This line is known to be covered by tests.
179+
result = std::numeric_limits<T>::quiet_NaN(); // LCOV_EXCL_LINE
175180
}
176181
else if (fpc_x == FP_ZERO)
177182
{
@@ -186,10 +191,6 @@ constexpr auto pow(const T x, const T a) noexcept
186191

187192
result = (signbit(a) ? std::numeric_limits<T>::infinity() : zero);
188193
}
189-
else if (fpc_a == FP_NAN)
190-
{
191-
result = std::numeric_limits<T>::quiet_NaN();
192-
}
193194
#else
194195
if (fpc_a == FP_NORMAL)
195196
{
@@ -207,14 +208,6 @@ constexpr auto pow(const T x, const T a) noexcept
207208

208209
result = (signbit(a) ? zero : std::numeric_limits<T>::infinity());
209210
}
210-
else if (fpc_a == FP_NAN)
211-
{
212-
result = std::numeric_limits<T>::quiet_NaN();
213-
}
214-
}
215-
else if (fpc_x != FP_NORMAL)
216-
{
217-
result = x;
218211
}
219212
#endif
220213
else

test/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ project : requirements
2929
#<toolset>gcc:<cxxflags>-Wduplicated-branches
3030
<toolset>gcc:<cxxflags>-Wfloat-equal
3131
<toolset>gcc:<cxxflags>-Wshadow
32+
<toolset>gcc:<cxxflags>-Wno-psabi
3233
# https://github.com/boostorg/decimal/issues/1291
3334
# GCC-7 does not support extra-semi, just pick one to try
3435
<toolset>gcc-13:<cxxflags>-Wextra-semi

test/test_asin.cpp

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Copyright 2024 - 2025 Matt Borland
2-
// Copyright 2024 - 2025 Christopher Kormanyos
1+
// Copyright 2024 - 2026 Matt Borland
2+
// Copyright 2024 - 2026 Christopher Kormanyos
33
// Distributed under the Boost Software License, Version 1.0.
44
// https://www.boost.org/LICENSE_1_0.txt
55

@@ -32,6 +32,7 @@
3232
#include <boost/math/special_functions/next.hpp>
3333
#include <boost/core/lightweight_test.hpp>
3434

35+
#include <chrono>
3536
#include <cmath>
3637
#include <random>
3738

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

52+
namespace local
53+
{
54+
template<typename IntegralTimePointType,
55+
typename ClockType = std::chrono::high_resolution_clock>
56+
auto time_point() noexcept -> IntegralTimePointType
57+
{
58+
using local_integral_time_point_type = IntegralTimePointType;
59+
using local_clock_type = ClockType;
60+
61+
const auto current_now =
62+
static_cast<std::uintmax_t>
63+
(
64+
std::chrono::duration_cast<std::chrono::nanoseconds>
65+
(
66+
local_clock_type::now().time_since_epoch()
67+
).count()
68+
);
69+
70+
return static_cast<local_integral_time_point_type>(current_now);
71+
}
72+
} // namespace local
73+
5174
template <typename Dec>
5275
void test_asin()
5376
{
@@ -178,8 +201,36 @@ auto test_asin_edge() -> void
178201

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

181-
BOOST_TEST_EQ(asin(my_zero<T>() + my_one<T>()), half_pi);
182-
BOOST_TEST_EQ(asin(my_zero<T>() - my_one<T>()), -half_pi);
204+
std::random_device rd;
205+
std::mt19937_64 gen(rd());
206+
207+
gen.seed(local::time_point<typename std::mt19937_64::result_type>());
208+
209+
auto dis =
210+
std::uniform_real_distribution<float>
211+
{
212+
static_cast<float>(1.01F),
213+
static_cast<float>(1.04F)
214+
};
215+
216+
BOOST_TEST_EQ(asin((my_zero<T>() * static_cast<T>(dis(gen))) + my_one<T>()), half_pi);
217+
BOOST_TEST_EQ(asin((my_zero<T>() * static_cast<T>(dis(gen))) - my_one<T>()), -half_pi);
218+
219+
for(auto i = static_cast<unsigned>(UINT8_C(0)); i < static_cast<unsigned>(UINT8_C(4)); ++i)
220+
{
221+
static_cast<void>(i);
222+
223+
const T near_one { my_one<T>() * static_cast<T>(dis(gen)) };
224+
225+
const T arg_one { T { static_cast<int>(near_one) } };
226+
227+
const auto val_one_pos = asin(+arg_one);
228+
const auto val_one_neg = asin(-arg_one);
229+
230+
BOOST_TEST_EQ(val_one_pos, +half_pi);
231+
BOOST_TEST_EQ(val_one_neg, -half_pi);
232+
}
233+
183234
}
184235

185236
template<typename T>

test/test_asinh.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright 2023 Matt Borland
2-
// Copyright 2023 Christopher Kormanyos
2+
// Copyright 2023 - 2026 Christopher Kormanyos
33
// Distributed under the Boost Software License, Version 1.0.
44
// https://www.boost.org/LICENSE_1_0.txt
55

@@ -236,14 +236,16 @@ auto main() -> int
236236
);
237237

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

244245
BOOST_TEST(result_eps_is_ok);
245246
BOOST_TEST(result_tiny_is_ok);
246247
BOOST_TEST(result_small_is_ok);
248+
BOOST_TEST(result_small_neg_is_ok);
247249
BOOST_TEST(result_medium_is_ok);
248250
BOOST_TEST(result_medium_neg_is_ok);
249251
BOOST_TEST(result_large_is_ok);

test/test_assoc_legendre.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
// Propogates up from boost.math
66
#define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING
77

8+
#ifdef _MSC_VER
9+
# pragma warning(push)
10+
# pragma warning(disable: 4714) // Marked as forceinline but not inlined
11+
#endif
12+
813
#include "testing_config.hpp"
914
#include <boost/decimal.hpp>
1015

@@ -28,22 +33,13 @@
2833
# pragma GCC diagnostic ignored "-Wuseless-cast"
2934
#endif
3035

31-
// Windows in Github actions has a broken chrono header
32-
#if defined(_WIN32)
33-
34-
int main()
35-
{
36-
return 0;
37-
}
38-
39-
#else
40-
4136
#include <boost/math/special_functions/next.hpp>
4237
#include <boost/math/special_functions/legendre.hpp>
4338
#include <boost/core/lightweight_test.hpp>
39+
40+
#include <cmath>
4441
#include <iostream>
4542
#include <random>
46-
#include <cmath>
4743

4844
static constexpr std::size_t N {10};
4945

@@ -245,4 +241,6 @@ int main()
245241
return boost::report_errors();
246242
}
247243

244+
#ifdef _MSC_VER
245+
# pragma warning(pop)
248246
#endif

0 commit comments

Comments
 (0)