Skip to content
Open
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
4 changes: 4 additions & 0 deletions libcxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,10 @@ function(cxx_link_system_libraries target)
target_link_libraries(${target} PRIVATE atomic)
endif()

if (LIBCXX_HAS_MATH_LIB)
target_link_libraries(${target} PRIVATE m)
endif()

if (MINGW)
target_link_libraries(${target} PRIVATE "${MINGW_LIBRARIES}")
endif()
Expand Down
6 changes: 6 additions & 0 deletions libcxx/cmake/config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -110,24 +110,30 @@ if(WIN32 AND NOT MINGW)
set(LIBCXX_HAS_PTHREAD_LIB NO)
set(LIBCXX_HAS_RT_LIB NO)
set(LIBCXX_HAS_ATOMIC_LIB NO)
set(LIBCXX_HAS_MATH_LIB NO)
elseif(APPLE)
set(LIBCXX_HAS_PTHREAD_LIB NO)
set(LIBCXX_HAS_RT_LIB NO)
set(LIBCXX_HAS_ATOMIC_LIB NO)
set(LIBCXX_HAS_MATH_LIB NO)
elseif(FUCHSIA)
set(LIBCXX_HAS_PTHREAD_LIB NO)
set(LIBCXX_HAS_RT_LIB NO)
check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
set(LIBCXX_HAS_MATH_LIB NO)
elseif(ANDROID)
set(LIBCXX_HAS_PTHREAD_LIB NO)
set(LIBCXX_HAS_RT_LIB NO)
set(LIBCXX_HAS_ATOMIC_LIB NO)
set(LIBCXX_HAS_MATH_LIB NO)
elseif(PICOLIBC)
set(LIBCXX_HAS_PTHREAD_LIB NO)
set(LIBCXX_HAS_RT_LIB NO)
set(LIBCXX_HAS_ATOMIC_LIB NO)
set(LIBCXX_HAS_MATH_LIB NO)
else()
check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB)
check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB)
check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
check_library_exists(m lgamma_r "" LIBCXX_HAS_MATH_LIB)
endif()
13 changes: 13 additions & 0 deletions libcxx/include/__configuration/availability.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
// in all versions of the library are available.
#if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS

# define _LIBCPP_INTRODUCED_IN_LLVM_22 1
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */

# define _LIBCPP_INTRODUCED_IN_LLVM_21 1
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */

Expand Down Expand Up @@ -120,6 +123,11 @@

// clang-format off

// LLVM 22
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_22 0
# define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE __attribute__((unavailable))

// LLVM 21
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_21 0
Expand Down Expand Up @@ -355,6 +363,11 @@
#define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
// No attribute, since we've had bad_function_call::what() in the headers before

// This controls whether we provide an implementation of a thread safe variant of the `std::lgamma`
// function in the dylib.
#define _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA _LIBCPP_INTRODUCED_IN_LLVM_22
// No attribute, since we call ::lgamma_r instead

// Define availability attributes that depend on both
// _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI.
#if !_LIBCPP_HAS_EXCEPTIONS || !_LIBCPP_HAS_RTTI
Expand Down
25 changes: 25 additions & 0 deletions libcxx/include/__math/gamma.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,31 @@ inline _LIBCPP_HIDE_FROM_ABI double tgamma(_A1 __x) _NOEXCEPT {
return __builtin_tgamma((double)__x);
}

// __lgamma_r

struct __lgamma_result {
double __result;
int __sign;
};
Comment on lines +60 to +63
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're never using the __sign. Should we remove that part? @lntue do you think this makes any difference in the implementation?


#if _LIBCPP_AVAILABILITY_HAS_THREAD_SAFE_LGAMMA
_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double) _NOEXCEPT;

inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
return __math::__lgamma_thread_safe_impl(__d);
}
Comment on lines +68 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for having another wrapper here?

#else
// When deploying to older targets, call `lgamma_r` directly but avoid declaring the actual
// function since different platforms declare the function slightly differently.
double __lgamma_r_shim(double, int*) _NOEXCEPT __asm__("lgamma_r");

inline _LIBCPP_HIDE_FROM_ABI __lgamma_result __lgamma_thread_safe(double __d) _NOEXCEPT {
int __sign;
double __res = __math::__lgamma_r_shim(__d, &__sign);
return __lgamma_result{__res, __sign};
}
#endif

} // namespace __math

_LIBCPP_END_NAMESPACE_STD
Expand Down
34 changes: 5 additions & 29 deletions libcxx/include/__random/binomial_distribution.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define _LIBCPP___RANDOM_BINOMIAL_DISTRIBUTION_H

