[libcxx] adds concept `std::uniform_random_bit_generator`

Implements parts of:
    - P0898R3 Standard Library Concepts
    - P1754 Rename concepts to standard_case for C++20, while we still can

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

GitOrigin-RevId: 9f4f6ac94bfcb474fa71dab40f1dbee6ee57398f
diff --git a/include/concepts b/include/concepts
index 478b865..dac6b69 100644
--- a/include/concepts
+++ b/include/concepts
@@ -228,7 +228,7 @@
 template<class _Fn, class... _Args>
 concept regular_invocable = invocable<_Fn, _Args...>;
 
-#endif //_LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
+#endif // _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/include/random b/include/random
index 6e0d2ec..1cbe9b5 100644
--- a/include/random
+++ b/include/random
@@ -17,6 +17,9 @@
 
 namespace std
 {
+// [rand.req.urng], uniform random bit generator requirements
+template<class G>
+concept uniform_random_bit_generator = see below; // C++20
 
 // Engines
 
@@ -1678,6 +1681,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <cmath>
+#include <concepts>
 #include <type_traits>
 #include <initializer_list>
 #include <limits>
@@ -1697,6 +1701,20 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
+
+// [rand.req.urng]
+template<class _Gen>
+concept uniform_random_bit_generator =
+  invocable<_Gen&> && unsigned_integral<invoke_result_t<_Gen&>> &&
+  requires {
+    { _Gen::min() } -> same_as<invoke_result_t<_Gen&>>;
+    { _Gen::max() } -> same_as<invoke_result_t<_Gen&>>;
+    requires bool_constant<(_Gen::min() < _Gen::max())>::value;
+  };
+
+#endif // _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
+
 // __is_seed_sequence
 
 template <class _Sseq, class _Engine>
diff --git a/test/std/concepts/lang/arithmetic.pass.cpp b/test/std/concepts/lang/arithmetic.pass.cpp
index 7835b1c..9b7b75b 100644
--- a/test/std/concepts/lang/arithmetic.pass.cpp
+++ b/test/std/concepts/lang/arithmetic.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+// UNSUPPORTED: c++03, c++11, c++14, c++17
 // UNSUPPORTED: libcpp-no-concepts
 
 // template<class T>
diff --git a/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp b/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp
deleted file mode 100644
index 1f764da..0000000
--- a/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-int main(int, char**)
-{
-
-  return 0;
-}
diff --git a/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp b/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp
new file mode 100644
index 0000000..c212f9e
--- /dev/null
+++ b/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class T>
+// concept uniform_random_bit_generator = // see below
+
+#include <random>
+
+static_assert(std::uniform_random_bit_generator<
+              std::linear_congruential_engine<unsigned int, 0U, 1U, 2U> >);
+
+#ifndef _LIBCPP_HAS_NO_INT128
+static_assert(std::uniform_random_bit_generator<
+              std::subtract_with_carry_engine<__uint128_t, 1U, 2U, 3U> >);
+#endif
+
+// Not invocable
+static_assert(!std::uniform_random_bit_generator<void>);
+static_assert(!std::uniform_random_bit_generator<int>);
+static_assert(!std::uniform_random_bit_generator<int[10]>);
+static_assert(!std::uniform_random_bit_generator<int*>);
+static_assert(!std::uniform_random_bit_generator<const int*>);
+static_assert(!std::uniform_random_bit_generator<volatile int*>);
+static_assert(!std::uniform_random_bit_generator<const volatile int*>);
+static_assert(!std::uniform_random_bit_generator<int&>);
+static_assert(!std::uniform_random_bit_generator<const int&>);
+static_assert(!std::uniform_random_bit_generator<volatile int&>);
+static_assert(!std::uniform_random_bit_generator<const volatile int&>);
+static_assert(!std::uniform_random_bit_generator<int&&>);
+static_assert(!std::uniform_random_bit_generator<const int&&>);
+static_assert(!std::uniform_random_bit_generator<volatile int&&>);
+static_assert(!std::uniform_random_bit_generator<const volatile int&&>);
+
+struct Empty {};
+static_assert(!std::uniform_random_bit_generator<Empty>);
+
+namespace WrongReturnType {
+using FunctionPointer = void (*)();
+static_assert(!std::uniform_random_bit_generator<FunctionPointer>);
+
+using FunctionReference = int (&)();
+static_assert(!std::uniform_random_bit_generator<FunctionReference>);
+
+struct FunctionObject {
+  unsigned long* operator()();
+};
+static_assert(!std::uniform_random_bit_generator<FunctionObject>);
+static_assert(!std::uniform_random_bit_generator<unsigned int Empty::*>);
+static_assert(!std::uniform_random_bit_generator<unsigned short (Empty::*)()>);
+} // namespace WrongReturnType
+
+namespace NoMinOrMax {
+using FunctionPointer = unsigned int (*)();
+static_assert(!std::uniform_random_bit_generator<FunctionPointer>);
+
+using FunctionReference = unsigned long long (&)();
+static_assert(!std::uniform_random_bit_generator<FunctionReference>);
+
+struct FunctionObject {
+  unsigned char operator()();
+};
+static_assert(!std::uniform_random_bit_generator<FunctionObject>);
+} // namespace NoMinOrMax
+
+namespace OnlyMinIsRight {
+struct NoMax {
+  unsigned char operator()();
+
+  static unsigned char min();
+};
+static_assert(!std::uniform_random_bit_generator<NoMax>);
+
+struct MaxHasWrongReturnType {
+  unsigned char operator()();
+
+  static unsigned char min();
+  static unsigned int max();
+};
+
+static_assert(!std::uniform_random_bit_generator<MaxHasWrongReturnType>);
+} // namespace OnlyMinIsRight
+
+namespace OnlyMaxIsRight {
+struct NoMin {
+  unsigned char operator()();
+
+  static unsigned char max();
+};
+static_assert(!std::uniform_random_bit_generator<NoMin>);
+
+struct MinHasWrongReturnType {
+  unsigned char operator()();
+
+  static unsigned int min();
+  static unsigned char max();
+};
+
+static_assert(!std::uniform_random_bit_generator<MinHasWrongReturnType>);
+} // namespace OnlyMaxIsRight
+
+namespace MinNotLessMax {
+struct NotConstexpr {
+  unsigned char operator()();
+
+  static unsigned char min();
+  static unsigned char max();
+};
+static_assert(!std::uniform_random_bit_generator<NotConstexpr>);
+
+struct MinEqualsMax {
+  unsigned char operator()();
+
+  static constexpr unsigned char min() { return 0; }
+  static constexpr unsigned char max() { return 0; }
+};
+static_assert(!std::uniform_random_bit_generator<MinEqualsMax>);
+
+struct MaxLessThanMin {
+  unsigned char operator()();
+
+  static constexpr unsigned char min() { return 1; }
+  static constexpr unsigned char max() { return 0; }
+};
+static_assert(!std::uniform_random_bit_generator<MaxLessThanMin>);
+} // namespace MinNotLessMax
+
+struct Works {
+  unsigned char operator()();
+
+  static constexpr unsigned char min() { return 0; }
+  static constexpr unsigned char max() { return 1; }
+};
+static_assert(std::uniform_random_bit_generator<Works>);
+
+int main(int, char**) { return 0; }