xref: /aosp_15_r20/external/abseil-cpp/absl/random/exponential_distribution_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker #include "absl/random/exponential_distribution.h"
16*9356374aSAndroid Build Coastguard Worker 
17*9356374aSAndroid Build Coastguard Worker #include <algorithm>
18*9356374aSAndroid Build Coastguard Worker #include <cfloat>
19*9356374aSAndroid Build Coastguard Worker #include <cmath>
20*9356374aSAndroid Build Coastguard Worker #include <cstddef>
21*9356374aSAndroid Build Coastguard Worker #include <cstdint>
22*9356374aSAndroid Build Coastguard Worker #include <iterator>
23*9356374aSAndroid Build Coastguard Worker #include <limits>
24*9356374aSAndroid Build Coastguard Worker #include <random>
25*9356374aSAndroid Build Coastguard Worker #include <sstream>
26*9356374aSAndroid Build Coastguard Worker #include <string>
27*9356374aSAndroid Build Coastguard Worker #include <type_traits>
28*9356374aSAndroid Build Coastguard Worker #include <vector>
29*9356374aSAndroid Build Coastguard Worker 
30*9356374aSAndroid Build Coastguard Worker #include "gmock/gmock.h"
31*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h"
33*9356374aSAndroid Build Coastguard Worker #include "absl/log/log.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/numeric/internal/representation.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/chi_square.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/distribution_test_util.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/pcg_engine.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/sequence_urbg.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/random/random.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_format.h"
42*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_replace.h"
43*9356374aSAndroid Build Coastguard Worker #include "absl/strings/strip.h"
44*9356374aSAndroid Build Coastguard Worker 
45*9356374aSAndroid Build Coastguard Worker namespace {
46*9356374aSAndroid Build Coastguard Worker 
47*9356374aSAndroid Build Coastguard Worker using absl::random_internal::kChiSquared;
48*9356374aSAndroid Build Coastguard Worker 
49*9356374aSAndroid Build Coastguard Worker template <typename RealType>
50*9356374aSAndroid Build Coastguard Worker class ExponentialDistributionTypedTest : public ::testing::Test {};
51*9356374aSAndroid Build Coastguard Worker 
52*9356374aSAndroid Build Coastguard Worker // double-double arithmetic is not supported well by either GCC or Clang; see
53*9356374aSAndroid Build Coastguard Worker // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,
54*9356374aSAndroid Build Coastguard Worker // https://bugs.llvm.org/show_bug.cgi?id=49131, and
55*9356374aSAndroid Build Coastguard Worker // https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests
56*9356374aSAndroid Build Coastguard Worker // with double doubles until compiler support is better.
57*9356374aSAndroid Build Coastguard Worker using RealTypes =
58*9356374aSAndroid Build Coastguard Worker     std::conditional<absl::numeric_internal::IsDoubleDouble(),
59*9356374aSAndroid Build Coastguard Worker                      ::testing::Types<float, double>,
60*9356374aSAndroid Build Coastguard Worker                      ::testing::Types<float, double, long double>>::type;
61*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE(ExponentialDistributionTypedTest, RealTypes);
62*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST(ExponentialDistributionTypedTest,SerializeTest)63*9356374aSAndroid Build Coastguard Worker TYPED_TEST(ExponentialDistributionTypedTest, SerializeTest) {
64*9356374aSAndroid Build Coastguard Worker   using param_type =
65*9356374aSAndroid Build Coastguard Worker       typename absl::exponential_distribution<TypeParam>::param_type;
66*9356374aSAndroid Build Coastguard Worker 
67*9356374aSAndroid Build Coastguard Worker   const TypeParam kParams[] = {
68*9356374aSAndroid Build Coastguard Worker       // Cases around 1.
69*9356374aSAndroid Build Coastguard Worker       1,                                           //
70*9356374aSAndroid Build Coastguard Worker       std::nextafter(TypeParam(1), TypeParam(0)),  // 1 - epsilon
71*9356374aSAndroid Build Coastguard Worker       std::nextafter(TypeParam(1), TypeParam(2)),  // 1 + epsilon
72*9356374aSAndroid Build Coastguard Worker       // Typical cases.
73*9356374aSAndroid Build Coastguard Worker       TypeParam(1e-8), TypeParam(1e-4), TypeParam(1), TypeParam(2),
74*9356374aSAndroid Build Coastguard Worker       TypeParam(1e4), TypeParam(1e8), TypeParam(1e20), TypeParam(2.5),
75*9356374aSAndroid Build Coastguard Worker       // Boundary cases.
76*9356374aSAndroid Build Coastguard Worker       std::numeric_limits<TypeParam>::max(),
77*9356374aSAndroid Build Coastguard Worker       std::numeric_limits<TypeParam>::epsilon(),
78*9356374aSAndroid Build Coastguard Worker       std::nextafter(std::numeric_limits<TypeParam>::min(),
79*9356374aSAndroid Build Coastguard Worker                      TypeParam(1)),           // min + epsilon
80*9356374aSAndroid Build Coastguard Worker       std::numeric_limits<TypeParam>::min(),  // smallest normal
81*9356374aSAndroid Build Coastguard Worker       // There are some errors dealing with denorms on apple platforms.
82*9356374aSAndroid Build Coastguard Worker       std::numeric_limits<TypeParam>::denorm_min(),  // smallest denorm
83*9356374aSAndroid Build Coastguard Worker       std::numeric_limits<TypeParam>::min() / 2,     // denorm
84*9356374aSAndroid Build Coastguard Worker       std::nextafter(std::numeric_limits<TypeParam>::min(),
85*9356374aSAndroid Build Coastguard Worker                      TypeParam(0)),  // denorm_max
86*9356374aSAndroid Build Coastguard Worker   };
87*9356374aSAndroid Build Coastguard Worker 
88*9356374aSAndroid Build Coastguard Worker   constexpr int kCount = 1000;
89*9356374aSAndroid Build Coastguard Worker   absl::InsecureBitGen gen;
90*9356374aSAndroid Build Coastguard Worker 
91*9356374aSAndroid Build Coastguard Worker   for (const TypeParam lambda : kParams) {
92*9356374aSAndroid Build Coastguard Worker     // Some values may be invalid; skip those.
93*9356374aSAndroid Build Coastguard Worker     if (!std::isfinite(lambda)) continue;
94*9356374aSAndroid Build Coastguard Worker     ABSL_ASSERT(lambda > 0);
95*9356374aSAndroid Build Coastguard Worker 
96*9356374aSAndroid Build Coastguard Worker     const param_type param(lambda);
97*9356374aSAndroid Build Coastguard Worker 
98*9356374aSAndroid Build Coastguard Worker     absl::exponential_distribution<TypeParam> before(lambda);
99*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(before.lambda(), param.lambda());
100*9356374aSAndroid Build Coastguard Worker 
101*9356374aSAndroid Build Coastguard Worker     {
102*9356374aSAndroid Build Coastguard Worker       absl::exponential_distribution<TypeParam> via_param(param);
103*9356374aSAndroid Build Coastguard Worker       EXPECT_EQ(via_param, before);
104*9356374aSAndroid Build Coastguard Worker       EXPECT_EQ(via_param.param(), before.param());
105*9356374aSAndroid Build Coastguard Worker     }
106*9356374aSAndroid Build Coastguard Worker 
107*9356374aSAndroid Build Coastguard Worker     // Smoke test.
108*9356374aSAndroid Build Coastguard Worker     auto sample_min = before.max();
109*9356374aSAndroid Build Coastguard Worker     auto sample_max = before.min();
110*9356374aSAndroid Build Coastguard Worker     for (int i = 0; i < kCount; i++) {
111*9356374aSAndroid Build Coastguard Worker       auto sample = before(gen);
112*9356374aSAndroid Build Coastguard Worker       EXPECT_GE(sample, before.min()) << before;
113*9356374aSAndroid Build Coastguard Worker       EXPECT_LE(sample, before.max()) << before;
114*9356374aSAndroid Build Coastguard Worker       if (sample > sample_max) sample_max = sample;
115*9356374aSAndroid Build Coastguard Worker       if (sample < sample_min) sample_min = sample;
116*9356374aSAndroid Build Coastguard Worker     }
117*9356374aSAndroid Build Coastguard Worker     if (!std::is_same<TypeParam, long double>::value) {
118*9356374aSAndroid Build Coastguard Worker       LOG(INFO) << "Range {" << lambda << "}: " << sample_min << ", "
119*9356374aSAndroid Build Coastguard Worker                 << sample_max << ", lambda=" << lambda;
120*9356374aSAndroid Build Coastguard Worker     }
121*9356374aSAndroid Build Coastguard Worker 
122*9356374aSAndroid Build Coastguard Worker     std::stringstream ss;
123*9356374aSAndroid Build Coastguard Worker     ss << before;
124*9356374aSAndroid Build Coastguard Worker 
125*9356374aSAndroid Build Coastguard Worker     if (!std::isfinite(lambda)) {
126*9356374aSAndroid Build Coastguard Worker       // Streams do not deserialize inf/nan correctly.
127*9356374aSAndroid Build Coastguard Worker       continue;
128*9356374aSAndroid Build Coastguard Worker     }
129*9356374aSAndroid Build Coastguard Worker     // Validate stream serialization.
130*9356374aSAndroid Build Coastguard Worker     absl::exponential_distribution<TypeParam> after(34.56f);
131*9356374aSAndroid Build Coastguard Worker 
132*9356374aSAndroid Build Coastguard Worker     EXPECT_NE(before.lambda(), after.lambda());
133*9356374aSAndroid Build Coastguard Worker     EXPECT_NE(before.param(), after.param());
134*9356374aSAndroid Build Coastguard Worker     EXPECT_NE(before, after);
135*9356374aSAndroid Build Coastguard Worker 
136*9356374aSAndroid Build Coastguard Worker     ss >> after;
137*9356374aSAndroid Build Coastguard Worker 
138*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(before.lambda(), after.lambda())  //
139*9356374aSAndroid Build Coastguard Worker         << ss.str() << " "                      //
140*9356374aSAndroid Build Coastguard Worker         << (ss.good() ? "good " : "")           //
141*9356374aSAndroid Build Coastguard Worker         << (ss.bad() ? "bad " : "")             //
142*9356374aSAndroid Build Coastguard Worker         << (ss.eof() ? "eof " : "")             //
143*9356374aSAndroid Build Coastguard Worker         << (ss.fail() ? "fail " : "");
144*9356374aSAndroid Build Coastguard Worker   }
145*9356374aSAndroid Build Coastguard Worker }
146*9356374aSAndroid Build Coastguard Worker 
147*9356374aSAndroid Build Coastguard Worker // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm
148*9356374aSAndroid Build Coastguard Worker 
149*9356374aSAndroid Build Coastguard Worker class ExponentialModel {
150*9356374aSAndroid Build Coastguard Worker  public:
ExponentialModel(double lambda)151*9356374aSAndroid Build Coastguard Worker   explicit ExponentialModel(double lambda)
152*9356374aSAndroid Build Coastguard Worker       : lambda_(lambda), beta_(1.0 / lambda) {}
153*9356374aSAndroid Build Coastguard Worker 
lambda() const154*9356374aSAndroid Build Coastguard Worker   double lambda() const { return lambda_; }
155*9356374aSAndroid Build Coastguard Worker 
mean() const156*9356374aSAndroid Build Coastguard Worker   double mean() const { return beta_; }
variance() const157*9356374aSAndroid Build Coastguard Worker   double variance() const { return beta_ * beta_; }
stddev() const158*9356374aSAndroid Build Coastguard Worker   double stddev() const { return std::sqrt(variance()); }
skew() const159*9356374aSAndroid Build Coastguard Worker   double skew() const { return 2; }
kurtosis() const160*9356374aSAndroid Build Coastguard Worker   double kurtosis() const { return 6.0; }
161*9356374aSAndroid Build Coastguard Worker 
CDF(double x)162*9356374aSAndroid Build Coastguard Worker   double CDF(double x) { return 1.0 - std::exp(-lambda_ * x); }
163*9356374aSAndroid Build Coastguard Worker 
164*9356374aSAndroid Build Coastguard Worker   // The inverse CDF, or PercentPoint function of the distribution
InverseCDF(double p)165*9356374aSAndroid Build Coastguard Worker   double InverseCDF(double p) {
166*9356374aSAndroid Build Coastguard Worker     ABSL_ASSERT(p >= 0.0);
167*9356374aSAndroid Build Coastguard Worker     ABSL_ASSERT(p < 1.0);
168*9356374aSAndroid Build Coastguard Worker     return -beta_ * std::log(1.0 - p);
169*9356374aSAndroid Build Coastguard Worker   }
170*9356374aSAndroid Build Coastguard Worker 
171*9356374aSAndroid Build Coastguard Worker  private:
172*9356374aSAndroid Build Coastguard Worker   const double lambda_;
173*9356374aSAndroid Build Coastguard Worker   const double beta_;
174*9356374aSAndroid Build Coastguard Worker };
175*9356374aSAndroid Build Coastguard Worker 
176*9356374aSAndroid Build Coastguard Worker struct Param {
177*9356374aSAndroid Build Coastguard Worker   double lambda;
178*9356374aSAndroid Build Coastguard Worker   double p_fail;
179*9356374aSAndroid Build Coastguard Worker   int trials;
180*9356374aSAndroid Build Coastguard Worker };
181*9356374aSAndroid Build Coastguard Worker 
182*9356374aSAndroid Build Coastguard Worker class ExponentialDistributionTests : public testing::TestWithParam<Param>,
183*9356374aSAndroid Build Coastguard Worker                                      public ExponentialModel {
184*9356374aSAndroid Build Coastguard Worker  public:
ExponentialDistributionTests()185*9356374aSAndroid Build Coastguard Worker   ExponentialDistributionTests() : ExponentialModel(GetParam().lambda) {}
186*9356374aSAndroid Build Coastguard Worker 
187*9356374aSAndroid Build Coastguard Worker   // SingleZTest provides a basic z-squared test of the mean vs. expected
188*9356374aSAndroid Build Coastguard Worker   // mean for data generated by the poisson distribution.
189*9356374aSAndroid Build Coastguard Worker   template <typename D>
190*9356374aSAndroid Build Coastguard Worker   bool SingleZTest(const double p, const size_t samples);
191*9356374aSAndroid Build Coastguard Worker 
192*9356374aSAndroid Build Coastguard Worker   // SingleChiSquaredTest provides a basic chi-squared test of the normal
193*9356374aSAndroid Build Coastguard Worker   // distribution.
194*9356374aSAndroid Build Coastguard Worker   template <typename D>
195*9356374aSAndroid Build Coastguard Worker   double SingleChiSquaredTest();
196*9356374aSAndroid Build Coastguard Worker 
197*9356374aSAndroid Build Coastguard Worker   // We use a fixed bit generator for distribution accuracy tests.  This allows
198*9356374aSAndroid Build Coastguard Worker   // these tests to be deterministic, while still testing the qualify of the
199*9356374aSAndroid Build Coastguard Worker   // implementation.
200*9356374aSAndroid Build Coastguard Worker   absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
201*9356374aSAndroid Build Coastguard Worker };
202*9356374aSAndroid Build Coastguard Worker 
203*9356374aSAndroid Build Coastguard Worker template <typename D>
SingleZTest(const double p,const size_t samples)204*9356374aSAndroid Build Coastguard Worker bool ExponentialDistributionTests::SingleZTest(const double p,
205*9356374aSAndroid Build Coastguard Worker                                                const size_t samples) {
206*9356374aSAndroid Build Coastguard Worker   D dis(lambda());
207*9356374aSAndroid Build Coastguard Worker 
208*9356374aSAndroid Build Coastguard Worker   std::vector<double> data;
209*9356374aSAndroid Build Coastguard Worker   data.reserve(samples);
210*9356374aSAndroid Build Coastguard Worker   for (size_t i = 0; i < samples; i++) {
211*9356374aSAndroid Build Coastguard Worker     const double x = dis(rng_);
212*9356374aSAndroid Build Coastguard Worker     data.push_back(x);
213*9356374aSAndroid Build Coastguard Worker   }
214*9356374aSAndroid Build Coastguard Worker 
215*9356374aSAndroid Build Coastguard Worker   const auto m = absl::random_internal::ComputeDistributionMoments(data);
216*9356374aSAndroid Build Coastguard Worker   const double max_err = absl::random_internal::MaxErrorTolerance(p);
217*9356374aSAndroid Build Coastguard Worker   const double z = absl::random_internal::ZScore(mean(), m);
218*9356374aSAndroid Build Coastguard Worker   const bool pass = absl::random_internal::Near("z", z, 0.0, max_err);
219*9356374aSAndroid Build Coastguard Worker 
220*9356374aSAndroid Build Coastguard Worker   if (!pass) {
221*9356374aSAndroid Build Coastguard Worker     // clang-format off
222*9356374aSAndroid Build Coastguard Worker     LOG(INFO)
223*9356374aSAndroid Build Coastguard Worker         << "p=" << p << " max_err=" << max_err << "\n"
224*9356374aSAndroid Build Coastguard Worker            " lambda=" << lambda() << "\n"
225*9356374aSAndroid Build Coastguard Worker            " mean=" << m.mean << " vs. " << mean() << "\n"
226*9356374aSAndroid Build Coastguard Worker            " stddev=" << std::sqrt(m.variance) << " vs. " << stddev() << "\n"
227*9356374aSAndroid Build Coastguard Worker            " skewness=" << m.skewness << " vs. " << skew() << "\n"
228*9356374aSAndroid Build Coastguard Worker            " kurtosis=" << m.kurtosis << " vs. " << kurtosis() << "\n"
229*9356374aSAndroid Build Coastguard Worker            " z=" << z << " vs. 0";
230*9356374aSAndroid Build Coastguard Worker     // clang-format on
231*9356374aSAndroid Build Coastguard Worker   }
232*9356374aSAndroid Build Coastguard Worker   return pass;
233*9356374aSAndroid Build Coastguard Worker }
234*9356374aSAndroid Build Coastguard Worker 
235*9356374aSAndroid Build Coastguard Worker template <typename D>
SingleChiSquaredTest()236*9356374aSAndroid Build Coastguard Worker double ExponentialDistributionTests::SingleChiSquaredTest() {
237*9356374aSAndroid Build Coastguard Worker   const size_t kSamples = 10000;
238*9356374aSAndroid Build Coastguard Worker   const int kBuckets = 50;
239*9356374aSAndroid Build Coastguard Worker 
240*9356374aSAndroid Build Coastguard Worker   // The InverseCDF is the percent point function of the distribution, and can
241*9356374aSAndroid Build Coastguard Worker   // be used to assign buckets roughly uniformly.
242*9356374aSAndroid Build Coastguard Worker   std::vector<double> cutoffs;
243*9356374aSAndroid Build Coastguard Worker   const double kInc = 1.0 / static_cast<double>(kBuckets);
244*9356374aSAndroid Build Coastguard Worker   for (double p = kInc; p < 1.0; p += kInc) {
245*9356374aSAndroid Build Coastguard Worker     cutoffs.push_back(InverseCDF(p));
246*9356374aSAndroid Build Coastguard Worker   }
247*9356374aSAndroid Build Coastguard Worker   if (cutoffs.back() != std::numeric_limits<double>::infinity()) {
248*9356374aSAndroid Build Coastguard Worker     cutoffs.push_back(std::numeric_limits<double>::infinity());
249*9356374aSAndroid Build Coastguard Worker   }
250*9356374aSAndroid Build Coastguard Worker 
251*9356374aSAndroid Build Coastguard Worker   D dis(lambda());
252*9356374aSAndroid Build Coastguard Worker 
253*9356374aSAndroid Build Coastguard Worker   std::vector<int32_t> counts(cutoffs.size(), 0);
254*9356374aSAndroid Build Coastguard Worker   for (int j = 0; j < kSamples; j++) {
255*9356374aSAndroid Build Coastguard Worker     const double x = dis(rng_);
256*9356374aSAndroid Build Coastguard Worker     auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);
257*9356374aSAndroid Build Coastguard Worker     counts[std::distance(cutoffs.begin(), it)]++;
258*9356374aSAndroid Build Coastguard Worker   }
259*9356374aSAndroid Build Coastguard Worker 
260*9356374aSAndroid Build Coastguard Worker   // Null-hypothesis is that the distribution is exponentially distributed
261*9356374aSAndroid Build Coastguard Worker   // with the provided lambda (not estimated from the data).
262*9356374aSAndroid Build Coastguard Worker   const int dof = static_cast<int>(counts.size()) - 1;
263*9356374aSAndroid Build Coastguard Worker 
264*9356374aSAndroid Build Coastguard Worker   // Our threshold for logging is 1-in-50.
265*9356374aSAndroid Build Coastguard Worker   const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);
266*9356374aSAndroid Build Coastguard Worker 
267*9356374aSAndroid Build Coastguard Worker   const double expected =
268*9356374aSAndroid Build Coastguard Worker       static_cast<double>(kSamples) / static_cast<double>(counts.size());
269*9356374aSAndroid Build Coastguard Worker 
270*9356374aSAndroid Build Coastguard Worker   double chi_square = absl::random_internal::ChiSquareWithExpected(
271*9356374aSAndroid Build Coastguard Worker       std::begin(counts), std::end(counts), expected);
272*9356374aSAndroid Build Coastguard Worker   double p = absl::random_internal::ChiSquarePValue(chi_square, dof);
273*9356374aSAndroid Build Coastguard Worker 
274*9356374aSAndroid Build Coastguard Worker   if (chi_square > threshold) {
275*9356374aSAndroid Build Coastguard Worker     for (size_t i = 0; i < cutoffs.size(); i++) {
276*9356374aSAndroid Build Coastguard Worker       LOG(INFO) << i << " : (" << cutoffs[i] << ") = " << counts[i];
277*9356374aSAndroid Build Coastguard Worker     }
278*9356374aSAndroid Build Coastguard Worker 
279*9356374aSAndroid Build Coastguard Worker     // clang-format off
280*9356374aSAndroid Build Coastguard Worker     LOG(INFO) << "lambda " << lambda() << "\n"
281*9356374aSAndroid Build Coastguard Worker                  " expected " << expected << "\n"
282*9356374aSAndroid Build Coastguard Worker               << kChiSquared << " " << chi_square << " (" << p << ")\n"
283*9356374aSAndroid Build Coastguard Worker               << kChiSquared << " @ 0.98 = " << threshold;
284*9356374aSAndroid Build Coastguard Worker     // clang-format on
285*9356374aSAndroid Build Coastguard Worker   }
286*9356374aSAndroid Build Coastguard Worker   return p;
287*9356374aSAndroid Build Coastguard Worker }
288*9356374aSAndroid Build Coastguard Worker 
TEST_P(ExponentialDistributionTests,ZTest)289*9356374aSAndroid Build Coastguard Worker TEST_P(ExponentialDistributionTests, ZTest) {
290*9356374aSAndroid Build Coastguard Worker   const size_t kSamples = 10000;
291*9356374aSAndroid Build Coastguard Worker   const auto& param = GetParam();
292*9356374aSAndroid Build Coastguard Worker   const int expected_failures =
293*9356374aSAndroid Build Coastguard Worker       std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));
294*9356374aSAndroid Build Coastguard Worker   const double p = absl::random_internal::RequiredSuccessProbability(
295*9356374aSAndroid Build Coastguard Worker       param.p_fail, param.trials);
296*9356374aSAndroid Build Coastguard Worker 
297*9356374aSAndroid Build Coastguard Worker   int failures = 0;
298*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i < param.trials; i++) {
299*9356374aSAndroid Build Coastguard Worker     failures += SingleZTest<absl::exponential_distribution<double>>(p, kSamples)
300*9356374aSAndroid Build Coastguard Worker                     ? 0
301*9356374aSAndroid Build Coastguard Worker                     : 1;
302*9356374aSAndroid Build Coastguard Worker   }
303*9356374aSAndroid Build Coastguard Worker   EXPECT_LE(failures, expected_failures);
304*9356374aSAndroid Build Coastguard Worker }
305*9356374aSAndroid Build Coastguard Worker 
TEST_P(ExponentialDistributionTests,ChiSquaredTest)306*9356374aSAndroid Build Coastguard Worker TEST_P(ExponentialDistributionTests, ChiSquaredTest) {
307*9356374aSAndroid Build Coastguard Worker   const int kTrials = 20;
308*9356374aSAndroid Build Coastguard Worker   int failures = 0;
309*9356374aSAndroid Build Coastguard Worker 
310*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i < kTrials; i++) {
311*9356374aSAndroid Build Coastguard Worker     double p_value =
312*9356374aSAndroid Build Coastguard Worker         SingleChiSquaredTest<absl::exponential_distribution<double>>();
313*9356374aSAndroid Build Coastguard Worker     if (p_value < 0.005) {  // 1/200
314*9356374aSAndroid Build Coastguard Worker       failures++;
315*9356374aSAndroid Build Coastguard Worker     }
316*9356374aSAndroid Build Coastguard Worker   }
317*9356374aSAndroid Build Coastguard Worker 
318*9356374aSAndroid Build Coastguard Worker   // There is a 0.10% chance of producing at least one failure, so raise the
319*9356374aSAndroid Build Coastguard Worker   // failure threshold high enough to allow for a flake rate < 10,000.
320*9356374aSAndroid Build Coastguard Worker   EXPECT_LE(failures, 4);
321*9356374aSAndroid Build Coastguard Worker }
322*9356374aSAndroid Build Coastguard Worker 
GenParams()323*9356374aSAndroid Build Coastguard Worker std::vector<Param> GenParams() {
324*9356374aSAndroid Build Coastguard Worker   return {
325*9356374aSAndroid Build Coastguard Worker       Param{1.0, 0.02, 100},
326*9356374aSAndroid Build Coastguard Worker       Param{2.5, 0.02, 100},
327*9356374aSAndroid Build Coastguard Worker       Param{10, 0.02, 100},
328*9356374aSAndroid Build Coastguard Worker       // large
329*9356374aSAndroid Build Coastguard Worker       Param{1e4, 0.02, 100},
330*9356374aSAndroid Build Coastguard Worker       Param{1e9, 0.02, 100},
331*9356374aSAndroid Build Coastguard Worker       // small
332*9356374aSAndroid Build Coastguard Worker       Param{0.1, 0.02, 100},
333*9356374aSAndroid Build Coastguard Worker       Param{1e-3, 0.02, 100},
334*9356374aSAndroid Build Coastguard Worker       Param{1e-5, 0.02, 100},
335*9356374aSAndroid Build Coastguard Worker   };
336*9356374aSAndroid Build Coastguard Worker }
337*9356374aSAndroid Build Coastguard Worker 
ParamName(const::testing::TestParamInfo<Param> & info)338*9356374aSAndroid Build Coastguard Worker std::string ParamName(const ::testing::TestParamInfo<Param>& info) {
339*9356374aSAndroid Build Coastguard Worker   const auto& p = info.param;
340*9356374aSAndroid Build Coastguard Worker   std::string name = absl::StrCat("lambda_", absl::SixDigits(p.lambda));
341*9356374aSAndroid Build Coastguard Worker   return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
342*9356374aSAndroid Build Coastguard Worker }
343*9356374aSAndroid Build Coastguard Worker 
344*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All, ExponentialDistributionTests,
345*9356374aSAndroid Build Coastguard Worker                          ::testing::ValuesIn(GenParams()), ParamName);
346*9356374aSAndroid Build Coastguard Worker 
347*9356374aSAndroid Build Coastguard Worker // NOTE: absl::exponential_distribution is not guaranteed to be stable.
TEST(ExponentialDistributionTest,StabilityTest)348*9356374aSAndroid Build Coastguard Worker TEST(ExponentialDistributionTest, StabilityTest) {
349*9356374aSAndroid Build Coastguard Worker   // absl::exponential_distribution stability relies on std::log1p and
350*9356374aSAndroid Build Coastguard Worker   // absl::uniform_real_distribution.
351*9356374aSAndroid Build Coastguard Worker   absl::random_internal::sequence_urbg urbg(
352*9356374aSAndroid Build Coastguard Worker       {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
353*9356374aSAndroid Build Coastguard Worker        0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
354*9356374aSAndroid Build Coastguard Worker        0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
355*9356374aSAndroid Build Coastguard Worker        0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
356*9356374aSAndroid Build Coastguard Worker 
357*9356374aSAndroid Build Coastguard Worker   std::vector<int> output(14);
358*9356374aSAndroid Build Coastguard Worker 
359*9356374aSAndroid Build Coastguard Worker   {
360*9356374aSAndroid Build Coastguard Worker     absl::exponential_distribution<double> dist;
361*9356374aSAndroid Build Coastguard Worker     std::generate(std::begin(output), std::end(output),
362*9356374aSAndroid Build Coastguard Worker                   [&] { return static_cast<int>(10000.0 * dist(urbg)); });
363*9356374aSAndroid Build Coastguard Worker 
364*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(14, urbg.invocations());
365*9356374aSAndroid Build Coastguard Worker     EXPECT_THAT(output,
366*9356374aSAndroid Build Coastguard Worker                 testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936,
367*9356374aSAndroid Build Coastguard Worker                                      804, 126, 12337, 17984, 27002, 0, 71913));
368*9356374aSAndroid Build Coastguard Worker   }
369*9356374aSAndroid Build Coastguard Worker 
370*9356374aSAndroid Build Coastguard Worker   urbg.reset();
371*9356374aSAndroid Build Coastguard Worker   {
372*9356374aSAndroid Build Coastguard Worker     absl::exponential_distribution<float> dist;
373*9356374aSAndroid Build Coastguard Worker     std::generate(std::begin(output), std::end(output),
374*9356374aSAndroid Build Coastguard Worker                   [&] { return static_cast<int>(10000.0f * dist(urbg)); });
375*9356374aSAndroid Build Coastguard Worker 
376*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(14, urbg.invocations());
377*9356374aSAndroid Build Coastguard Worker     EXPECT_THAT(output,
378*9356374aSAndroid Build Coastguard Worker                 testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936,
379*9356374aSAndroid Build Coastguard Worker                                      804, 126, 12337, 17984, 27002, 0, 71913));
380*9356374aSAndroid Build Coastguard Worker   }
381*9356374aSAndroid Build Coastguard Worker }
382*9356374aSAndroid Build Coastguard Worker 
TEST(ExponentialDistributionTest,AlgorithmBounds)383*9356374aSAndroid Build Coastguard Worker TEST(ExponentialDistributionTest, AlgorithmBounds) {
384*9356374aSAndroid Build Coastguard Worker   // Relies on absl::uniform_real_distribution, so some of these comments
385*9356374aSAndroid Build Coastguard Worker   // reference that.
386*9356374aSAndroid Build Coastguard Worker 
387*9356374aSAndroid Build Coastguard Worker #if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0
388*9356374aSAndroid Build Coastguard Worker   // We're using an x87-compatible FPU, and intermediate operations can be
389*9356374aSAndroid Build Coastguard Worker   // performed with 80-bit floats. This produces slightly different results from
390*9356374aSAndroid Build Coastguard Worker   // what we expect below.
391*9356374aSAndroid Build Coastguard Worker   GTEST_SKIP()
392*9356374aSAndroid Build Coastguard Worker       << "Skipping the test because we detected x87 floating-point semantics";
393*9356374aSAndroid Build Coastguard Worker #endif
394*9356374aSAndroid Build Coastguard Worker 
395*9356374aSAndroid Build Coastguard Worker   absl::exponential_distribution<double> dist;
396*9356374aSAndroid Build Coastguard Worker 
397*9356374aSAndroid Build Coastguard Worker   {
398*9356374aSAndroid Build Coastguard Worker     // This returns the smallest value >0 from absl::uniform_real_distribution.
399*9356374aSAndroid Build Coastguard Worker     absl::random_internal::sequence_urbg urbg({0x0000000000000001ull});
400*9356374aSAndroid Build Coastguard Worker     double a = dist(urbg);
401*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(a, 5.42101086242752217004e-20);
402*9356374aSAndroid Build Coastguard Worker   }
403*9356374aSAndroid Build Coastguard Worker 
404*9356374aSAndroid Build Coastguard Worker   {
405*9356374aSAndroid Build Coastguard Worker     // This returns a value very near 0.5 from absl::uniform_real_distribution.
406*9356374aSAndroid Build Coastguard Worker     absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull});
407*9356374aSAndroid Build Coastguard Worker     double a = dist(urbg);
408*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(a, 0.693147180559945175204);
409*9356374aSAndroid Build Coastguard Worker   }
410*9356374aSAndroid Build Coastguard Worker 
411*9356374aSAndroid Build Coastguard Worker   {
412*9356374aSAndroid Build Coastguard Worker     // This returns the largest value <1 from absl::uniform_real_distribution.
413*9356374aSAndroid Build Coastguard Worker     // WolframAlpha: ~39.1439465808987766283058547296341915292187253
414*9356374aSAndroid Build Coastguard Worker     absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFeFull});
415*9356374aSAndroid Build Coastguard Worker     double a = dist(urbg);
416*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(a, 36.7368005696771007251);
417*9356374aSAndroid Build Coastguard Worker   }
418*9356374aSAndroid Build Coastguard Worker   {
419*9356374aSAndroid Build Coastguard Worker     // This *ALSO* returns the largest value <1.
420*9356374aSAndroid Build Coastguard Worker     absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull});
421*9356374aSAndroid Build Coastguard Worker     double a = dist(urbg);
422*9356374aSAndroid Build Coastguard Worker     EXPECT_EQ(a, 36.7368005696771007251);
423*9356374aSAndroid Build Coastguard Worker   }
424*9356374aSAndroid Build Coastguard Worker }
425*9356374aSAndroid Build Coastguard Worker 
426*9356374aSAndroid Build Coastguard Worker }  // namespace
427