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