Skip to content

Commit e054637

Browse files
committed
Handle Git issue 1137
1 parent 7cfb824 commit e054637

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

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

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

@@ -41,20 +42,26 @@ constexpr auto asin_impl(const T x) noexcept
4142
return x;
4243
}
4344

44-
const auto absx {fabs(x)};
45-
T result {};
45+
const auto absx { fabs(x) };
4646

47-
if (absx <= std::numeric_limits<T>::epsilon())
47+
T result { };
48+
49+
constexpr T cbrt_eps { cbrt(std::numeric_limits<T>::epsilon()) };
50+
51+
constexpr T one { 1 };
52+
53+
if (absx <= cbrt_eps)
4854
{
49-
result = absx;
55+
result = absx * (one + (absx / 6) * absx);
5056
}
51-
else if (absx <= T{5, -1})
57+
else if (absx <= T { 5, -1 })
5258
{
5359
result = asin_series(absx);
5460
}
55-
else if (absx <= T{1, 0})
61+
else if (absx <= one)
5662
{
5763
constexpr T half_pi {numbers::pi_v<T> / 2};
64+
5865
result = half_pi - 2 * asin_series(sqrt((1 - absx) / 2));
5966
}
6067
else

test/test_asin.cpp

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

@@ -137,6 +138,40 @@ void print_value(T value, const char* str)
137138
<< "\nExp: " << ptr << "\n" << std::endl;
138139
}
139140

141+
template<typename T>
142+
auto test_asin_edge() -> void
143+
{
144+
using nl = std::numeric_limits<T>;
145+
146+
const T tiny0 { nl::epsilon() * 999 / 1000 };
147+
const T tiny1 { nl::epsilon() };
148+
const T tiny2 { nl::epsilon() * 1000 / 999 };
149+
150+
const T asin_tiny0 { asin(tiny0) };
151+
const T asin_tiny1 { asin(tiny1) };
152+
const T asin_tiny2 { asin(tiny2) };
153+
154+
// tiny1: 1
155+
// tiny2: 1.001001
156+
// tiny0: 0.999
157+
// tiny1: 1
158+
// tiny2: 1.001001001001001
159+
// tiny0: 0.999
160+
// tiny1: 1
161+
// tiny2: 1.001001001001001001001001001001001
162+
163+
constexpr T ctrl_tiny2
164+
{
165+
std::numeric_limits<T>::digits10 < 10 ? T("1.001001")
166+
: std::numeric_limits<T>::digits10 < 20 ? T("1.001001001001001")
167+
: T("1.001001001001001001001001001001001")
168+
};
169+
170+
BOOST_TEST_EQ(asin_tiny0 / nl::epsilon(), T(999, -3));
171+
BOOST_TEST_EQ(asin_tiny1 / nl::epsilon(), T(1));
172+
BOOST_TEST_EQ(asin_tiny2 / nl::epsilon(), ctrl_tiny2);
173+
}
174+
140175
int main()
141176
{
142177
#ifdef BOOST_DECIMAL_GENERATE_CONSTANT_SIGS
@@ -188,6 +223,10 @@ int main()
188223
test_asin<decimal32_t>();
189224
test_asin<decimal64_t>();
190225

226+
test_asin_edge<decimal32_t>();
227+
test_asin_edge<decimal64_t>();
228+
test_asin_edge<decimal128_t>();
229+
191230
#if !defined(BOOST_DECIMAL_REDUCE_TEST_DEPTH)
192231
test_asin<decimal128_t>();
193232
#endif

0 commit comments

Comments
 (0)