Skip to content

Commit ddd93ec

Browse files
committed
[libc++] Avoid redeclaring lgamma_r
This causes issues when building with modules, and redeclaring functions provided by another library (here the C library) is bad hygiene. Instead, use <math.h> to access the declaration provided by the system. As a drive-by, this also starts using ::lgamma_r instead of ::lgamma when building on top of LLVM-libc. We didn't do that previously due to a declration conflict, but using the _r version when we can should only make things thread safe.
1 parent dbc96f4 commit ddd93ec

File tree

5 files changed

+70
-29
lines changed

5 files changed

+70
-29
lines changed

libcxx/include/__configuration/availability.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@
8484
// in all versions of the library are available.
8585
#if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
8686

87+
# define _LIBCPP_INTRODUCED_IN_LLVM_22 1
88+
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
89+
8790
# define _LIBCPP_INTRODUCED_IN_LLVM_21 1
8891
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */
8992

@@ -120,6 +123,11 @@
120123

121124
// clang-format off
122125

126+
// LLVM 22
127+
// TODO: Fill this in
128+
# define _LIBCPP_INTRODUCED_IN_LLVM_22 0
129+
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable))
130+
123131
// LLVM 21
124132
// TODO: Fill this in
125133
# define _LIBCPP_INTRODUCED_IN_LLVM_21 0
@@ -355,6 +363,11 @@
355363
#define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
356364
// No attribute, since we've had bad_function_call::what() in the headers before
357365

366+
// This controls whether we provide an implementation of a thread safe variant of the `std::lgamma`
367+
// function in the dylib.
368+
#define _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA _LIBCPP_INTRODUCED_IN_LLVM_22
369+
// No attribute, since we call ::lgamma_r instead
370+
358371
// Define availability attributes that depend on both
359372
// _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI.
360373
#if !_LIBCPP_HAS_EXCEPTIONS || !_LIBCPP_HAS_RTTI

libcxx/include/__math/gamma.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,31 @@ inline _LIBCPP_HIDE_FROM_ABI double tgamma(_A1 __x) _NOEXCEPT {
5555
return __builtin_tgamma((double)__x);
5656
}
5757

58+
// __lgamma_r
59+
60+
struct __lgamma_result {
61+
double __result;
62+
int __sign;
63+
};
64+
65+
#if _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA
66+
_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double) _NOEXCEPT;
67+
68+
inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
69+
return __math::__lgamma_thread_safe_impl(__d);
70+
}
71+
#else
72+
// When deploying to older targets, call `lgamma_r` directly but avoid declaring the actual
73+
// function since different platforms declare the function slightly differently.
74+
double __lgamma_r_shim(double, int*) _NOEXCEPT __asm__("lgamma_r");
75+
76+
inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
77+
int __sign;
78+
double __res = __math::__lgamma_r_shim(__d, &__sign);
79+
return __lgamma_result{__res, __sign};
80+
}
81+
#endif
82+
5883
} // namespace __math
5984

6085
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__random/binomial_distribution.h

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define _LIBCPP___RANDOM_BINOMIAL_DISTRIBUTION_H
1111

1212
#include <__config>
13+
#include <__math/gamma.h>
1314
#include <__random/is_valid.h>
1415
#include <__random/uniform_real_distribution.h>
1516
#include <cmath>
@@ -97,39 +98,14 @@ class binomial_distribution {
9798
}
9899
};
99100

100-
// Some libc declares the math functions to be `noexcept`.
101-
#if defined(_LIBCPP_GLIBC_PREREQ)
102-
# if _LIBCPP_GLIBC_PREREQ(2, 8)
103-
# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
104-
# else
105-
# define _LIBCPP_LGAMMA_R_NOEXCEPT
106-
# endif
107-
#elif defined(__LLVM_LIBC__)
108-
# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
109-
#else
110-
# define _LIBCPP_LGAMMA_R_NOEXCEPT
111-
#endif
112-
113-
#if !defined(_LIBCPP_MSVCRT_LIKE)
114-
extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT;
115-
#endif
116-
117-
inline _LIBCPP_HIDE_FROM_ABI double __libcpp_lgamma(double __d) {
118-
#if defined(_LIBCPP_MSVCRT_LIKE)
119-
return lgamma(__d);
120-
#else
121-
int __sign;
122-
return lgamma_r(__d, &__sign);
123-
#endif
124-
}
125-
126101
template <class _IntType>
127102
binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) : __t_(__t), __p_(__p) {
128103
if (0 < __p_ && __p_ < 1) {
129104
__r0_ = static_cast<result_type>((__t_ + 1) * __p_);
130-
__pr_ = std::exp(
131-
std::__libcpp_lgamma(__t_ + 1.) - std::__libcpp_lgamma(__r0_ + 1.) - std::__libcpp_lgamma(__t_ - __r0_ + 1.) +
132-
__r0_ * std::log(__p_) + (__t_ - __r0_) * std::log(1 - __p_));
105+
__pr_ =
106+
std::exp(__math::__lgamma_thread_safe(__t_ + 1.).__result - __math::__lgamma_thread_safe(__r0_ + 1.).__result -
107+
__math::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) +
108+
(__t_ - __r0_) * std::log(1 - __p_));
133109
__odds_ratio_ = __p_ / (1 - __p_);
134110
}
135111
}

libcxx/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ set(LIBCXX_SOURCES
3030
include/ryu/ryu.h
3131
include/to_chars_floating_point.h
3232
include/from_chars_floating_point.h
33+
math.cpp
3334
memory.cpp
3435
memory_resource.cpp
3536
new_handler.cpp

libcxx/src/math.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifdef __APPLE__
10+
# define _REENTRANT
11+
#endif
12+
13+
#include <cmath>
14+
#include <math.h> // for lgamma_r
15+
16+
_LIBCPP_BEGIN_NAMESPACE_STD
17+
namespace __math {
18+
19+
_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
20+
int __sign;
21+
double __result = ::lgamma_r(__d, &__sign);
22+
return __lgamma_result{__result, __sign};
23+
}
24+
25+
} // namespace __math
26+
_LIBCPP_END_NAMESPACE_STD

0 commit comments

Comments
 (0)