xref: /aosp_15_r20/external/skia/tests/RandomTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkTypes.h"
9 #include "include/private/base/SkMath.h"
10 #include "src/base/SkRandom.h"
11 #include "src/base/SkTSort.h"
12 #include "tests/Test.h"
13 
14 #include <cmath>
15 #include <cstring>
16 
anderson_darling_test(double p[32])17 static bool anderson_darling_test(double p[32]) {
18     // Min and max Anderson-Darling values allowable for k=32
19     const double kADMin32 = 0.202;        // p-value of ~0.1
20     const double kADMax32 = 3.89;         // p-value of ~0.99
21 
22     // sort p values
23     SkTQSort<double>(p, p + 32);
24 
25     // and compute Anderson-Darling statistic to ensure these are uniform
26     double s = 0.0;
27     for(int k = 0; k < 32; k++) {
28         double v = p[k]*(1.0 - p[31-k]);
29         if (v < 1.0e-30) {
30            v = 1.0e-30;
31         }
32         s += (2.0*(k+1)-1.0)*log(v);
33     }
34     double a2 = -32.0 - 0.03125*s;
35 
36     return (kADMin32 < a2 && a2 < kADMax32);
37 }
38 
chi_square_test(int bins[256],int e)39 static bool chi_square_test(int bins[256], int e) {
40     // Min and max chisquare values allowable
41     const double kChiSqMin256 = 206.3179;        // probability of chance = 0.99 with k=256
42     const double kChiSqMax256 = 311.5603;        // probability of chance = 0.01 with k=256
43 
44     // compute chi-square
45     double chi2 = 0.0;
46     for (int j = 0; j < 256; ++j) {
47         double delta = bins[j] - e;
48         chi2 += delta*delta/e;
49     }
50 
51     return (kChiSqMin256 < chi2 && chi2 < kChiSqMax256);
52 }
53 
54 // Approximation to the normal distribution CDF
55 // From Waissi and Rossin, 1996
normal_cdf(double z)56 static double normal_cdf(double z) {
57     double t = ((-0.0004406*z*z* + 0.0418198)*z*z + 0.9)*z;
58     t *= -1.77245385091;  // -sqrt(PI)
59     double p = 1.0/(1.0 + exp(t));
60 
61     return p;
62 }
63 
test_random_byte(skiatest::Reporter * reporter,int shift)64 static void test_random_byte(skiatest::Reporter* reporter, int shift) {
65     int bins[256];
66     memset(bins, 0, sizeof(int)*256);
67 
68     SkRandom rand;
69     for (int i = 0; i < 256*10000; ++i) {
70         bins[(rand.nextU() >> shift) & 0xff]++;
71     }
72 
73     REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
74 }
75 
test_random_float(skiatest::Reporter * reporter)76 static void test_random_float(skiatest::Reporter* reporter) {
77     int bins[256];
78     memset(bins, 0, sizeof(int)*256);
79 
80     SkRandom rand;
81     for (int i = 0; i < 256*10000; ++i) {
82         float f = rand.nextF();
83         REPORTER_ASSERT(reporter, 0.0f <= f && f < 1.0f);
84         bins[(int)(f*256.f)]++;
85     }
86     REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
87 
88     double p[32];
89     for (int j = 0; j < 32; ++j) {
90         float f = rand.nextF();
91         REPORTER_ASSERT(reporter, 0.0f <= f && f < 1.0f);
92         p[j] = f;
93     }
94     REPORTER_ASSERT(reporter, anderson_darling_test(p));
95 }
96 
97 // This is a test taken from tuftests by Marsaglia and Tsang. The idea here is that
98 // we are using the random bit generated from a single shift position to generate
99 // "strings" of 16 bits in length, shifting the string and adding a new bit with each
100 // iteration. We track the numbers generated. The ones that we don't generate will
101 // have a normal distribution with mean ~24108 and standard deviation ~127. By
102 // creating a z-score (# of deviations from the mean) for one iteration of this step
103 // we can determine its probability.
104 //
105 // The original test used 26 bit strings, but is somewhat slow. This version uses 16
106 // bits which is less rigorous but much faster to generate.
test_single_gorilla(skiatest::Reporter * reporter,int shift)107 static double test_single_gorilla(skiatest::Reporter* reporter, int shift) {
108     const int kWordWidth = 16;
109     const double kMean = 24108.0;
110     const double kStandardDeviation = 127.0;
111     const int kN = (1 << kWordWidth);
112     const int kNumEntries = kN >> 5;  // dividing by 32
113     unsigned int entries[kNumEntries];
114 
115     SkRandom rand;
116     memset(entries, 0, sizeof(unsigned int)*kNumEntries);
117     // pre-seed our string value
118     int value = 0;
119     for (int i = 0; i < kWordWidth-1; ++i) {
120         value <<= 1;
121         unsigned int rnd = rand.nextU();
122         value |= ((rnd >> shift) & 0x1);
123     }
124 
125     // now make some strings and track them
126     for (int i = 0; i < kN; ++i) {
127         value = SkLeftShift(value, 1);
128         unsigned int rnd = rand.nextU();
129         value |= ((rnd >> shift) & 0x1);
130 
131         int index = value & (kNumEntries-1);
132         SkASSERT(index < kNumEntries);
133         int entry_shift = (value >> (kWordWidth-5)) & 0x1f;
134         entries[index] |= (0x1 << entry_shift);
135     }
136 
137     // count entries
138     int total = 0;
139     for (int i = 0; i < kNumEntries; ++i) {
140         unsigned int entry = entries[i];
141         while (entry) {
142             total += (entry & 0x1);
143             entry >>= 1;
144         }
145     }
146 
147     // convert counts to normal distribution z-score
148     double z = ((kN-total)-kMean)/kStandardDeviation;
149 
150     // compute probability from normal distibution CDF
151     double p = normal_cdf(z);
152 
153     REPORTER_ASSERT(reporter, 0.01 < p && p < 0.99);
154     return p;
155 }
156 
test_gorilla(skiatest::Reporter * reporter)157 static void test_gorilla(skiatest::Reporter* reporter) {
158 
159     double p[32];
160     for (int bit_position = 0; bit_position < 32; ++bit_position) {
161         p[bit_position] = test_single_gorilla(reporter, bit_position);
162     }
163 
164     REPORTER_ASSERT(reporter, anderson_darling_test(p));
165 }
166 
test_range(skiatest::Reporter * reporter)167 static void test_range(skiatest::Reporter* reporter) {
168     SkRandom rand;
169 
170     // just to make sure we don't crash in this case
171     (void) rand.nextRangeU(0, 0xffffffff);
172 
173     // check a case to see if it's uniform
174     int bins[256];
175     memset(bins, 0, sizeof(int)*256);
176     for (int i = 0; i < 256*10000; ++i) {
177         unsigned int u = rand.nextRangeU(17, 17+255);
178         REPORTER_ASSERT(reporter, 17 <= u && u <= 17+255);
179         bins[u - 17]++;
180     }
181 
182     REPORTER_ASSERT(reporter, chi_square_test(bins, 10000));
183 }
184 
DEF_TEST(Random,reporter)185 DEF_TEST(Random, reporter) {
186     // check uniform distributions of each byte in 32-bit word
187     test_random_byte(reporter, 0);
188     test_random_byte(reporter, 8);
189     test_random_byte(reporter, 16);
190     test_random_byte(reporter, 24);
191 
192     test_random_float(reporter);
193 
194     test_gorilla(reporter);
195 
196     test_range(reporter);
197 }
198