[flang][runtime] Don't let random seed queries change the sequence

When the current seed of the pseudo-random generator is queried
with CALL RANDOM_SEED(GET=n), that query should not change the
stream of pseudo-random numbers produced by CALL RANDOM_NUMBER().

Differential Revision: https://reviews.llvm.org/D127023
This commit is contained in:
Peter Klausler 2022-06-03 22:58:45 -07:00
parent 369ce54bb3
commit ea1a69d66d

View file

@ -40,6 +40,19 @@ static constexpr int rangeBits{
static Lock lock;
static Generator generator;
static std::optional<GeneratedWord> 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 <typename REAL, int PREC>
inline void Generate(const Descriptor &harvest) {
@ -55,12 +68,12 @@ inline void Generate(const Descriptor &harvest) {
CriticalSection critical{lock};
for (std::size_t j{0}; j < elements; ++j) {
while (true) {
Int fraction{generator()};
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{(generator() - generator.min()) & rangeMask};
GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask};
fraction = (fraction << rangeBits) | word;
}
}
@ -161,6 +174,7 @@ void RTNAME(RandomSeedPut)(
{
CriticalSection critical{lock};
generator.seed(seed);
nextValue = seed;
}
}
@ -183,8 +197,8 @@ void RTNAME(RandomSeedGet)(
GeneratedWord seed;
{
CriticalSection critical{lock};
seed = generator();
generator.seed(seed);
seed = GetNextValue();
nextValue = seed;
}
switch (kind) {
case 4: