Home | History | Annotate | Line # | Download | only in tests
tnrandom_chisq.c revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  pgoyette /* Chi-squared test for mpfr_nrandom
      2  1.1.1.1.2.2  pgoyette 
      3  1.1.1.1.2.2  pgoyette Copyright 2011-2018 Free Software Foundation, Inc.
      4  1.1.1.1.2.2  pgoyette Contributed by Charles Karney <charles (at) karney.com>, SRI International.
      5  1.1.1.1.2.2  pgoyette 
      6  1.1.1.1.2.2  pgoyette This file is part of the GNU MPFR Library.
      7  1.1.1.1.2.2  pgoyette 
      8  1.1.1.1.2.2  pgoyette The GNU MPFR Library is free software; you can redistribute it and/or modify
      9  1.1.1.1.2.2  pgoyette it under the terms of the GNU Lesser General Public License as published by
     10  1.1.1.1.2.2  pgoyette the Free Software Foundation; either version 3 of the License, or (at your
     11  1.1.1.1.2.2  pgoyette option) any later version.
     12  1.1.1.1.2.2  pgoyette 
     13  1.1.1.1.2.2  pgoyette The GNU MPFR Library is distributed in the hope that it will be useful, but
     14  1.1.1.1.2.2  pgoyette WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15  1.1.1.1.2.2  pgoyette or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     16  1.1.1.1.2.2  pgoyette License for more details.
     17  1.1.1.1.2.2  pgoyette 
     18  1.1.1.1.2.2  pgoyette You should have received a copy of the GNU Lesser General Public License
     19  1.1.1.1.2.2  pgoyette along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
     20  1.1.1.1.2.2  pgoyette http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
     21  1.1.1.1.2.2  pgoyette 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
     22  1.1.1.1.2.2  pgoyette 
     23  1.1.1.1.2.2  pgoyette #include "mpfr-test.h"
     24  1.1.1.1.2.2  pgoyette 
     25  1.1.1.1.2.2  pgoyette /* Return Phi(x) = erf(x / sqrt(2)) / 2, the cumulative probability function
     26  1.1.1.1.2.2  pgoyette  * for the normal distribution.  We only take differences of this function so
     27  1.1.1.1.2.2  pgoyette  * the offset doesn't matter; here Phi(0) = 0. */
     28  1.1.1.1.2.2  pgoyette static void
     29  1.1.1.1.2.2  pgoyette normal_cumulative (mpfr_t z, mpfr_t x, mpfr_rnd_t rnd)
     30  1.1.1.1.2.2  pgoyette {
     31  1.1.1.1.2.2  pgoyette   mpfr_sqrt_ui (z, 2, rnd);
     32  1.1.1.1.2.2  pgoyette   mpfr_div (z, x, z, rnd);
     33  1.1.1.1.2.2  pgoyette   mpfr_erf (z, z, rnd);
     34  1.1.1.1.2.2  pgoyette   mpfr_div_ui (z, z, 2, rnd);
     35  1.1.1.1.2.2  pgoyette }
     36  1.1.1.1.2.2  pgoyette 
     37  1.1.1.1.2.2  pgoyette /* Given nu and chisqp, compute probability that chisq > chisqp.  This uses,
     38  1.1.1.1.2.2  pgoyette  * A&S 26.4.16,
     39  1.1.1.1.2.2  pgoyette  *
     40  1.1.1.1.2.2  pgoyette  * Q(nu,chisqp) =
     41  1.1.1.1.2.2  pgoyette  *     erfc( (3/2)*sqrt(nu) * ( cbrt(chisqp/nu) - 1 + 2/(9*nu) ) ) / 2
     42  1.1.1.1.2.2  pgoyette  *
     43  1.1.1.1.2.2  pgoyette  * which is valid for nu > 30.  This is the basis for the formula in Knuth,
     44  1.1.1.1.2.2  pgoyette  * TAOCP, Vol 2, 3.3.1, Table 1.  It more accurate than the similar formula,
     45  1.1.1.1.2.2  pgoyette  * DLMF 8.11.10. */
     46  1.1.1.1.2.2  pgoyette static void
     47  1.1.1.1.2.2  pgoyette chisq_prob (mpfr_t q, long nu, mpfr_t chisqp)
     48  1.1.1.1.2.2  pgoyette {
     49  1.1.1.1.2.2  pgoyette   mpfr_t t;
     50  1.1.1.1.2.2  pgoyette   mpfr_rnd_t rnd;
     51  1.1.1.1.2.2  pgoyette 
     52  1.1.1.1.2.2  pgoyette   rnd = MPFR_RNDN;  /* This uses an approx formula.  Might as well use RNDN. */
     53  1.1.1.1.2.2  pgoyette   mpfr_init2 (t, mpfr_get_prec (q));
     54  1.1.1.1.2.2  pgoyette 
     55  1.1.1.1.2.2  pgoyette   mpfr_div_si (q, chisqp, nu, rnd); /* chisqp/nu */
     56  1.1.1.1.2.2  pgoyette   mpfr_cbrt (q, q, rnd);            /* (chisqp/nu)^(1/3) */
     57  1.1.1.1.2.2  pgoyette   mpfr_sub_ui (q, q, 1, rnd);       /* (chisqp/nu)^(1/3) - 1 */
     58  1.1.1.1.2.2  pgoyette   mpfr_set_ui (t, 2, rnd);
     59  1.1.1.1.2.2  pgoyette   mpfr_div_si (t, t, 9*nu, rnd); /* 2/(9*nu) */
     60  1.1.1.1.2.2  pgoyette   mpfr_add (q, q, t, rnd);       /* (chisqp/nu)^(1/3) - 1 + 2/(9*nu) */
     61  1.1.1.1.2.2  pgoyette   mpfr_sqrt_ui (t, nu, rnd);     /* sqrt(nu) */
     62  1.1.1.1.2.2  pgoyette   mpfr_mul_d (t, t, 1.5, rnd);   /* (3/2)*sqrt(nu) */
     63  1.1.1.1.2.2  pgoyette   mpfr_mul (q, q, t, rnd);       /* arg to erfc */
     64  1.1.1.1.2.2  pgoyette   mpfr_erfc (q, q, rnd);         /* erfc(...) */
     65  1.1.1.1.2.2  pgoyette   mpfr_div_ui (q, q, 2, rnd);    /* erfc(...)/2 */
     66  1.1.1.1.2.2  pgoyette 
     67  1.1.1.1.2.2  pgoyette   mpfr_clear (t);
     68  1.1.1.1.2.2  pgoyette }
     69  1.1.1.1.2.2  pgoyette 
     70  1.1.1.1.2.2  pgoyette /* The continuous chi-squared test on with a set of bins of equal width.
     71  1.1.1.1.2.2  pgoyette  *
     72  1.1.1.1.2.2  pgoyette  * A single precision is picked for sampling and the chi-squared calculation.
     73  1.1.1.1.2.2  pgoyette  * This should picked high enough so that binning in test doesn't need to be
     74  1.1.1.1.2.2  pgoyette  * accurately aligned with possible values of the deviates.  Also we need the
     75  1.1.1.1.2.2  pgoyette  * precision big enough that chi-squared calculation itself is reliable.
     76  1.1.1.1.2.2  pgoyette  *
     77  1.1.1.1.2.2  pgoyette  * There's no particular benefit is testing with at very higher precisions;
     78  1.1.1.1.2.2  pgoyette  * because of the way tnrandom samples, this just adds additional barely
     79  1.1.1.1.2.2  pgoyette  * significant random bits to the deviates.  So this chi-squared test with
     80  1.1.1.1.2.2  pgoyette  * continuous equal width bins isn't a good tool for finding problems here.
     81  1.1.1.1.2.2  pgoyette  *
     82  1.1.1.1.2.2  pgoyette  * The testing of low precision normal deviates is done by
     83  1.1.1.1.2.2  pgoyette  * test_nrandom_chisq_disc. */
     84  1.1.1.1.2.2  pgoyette static double
     85  1.1.1.1.2.2  pgoyette test_nrandom_chisq_cont (long num, mpfr_prec_t prec, int nu,
     86  1.1.1.1.2.2  pgoyette                          double xmin, double xmax, int verbose)
     87  1.1.1.1.2.2  pgoyette {
     88  1.1.1.1.2.2  pgoyette   mpfr_t x, a, b, dx, z, pa, pb, ps, t;
     89  1.1.1.1.2.2  pgoyette   long *counts;
     90  1.1.1.1.2.2  pgoyette   int i, inexact;
     91  1.1.1.1.2.2  pgoyette   long k;
     92  1.1.1.1.2.2  pgoyette   mpfr_rnd_t rnd, rndd;
     93  1.1.1.1.2.2  pgoyette   double Q, chisq;
     94  1.1.1.1.2.2  pgoyette 
     95  1.1.1.1.2.2  pgoyette   rnd = MPFR_RNDN;              /* For chi-squared calculation */
     96  1.1.1.1.2.2  pgoyette   rndd = MPFR_RNDD;             /* For sampling and figuring the bins */
     97  1.1.1.1.2.2  pgoyette   mpfr_inits2 (prec, x, a, b, dx, z, pa, pb, ps, t, (mpfr_ptr) 0);
     98  1.1.1.1.2.2  pgoyette 
     99  1.1.1.1.2.2  pgoyette   counts = (long *) tests_allocate ((nu + 1) * sizeof (long));
    100  1.1.1.1.2.2  pgoyette   for (i = 0; i <= nu; i++)
    101  1.1.1.1.2.2  pgoyette     counts[i] = 0;
    102  1.1.1.1.2.2  pgoyette 
    103  1.1.1.1.2.2  pgoyette   /* a and b are bounds of nu equally spaced bins.  Set dx = (b-a)/nu */
    104  1.1.1.1.2.2  pgoyette   mpfr_set_d (a, xmin, rnd);
    105  1.1.1.1.2.2  pgoyette   mpfr_set_d (b, xmax, rnd);
    106  1.1.1.1.2.2  pgoyette 
    107  1.1.1.1.2.2  pgoyette   mpfr_sub (dx, b, a, rnd);
    108  1.1.1.1.2.2  pgoyette   mpfr_div_si (dx, dx, nu, rnd);
    109  1.1.1.1.2.2  pgoyette 
    110  1.1.1.1.2.2  pgoyette   for (k = 0; k < num; ++k)
    111  1.1.1.1.2.2  pgoyette     {
    112  1.1.1.1.2.2  pgoyette       inexact = mpfr_nrandom (x, RANDS, rndd);
    113  1.1.1.1.2.2  pgoyette       if (inexact == 0)
    114  1.1.1.1.2.2  pgoyette         {
    115  1.1.1.1.2.2  pgoyette           /* one call in the loop pretended to return an exact number! */
    116  1.1.1.1.2.2  pgoyette           printf ("Error: mpfr_nrandom() returns a zero ternary value.\n");
    117  1.1.1.1.2.2  pgoyette           exit (1);
    118  1.1.1.1.2.2  pgoyette         }
    119  1.1.1.1.2.2  pgoyette       mpfr_sub (x, x, a, rndd);
    120  1.1.1.1.2.2  pgoyette       mpfr_div (x, x, dx, rndd);
    121  1.1.1.1.2.2  pgoyette       i = mpfr_get_si (x, rndd);
    122  1.1.1.1.2.2  pgoyette       ++counts[i >= 0 && i < nu ? i : nu];
    123  1.1.1.1.2.2  pgoyette     }
    124  1.1.1.1.2.2  pgoyette 
    125  1.1.1.1.2.2  pgoyette   mpfr_set (x, a, rnd);
    126  1.1.1.1.2.2  pgoyette   normal_cumulative (pa, x, rnd);
    127  1.1.1.1.2.2  pgoyette   mpfr_add_ui (ps, pa, 1, rnd);
    128  1.1.1.1.2.2  pgoyette   mpfr_set_zero (t, 1);
    129  1.1.1.1.2.2  pgoyette   for (i = 0; i <= nu; ++i)
    130  1.1.1.1.2.2  pgoyette     {
    131  1.1.1.1.2.2  pgoyette       if (i < nu)
    132  1.1.1.1.2.2  pgoyette         {
    133  1.1.1.1.2.2  pgoyette           mpfr_add (x, x, dx, rnd);
    134  1.1.1.1.2.2  pgoyette           normal_cumulative (pb, x, rnd);
    135  1.1.1.1.2.2  pgoyette           mpfr_sub (pa, pb, pa, rnd); /* prob for this bin */
    136  1.1.1.1.2.2  pgoyette         }
    137  1.1.1.1.2.2  pgoyette       else
    138  1.1.1.1.2.2  pgoyette         mpfr_sub (pa, ps, pa, rnd); /* prob for last bin, i = nu */
    139  1.1.1.1.2.2  pgoyette 
    140  1.1.1.1.2.2  pgoyette       /* Compute z = counts[i] - num * p; t += z * z / (num * p) */
    141  1.1.1.1.2.2  pgoyette       mpfr_mul_ui (pa, pa, num, rnd);
    142  1.1.1.1.2.2  pgoyette       mpfr_ui_sub (z, counts[i], pa, rnd);
    143  1.1.1.1.2.2  pgoyette       mpfr_sqr (z, z, rnd);
    144  1.1.1.1.2.2  pgoyette       mpfr_div (z, z, pa, rnd);
    145  1.1.1.1.2.2  pgoyette       mpfr_add (t, t, z, rnd);
    146  1.1.1.1.2.2  pgoyette       mpfr_swap (pa, pb);       /* i.e., pa = pb */
    147  1.1.1.1.2.2  pgoyette     }
    148  1.1.1.1.2.2  pgoyette 
    149  1.1.1.1.2.2  pgoyette   chisq = mpfr_get_d (t, rnd);
    150  1.1.1.1.2.2  pgoyette   chisq_prob (t, nu, t);
    151  1.1.1.1.2.2  pgoyette   Q = mpfr_get_d (t, rnd);
    152  1.1.1.1.2.2  pgoyette   if (verbose)
    153  1.1.1.1.2.2  pgoyette     {
    154  1.1.1.1.2.2  pgoyette       printf ("num = %ld, equal bins in [%.2f, %.2f], nu = %d: chisq = %.2f\n",
    155  1.1.1.1.2.2  pgoyette               num, xmin, xmax, nu, chisq);
    156  1.1.1.1.2.2  pgoyette       if (Q < 0.05)
    157  1.1.1.1.2.2  pgoyette         printf ("    WARNING: probability (less than 5%%) = %.2e\n", Q);
    158  1.1.1.1.2.2  pgoyette     }
    159  1.1.1.1.2.2  pgoyette 
    160  1.1.1.1.2.2  pgoyette   tests_free (counts, (nu + 1) * sizeof (long));
    161  1.1.1.1.2.2  pgoyette   mpfr_clears (x, a, b, dx, z, pa, pb, ps, t, (mpfr_ptr) 0);
    162  1.1.1.1.2.2  pgoyette   return Q;
    163  1.1.1.1.2.2  pgoyette }
    164  1.1.1.1.2.2  pgoyette 
    165  1.1.1.1.2.2  pgoyette /* Return a sequential number for a positive low-precision x.  x is altered by
    166  1.1.1.1.2.2  pgoyette  * this fuction.  low precision means prec = 2, 3, or 4.  High values of
    167  1.1.1.1.2.2  pgoyette  * precision will result in integer overflow. */
    168  1.1.1.1.2.2  pgoyette static long
    169  1.1.1.1.2.2  pgoyette sequential (mpfr_t x)
    170  1.1.1.1.2.2  pgoyette {
    171  1.1.1.1.2.2  pgoyette   long expt, prec;
    172  1.1.1.1.2.2  pgoyette 
    173  1.1.1.1.2.2  pgoyette   prec = mpfr_get_prec (x);
    174  1.1.1.1.2.2  pgoyette   expt =  mpfr_get_exp (x);
    175  1.1.1.1.2.2  pgoyette   mpfr_mul_2si (x, x, prec - expt, MPFR_RNDN);
    176  1.1.1.1.2.2  pgoyette 
    177  1.1.1.1.2.2  pgoyette   return expt * (1 << (prec - 1)) + mpfr_get_si (x, MPFR_RNDN);
    178  1.1.1.1.2.2  pgoyette }
    179  1.1.1.1.2.2  pgoyette 
    180  1.1.1.1.2.2  pgoyette /* The chi-squared test on low precision normal deviates.  wprec is the working
    181  1.1.1.1.2.2  pgoyette  * precision for the chi-squared calculation.  prec is the precision for the
    182  1.1.1.1.2.2  pgoyette  * sampling; choose this in [2,5].  The bins consist of all the possible
    183  1.1.1.1.2.2  pgoyette  * deviate values in the range [xmin, xmax] coupled with the value of inexact.
    184  1.1.1.1.2.2  pgoyette  * Thus with prec = 2, the bins are
    185  1.1.1.1.2.2  pgoyette  *   ...
    186  1.1.1.1.2.2  pgoyette  *   (7/16, 1/2)  x = 1/2, inexact = +1
    187  1.1.1.1.2.2  pgoyette  *   (1/2 , 5/8)  x = 1/2, inexact = -1
    188  1.1.1.1.2.2  pgoyette  *   (5/8 , 3/4)  x = 3/4, inexact = +1
    189  1.1.1.1.2.2  pgoyette  *   (3/4 , 7/8)  x = 3/4, inexact = -1
    190  1.1.1.1.2.2  pgoyette  *   (7/8 , 1  )  x = 1  , inexact = +1
    191  1.1.1.1.2.2  pgoyette  *   (1   , 5/4)  x = 1  , inexact = -1
    192  1.1.1.1.2.2  pgoyette  *   (5/4 , 3/2)  x = 3/2, inexact = +1
    193  1.1.1.1.2.2  pgoyette  *   (3/2 , 7/4)  x = 3/2, inexact = -1
    194  1.1.1.1.2.2  pgoyette  *   ...
    195  1.1.1.1.2.2  pgoyette  * In addition, two bins are allocated for [0,xmin) and (xmax,inf).
    196  1.1.1.1.2.2  pgoyette  *
    197  1.1.1.1.2.2  pgoyette  * This test is applied to the absolute values of the deviates.  The sign is
    198  1.1.1.1.2.2  pgoyette  * tested by test_nrandom_chisq_cont.  In any case, the way the sign is
    199  1.1.1.1.2.2  pgoyette  * assigned in mpfr_nrandom is trivial.  In addition, the sampling is with
    200  1.1.1.1.2.2  pgoyette  * MPFR_RNDN.  This is the rounding mode which elicits the most information.
    201  1.1.1.1.2.2  pgoyette  * trandom_deviate includes checks on the consistency of the results extracted
    202  1.1.1.1.2.2  pgoyette  * from a random_deviate with other rounding modes.  */
    203  1.1.1.1.2.2  pgoyette static double
    204  1.1.1.1.2.2  pgoyette test_nrandom_chisq_disc (long num, mpfr_prec_t wprec, int prec,
    205  1.1.1.1.2.2  pgoyette                          double xmin, double xmax, int verbose)
    206  1.1.1.1.2.2  pgoyette {
    207  1.1.1.1.2.2  pgoyette   mpfr_t x, v, pa, pb, z, t;
    208  1.1.1.1.2.2  pgoyette   mpfr_rnd_t rnd;
    209  1.1.1.1.2.2  pgoyette   int i, inexact, nu;
    210  1.1.1.1.2.2  pgoyette   long *counts;
    211  1.1.1.1.2.2  pgoyette   long k, seqmin, seqmax, seq;
    212  1.1.1.1.2.2  pgoyette   double Q, chisq;
    213  1.1.1.1.2.2  pgoyette 
    214  1.1.1.1.2.2  pgoyette   rnd = MPFR_RNDN;
    215  1.1.1.1.2.2  pgoyette   mpfr_init2 (x, prec);
    216  1.1.1.1.2.2  pgoyette   mpfr_init2 (v, prec+1);
    217  1.1.1.1.2.2  pgoyette   mpfr_inits2 (wprec, pa, pb, z, t, (mpfr_ptr) 0);
    218  1.1.1.1.2.2  pgoyette 
    219  1.1.1.1.2.2  pgoyette   mpfr_set_d (x, xmin, rnd);
    220  1.1.1.1.2.2  pgoyette   xmin = mpfr_get_d (x, rnd);
    221  1.1.1.1.2.2  pgoyette   mpfr_set (v, x, rnd);
    222  1.1.1.1.2.2  pgoyette   seqmin = sequential (x);
    223  1.1.1.1.2.2  pgoyette   mpfr_set_d (x, xmax, rnd);
    224  1.1.1.1.2.2  pgoyette   xmax = mpfr_get_d (x, rnd);
    225  1.1.1.1.2.2  pgoyette   seqmax = sequential (x);
    226  1.1.1.1.2.2  pgoyette 
    227  1.1.1.1.2.2  pgoyette   /* Two bins for each sequential number (for inexact = +/- 1), plus 1 for u <
    228  1.1.1.1.2.2  pgoyette    * umin and 1 for u > umax, minus 1 for degrees of freedom */
    229  1.1.1.1.2.2  pgoyette   nu = 2 * (seqmax - seqmin + 1) + 2 - 1;
    230  1.1.1.1.2.2  pgoyette   counts = (long *) tests_allocate ((nu + 1) * sizeof (long));
    231  1.1.1.1.2.2  pgoyette   for (i = 0; i <= nu; i++)
    232  1.1.1.1.2.2  pgoyette     counts[i] = 0;
    233  1.1.1.1.2.2  pgoyette 
    234  1.1.1.1.2.2  pgoyette   for (k = 0; k < num; ++k)
    235  1.1.1.1.2.2  pgoyette     {
    236  1.1.1.1.2.2  pgoyette       inexact = mpfr_nrandom (x, RANDS, rnd);
    237  1.1.1.1.2.2  pgoyette       if (mpfr_signbit (x))
    238  1.1.1.1.2.2  pgoyette         {
    239  1.1.1.1.2.2  pgoyette           inexact = -inexact;
    240  1.1.1.1.2.2  pgoyette           mpfr_setsign (x, x, 0, rnd);
    241  1.1.1.1.2.2  pgoyette         }
    242  1.1.1.1.2.2  pgoyette       /* Don't call sequential with small args to avoid undefined behavior with
    243  1.1.1.1.2.2  pgoyette        * zero and possibility of overflow. */
    244  1.1.1.1.2.2  pgoyette       seq = mpfr_greaterequal_p (x, v) ? sequential (x) : seqmin - 1;
    245  1.1.1.1.2.2  pgoyette       ++counts[seq < seqmin ? 0 :
    246  1.1.1.1.2.2  pgoyette                seq <= seqmax ? 2 * (seq - seqmin) + 1 + (inexact > 0 ? 0 : 1) :
    247  1.1.1.1.2.2  pgoyette                nu];
    248  1.1.1.1.2.2  pgoyette     }
    249  1.1.1.1.2.2  pgoyette 
    250  1.1.1.1.2.2  pgoyette   mpfr_set_zero (v, 1);
    251  1.1.1.1.2.2  pgoyette   normal_cumulative (pa, v, rnd);
    252  1.1.1.1.2.2  pgoyette   /* Cycle through all the bin boundaries using mpfr_nextabove at precision
    253  1.1.1.1.2.2  pgoyette    * prec + 1 starting at mpfr_nextbelow (xmin) */
    254  1.1.1.1.2.2  pgoyette   mpfr_set_d (x, xmin, rnd);
    255  1.1.1.1.2.2  pgoyette   mpfr_set (v, x, rnd);
    256  1.1.1.1.2.2  pgoyette   mpfr_nextbelow (v);
    257  1.1.1.1.2.2  pgoyette   mpfr_nextbelow (v);
    258  1.1.1.1.2.2  pgoyette   mpfr_set_zero (t, 1);
    259  1.1.1.1.2.2  pgoyette   for (i = 0; i <= nu; ++i)
    260  1.1.1.1.2.2  pgoyette     {
    261  1.1.1.1.2.2  pgoyette       if (i < nu)
    262  1.1.1.1.2.2  pgoyette         mpfr_nextabove (v);
    263  1.1.1.1.2.2  pgoyette       else
    264  1.1.1.1.2.2  pgoyette         mpfr_set_inf (v, 1);
    265  1.1.1.1.2.2  pgoyette       normal_cumulative (pb, v, rnd);
    266  1.1.1.1.2.2  pgoyette       mpfr_sub (pa, pb, pa, rnd);
    267  1.1.1.1.2.2  pgoyette 
    268  1.1.1.1.2.2  pgoyette       /* Compute z = counts[i] - num * p; t += z * z / (num * p).  2*num to
    269  1.1.1.1.2.2  pgoyette        * account for the fact the p needs to be doubled since we are
    270  1.1.1.1.2.2  pgoyette        * considering only the absolute value of the deviates. */
    271  1.1.1.1.2.2  pgoyette       mpfr_mul_ui (pa, pa, 2*num, rnd);
    272  1.1.1.1.2.2  pgoyette       mpfr_ui_sub (z, counts[i], pa, rnd);
    273  1.1.1.1.2.2  pgoyette       mpfr_sqr (z, z, rnd);
    274  1.1.1.1.2.2  pgoyette       mpfr_div (z, z, pa, rnd);
    275  1.1.1.1.2.2  pgoyette       mpfr_add (t, t, z, rnd);
    276  1.1.1.1.2.2  pgoyette       mpfr_swap (pa, pb);       /* i.e., pa = pb */
    277  1.1.1.1.2.2  pgoyette     }
    278  1.1.1.1.2.2  pgoyette 
    279  1.1.1.1.2.2  pgoyette   chisq = mpfr_get_d (t, rnd);
    280  1.1.1.1.2.2  pgoyette   chisq_prob (t, nu, t);
    281  1.1.1.1.2.2  pgoyette   Q = mpfr_get_d (t, rnd);
    282  1.1.1.1.2.2  pgoyette   if (verbose)
    283  1.1.1.1.2.2  pgoyette     {
    284  1.1.1.1.2.2  pgoyette       printf ("num = %ld, discrete (prec = %d) bins in [%.6f, %.2f], "
    285  1.1.1.1.2.2  pgoyette               "nu = %d: chisq = %.2f\n", num, prec, xmin, xmax, nu, chisq);
    286  1.1.1.1.2.2  pgoyette       if (Q < 0.05)
    287  1.1.1.1.2.2  pgoyette         printf ("    WARNING: probability (less than 5%%) = %.2e\n", Q);
    288  1.1.1.1.2.2  pgoyette     }
    289  1.1.1.1.2.2  pgoyette 
    290  1.1.1.1.2.2  pgoyette   tests_free (counts, (nu + 1) * sizeof (long));
    291  1.1.1.1.2.2  pgoyette   mpfr_clears (x, v, pa, pb, z, t, (mpfr_ptr) 0);
    292  1.1.1.1.2.2  pgoyette   return Q;
    293  1.1.1.1.2.2  pgoyette }
    294  1.1.1.1.2.2  pgoyette 
    295  1.1.1.1.2.2  pgoyette static void
    296  1.1.1.1.2.2  pgoyette run_chisq (double (*f)(long, mpfr_prec_t, int, double, double, int),
    297  1.1.1.1.2.2  pgoyette            long num, mpfr_prec_t prec, int bin,
    298  1.1.1.1.2.2  pgoyette            double xmin, double xmax, int verbose)
    299  1.1.1.1.2.2  pgoyette {
    300  1.1.1.1.2.2  pgoyette   double Q, Qcum, Qbad, Qthresh;
    301  1.1.1.1.2.2  pgoyette   int i;
    302  1.1.1.1.2.2  pgoyette 
    303  1.1.1.1.2.2  pgoyette   Qcum = 1;
    304  1.1.1.1.2.2  pgoyette   Qbad = 1.e-9;
    305  1.1.1.1.2.2  pgoyette   Qthresh = 0.01;
    306  1.1.1.1.2.2  pgoyette   for (i = 0; i < 3; ++i)
    307  1.1.1.1.2.2  pgoyette     {
    308  1.1.1.1.2.2  pgoyette       Q = (*f)(num, prec, bin, xmin, xmax, verbose);
    309  1.1.1.1.2.2  pgoyette       Qcum *= Q;
    310  1.1.1.1.2.2  pgoyette       if (Q > Qthresh)
    311  1.1.1.1.2.2  pgoyette         return;
    312  1.1.1.1.2.2  pgoyette       else if (Q < Qbad)
    313  1.1.1.1.2.2  pgoyette         {
    314  1.1.1.1.2.2  pgoyette           printf ("Error: mpfr_nrandom chi-squared failure "
    315  1.1.1.1.2.2  pgoyette                   "(prob = %.2e)\n", Q);
    316  1.1.1.1.2.2  pgoyette           exit (1);
    317  1.1.1.1.2.2  pgoyette         }
    318  1.1.1.1.2.2  pgoyette       num *= 10;
    319  1.1.1.1.2.2  pgoyette       Qthresh /= 10;
    320  1.1.1.1.2.2  pgoyette     }
    321  1.1.1.1.2.2  pgoyette   if (Qcum < Qbad)              /* Presumably this is true */
    322  1.1.1.1.2.2  pgoyette     {
    323  1.1.1.1.2.2  pgoyette       printf ("Error: mpfr_nrandom combined chi-squared failure "
    324  1.1.1.1.2.2  pgoyette               "(prob = %.2e)\n", Qcum);
    325  1.1.1.1.2.2  pgoyette       exit (1);
    326  1.1.1.1.2.2  pgoyette     }
    327  1.1.1.1.2.2  pgoyette }
    328  1.1.1.1.2.2  pgoyette 
    329  1.1.1.1.2.2  pgoyette int
    330  1.1.1.1.2.2  pgoyette main (int argc, char *argv[])
    331  1.1.1.1.2.2  pgoyette {
    332  1.1.1.1.2.2  pgoyette   long nbtests;
    333  1.1.1.1.2.2  pgoyette   int verbose;
    334  1.1.1.1.2.2  pgoyette 
    335  1.1.1.1.2.2  pgoyette   tests_start_mpfr ();
    336  1.1.1.1.2.2  pgoyette 
    337  1.1.1.1.2.2  pgoyette   verbose = 0;
    338  1.1.1.1.2.2  pgoyette   nbtests = 100000;
    339  1.1.1.1.2.2  pgoyette   if (argc > 1)
    340  1.1.1.1.2.2  pgoyette     {
    341  1.1.1.1.2.2  pgoyette       long a = atol (argv[1]);
    342  1.1.1.1.2.2  pgoyette       verbose = 1;
    343  1.1.1.1.2.2  pgoyette       if (a != 0)
    344  1.1.1.1.2.2  pgoyette         nbtests = a;
    345  1.1.1.1.2.2  pgoyette     }
    346  1.1.1.1.2.2  pgoyette 
    347  1.1.1.1.2.2  pgoyette   run_chisq (test_nrandom_chisq_cont, nbtests, 64, 60, -4, 4, verbose);
    348  1.1.1.1.2.2  pgoyette   run_chisq (test_nrandom_chisq_disc, nbtests, 64, 2, 0.0005, 3, verbose);
    349  1.1.1.1.2.2  pgoyette   run_chisq (test_nrandom_chisq_disc, nbtests, 64, 3, 0.002, 4, verbose);
    350  1.1.1.1.2.2  pgoyette   run_chisq (test_nrandom_chisq_disc, nbtests, 64, 4, 0.004, 4, verbose);
    351  1.1.1.1.2.2  pgoyette 
    352  1.1.1.1.2.2  pgoyette   tests_end_mpfr ();
    353  1.1.1.1.2.2  pgoyette   return 0;
    354  1.1.1.1.2.2  pgoyette }
    355