Index: flang/runtime/random.cpp =================================================================== --- flang/runtime/random.cpp +++ flang/runtime/random.cpp @@ -40,6 +40,19 @@ static Lock lock; static Generator generator; +static std::optional nextValue; + +// Call only with lock held +static GeneratedWord GetNextValue() { + GeneratedWord result; + if (nextValue.has_value()) { + result = *nextValue; + nextValue.reset(); + } else { + result = generator(); + } + return result; +} template inline void Generate(const Descriptor &harvest) { @@ -54,17 +67,23 @@ { CriticalSection critical{lock}; for (std::size_t j{0}; j < elements; ++j) { - Int fraction{generator()}; - if constexpr (words > 1) { - for (std::size_t k{1}; k < words; ++k) { - static constexpr auto rangeMask{(GeneratedWord{1} << rangeBits) - 1}; - GeneratedWord word{(generator() - generator.min()) & rangeMask}; - fraction = (fraction << rangeBits) | word; + while (true) { + Int fraction{GetNextValue()}; + if constexpr (words > 1) { + for (std::size_t k{1}; k < words; ++k) { + static constexpr auto rangeMask{ + (GeneratedWord{1} << rangeBits) - 1}; + GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask}; + fraction = (fraction << rangeBits) | word; + } + } + fraction >>= words * rangeBits - PREC; + REAL next{std::ldexp(static_cast(fraction), -(PREC + 1))}; + if (next >= 0.0 && next < 1.0) { + *harvest.Element(at) = next; + break; } } - fraction >>= words * rangeBits - PREC; - *harvest.Element(at) = - std::ldexp(static_cast(fraction), -(PREC + 1)); harvest.IncrementSubscripts(at); } } @@ -155,6 +174,7 @@ { CriticalSection critical{lock}; generator.seed(seed); + nextValue = seed; } } @@ -177,8 +197,8 @@ GeneratedWord seed; { CriticalSection critical{lock}; - seed = generator(); - generator.seed(seed); + seed = GetNextValue(); + nextValue = seed; } switch (kind) { case 4: