ed31476e354860737a9ded7eefa22eedb7caba64
[platform/upstream/mpc.git] / tests / random.c
1 /* Handle seed for random numbers.
2
3 Copyright (C) 2008, 2009 Philippe Th\'eveny, Paul Zimmermann, Andreas Enge
4
5 This file is part of the MPC Library.
6
7 The MPC Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or (at your
10 option) any later version.
11
12 The MPC Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the MPC Library; see the file COPYING.LIB.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 MA 02111-1307, USA. */
21
22 /* Put test_start at the beginning of your test function and
23    test_end at the end.
24    These are an adaptation of those of MPFR. */
25
26 #include <stdlib.h>
27
28 #include "mpc-tests.h"
29
30 #include "config.h"
31
32 #ifdef TIME_WITH_SYS_TIME
33 # include <sys/time.h>
34 # include <time.h>
35 #else
36 # ifdef HAVE_SYS_TIME_H
37 #  include <sys/time.h>
38 # else
39 #  include <time.h>
40 # endif
41 #endif
42
43 gmp_randstate_t  rands;
44 char             rands_initialized;
45
46 void
47 test_start (void)
48 {
49   char *environment_seed;
50   unsigned long seed;
51
52   tests_memory_start ();
53
54   if (rands_initialized)
55     {
56       fprintf (stderr,
57                "Put test_start at the beginning of your test function.\n");
58       exit (1);
59     }
60
61   gmp_randinit_default (rands);
62   rands_initialized = 1;
63
64   environment_seed = getenv ("GMP_CHECK_RANDOMIZE");
65   if (environment_seed == NULL)
66       gmp_randseed_ui (rands, 0xfac11e);
67   else
68     {
69       seed = atoi (environment_seed);
70       if (seed == 0 || seed == 1)
71         {
72 #if HAVE_GETTIMEOFDAY
73           struct timeval  tv;
74           gettimeofday (&tv, NULL);
75           seed = tv.tv_sec + tv.tv_usec;
76 #else
77           time_t  tv;
78           time (&tv);
79           seed = tv;
80 #endif
81           gmp_randseed_ui (rands, seed);
82           printf ("Seed GMP_CHECK_RANDOMIZE=%lu "
83                   "(include this in bug reports)\n", seed);
84         }
85       else
86         {
87           printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
88           gmp_randseed_ui (rands, seed);
89         }
90     }
91 }
92
93 void
94 test_end (void)
95 {
96   if (rands_initialized)
97     {
98       rands_initialized = 0;
99       gmp_randclear (rands);
100     }
101   mpfr_free_cache ();
102   tests_memory_end ();
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
113 test_default_random (mpc_ptr z, mp_exp_t emin, mp_exp_t emax,
114                      unsigned int negative_probability,
115                      unsigned int zero_probability)
116 {
117   const unsigned long range = (long)emax - (long)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_RE (z)) || mpfr_zero_p (MPC_IM (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_RE (z), 0, GMP_RNDN);
149       if (zero_im_p)
150         mpfr_set_ui (MPC_IM (z), 0, GMP_RNDN);
151     }
152   if (!mpfr_zero_p (MPC_RE (z)))
153     mpfr_set_exp (MPC_RE (z), (mp_exp_t) gmp_urandomm_ui (rands, range) + emin);
154
155   if (!mpfr_zero_p (MPC_IM (z)))
156     mpfr_set_exp (MPC_IM (z), (mp_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_RE (z), MPC_RE (z), GMP_RNDN);
163   if (((r>>8) & 0xFF) < negative_probability)
164     mpfr_neg (MPC_IM (z), MPC_IM (z), GMP_RNDN);
165 }