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