[BACK]Return to stat.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / tests / rand

Annotation of OpenXM_contrib/gmp/tests/rand/stat.c, Revision 1.1.1.1

1.1       maekawa     1: /* stat.c -- statistical tests of random number sequences. */
                      2:
                      3: /*
                      4: Copyright (C) 1999, 2000 Free Software Foundation, Inc.
                      5:
                      6: This file is part of the GNU MP Library.
                      7:
                      8: The GNU MP Library is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU Lesser General Public License as published by
                     10: the Free Software Foundation; either version 2.1 of the License, or (at your
                     11: option) any later version.
                     12:
                     13: The GNU MP Library is distributed in the hope that it will be useful, but
                     14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     16: License for more details.
                     17:
                     18: You should have received a copy of the GNU Lesser General Public License
                     19: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     21: MA 02111-1307, USA.
                     22: */
                     23:
                     24: /* Examples:
                     25:
                     26:   $ gen 1000 | stat
                     27: Test 1000 real numbers.
                     28:
                     29:   $ gen 30000 | stat -2 1000
                     30: Test 1000 real numbers 30 times and then test the 30 results in a
                     31: ``second level''.
                     32:
                     33:   $ gen -f mpz_urandomb 1000 | stat -i 0xffffffff
                     34: Test 1000 integers 0 <= X <= 2^32-1.
                     35:
                     36:   $ gen -f mpz_urandomb -z 34 1000 | stat -i 0x3ffffffff
                     37: Test 1000 integers 0 <= X <= 2^34-1.
                     38:
                     39: */
                     40:
                     41: #include <stdio.h>
                     42: #include <stdlib.h>
                     43: #include <unistd.h>
                     44: #include <math.h>
                     45: #include "gmp.h"
                     46: #include "gmpstat.h"
                     47:
                     48: #if !HAVE_DECL_OPTARG
                     49: extern char *optarg;
                     50: extern int optind, opterr;
                     51: #endif
                     52:
                     53: #define FVECSIZ (100000L)
                     54:
                     55: int g_debug = 0;
                     56:
                     57: static void
                     58: print_ks_results (mpf_t f_p, mpf_t f_p_prob,
                     59:                  mpf_t f_m, mpf_t f_m_prob,
                     60:                  FILE *fp)
                     61: {
                     62:   double p, pp, m, mp;
                     63:
                     64:   p = mpf_get_d (f_p);
                     65:   m = mpf_get_d (f_m);
                     66:   pp = mpf_get_d (f_p_prob);
                     67:   mp = mpf_get_d (f_m_prob);
                     68:
                     69:   fprintf (fp, "%.4f (%.0f%%)\t", p, pp * 100.0);
                     70:   fprintf (fp, "%.4f (%.0f%%)\n", m, mp * 100.0);
                     71: }
                     72:
                     73: static void
                     74: print_x2_table (unsigned int v, FILE *fp)
                     75: {
                     76:   double t[7];
                     77:   int f;
                     78:
                     79:
                     80:   fprintf (fp, "Chi-square table for v=%u\n", v);
                     81:   fprintf (fp, "1%%\t5%%\t25%%\t50%%\t75%%\t95%%\t99%%\n");
                     82:   x2_table (t, v);
                     83:   for (f = 0; f < 7; f++)
                     84:     fprintf (fp, "%.2f\t", t[f]);
                     85:   fputs ("\n", fp);
                     86: }
                     87:
                     88:
                     89:
                     90: /* Pks () -- Distribution function for KS results with a big n (like 1000
                     91:    or so):  F(x) = 1 - pow(e, -2*x^2) [Knuth, vol 2, p.51]. */
                     92: /* gnuplot: plot [0:1] Pks(x), Pks(x) = 1-exp(-2*x**2)  */
                     93:
                     94: static void
                     95: Pks (mpf_t p, mpf_t x)
                     96: {
                     97:   double dt;                   /* temp double */
                     98:
                     99:   mpf_set (p, x);
                    100:   mpf_mul (p, p, p);           /* p = x^2 */
                    101:   mpf_mul_ui (p, p, 2);                /* p = 2*x^2 */
                    102:   mpf_neg (p, p);              /* p = -2*x^2 */
                    103:   /* No pow() in gmp.  Use doubles. */
                    104:   /* FIXME: Use exp()? */
                    105:   dt = pow (M_E, mpf_get_d (p));
                    106:   mpf_set_d (p, dt);
                    107:   mpf_ui_sub (p, 1, p);
                    108: }
                    109:
                    110: /* f_freq() -- frequency test on real numbers 0<=f<1*/
                    111: static void
                    112: f_freq (const unsigned l1runs, const unsigned l2runs,
                    113:        mpf_t fvec[], const unsigned long n)
                    114: {
                    115:   unsigned f;
                    116:   mpf_t f_p, f_p_prob;
                    117:   mpf_t f_m, f_m_prob;
                    118:   mpf_t *l1res;                        /* level 1 result array */
                    119:
                    120:   mpf_init (f_p);  mpf_init (f_m);
                    121:   mpf_init (f_p_prob);  mpf_init (f_m_prob);
                    122:
                    123:
                    124:   /* Allocate space for 1st level results. */
                    125:   l1res = (mpf_t *) malloc (l2runs * 2 * sizeof (mpf_t));
                    126:   if (NULL == l1res)
                    127:     {
                    128:       fprintf (stderr, "stat: malloc failure\n");
                    129:       exit (1);
                    130:     }
                    131:
                    132:   printf ("\nEquidistribution/Frequency test on real numbers (0<=X<1):\n");
                    133:   printf ("\tKp\t\tKm\n");
                    134:
                    135:   for (f = 0; f < l2runs; f++)
                    136:     {
                    137:       /*  f_printvec (fvec, n); */
                    138:       mpf_freqt (f_p, f_m, fvec + f * n, n);
                    139:
                    140:       /* what's the probability of getting these results? */
                    141:       ks_table (f_p_prob, f_p, n);
                    142:       ks_table (f_m_prob, f_m, n);
                    143:
                    144:       if (l1runs == 0)
                    145:        {
                    146:          /*printf ("%u:\t", f + 1);*/
                    147:          print_ks_results (f_p, f_p_prob, f_m, f_m_prob, stdout);
                    148:        }
                    149:       else
                    150:        {
                    151:          /* save result */
                    152:          mpf_init_set (l1res[f], f_p);
                    153:          mpf_init_set (l1res[f + l2runs], f_m);
                    154:        }
                    155:     }
                    156:
                    157:   /* Now, apply the KS test on the results from the 1st level rounds
                    158:      with the distribution
                    159:      F(x) = 1 - pow(e, -2*x^2) [Knuth, vol 2, p.51] */
                    160:
                    161:   if (l1runs != 0)
                    162:     {
                    163:       /*printf ("-------------------------------------\n");*/
                    164:
                    165:       /* The Kp's. */
                    166:       ks (f_p, f_m, l1res, Pks, l2runs);
                    167:       ks_table (f_p_prob, f_p, l2runs);
                    168:       ks_table (f_m_prob, f_m, l2runs);
                    169:       printf ("Kp:\t");
                    170:       print_ks_results (f_p, f_p_prob, f_m, f_m_prob, stdout);
                    171:
                    172:       /* The Km's. */
                    173:       ks (f_p, f_m, l1res + l2runs, Pks, l2runs);
                    174:       ks_table (f_p_prob, f_p, l2runs);
                    175:       ks_table (f_m_prob, f_m, l2runs);
                    176:       printf ("Km:\t");
                    177:       print_ks_results (f_p, f_p_prob, f_m, f_m_prob, stdout);
                    178:     }
                    179:
                    180:   mpf_clear (f_p);  mpf_clear (f_m);
                    181:   mpf_clear (f_p_prob);  mpf_clear (f_m_prob);
                    182:   free (l1res);
                    183: }
                    184:
                    185: /* z_freq(l1runs, l2runs, zvec, n, max) -- frequency test on integers
                    186:    0<=z<=MAX */
                    187: static void
                    188: z_freq (const unsigned l1runs,
                    189:        const unsigned l2runs,
                    190:        mpz_t zvec[],
                    191:        const unsigned long n,
                    192:        unsigned int max)
                    193: {
                    194:   mpf_t V;                     /* result */
                    195:   double d_V;                  /* result as a double */
                    196:
                    197:   mpf_init (V);
                    198:
                    199:
                    200:   printf ("\nEquidistribution/Frequency test on integers (0<=X<=%u):\n", max);
                    201:   print_x2_table (max, stdout);
                    202:
                    203:   mpz_freqt (V, zvec, max, n);
                    204:
                    205:   d_V = mpf_get_d (V);
                    206:   printf ("V = %.2f (n = %lu)\n", d_V, n);
                    207:
                    208:   mpf_clear (V);
                    209: }
                    210:
                    211: unsigned int stat_debug = 0;
                    212:
                    213: int
                    214: main (argc, argv)
                    215:      int argc;
                    216:      char *argv[];
                    217: {
                    218:   const char usage[] =
                    219:     "usage: stat [-d] [-2 runs] [-i max | -r max] [file]\n" \
                    220:     "       file     filename\n" \
                    221:     "       -2 runs  perform 2-level test with RUNS runs on 1st level\n" \
                    222:     "       -d       increase debugging level\n" \
                    223:     "       -i max   input is integers 0 <= Z <= MAX\n" \
                    224:     "       -r max   input is real numbers 0 <= R < 1 and use MAX as\n" \
                    225:     "                maximum value when converting real numbers to integers\n" \
                    226:     "";
                    227:
                    228:   mpf_t fvec[FVECSIZ];
                    229:   mpz_t zvec[FVECSIZ];
                    230:   unsigned long int f, n, vecentries;
                    231:   char *filen;
                    232:   FILE *fp;
                    233:   int c;
                    234:   int omitoutput = 0;
                    235:   int realinput = -1;          /* 1: input is real numbers 0<=R<1;
                    236:                                   0: input is integers 0 <= Z <= MAX. */
                    237:   long l1runs = 0,             /* 1st level runs */
                    238:     l2runs = 1;                        /* 2nd level runs */
                    239:   mpf_t f_temp;
                    240:   mpz_t z_imax;                        /* max value when converting between
                    241:                                    real number and integer. */
                    242:   mpf_t f_imax_plus1;          /* f_imax + 1 stored in an mpf_t for
                    243:                                    convenience */
                    244:   mpf_t f_imax_minus1;         /* f_imax - 1 stored in an mpf_t for
                    245:                                    convenience */
                    246:
                    247:
                    248:   mpf_init (f_temp);
                    249:   mpz_init_set_ui (z_imax, 0x7fffffff);
                    250:   mpf_init (f_imax_plus1);
                    251:   mpf_init (f_imax_minus1);
                    252:
                    253:   while ((c = getopt (argc, argv, "d2:i:r:")) != -1)
                    254:     switch (c)
                    255:       {
                    256:       case '2':
                    257:        l1runs = atol (optarg);
                    258:        l2runs = -1;            /* set later on */
                    259:        break;
                    260:       case 'd':                        /* increase debug level */
                    261:        stat_debug++;
                    262:        break;
                    263:       case 'i':
                    264:        if (1 == realinput)
                    265:          {
                    266:            fputs ("stat: options -i and -r are mutually exclusive\n", stderr);
                    267:            exit (1);
                    268:          }
                    269:        if (mpz_set_str (z_imax, optarg, 0))
                    270:          {
                    271:            fprintf (stderr, "stat: bad max value %s\n", optarg);
                    272:            exit (1);
                    273:          }
                    274:        realinput = 0;
                    275:        break;
                    276:       case 'r':
                    277:        if (0 == realinput)
                    278:          {
                    279:            fputs ("stat: options -i and -r are mutually exclusive\n", stderr);
                    280:            exit (1);
                    281:          }
                    282:        if (mpz_set_str (z_imax, optarg, 0))
                    283:          {
                    284:            fprintf (stderr, "stat: bad max value %s\n", optarg);
                    285:            exit (1);
                    286:          }
                    287:        realinput = 1;
                    288:        break;
                    289:       case 'o':
                    290:        omitoutput = atoi (optarg);
                    291:        break;
                    292:       case '?':
                    293:       default:
                    294:        fputs (usage, stderr);
                    295:        exit (1);
                    296:       }
                    297:   argc -= optind;
                    298:   argv += optind;
                    299:
                    300:   if (argc < 1)
                    301:     fp = stdin;
                    302:   else
                    303:     filen = argv[0];
                    304:
                    305:   if (fp != stdin)
                    306:     if (NULL == (fp = fopen (filen, "r")))
                    307:       {
                    308:        perror (filen);
                    309:        exit (1);
                    310:       }
                    311:
                    312:   if (-1 == realinput)
                    313:     realinput = 1;             /* default is real numbers */
                    314:
                    315:   /* read file and fill appropriate vec */
                    316:   if (1 == realinput)          /* real input */
                    317:     {
                    318:       for (f = 0; f < FVECSIZ ; f++)
                    319:        {
                    320:          mpf_init (fvec[f]);
                    321:          if (!mpf_inp_str (fvec[f], fp, 10))
                    322:            break;
                    323:        }
                    324:     }
                    325:   else                         /* integer input */
                    326:     {
                    327:       for (f = 0; f < FVECSIZ ; f++)
                    328:        {
                    329:          mpz_init (zvec[f]);
                    330:          if (!mpz_inp_str (zvec[f], fp, 10))
                    331:            break;
                    332:        }
                    333:     }
                    334:   vecentries = n = f;          /* number of entries read */
                    335:   fclose (fp);
                    336:
                    337:   if (FVECSIZ == f)
                    338:     fprintf (stderr, "stat: warning: discarding input due to lazy allocation "\
                    339:             "of only %ld entries.  sorry.\n", FVECSIZ);
                    340:
                    341:   printf ("Got %lu numbers.\n", n);
                    342:
                    343:   /* convert and fill the other vec */
                    344:   /* since fvec[] contains 0<=f<1 and we want ivec[] to contain
                    345:      0<=z<=imax and we are truncating all fractions when
                    346:      converting float to int, we have to add 1 to imax.*/
                    347:   mpf_set_z (f_imax_plus1, z_imax);
                    348:   mpf_add_ui (f_imax_plus1, f_imax_plus1, 1);
                    349:   if (1 == realinput)          /* fill zvec[] */
                    350:     {
                    351:       for (f = 0; f < n; f++)
                    352:        {
                    353:          mpf_mul (f_temp, fvec[f], f_imax_plus1);
                    354:          mpz_init (zvec[f]);
                    355:          mpz_set_f (zvec[f], f_temp); /* truncating fraction */
                    356:          if (stat_debug > 1)
                    357:            {
                    358:              mpz_out_str (stderr, 10, zvec[f]);
                    359:              fputs ("\n", stderr);
                    360:            }
                    361:        }
                    362:     }
                    363:   else                         /* integer input; fill fvec[] */
                    364:     {
                    365:       /*    mpf_set_z (f_imax_minus1, z_imax);
                    366:            mpf_sub_ui (f_imax_minus1, f_imax_minus1, 1);*/
                    367:       for (f = 0; f < n; f++)
                    368:        {
                    369:          mpf_init (fvec[f]);
                    370:          mpf_set_z (fvec[f], zvec[f]);
                    371:          mpf_div (fvec[f], fvec[f], f_imax_plus1);
                    372:          if (stat_debug > 1)
                    373:            {
                    374:              mpf_out_str (stderr, 10, 0, fvec[f]);
                    375:              fputs ("\n", stderr);
                    376:            }
                    377:        }
                    378:     }
                    379:
                    380:   /* 2 levels? */
                    381:   if (1 != l2runs)
                    382:     {
                    383:       l2runs = n / l1runs;
                    384:       printf ("Doing %ld second level rounds "\
                    385:              "with %ld entries in each round", l2runs, l1runs);
                    386:       if (n % l1runs)
                    387:        printf (" (discarding %ld entr%s)", n % l1runs,
                    388:                n % l1runs == 1 ? "y" : "ies");
                    389:       puts (".");
                    390:       n = l1runs;
                    391:     }
                    392:
                    393: #ifndef DONT_FFREQ
                    394:   f_freq (l1runs, l2runs, fvec, n);
                    395: #endif
                    396: #ifdef DO_ZFREQ
                    397:   z_freq (l1runs, l2runs, zvec, n, mpz_get_ui (z_imax));
                    398: #endif
                    399:
                    400:   mpf_clear (f_temp); mpz_clear (z_imax);
                    401:   mpf_clear (f_imax_plus1);
                    402:   mpf_clear (f_imax_minus1);
                    403:   for (f = 0; f < vecentries; f++)
                    404:     {
                    405:       mpf_clear (fvec[f]);
                    406:       mpz_clear (zvec[f]);
                    407:     }
                    408:
                    409:   return 0;
                    410: }
                    411:
                    412:
                    413:
                    414:
                    415:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>