[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     ! 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>