template <unsigned long long __a, unsigned long long __c,
unsigned long long __m, unsigned long long _Mp,
- bool _MightOverflow = (__a != 0 && __m != 0 && __m-1 > (_Mp-__c)/__a)>
+ bool _MightOverflow = (__a != 0 && __m != 0 && __m-1 > (_Mp-__c)/__a),
+ bool _OverflowOK = ((__m|__m-1) > __m), // m = 2^n
+ bool _SchrageOK = (__a != 0 && __m != 0 && __m % __a <= __m / __a)> // r <= q
+struct __lce_alg_picker
+{
+ static_assert(__a != 0 || __m != 0 || !_MightOverflow || _OverflowOK || _SchrageOK,
+ "The current values of a, c, and m cannot generate a number "
+ "within bounds of linear_congruential_engine.");
+
+ static _LIBCPP_CONSTEXPR const bool __use_schrage = _MightOverflow &&
+ !_OverflowOK &&
+ _SchrageOK;
+};
+
+template <unsigned long long __a, unsigned long long __c,
+ unsigned long long __m, unsigned long long _Mp,
+ bool _UseSchrage = __lce_alg_picker<__a, __c, __m, _Mp>::__use_schrage>
struct __lce_ta;
// 64
static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters");
static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters");
+ static_assert(_VSTD::is_unsigned<_UIntType>::value, "_UIntType must be unsigned type");
public:
static _LIBCPP_CONSTEXPR const result_type _Min = __c == 0u ? 1u: 0u;
static _LIBCPP_CONSTEXPR const result_type _Max = __m - 1u;
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <random>
+
+// template <class UIntType, UIntType a, UIntType c, UIntType m>
+// class linear_congruential_engine;
+
+// result_type operator()();
+
+#include <random>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main(int, char**)
+{
+ typedef unsigned long long T;
+
+ // m might overflow, but the overflow is OK so it shouldn't use schrage's algorithm
+ typedef std::linear_congruential_engine<T, 25214903917ull, 1, (1ull<<48)> E1;
+ E1 e1;
+ // make sure the right algorithm was used
+ assert(e1() == 25214903918);
+ assert(e1() == 205774354444503);
+ assert(e1() == 158051849450892);
+ // make sure result is in bounds
+ assert(e1() < (1ull<<48));
+ assert(e1() < (1ull<<48));
+ assert(e1() < (1ull<<48));
+ assert(e1() < (1ull<<48));
+ assert(e1() < (1ull<<48));
+
+ // m might overflow. The overflow is not OK and result will be in bounds
+ // so we should use shrage's algorithm
+ typedef std::linear_congruential_engine<T, (1ull<<2), 0, (1ull<<63) + 1> E2;
+ E2 e2;
+ // make sure shrage's algorithm is used (it would be 0s otherwise)
+ assert(e2() == 4);
+ assert(e2() == 16);
+ assert(e2() == 64);
+ // make sure result is in bounds
+ assert(e2() < (1ull<<48) + 1);
+ assert(e2() < (1ull<<48) + 1);
+ assert(e2() < (1ull<<48) + 1);
+ assert(e2() < (1ull<<48) + 1);
+ assert(e2() < (1ull<<48) + 1);
+
+ // m will not overflow so we should not use shrage's algorithm
+ typedef std::linear_congruential_engine<T, 1ull, 1, (1ull<<48)> E3;
+ E3 e3;
+ // make sure the correct algorithm was used
+ assert(e3() == 2);
+ assert(e3() == 3);
+ assert(e3() == 4);
+ // make sure result is in bounds
+ assert(e3() < (1ull<<48));
+ assert(e3() < (1ull<<48));
+ assert(e3() < (1ull<<48));
+ assert(e3() < (1ull<<48));
+ assert(e2() < (1ull<<48));
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <random>
+
+// template <class UIntType, UIntType a, UIntType c, UIntType m>
+// class linear_congruential_engine;
+
+// requirements on parameters
+
+#include <random>
+
+int main(int, char**)
+{
+ typedef unsigned long long T;
+
+ // expected-error@random:* {{static_assert failed due to requirement '1ULL == 0 || 1ULL < 1ULL' "linear_congruential_engine invalid parameters"}}
+ std::linear_congruential_engine<T, 0, 0, 0> e2;
+ // expected-error@random:* {{static_assert failed due to requirement '1ULL == 0 || 1ULL < 1ULL' "linear_congruential_engine invalid parameters"}}
+ std::linear_congruential_engine<T, 0, 1, 1> e3;
+ std::linear_congruential_engine<T, 1, 0, 1> e4;
+ // expected-error@random:* {{static_assert failed due to requirement 'std::__1::is_unsigned<int>::value' "_UIntType must be unsigned type"}}
+ std::linear_congruential_engine<int, 0, 0, 0> e5;
+
+ return 0;
+}
\ No newline at end of file