[libc++] Make all of <random> depend on <__math/FOO.h> instead of <cmath> (#213084) Some of `<random>` functionality depends on the system's `math.h` header instead of `__math/FOO.h`. System's are just undefined symbol to be linked, but the `__math/FOO.h` are implemented with potentially constexpr-friendly builtins. Also, some of the functionality seems to be using `__math::` namespace and some doesn't, seemingly randomly. This PR fixes such inconsistency, avoids using non-constexpr functions from the system's `math.h`, and in turn removes obstacles for P3791 `constexpr <random>`. Co-authored-by: Louis Dionne <ldionne.2@gmail.com> GitOrigin-RevId: ada3786e91ca2058f3ac8255a024c12ae7d263ee
diff --git a/include/__random/binomial_distribution.h b/include/__random/binomial_distribution.h index e4fe921..abc9d75 100644 --- a/include/__random/binomial_distribution.h +++ b/include/__random/binomial_distribution.h
@@ -10,10 +10,11 @@ #define _LIBCPP___RANDOM_BINOMIAL_DISTRIBUTION_H #include <__config> +#include <__math/exponential_functions.h> #include <__math/gamma.h> +#include <__math/logarithms.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -102,9 +103,9 @@ 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(__math::__lgamma_r(__t_ + 1.) - __math::__lgamma_r(__r0_ + 1.) - - __math::__lgamma_r(__t_ - __r0_ + 1.) + __r0_ * std::log(__p_) + (__t_ - __r0_) * std::log(1 - __p_)); + __pr_ = __math::exp( + __math::__lgamma_r(__t_ + 1.) - __math::__lgamma_r(__r0_ + 1.) - __math::__lgamma_r(__t_ - __r0_ + 1.) + + __r0_ * __math::log(__p_) + (__t_ - __r0_) * __math::log(1 - __p_)); __odds_ratio_ = __p_ / (1 - __p_); } }
diff --git a/include/__random/cauchy_distribution.h b/include/__random/cauchy_distribution.h index 65e8309..ad88b5a 100644 --- a/include/__random/cauchy_distribution.h +++ b/include/__random/cauchy_distribution.h
@@ -10,9 +10,9 @@ #define _LIBCPP___RANDOM_CAUCHY_DISTRIBUTION_H #include <__config> +#include <__math/trigonometric_functions.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -100,7 +100,7 @@ static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); uniform_real_distribution<result_type> __gen; // purposefully let tan arg get as close to pi/2 as it wants, tan will return a finite - return __p.a() + __p.b() * std::tan(3.1415926535897932384626433832795 * __gen(__g)); + return __p.a() + __p.b() * __math::tan(3.1415926535897932384626433832795 * __gen(__g)); } template <class _CharT, class _Traits, class _RT>
diff --git a/include/__random/clamp_to_integral.h b/include/__random/clamp_to_integral.h index 9ddf41e..0990ad4 100644 --- a/include/__random/clamp_to_integral.h +++ b/include/__random/clamp_to_integral.h
@@ -10,7 +10,9 @@ #define _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H #include <__config> -#include <cmath> +#include <__math/rounding_functions.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> #include <limits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -42,12 +44,13 @@ // The behavior is undefined if `__r` is NaN. template <class _IntT, class _RealT> _LIBCPP_HIDE_FROM_ABI _IntT __clamp_to_integral(_RealT __r) _NOEXCEPT { - using _Lim = numeric_limits<_IntT>; + using _IntLim = numeric_limits<_IntT>; + using _RealLim = numeric_limits<_RealT>; const _IntT __max_val = std::__max_representable_int_for_float<_IntT, _RealT>(); - if (__r >= ::nextafter(static_cast<_RealT>(__max_val), INFINITY)) { - return _Lim::max(); - } else if (__r <= _Lim::lowest()) { - return _Lim::min(); + if (__r >= __math::nextafter(static_cast<_RealT>(__max_val), _RealLim::infinity())) { + return _IntLim::max(); + } else if (__r <= _IntLim::lowest()) { + return _IntLim::min(); } return static_cast<_IntT>(__r); }
diff --git a/include/__random/exponential_distribution.h b/include/__random/exponential_distribution.h index 17f566e..c029db4 100644 --- a/include/__random/exponential_distribution.h +++ b/include/__random/exponential_distribution.h
@@ -10,10 +10,10 @@ #define _LIBCPP___RANDOM_EXPONENTIAL_DISTRIBUTION_H #include <__config> +#include <__math/logarithms.h> #include <__random/generate_canonical.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -96,7 +96,7 @@ template <class _URNG> _RealType exponential_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); - return -std::log(result_type(1) - std::generate_canonical<result_type, numeric_limits<result_type>::digits>(__g)) / + return -__math::log(result_type(1) - std::generate_canonical<result_type, numeric_limits<result_type>::digits>(__g)) / __p.lambda(); }
diff --git a/include/__random/extreme_value_distribution.h b/include/__random/extreme_value_distribution.h index e59079b..ce26da1 100644 --- a/include/__random/extreme_value_distribution.h +++ b/include/__random/extreme_value_distribution.h
@@ -10,9 +10,9 @@ #define _LIBCPP___RANDOM_EXTREME_VALUE_DISTRIBUTION_H #include <__config> +#include <__math/logarithms.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -100,7 +100,7 @@ template <class _URNG> _RealType extreme_value_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); - return __p.a() - __p.b() * std::log(-std::log(1 - uniform_real_distribution<result_type>()(__g))); + return __p.a() - __p.b() * __math::log(-__math::log(1 - uniform_real_distribution<result_type>()(__g))); } template <class _CharT, class _Traits, class _RT>
diff --git a/include/__random/gamma_distribution.h b/include/__random/gamma_distribution.h index aa418fd..19185d3 100644 --- a/include/__random/gamma_distribution.h +++ b/include/__random/gamma_distribution.h
@@ -10,10 +10,13 @@ #define _LIBCPP___RANDOM_GAMMA_DISTRIBUTION_H #include <__config> +#include <__math/exponential_functions.h> +#include <__math/gamma.h> +#include <__math/logarithms.h> +#include <__math/roots.h> #include <__random/exponential_distribution.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -114,13 +117,13 @@ const result_type __v = __gen(__g); const result_type __w = __u * (1 - __u); if (__w != 0) { - const result_type __y = std::sqrt(__c / __w) * (__u - result_type(0.5)); + const result_type __y = __math::sqrt(__c / __w) * (__u - result_type(0.5)); __x = __b + __y; if (__x >= 0) { const result_type __z = 64 * __w * __w * __w * __v * __v; if (__z <= 1 - 2 * __y * __y / __x) break; - if (std::log(__z) <= 2 * (__b * std::log(__x / __b) - __y)) + if (__math::log(__z) <= 2 * (__b * __math::log(__x / __b) - __y)) break; } } @@ -131,12 +134,12 @@ const result_type __u = __gen(__g); const result_type __es = __egen(__g); if (__u <= 1 - __a) { - __x = std::pow(__u, 1 / __a); + __x = __math::pow(__u, 1 / __a); if (__x <= __es) break; } else { - const result_type __e = -std::log((1 - __u) / __a); - __x = std::pow(1 - __a + __a * __e, 1 / __a); + const result_type __e = -__math::log((1 - __u) / __a); + __x = __math::pow(1 - __a + __a * __e, 1 / __a); if (__x <= __e + __es) break; }
diff --git a/include/__random/lognormal_distribution.h b/include/__random/lognormal_distribution.h index a94918a..da5c644 100644 --- a/include/__random/lognormal_distribution.h +++ b/include/__random/lognormal_distribution.h
@@ -10,9 +10,9 @@ #define _LIBCPP___RANDOM_LOGNORMAL_DISTRIBUTION_H #include <__config> +#include <__math/exponential_functions.h> #include <__random/is_valid.h> #include <__random/normal_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -69,13 +69,13 @@ // generating functions template <class _URNG> [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g) { - return std::exp(__nd_(__g)); + return __math::exp(__nd_(__g)); } template <class _URNG> [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p) { typename normal_distribution<result_type>::param_type __pn(__p.m(), __p.s()); - return std::exp(__nd_(__g, __pn)); + return __math::exp(__nd_(__g, __pn)); } // property functions
diff --git a/include/__random/normal_distribution.h b/include/__random/normal_distribution.h index 4ebfd75..999c7cc 100644 --- a/include/__random/normal_distribution.h +++ b/include/__random/normal_distribution.h
@@ -10,9 +10,10 @@ #define _LIBCPP___RANDOM_NORMAL_DISTRIBUTION_H #include <__config> +#include <__math/logarithms.h> +#include <__math/roots.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -123,7 +124,7 @@ __v = __uni(__g); __s = __u * __u + __v * __v; } while (__s > 1 || __s == 0); - result_type __fp = std::sqrt(-2 * std::log(__s) / __s); + result_type __fp = __math::sqrt(-2 * __math::log(__s) / __s); __v_ = __v * __fp; __v_hot_ = true; __up = __u * __fp;
diff --git a/include/__random/piecewise_linear_distribution.h b/include/__random/piecewise_linear_distribution.h index ddf6416..fb5be22 100644 --- a/include/__random/piecewise_linear_distribution.h +++ b/include/__random/piecewise_linear_distribution.h
@@ -14,11 +14,11 @@ #include <__config> #include <__cstddef/ptrdiff_t.h> #include <__iterator/back_insert_iterator.h> +#include <__math/roots.h> #include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> #include <__vector/comparison.h> #include <__vector/vector.h> -#include <cmath> #include <initializer_list> #include <iosfwd> @@ -257,7 +257,8 @@ return __u / __dk + __bk; const result_type __bk1 = __p.__b_[__k + 1]; const result_type __deltab = __bk1 - __bk; - return (__bk * __dk1 - __bk1 * __dk + std::sqrt(__deltab * (__deltab * __dk * __dk + 2 * __deltad * __u))) / __deltad; + return (__bk * __dk1 - __bk1 * __dk + __math::sqrt(__deltab * (__deltab * __dk * __dk + 2 * __deltad * __u))) / + __deltad; } template <class _CharT, class _Traits, class _RT>
diff --git a/include/__random/poisson_distribution.h b/include/__random/poisson_distribution.h index 118f148..ccb459a 100644 --- a/include/__random/poisson_distribution.h +++ b/include/__random/poisson_distribution.h
@@ -10,12 +10,17 @@ #define _LIBCPP___RANDOM_POISSON_DISTRIBUTION_H #include <__config> +#include <__math/abs.h> +#include <__math/exponential_functions.h> +#include <__math/logarithms.h> +#include <__math/roots.h> +#include <__math/rounding_functions.h> +#include <__math/traits.h> #include <__random/clamp_to_integral.h> #include <__random/exponential_distribution.h> #include <__random/is_valid.h> #include <__random/normal_distribution.h> #include <__random/uniform_real_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -107,11 +112,11 @@ // According to the standard `inf` is a valid input, but it causes the // distribution to hang, so we replace it with the maximum representable // mean. - : __mean_(isinf(__mean) ? numeric_limits<double>::max() : __mean) { + : __mean_(__math::isinf(__mean) ? numeric_limits<double>::max() : __mean) { if (__mean_ < 10) { __s_ = 0; __d_ = 0; - __l_ = std::exp(-__mean_); + __l_ = __math::exp(-__mean_); __omega_ = 0; __c3_ = 0; __c2_ = 0; @@ -119,9 +124,9 @@ __c0_ = 0; __c_ = 0; } else { - __s_ = std::sqrt(__mean_); + __s_ = __math::sqrt(__mean_); __d_ = 6 * __mean_ * __mean_; - __l_ = std::trunc(__mean_ - 1.1484); + __l_ = __math::trunc(__mean_ - 1.1484); __omega_ = .3989423 / __s_; double __b1 = .4166667E-1 / __mean_; double __b2 = .3 * __b1 * __b1; @@ -148,7 +153,7 @@ double __g = __pr.__mean_ + __pr.__s_ * normal_distribution<double>()(__urng); double __u; if (__g > 0) { - __tx = std::trunc(__g); + __tx = __math::trunc(__g); if (__tx >= __pr.__l_) return std::__clamp_to_integral<result_type>(__tx); __difmuk = __pr.__mean_ - __tx; @@ -167,7 +172,7 @@ __u += __u - 1; __t = 1.8 + (__u < 0 ? -__e : __e); } while (__t <= -.6744); - __tx = std::trunc(__pr.__mean_ + __pr.__s_ * __t); + __tx = __math::trunc(__pr.__mean_ + __pr.__s_ * __t); __difmuk = __pr.__mean_ - __tx; __using_exp_dist = true; } @@ -176,13 +181,13 @@ if (__tx < 10 && __tx >= 0) { const double __fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880}; __px = -__pr.__mean_; - __py = std::pow(__pr.__mean_, (double)__tx) / __fac[static_cast<int>(__tx)]; + __py = __math::pow(__pr.__mean_, (double)__tx) / __fac[static_cast<int>(__tx)]; } else { double __del = .8333333E-1 / __tx; __del -= 4.8 * __del * __del * __del; double __v = __difmuk / __tx; - if (std::abs(__v) > 0.25) - __px = __tx * std::log(1 + __v) - __difmuk - __del; + if (__math::abs(__v) > 0.25) + __px = __tx * __math::log(1 + __v) - __difmuk - __del; else __px = __tx * __v * __v * (((((((.1250060 * __v + -.1384794) * __v + .1421878) * __v + -.1661269) * __v + .2000118) * __v + @@ -192,17 +197,17 @@ __v + -.5) - __del; - __py = .3989423 / std::sqrt(__tx); + __py = .3989423 / __math::sqrt(__tx); } double __r = (0.5 - __difmuk) / __pr.__s_; double __r2 = __r * __r; double __fx = -0.5 * __r2; double __fy = __pr.__omega_ * (((__pr.__c3_ * __r2 + __pr.__c2_) * __r2 + __pr.__c1_) * __r2 + __pr.__c0_); if (__using_exp_dist) { - if (__pr.__c_ * std::abs(__u) <= __py * std::exp(__px + __e) - __fy * std::exp(__fx + __e)) + if (__pr.__c_ * __math::abs(__u) <= __py * __math::exp(__px + __e) - __fy * __math::exp(__fx + __e)) break; } else { - if (__fy - __u * __fy <= __py * std::exp(__px - __fx)) + if (__fy - __u * __fy <= __py * __math::exp(__px - __fx)) break; } }
diff --git a/include/__random/student_t_distribution.h b/include/__random/student_t_distribution.h index 1657996..21e2927 100644 --- a/include/__random/student_t_distribution.h +++ b/include/__random/student_t_distribution.h
@@ -10,10 +10,10 @@ #define _LIBCPP___RANDOM_STUDENT_T_DISTRIBUTION_H #include <__config> +#include <__math/roots.h> #include <__random/gamma_distribution.h> #include <__random/is_valid.h> #include <__random/normal_distribution.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -96,7 +96,7 @@ _RealType student_t_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); gamma_distribution<result_type> __gd(__p.n() * .5, 2); - return __nd_(__g) * std::sqrt(__p.n() / __gd(__g)); + return __nd_(__g) * __math::sqrt(__p.n() / __gd(__g)); } template <class _CharT, class _Traits, class _RT>
diff --git a/include/__random/weibull_distribution.h b/include/__random/weibull_distribution.h index 333699c..7fb913f 100644 --- a/include/__random/weibull_distribution.h +++ b/include/__random/weibull_distribution.h
@@ -10,9 +10,9 @@ #define _LIBCPP___RANDOM_WEIBULL_DISTRIBUTION_H #include <__config> +#include <__math/exponential_functions.h> #include <__random/exponential_distribution.h> #include <__random/is_valid.h> -#include <cmath> #include <iosfwd> #include <limits> @@ -75,7 +75,7 @@ } template <class _URNG> [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p) { - return __p.b() * std::pow(exponential_distribution<result_type>()(__g), 1 / __p.a()); + return __p.b() * __math::pow(exponential_distribution<result_type>()(__g), 1 / __p.a()); } // property functions
diff --git a/include/random b/include/random index 65121be..69a3608 100644 --- a/include/random +++ b/include/random
@@ -1729,6 +1729,10 @@ # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER >= 17 && _LIBCPP_STD_VER <= 23 # include <optional> # endif + +# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23 +# include <cmath> +# endif #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP_RANDOM
diff --git a/test/libcxx/transitive_includes/cxx26.csv b/test/libcxx/transitive_includes/cxx26.csv index caf94dc..87a446b 100644 --- a/test/libcxx/transitive_includes/cxx26.csv +++ b/test/libcxx/transitive_includes/cxx26.csv
@@ -742,7 +742,6 @@ queue version random cctype random climits -random cmath random compare random cstdint random cstdio