9#ifndef FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_
10#define FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_
13#include "numeric-templates.h"
14#include "flang/Common/optional.h"
15#include "flang/Runtime/descriptor.h"
19namespace Fortran::runtime::random {
25 std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647>;
27using GeneratedWord =
typename Generator::result_type;
28static constexpr std::uint64_t range{
29 static_cast<std::uint64_t
>(Generator::max() - Generator::min() + 1)};
30static constexpr bool rangeIsPowerOfTwo{(range & (range - 1)) == 0};
31static constexpr int rangeBits{
32 64 - common::LeadingZeroBitCount(range) - !rangeIsPowerOfTwo};
35extern Generator generator;
36extern Fortran::common::optional<GeneratedWord> nextValue;
39static GeneratedWord GetNextValue() {
41 if (nextValue.has_value()) {
50template <
typename REAL,
int PREC>
51inline void GenerateReal(
const Descriptor &harvest) {
52 static constexpr std::size_t minBits{
53 std::max<std::size_t>(PREC, 8 *
sizeof(GeneratedWord))};
54 using Int = common::HostUnsignedIntType<minBits>;
55 static constexpr std::size_t words{
56 static_cast<std::size_t
>(PREC + rangeBits - 1) / rangeBits};
57 std::size_t elements{harvest.Elements()};
58 SubscriptValue at[maxRank];
59 harvest.GetLowerBounds(at);
61 CriticalSection critical{lock};
62 for (std::size_t j{0}; j < elements; ++j) {
64 Int fraction{GetNextValue()};
65 if constexpr (words > 1) {
66 for (std::size_t k{1}; k < words; ++k) {
67 static constexpr auto rangeMask{
68 (GeneratedWord{1} << rangeBits) - 1};
69 GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask};
70 fraction = (fraction << rangeBits) | word;
73 fraction >>= words * rangeBits - PREC;
75 LDEXPTy<REAL>::compute(
static_cast<REAL
>(fraction), -(PREC + 1))};
76 if (next >= 0.0 && next < 1.0) {
77 *harvest.Element<REAL>(at) = next;
81 harvest.IncrementSubscripts(at);
86template <
typename UINT>
87inline void GenerateUnsigned(
const Descriptor &harvest) {
88 static constexpr std::size_t words{
89 (8 *
sizeof(UINT) + rangeBits - 1) / rangeBits};
90 std::size_t elements{harvest.Elements()};
91 SubscriptValue at[maxRank];
92 harvest.GetLowerBounds(at);
94 CriticalSection critical{lock};
95 for (std::size_t j{0}; j < elements; ++j) {
96 UINT next{
static_cast<UINT
>(GetNextValue())};
97 if constexpr (words > 1) {
98 for (std::size_t k{1}; k < words; ++k) {
100 next |= GetNextValue();
103 *harvest.Element<UINT>(at) = next;
104 harvest.IncrementSubscripts(at);