xref: /netbsd-src/external/lgpl3/mpc/dist/tests/random.c (revision 39f28e1e142c5bfb6be935a49cb55e2287fec7ea)
1 /* random.c -- Handle seed for random numbers.
2 
3 // Copyright (C) 2008, 2009, 2010, 2011, 2012 INRIA
4 
5 This file is part of GNU MPC.
6 
7 GNU MPC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/ .
19 */
20 
21 /* Put test_start at the beginning of your test function and
22    test_end at the end.
23    These are an adaptation of those of MPFR. */
24 
25 #include "config.h"
26 #include <stdlib.h>
27 #include "mpc-tests.h"
28 
29 
30 #ifdef TIME_WITH_SYS_TIME
31 # include <sys/time.h>
32 # include <time.h>
33 #else
34 # ifdef HAVE_SYS_TIME_H
35 #  include <sys/time.h>
36 # else
37 #  include <time.h>
38 # endif
39 #endif
40 
41 gmp_randstate_t  rands;
42 static char      rands_initialized;
43 
44 void
test_start(void)45 test_start (void)
46 {
47   char *environment_seed;
48   unsigned long seed;
49 
50   if (rands_initialized)
51     {
52       fprintf (stderr,
53                "Put test_start at the beginning of your test function.\n");
54       exit (1);
55     }
56 
57   gmp_randinit_default (rands);
58   rands_initialized = 1;
59 
60   environment_seed = getenv ("GMP_CHECK_RANDOMIZE");
61   if (environment_seed == NULL)
62       gmp_randseed_ui (rands, 0xfac11e);
63   else
64     {
65       seed = (unsigned long int) atoi (environment_seed);
66       if (seed == 0 || seed == 1)
67         {
68 #if defined HAVE_GETTIMEOFDAY
69           struct timeval  tv;
70           gettimeofday (&tv, NULL);
71           seed = (unsigned long int) (tv.tv_sec + tv.tv_usec);
72 #else
73           time_t  tv;
74           time (&tv);
75           seed = (unsigned long int) tv;
76 #endif
77           gmp_randseed_ui (rands, seed);
78           printf ("Seed GMP_CHECK_RANDOMIZE=%lu "
79                   "(include this in bug reports)\n", seed);
80         }
81       else
82         {
83           printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
84           gmp_randseed_ui (rands, seed);
85         }
86     }
87 
88   /* some tests assume a given exponent range for MPFR, thus since the
89      default exponent range for MPFR is not specified, we hard-code it */
90   mpfr_set_emax (1073741821);
91   mpfr_set_emin (-1073741821);
92 }
93 
94 void
test_end(void)95 test_end (void)
96 {
97   if (rands_initialized)
98     {
99       rands_initialized = 0;
100       gmp_randclear (rands);
101     }
102   mpfr_free_cache ();
103 }
104 
105 /* Set z to a non zero value random value with absolute values of Re(z) and
106    Im(z) either zero (but not both in the same time) or otherwise greater than
107    or equal to 2^{emin-1} and less than 2^emax.
108    Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
109    The result has one zero part (but never the two of them) with probability
110    equal to ZERO_PROBABILITY / 256.
111 */
112 void
test_default_random(mpc_ptr z,mpfr_exp_t emin,mpfr_exp_t emax,unsigned int negative_probability,unsigned int zero_probability)113 test_default_random (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
114                      unsigned int negative_probability,
115                      unsigned int zero_probability)
116 {
117   const unsigned long range = (unsigned long int) (emax - emin) + 1;
118   unsigned long r;
119 
120   if (!rands_initialized)
121     {
122       fprintf (stderr,
123                "Put test_start at the beginning of your test function.\n");
124       exit (1);
125     }
126 
127   do
128     {
129       mpc_urandom (z, rands);
130     } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
131 
132   if (zero_probability > 256)
133     zero_probability = 256;
134   r = gmp_urandomb_ui (rands, 19);
135   if ((r & 0x1FF) < zero_probability
136       || ((r >> 9) & 0x1FF) < zero_probability)
137     {
138       int zero_re_p = (r & 0x1FF) < zero_probability;
139       int zero_im_p = ((r >> 9) & 0x1FF) < zero_probability;
140 
141       if (zero_re_p && zero_im_p)
142         {
143           /* we just want one zero part. */
144           zero_re_p = (r >> 18) & 1;
145           zero_im_p = !zero_re_p;
146         }
147       if (zero_re_p)
148         mpfr_set_ui (mpc_realref (z), 0, MPFR_RNDN);
149       if (zero_im_p)
150         mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN);
151     }
152   if (!mpfr_zero_p (mpc_realref (z)))
153     mpfr_set_exp (mpc_realref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
154 
155   if (!mpfr_zero_p (mpc_imagref (z)))
156     mpfr_set_exp (mpc_imagref (z), (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
157 
158   if (negative_probability > 256)
159     negative_probability = 256;
160   r = gmp_urandomb_ui (rands, 16);
161   if ((r & 0xFF) < negative_probability)
162     mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
163   if (((r>>8) & 0xFF) < negative_probability)
164     mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);
165 }
166 
167 /* Set n to a non zero value random value with absolute values less than
168    2^emax.
169 
170    n is negative with probability equal to NEGATIVE_PROBABILITY / 256.
171 */
test_random_si(long int * n,unsigned long emax,unsigned int negative_probability)172 void test_random_si (long int *n, unsigned long emax,
173                      unsigned int negative_probability)
174 {
175   unsigned long r;
176 
177   if (!rands_initialized)
178     {
179       fprintf (stderr,
180                "Put test_start at the beginning of your test function.\n");
181       exit (1);
182     }
183 
184   do
185     {
186       *n = gmp_urandomb_ui (rands, emax);
187     } while (*n == 0);
188 
189   if (negative_probability > 256)
190     negative_probability = 256;
191   r = gmp_urandomb_ui (rands, 8);
192   if ((r & 0xFF) < negative_probability)
193     *n = -(*n);
194 }
195 
196 /* Set x to a non zero value random value with absolute values greater than
197    or equal to 2^{emin-1} and less than 2^emax.
198 
199    x is negative with probability equal to NEGATIVE_PROBABILITY / 256.
200 */
201 void
test_random_mpfr(mpfr_ptr x,mpfr_exp_t emin,mpfr_exp_t emax,unsigned int negative_probability)202 test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
203                   unsigned int negative_probability)
204 {
205   const unsigned long range = (unsigned long int) (emax - emin) + 1;
206   unsigned long r;
207 
208   if (!rands_initialized)
209     {
210       fprintf (stderr,
211                "Put test_start at the beginning of your test function.\n");
212       exit (1);
213     }
214 
215   do
216     {
217       mpfr_urandom (x, rands, MPFR_RNDN);
218     } while (mpfr_zero_p (x));
219 
220   mpfr_set_exp (x, (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
221   if (negative_probability > 256)
222     negative_probability = 256;
223   r = gmp_urandomb_ui (rands, 8);
224   if ((r & 0xFF) < negative_probability)
225     mpfr_neg (x, x, MPFR_RNDN);
226 }
227 
228 /* Set x to a non zero value random value.
229    x is negative with probability equal to NEGATIVE_PROBABILITY / 256.
230 */
231 void
test_random_d(double * x,unsigned int negative_probability)232 test_random_d (double *x, unsigned int negative_probability)
233 {
234   MPFR_DECL_INIT (mpfr_x, 53);
235   test_random_mpfr (mpfr_x, -1022, 1022, negative_probability);
236   *x = mpfr_get_d (mpfr_x, MPFR_RNDN);
237 }
238 
239 /* Set z to a non zero value random value with absolute values of Re(z) and
240    Im(z) greater than or equal to 2^{emin-1} and less than 2^emax.
241 
242    Each part is negative with probability equal to NEGATIVE_PROBABILITY / 256.
243 */
244 void
test_random_mpc(mpc_ptr z,mpfr_exp_t emin,mpfr_exp_t emax,unsigned int negative_probability)245 test_random_mpc (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
246                  unsigned int negative_probability)
247 {
248   const unsigned long range = (unsigned long int) (emax - emin) + 1;
249   unsigned long r;
250 
251   if (!rands_initialized)
252     {
253       fprintf (stderr,
254                "Put test_start at the beginning of your test function.\n");
255       exit (1);
256     }
257 
258   do
259     {
260       mpc_urandom (z, rands);
261     } while (mpfr_zero_p (mpc_realref (z)) || mpfr_zero_p (mpc_imagref (z)));
262 
263     mpfr_set_exp (mpc_realref (z),
264                   (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
265 
266     mpfr_set_exp (mpc_imagref (z),
267                   (mpfr_exp_t) gmp_urandomm_ui (rands, range) + emin);
268 
269   if (negative_probability > 256)
270     negative_probability = 256;
271   r = gmp_urandomb_ui (rands, 16);
272   if ((r & 0xFF) < negative_probability)
273     mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
274   if (((r>>8) & 0xFF) < negative_probability)
275     mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);
276 }
277