[libcxx-commits] [libcxx] 81eda00 - [libc++] Extract __clamp_to_integral to its own header

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 8 05:33:42 PST 2021


Author: Louis Dionne
Date: 2021-12-08T08:33:37-05:00
New Revision: 81eda008e952e6b46d20b97f7fbfd6f2e69bd3a1

URL: https://github.com/llvm/llvm-project/commit/81eda008e952e6b46d20b97f7fbfd6f2e69bd3a1
DIFF: https://github.com/llvm/llvm-project/commit/81eda008e952e6b46d20b97f7fbfd6f2e69bd3a1.diff

LOG: [libc++] Extract __clamp_to_integral to its own header

In addition to being more consistent with our approach for helpers, this
solves an actual issue where <cmath> was using numeric_limits but never
including the <limits> header directly. In a normal setup, this is not
an issue because the <math.h> header included by <cmath> does include
<limits>. However, I did stumble upon some code where that didn't work,
most likely because they were placing their own <math.h> header in front
of ours. I didn't bother investigating further.

Differential Revision: https://reviews.llvm.org/D115282

Added: 
    libcxx/include/__random/clamp_to_integral.h
    libcxx/test/libcxx/diagnostics/detail.headers/random/clamp_to_integral.module.verify.cpp

Modified: 
    libcxx/include/CMakeLists.txt
    libcxx/include/__random/poisson_distribution.h
    libcxx/include/cmath
    libcxx/include/module.modulemap
    libcxx/include/random
    libcxx/test/libcxx/numerics/clamp_to_integral.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index df91edb44c3a0..17f760c3a2891 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -257,6 +257,7 @@ set(files
   __random/binomial_distribution.h
   __random/cauchy_distribution.h
   __random/chi_squared_distribution.h
+  __random/clamp_to_integral.h
   __random/default_random_engine.h
   __random/discard_block_engine.h
   __random/discrete_distribution.h

diff  --git a/libcxx/include/__random/clamp_to_integral.h b/libcxx/include/__random/clamp_to_integral.h
new file mode 100644
index 0000000000000..dd5d2b0186e40
--- /dev/null
+++ b/libcxx/include/__random/clamp_to_integral.h
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H
+#define _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H
+
+#include <__config>
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _IntT, class _FloatT,
+    bool _FloatBigger = (numeric_limits<_FloatT>::digits > numeric_limits<_IntT>::digits),
+    int _Bits = (numeric_limits<_IntT>::digits - numeric_limits<_FloatT>::digits)>
+_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_CONSTEXPR _IntT __max_representable_int_for_float() _NOEXCEPT {
+  static_assert(is_floating_point<_FloatT>::value, "must be a floating point type");
+  static_assert(is_integral<_IntT>::value, "must be an integral type");
+  static_assert(numeric_limits<_FloatT>::radix == 2, "FloatT has incorrect radix");
+  static_assert((_IsSame<_FloatT, float>::value || _IsSame<_FloatT, double>::value
+                 || _IsSame<_FloatT,long double>::value), "unsupported floating point type");
+  return _FloatBigger ? numeric_limits<_IntT>::max() :  (numeric_limits<_IntT>::max() >> _Bits << _Bits);
+}
+
+// Convert a floating point number to the specified integral type after
+// clamping to the integral type's representable range.
+//
+// The behavior is undefined if `__r` is NaN.
+template <class _IntT, class _RealT>
+_LIBCPP_INLINE_VISIBILITY
+_IntT __clamp_to_integral(_RealT __r) _NOEXCEPT {
+  using _Lim = numeric_limits<_IntT>;
+  const _IntT _MaxVal = __max_representable_int_for_float<_IntT, _RealT>();
+  if (__r >= ::nextafter(static_cast<_RealT>(_MaxVal), INFINITY)) {
+    return _Lim::max();
+  } else if (__r <= _Lim::lowest()) {
+    return _Lim::min();
+  }
+  return static_cast<_IntT>(__r);
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANDOM_CLAMP_TO_INTEGRAL_H

diff  --git a/libcxx/include/__random/poisson_distribution.h b/libcxx/include/__random/poisson_distribution.h
index fb213b0103ada..d157e8f230ef1 100644
--- a/libcxx/include/__random/poisson_distribution.h
+++ b/libcxx/include/__random/poisson_distribution.h
@@ -10,6 +10,7 @@
 #define _LIBCPP___RANDOM_POISSON_DISTRIBUTION_H
 
 #include <__config>
+#include <__random/clamp_to_integral.h>
 #include <__random/exponential_distribution.h>
 #include <__random/normal_distribution.h>
 #include <__random/uniform_real_distribution.h>

diff  --git a/libcxx/include/cmath b/libcxx/include/cmath
index 3a7985f7d454c..b5c332c81ad6b 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -638,36 +638,6 @@ lerp(long double __a, long double __b, long double __t) _NOEXCEPT { return __ler
 
 #endif // _LIBCPP_STD_VER > 17
 
-template <class _IntT, class _FloatT,
-    bool _FloatBigger = (numeric_limits<_FloatT>::digits > numeric_limits<_IntT>::digits),
-    int _Bits = (numeric_limits<_IntT>::digits - numeric_limits<_FloatT>::digits)>
-_LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR _IntT __max_representable_int_for_float() _NOEXCEPT {
-  static_assert(is_floating_point<_FloatT>::value, "must be a floating point type");
-  static_assert(is_integral<_IntT>::value, "must be an integral type");
-  static_assert(numeric_limits<_FloatT>::radix == 2, "FloatT has incorrect radix");
-  static_assert((_IsSame<_FloatT, float>::value || _IsSame<_FloatT, double>::value
-                 || _IsSame<_FloatT,long double>::value), "unsupported floating point type");
-  return _FloatBigger ? numeric_limits<_IntT>::max() :  (numeric_limits<_IntT>::max() >> _Bits << _Bits);
-}
-
-// Convert a floating point number to the specified integral type after
-// clamping to the integral types representable range.
-//
-// The behavior is undefined if `__r` is NaN.
-template <class _IntT, class _RealT>
-_LIBCPP_INLINE_VISIBILITY
-_IntT __clamp_to_integral(_RealT __r) _NOEXCEPT {
-  using _Lim = numeric_limits<_IntT>;
-  const _IntT _MaxVal = __max_representable_int_for_float<_IntT, _RealT>();
-  if (__r >= ::nextafter(static_cast<_RealT>(_MaxVal), INFINITY)) {
-    return _Lim::max();
-  } else if (__r <= _Lim::lowest()) {
-    return _Lim::min();
-  }
-  return static_cast<_IntT>(__r);
-}
-
 _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS

diff  --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index ea0a6f83b33ae..ae1d2aeba9808 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -704,6 +704,7 @@ module std [system] {
       module binomial_distribution           { private header "__random/binomial_distribution.h" }
       module cauchy_distribution             { private header "__random/cauchy_distribution.h" }
       module chi_squared_distribution        { private header "__random/chi_squared_distribution.h" }
+      module clamp_to_integral               { private header "__random/clamp_to_integral.h" }
       module default_random_engine           { private header "__random/default_random_engine.h" }
       module discard_block_engine            { private header "__random/discard_block_engine.h" }
       module discrete_distribution           { private header "__random/discrete_distribution.h" }

diff  --git a/libcxx/include/random b/libcxx/include/random
index 9eb70bac00b9e..c88bfce03b197 100644
--- a/libcxx/include/random
+++ b/libcxx/include/random
@@ -1682,6 +1682,7 @@ class piecewise_linear_distribution
 #include <__random/binomial_distribution.h>
 #include <__random/cauchy_distribution.h>
 #include <__random/chi_squared_distribution.h>
+#include <__random/clamp_to_integral.h>
 #include <__random/default_random_engine.h>
 #include <__random/discard_block_engine.h>
 #include <__random/discrete_distribution.h>

diff  --git a/libcxx/test/libcxx/diagnostics/detail.headers/random/clamp_to_integral.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/random/clamp_to_integral.module.verify.cpp
new file mode 100644
index 0000000000000..9909f48b0c6fb
--- /dev/null
+++ b/libcxx/test/libcxx/diagnostics/detail.headers/random/clamp_to_integral.module.verify.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: modules-build
+
+// WARNING: This test was generated by 'generate_private_header_tests.py'
+// and should not be edited manually.
+
+// expected-error@*:* {{use of private header from outside its module: '__random/clamp_to_integral.h'}}
+#include <__random/clamp_to_integral.h>

diff  --git a/libcxx/test/libcxx/numerics/clamp_to_integral.pass.cpp b/libcxx/test/libcxx/numerics/clamp_to_integral.pass.cpp
index cbaf4b761033b..a826555d48dda 100644
--- a/libcxx/test/libcxx/numerics/clamp_to_integral.pass.cpp
+++ b/libcxx/test/libcxx/numerics/clamp_to_integral.pass.cpp
@@ -12,9 +12,10 @@
 // closest representable value for the specified integer type, or
 // numeric_limits<IntT>::max()/min() if the value isn't representable.
 
-#include <limits>
 #include <cassert>
 #include <cmath>
+#include <limits>
+#include <random> // for __clamp_to_integral
 
 template <class IntT>
 void test() {


        


More information about the libcxx-commits mailing list