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