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