#include <__config>
#include <__math/gamma.h>
#include <__random/is_valid.h>
#include <__random/uniform_real_distribution.h>
#include <cmath>
Expand Down Expand Up @@ -97,39 +98,14 @@ class binomial_distribution {
}
};

// Some libc declares the math functions to be `noexcept`.
#if defined(_LIBCPP_GLIBC_PREREQ)
# if _LIBCPP_GLIBC_PREREQ(2, 8)
# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
# else
# define _LIBCPP_LGAMMA_R_NOEXCEPT
# endif
#elif defined(__LLVM_LIBC__)
# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
#else
# define _LIBCPP_LGAMMA_R_NOEXCEPT
#endif

#if !defined(_LIBCPP_MSVCRT_LIKE)
extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT;
#endif

inline _LIBCPP_HIDE_FROM_ABI double __libcpp_lgamma(double __d) {
#if defined(_LIBCPP_MSVCRT_LIKE)
return lgamma(__d);
#else
int __sign;
return lgamma_r(__d, &__sign);
#endif
}

template <class _IntType>
binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p) : __t_(__t), __p_(__p) {
if (0 < __p_ && __p_ < 1) {
__r0_ = static_cast<result_type>((__t_ + 1) * __p_);
__pr_ = std::exp(
std::__libcpp_lgamma(__t_ + 1.) - std::__libcpp_lgamma(__r0_ + 1.) - std::__libcpp_lgamma(__t_ - __r0_ + 1.) +
__r0_ * std::log(__p_) + (__t_ - __r0_) * std::log(1 - __p_));
__pr_ =
std::exp(__math::__lgamma_thread_safe(__t_ + 1.).__result - __math::__lgamma_thread_safe(__r0_ + 1.).__result -
__math::__lgamma_thread_safe(__t_ - __r0_ + 1.).__result + __r0_ * std::log(__p_) +
(__t_ - __r0_) * std::log(1 - __p_));
__odds_ratio_ = __p_ / (1 - __p_);
}
}
Expand Down
10 changes: 10 additions & 0 deletions libcxx/lib/abi/CHANGELOG.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ New entries should be added directly below the "Version" header.
Version 22.0
------------

* [libc++] Add a thread-safe version of std::lgamma in the dylib

This patch adds a new function __lgamma_thread_safe in the dylib to avoid having to redeclare
::lgamma_r within libc++'s own headers. This merely introduces a new symbol so it's not an ABI
break.

All platforms
-------------
Symbol added: _ZNSt3__16__math25__lgamma_thread_safe_implEd

* [libc++] Remove __time_get_storage::{__analyze,init} from the ABI

These functions have never been used outside the dylib, so there is no point in exporting them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,7 @@
{'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk16__clocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u64toaEyPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEyPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEi', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12steady_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock11from_time_tEl', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__16chrono12system_clock3nowEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,7 @@
{'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk16__clocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__itoa8__u64toaEmPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,7 @@
{'is_defined': True, 'name': '_ZNSt3__15wcoutE', 'size': 384, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,7 @@
{'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,7 @@
{'is_defined': True, 'name': '_ZNSt3__16__clocEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__itoa8__u64toaEmPc', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__math25__lgamma_thread_safe_implEd', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'}
Expand Down
1 change: 1 addition & 0 deletions libcxx/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ set(LIBCXX_SOURCES
include/ryu/ryu.h
include/to_chars_floating_point.h
include/from_chars_floating_point.h
math.cpp
memory.cpp
memory_resource.cpp
new_handler.cpp
Expand Down
26 changes: 26 additions & 0 deletions libcxx/src/math.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifdef __APPLE__
# define _REENTRANT
#endif

#include <cmath>
#include <math.h> // for lgamma_r

_LIBCPP_BEGIN_NAMESPACE_STD
namespace __math {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to enshrine the __math namespace forever in our ABI?


_LIBCPP_EXPORTED_FROM_ABI __lgamma_result __lgamma_thread_safe_impl(double __d) noexcept {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _LIBCPP_EXPORTED_FROM_ABI shouldn't be required here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't hurt to have it though and we do have a bunch of functions in .cpp files that specify _LIBCPP_EXPORTED_FROM_ABI too, which IMO helps spot which functions are exported and which ones are not. In this case it's not super helpful since there's currently only one function in that .cpp file, but still.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to say I completely disagree. IMO this significantly hurts readability. We should instead just have non-_Uglified names for library-internal functions (which itself helps with readability in general). Spotting exported ones is trivial in that case. Removing the attribute here also ensures that the correct declarations are visible at the definition, which helps avoid declaration mismatches.

int __sign;
double __result = ::lgamma_r(__d, &__sign);
return __lgamma_result{__result, __sign};
}

} // namespace __math
_LIBCPP_END_NAMESPACE_STD
Loading