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