random/generator-test.cc

Test of random number generator classes.
00001 //
00002 // $Id: generator-test.cc,v 1.6 2006-05-01 14:24:57 cholm Exp $ 
00003 //  
00004 //  random/random-test.cc
00005 //  Copyright (C) 2002 Christian Holm Christensen <cholm@nbi.dk> 
00006 //
00007 //  This library is free software; you can redistribute it and/or 
00008 //  modify it under the terms of the GNU Lesser General Public License 
00009 //  as published by the Free Software Foundation; either version 2.1 
00010 //  of the License, or (at your option) any later version. 
00011 //
00012 //  This library is distributed in the hope that it will be useful, 
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
00015 //  Lesser General Public License for more details. 
00016 // 
00017 //  You should have received a copy of the GNU Lesser General Public 
00018 //  License along with this library; if not, write to the Free 
00019 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
00020 //  02111-1307 USA 
00021 //
00022 #ifndef __IOSTREAM__
00023 #include <iostream>
00024 #endif
00025 #ifndef GSLMM_math_type_trait
00026 #include <gslmm/math/type_trait.hh>
00027 #endif
00028 #ifndef GSLMM_random_generator
00029 #include <gslmm/random/generator.hh>
00030 #endif
00031 #ifndef GSLMM_test_suite
00032 #include <gslmm/test/test_suite.hh>
00033 #endif
00034 #ifndef __FSTREAM__
00035 #include <fstream>
00036 #endif
00037 #ifndef __IOMANIP__
00038 #include <iomanip>
00039 #endif
00040 
00046 #define N2 200000
00047 #define N  10000
00048 
00049 //____________________________________________________________________  
00050 void
00051 random_test(gslmm::test_suite& ts,
00052             gslmm::generator::backend t, 
00053             unsigned long seed, 
00054             size_t n, 
00055             unsigned long result) 
00056 {
00057   gslmm::generator r(t);
00058   if (seed) r.set(seed);
00059   unsigned long int k = 0;
00060   for (size_t i = 0; i < n; i++) k = r.get();
00061   ts.test(k, result, "%s, %u steps", r.name(), n);
00062 }
00063 
00064 //____________________________________________________________________  
00065 void
00066 float_test(gslmm::test_suite& ts,
00067            gslmm::generator::backend_type t)
00068 {
00069   gslmm::generator ri(t);
00070   gslmm::generator rf(t);
00071   
00072   unsigned long int k = 0;
00073   double            u = 0;
00074   
00075   do {
00076     k = ri.get();
00077     u = rf.get();
00078   }
00079   while (k == 0);
00080   
00081   bool status = true;
00082   
00083   double c = k / u;
00084   for (size_t i = 0; i < N2; i++) {
00085     k = ri.get();
00086     u = rf.get();
00087     if (c * k != u) status = false;
00088     break;
00089   }
00090   ts.test(c*k, u, "%s, ratio of int to double", ri.name());
00091 }
00092 
00093 //____________________________________________________________________  
00094 void
00095 state_test(gslmm::test_suite& ts,
00096            gslmm::generator::backend_type t)
00097 {
00098   unsigned long int test_a[N], test_b[N];
00099   
00100   gslmm::generator r(t);
00101   gslmm::generator r_save(t);
00102 
00103   for (size_t i = 0; i < N; i++) r.get();
00104   r_save = r;
00105   for (size_t i = 0; i < N; i++) test_a[i] = r.get();
00106   r = r_save;
00107   for (size_t i = 0; i < N; i++) test_b[i] = r.get();
00108 
00109   int status = 0;
00110   for (size_t i = 0; i < N; i++) status |= (test_b[i] != test_a[i]);
00111   
00112   ts.status(status, "%s, random number state consistency", 
00113             r.name());
00114 }
00115 
00116 
00117 //____________________________________________________________________  
00118 void
00119 parallel_state_test(gslmm::test_suite& ts,
00120                     gslmm::generator::backend_type t)
00121 {
00122   unsigned long int test_a[N], test_b[N];
00123   unsigned long int test_c[N], test_d[N];
00124   double test_e[N], test_f[N];
00125   
00126   gslmm::generator r1(t);
00127   gslmm::generator r2(t);
00128 
00129   for (size_t i = 0; i < N; i++) r1.get();
00130   r2 = r1;
00131   for (size_t i = 0; i < N; i++) {
00132     test_a[i] = r1.get();
00133     test_b[i] = r2.get();
00134     test_c[i] = r1.integer(1234);
00135     test_d[i] = r2.integer(1234);
00136     test_e[i] = r1.uniform();
00137     test_f[i] = r2.uniform();
00138   }
00139   
00140   int status = 0;
00141   for (size_t i = 0; i < N; i++) {
00142     status |= (test_b[i] != test_a[i]);
00143     status |= (test_d[i] != test_c[i]);
00144     status |= (test_e[i] != test_f[i]);
00145   }
00146   
00147   ts.status(status, "%s, parallel random number state consistency", 
00148             r1.name());
00149 }
00150 
00151 //____________________________________________________________________  
00152 int
00153 max_test(gslmm::generator& r,
00154          unsigned long int& kmax, 
00155          unsigned long int  ran_max)
00156 {
00157   unsigned long int max = 0;
00158   for (size_t i = 0; i < N2; ++i) {
00159     unsigned long int k = r.get();
00160     if (k > max) max = k;
00161   }
00162   kmax = max;
00163 
00164   unsigned long int actual_uncovered = ran_max - max;
00165   double            expect_uncovered = (double) ran_max / (double) N2;
00166 
00167   return  (max > ran_max) || (actual_uncovered > 7 * expect_uncovered);
00168 }
00169 
00170 //____________________________________________________________________  
00171 int
00172 min_test(gslmm::generator& r,
00173          unsigned long int& kmin, 
00174          unsigned long int  ran_min,
00175          unsigned long int  ran_max)
00176 {
00177   unsigned long int min = 1000000000UL;
00178 
00179   for (size_t i = 0; i < N2; ++i) {
00180     unsigned long int k = r.get();
00181     if (k < min) min = k;
00182   }
00183   kmin = min;
00184 
00185   unsigned long int actual_uncovered = min - ran_min;
00186   double            expect_uncovered = (double) ran_max / (double) N2;
00187 
00188   bool ret = ((min < ran_min) || (actual_uncovered > 7 * expect_uncovered));
00189 #if 0
00190   if (!ret) 
00191     std::cout << " min:\t" << min 
00192               << " ran_min:\t" << ran_min
00193               << " actual:\t" << actual_uncovered 
00194               << " expect:\t" << expect_uncovered
00195               << std::endl;
00196 #endif
00197   return  ret;
00198   
00199 }
00200 
00201 //____________________________________________________________________  
00202 bool
00203 sum_test(gslmm::test_suite& ts,
00204          gslmm::generator& r) 
00205 {
00206   double sum = 0;
00207 
00208   for (size_t i = 0; i < N2; ++i) {
00209     double x = r.uniform() - 0.5;
00210     sum += x;
00211   }
00212   sum /= N2;
00213  
00214   /* expect the average to have a variance of 1/(12 n) */
00215   double sigma = fabs(sum * std::sqrt(12.0 * N2)); 
00216   return ts.range(sigma, .003, 3., "%s, sum test within acceptable sigma",
00217                   r.name());
00218 
00219 }
00220 
00221 #define BINS 17
00222 #define EXTRA 10
00223 //____________________________________________________________________  
00224 bool
00225 bin_test(gslmm::test_suite& ts,
00226          gslmm::generator& r) 
00227 {
00228   int count[BINS+EXTRA];
00229  
00230   for (size_t i = 0; i < BINS+EXTRA; i++) count[i] = 0 ;
00231   for (size_t i = 0; i < N2; i++) {
00232     int j = r.integer(BINS);
00233     count[j]++ ;
00234   }
00235 
00236   double chisq = 0 ;
00237   for (size_t i = 0; i < BINS; i++) {
00238     double x =  (double)N2/(double)BINS ;
00239     double d =  (count[i] - x) ;
00240     chisq    += (d * d) / x;
00241   }
00242 
00243   bool ret;
00244   double sigma = sqrt(chisq/BINS) ;
00245   /* more than 3 sigma is an error */
00246   // status = (fabs (sigma) > 3 || fabs(sigma) < 0.003);
00247   ret = ts.factor(fabs(sigma), 1, 3, "%s, bin test within acceptable chisq", 
00248                   r.name());
00249   for (size_t i = BINS; i < BINS+EXTRA; i++) {
00250     ret = ts.test(count[i], 0, 
00251                   "%s, wrote outside range in bin test ", r.name());
00252   }
00253   return ret;
00254 }
00255 
00256 //____________________________________________________________________  
00257 void
00258 generic_test(gslmm::test_suite& ts,
00259              gslmm::generator::backend_type t)
00260 {
00261   gslmm::generator r(t);
00262   unsigned long int kmax = 0, kmin = 1000;
00263   const unsigned long int ran_max = r.max();
00264   const unsigned long int ran_min = r.min();
00265 
00266   int status;
00267   
00268   status = max_test(r, kmax, ran_max);
00269   ts.status(status, "%s, observed vs theoretical maximum",
00270             r.name(), kmax, ran_max);
00271 
00272   status = min_test(r, kmin, ran_min, ran_max);
00273   ts.status(status, "%s, observed vs theoretical minimum",
00274             r.name(), kmin, ran_min);
00275 
00276   sum_test(ts,r);
00277  
00278   bin_test (ts, r);
00279  
00280   status = 0;
00281   
00282   r.set(1);   
00283   status |= max_test(r, kmax, ran_max);
00284  
00285   r.set(1);   
00286   status |= min_test(r, kmin, ran_min, ran_max);
00287  
00288   r.set(1);   
00289   status |= (sum_test(ts,r) ? 0 : 1);
00290  
00291   r.set(12345);
00292   status |= max_test(r, kmax, ran_max);
00293  
00294   r.set(12345);
00295   status |= min_test(r, kmin, ran_min, ran_max);
00296  
00297   r.set(12345);
00298   status |= (sum_test(ts,r) ? 0 : 1);
00299  
00300   ts.status(status, "%s, maximum and sum tests for non-default seeds", 
00301             r.name()); 
00302 }
00303   
00304 
00305   
00306 //____________________________________________________________________  
00307 int main(int argc, char** argv) 
00308 {
00309   gslmm::test_suite ts("generator", argc, argv);
00310 
00311   gslmm::generator::backend_type_list rngs = 
00312     gslmm::generator::types();
00313   
00314   /* specific tests of known results for 10000 iterations with seed = 1 */
00315   random_test(ts,gslmm::generator::rand, 1, 10000, 1910041713);
00316   random_test(ts,gslmm::generator::randu, 1, 10000, 1623524161);
00317   random_test(ts,gslmm::generator::cmrg, 1, 10000, 719452880);
00318   random_test(ts,gslmm::generator::minstd, 1, 10000, 1043618065);
00319   random_test(ts,gslmm::generator::mrg, 1, 10000, 2064828650);
00320   random_test(ts,gslmm::generator::taus, 1, 10000, 2733957125UL);
00321   random_test(ts,gslmm::generator::taus113, 1, 1000, 1925420673UL);
00322   random_test(ts,gslmm::generator::transputer, 1, 10000, 1244127297UL);
00323   random_test(ts,gslmm::generator::vax, 1, 10000, 3051034865UL);
00324 
00325   /* Borosh13 test value from PARI: (1812433253^10000)%(2^32) */
00326   random_test(ts,gslmm::generator::borosh13, 1, 10000, 2513433025UL);
00327 
00328   /* Fishman18 test value from PARI: (62089911^10000)%(2^31-1) */
00329   random_test(ts,gslmm::generator::fishman18, 1, 10000, 330402013UL);
00330 
00331   /* Fishman2x test value from PARI: 
00332      ((48271^10000)%(2^31-1) - (40692^10000)%(2^31-249))%(2^31-1) */
00333   random_test(ts,gslmm::generator::fishman2x, 1, 10000, 540133597UL);
00334 
00335   /* Knuthran2 test value from PARI: 
00336      { xn1=1; xn2=1; for (n=1,10000, 
00337             xn = (271828183*xn1 - 314159269*xn2)%(2^31-1);
00338             xn2=xn1; xn1=xn; print(xn); ) } */
00339   random_test(ts,gslmm::generator::knuthran2, 1, 10000, 1084477620UL);
00340 
00341   /* Knuthran test value taken from p188 in Knuth Vol 2. 3rd Ed */
00342   random_test(ts,gslmm::generator::knuthran, 310952, 1009 * 2009 + 1, 461390032);
00343 
00344   /* Lecuyer21 test value from PARI: (40692^10000)%(2^31-249) */
00345   random_test(ts,gslmm::generator::lecuyer21, 1, 10000, 2006618587UL);
00346 
00347   /* Waterman14 test value from PARI: (1566083941^10000)%(2^32) */
00348   random_test(ts,gslmm::generator::waterman14, 1, 10000, 3776680385UL);
00349 
00350   /* specific tests of known results for 10000 iterations with seed = 6 */
00351 
00352   /* Coveyou test value from PARI:
00353      x=6; for(n=1,10000,x=(x*(x+1))%(2^32);print(x);) */
00354   random_test(ts,gslmm::generator::coveyou, 6, 10000, 1416754246UL);
00355 
00356   /* Fishman20 test value from PARI: (6*48271^10000)%(2^31-1) */
00357   random_test(ts,gslmm::generator::fishman20, 6, 10000, 248127575UL);
00358 
00359   /* FIXME: the ranlux tests below were made by running the fortran code and
00360      getting the expected value from that. An analytic calculation
00361      would be preferable. */
00362   random_test(ts,gslmm::generator::ranlux, 314159265, 10000, 12077992);
00363   random_test(ts,gslmm::generator::ranlux389, 314159265, 10000, 165942);
00364   random_test(ts,gslmm::generator::ranlxs0, 1, 10000, 11904320);
00365   /* 0.709552764892578125 * ldexp(1.0,24) */
00366   random_test(ts,gslmm::generator::ranlxs1, 1, 10000, 8734328);
00367   /* 0.520606517791748047 * ldexp(1.0,24) */
00368   random_test(ts,gslmm::generator::ranlxs2, 1, 10000, 6843140); 
00369   /* 0.407882928848266602 * ldexp(1.0,24) */
00370   random_test(ts,gslmm::generator::ranlxd1, 1, 10000, 1998227290UL);
00371   /* 0.465248546261094020 * ldexp(1.0,32) */
00372   random_test(ts,gslmm::generator::ranlxd2, 1, 10000, 3949287736UL);
00373   /* 0.919515205581550532 * ldexp(1.0,32) */
00374 
00375   /* FIXME: the tests below were made by running the original code in
00376      the ../random directory and getting the expected value from
00377      that. An analytic calculation would be preferable. */
00378   random_test(ts,gslmm::generator::slatec, 1, 10000, 45776);
00379   random_test(ts,gslmm::generator::uni, 1, 10000, 9214);
00380   random_test(ts,gslmm::generator::uni32, 1, 10000, 1155229825);
00381   random_test(ts,gslmm::generator::zuf, 1, 10000, 3970);
00382 
00383   /* The tests below were made by running the original code and
00384      getting the expected value from that. An analytic calculation
00385      would be preferable. */
00386   random_test(ts,gslmm::generator::r250, 1, 10000, 1100653588);
00387   random_test(ts,gslmm::generator::mt19937, 4357, 1000, 1186927261);
00388   random_test(ts,gslmm::generator::mt19937_1999, 4357, 1000, 1030650439);
00389   random_test(ts,gslmm::generator::mt19937_1998, 4357, 1000, 1309179303);
00390   random_test(ts,gslmm::generator::tt800, 0, 10000, 2856609219UL);
00391 
00392   random_test(ts,gslmm::generator::ran0, 0, 10000, 1115320064);
00393   random_test(ts,gslmm::generator::ran1, 0, 10000, 1491066076);
00394   random_test(ts,gslmm::generator::ran2, 0, 10000, 1701364455);
00395   random_test(ts,gslmm::generator::ran3, 0, 10000, 186340785);
00396 
00397   random_test(ts,gslmm::generator::ranmar, 1, 10000, 14428370);
00398 
00399   random_test(ts,gslmm::generator::rand48, 0, 10000, 0xDE095043UL);
00400   random_test(ts,gslmm::generator::rand48, 1, 10000, 0xEDA54977UL);
00401 
00402   random_test(ts,gslmm::generator::random_glibc2, 0, 10000, 1908609430);
00403   random_test(ts,gslmm::generator::random8_glibc2, 0, 10000, 1910041713);
00404   random_test(ts,gslmm::generator::random32_glibc2, 0, 10000, 1587395585);
00405   random_test(ts,gslmm::generator::random64_glibc2, 0, 10000, 52848624);
00406   random_test(ts,gslmm::generator::random128_glibc2, 0, 10000, 1908609430);
00407   random_test(ts,gslmm::generator::random256_glibc2, 0, 10000, 179943260);
00408 
00409   random_test(ts,gslmm::generator::random_bsd, 0, 10000, 1457025928);
00410   random_test(ts,gslmm::generator::random8_bsd, 0, 10000, 1910041713);
00411   random_test(ts,gslmm::generator::random32_bsd, 0, 10000, 1663114331);
00412   random_test(ts,gslmm::generator::random64_bsd, 0, 10000, 864469165);
00413   random_test(ts,gslmm::generator::random128_bsd, 0, 10000, 1457025928);
00414   random_test(ts,gslmm::generator::random256_bsd, 0, 10000, 1216357476);
00415 
00416   random_test(ts,gslmm::generator::random_libc5, 0, 10000, 428084942);
00417   random_test(ts,gslmm::generator::random8_libc5, 0, 10000, 1910041713);
00418   random_test(ts,gslmm::generator::random32_libc5, 0, 10000, 1967452027);
00419   random_test(ts,gslmm::generator::random64_libc5, 0, 10000, 2106639801);
00420   random_test(ts,gslmm::generator::random128_libc5, 0, 10000, 428084942);
00421   random_test(ts,gslmm::generator::random256_libc5, 0, 10000, 116367984);
00422 
00423   random_test(ts,gslmm::generator::ranf, 0, 10000, 2152890433UL);
00424   random_test(ts,gslmm::generator::ranf, 2, 10000, 339327233);
00425 
00426   /* Test constant relationship between int and double functions */
00427   for (gslmm::generator::backend_type_list::iterator r = rngs.begin(); 
00428        r != rngs.end(); ++r) float_test(ts,*r);
00429 
00430   /* Test save/restore functions */
00431   for (gslmm::generator::backend_type_list::iterator r = rngs.begin(); 
00432        r != rngs.end(); ++r) state_test(ts,*r);
00433   for (gslmm::generator::backend_type_list::iterator r = rngs.begin(); 
00434        r != rngs.end(); ++r) parallel_state_test(ts,*r);
00435 
00436   /* generic statistical tests (these are just to make sure that we
00437      don't get any crazy results back from the generator, i.e. they
00438      aren't a test of the algorithm, just the implementation) */
00439   for (gslmm::generator::backend_type_list::iterator r = rngs.begin(); 
00440        r != rngs.end(); ++r) generic_test(ts,*r);
00441 
00442   return ts.summary() ? 0 : 1;
00443 }
00444 
00445 //____________________________________________________________________  
00446 //
00447 // EOF
00448 //  
Top of page Last update Tue May 9 10:11:11 2006
Christian Holm
Created by DoxyGen 1.4.6