1 //===-- flang/unittests/RuntimeGTest/Random.cpp -----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Runtime/random.h"
10 #include "gtest/gtest.h"
11 #include "flang/Runtime/descriptor.h"
12 #include "flang/Runtime/type-code.h"
13 #include <cmath>
14 
15 using namespace Fortran::runtime;
16 
TEST(RandomNumber,Real4)17 TEST(RandomNumber, Real4) {
18   StaticDescriptor<1> statDesc;
19   Descriptor &harvest{statDesc.descriptor()};
20   static constexpr int n{10000};
21   float xs[n]{};
22   SubscriptValue extent[1]{n};
23   harvest.Establish(TypeCategory::Real, 4, xs, 1, extent);
24   RTNAME(RandomNumber)(harvest, __FILE__, __LINE__);
25   double sum{0};
26   for (int j{0}; j < n; ++j) {
27     sum += xs[j];
28   }
29   double mean{sum / n};
30   std::fprintf(stderr, "mean of %d random numbers: %g\n", n, mean);
31   EXPECT_GE(mean, 0.95 * 0.5); // mean of uniform dist [0..1] is of course 0.5
32   EXPECT_LE(mean, 1.05 * 0.5);
33   double sumsq{0};
34   for (int j{0}; j < n; ++j) {
35     double diff{xs[j] - mean};
36     sumsq += diff * diff;
37   }
38   double sdev{std::sqrt(sumsq / n)};
39   std::fprintf(stderr, "stddev of %d random numbers: %g\n", n, sdev);
40   double expect{1.0 / std::sqrt(12.0)}; // stddev of uniform dist [0..1]
41   EXPECT_GE(sdev, 0.95 * expect);
42   EXPECT_LT(sdev, 1.05 * expect);
43 }
44 
TEST(RandomNumber,RandomSeed)45 TEST(RandomNumber, RandomSeed) {
46   StaticDescriptor<1> statDesc[2];
47   Descriptor &desc{statDesc[0].descriptor()};
48   std::int32_t n;
49   desc.Establish(TypeCategory::Integer, 4, &n, 0, nullptr);
50   RTNAME(RandomSeedSize)(desc, __FILE__, __LINE__);
51   EXPECT_EQ(n, 1);
52   SubscriptValue extent[1]{1};
53   desc.Establish(TypeCategory::Integer, 4, &n, 1, extent);
54   RTNAME(RandomSeedGet)(desc, __FILE__, __LINE__);
55   Descriptor &harvest{statDesc[1].descriptor()};
56   float x;
57   harvest.Establish(TypeCategory::Real, 4, &x, 1, extent);
58   RTNAME(RandomNumber)(harvest, __FILE__, __LINE__);
59   float got{x};
60   RTNAME(RandomSeedPut)(desc, __FILE__, __LINE__); // n from RandomSeedGet()
61   RTNAME(RandomNumber)(harvest, __FILE__, __LINE__);
62   EXPECT_EQ(x, got);
63 }
64