source: trunk/third/gmp/tests/misc.c @ 22254

Revision 22254, 8.1 KB checked in by ghudson, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22253, which included commits to RCS files with non-trunk default branches.
Line 
1/* Miscellaneous test program support routines.
2
3Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation; either version 2.1 of the License, or (at your
10option) any later version.
11
12The GNU MP Library is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15License for more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20MA 02111-1307, USA. */
21
22#include "config.h"
23
24#include <ctype.h>
25#include <stdio.h>
26#include <stdlib.h>     /* for getenv */
27#include <string.h>
28
29#if TIME_WITH_SYS_TIME
30# include <sys/time.h>  /* for struct timeval */
31# include <time.h>
32#else
33# if HAVE_SYS_TIME_H
34#  include <sys/time.h>
35# else
36#  include <time.h>
37# endif
38#endif
39
40#include "gmp.h"
41#include "gmp-impl.h"
42#include "tests.h"
43
44
45/* The various tests setups and final checks, collected up together. */
46void
47tests_start (void)
48{
49  tests_memory_start ();
50  tests_rand_start ();
51}
52void
53tests_end (void)
54{
55  tests_rand_end ();
56  tests_memory_end ();
57}
58
59
60void
61tests_rand_start (void)
62{
63  gmp_randstate_ptr  rands;
64  char           *perform_seed;
65  unsigned long  seed;
66
67  if (__gmp_rands_initialized)
68    {
69      printf ("Please let tests_start() initialize the global __gmp_rands.\n");
70      printf ("ie. ensure that function is called before the first use of RANDS.\n");
71      abort ();
72    }
73  rands = RANDS;
74
75  perform_seed = getenv ("GMP_CHECK_RANDOMIZE");
76  if (perform_seed != NULL)
77    {
78      seed = atoi (perform_seed);
79      if (! (seed == 0 || seed == 1))
80        {
81          printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
82          gmp_randseed_ui (rands, seed);
83        }
84      else
85        {
86#if HAVE_GETTIMEOFDAY
87          struct timeval  tv;
88          gettimeofday (&tv, NULL);
89          seed = tv.tv_sec ^ (tv.tv_usec << 12);
90#else
91          time_t  tv;
92          time (&tv);
93          seed = tv;
94#endif
95          gmp_randseed_ui (rands, seed);
96          printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed);
97        }
98      fflush (stdout);
99    }
100}
101void
102tests_rand_end (void)
103{
104  RANDS_CLEAR ();
105}
106
107
108/* Only used if CPU calling conventions checking is available. */
109mp_limb_t (*calling_conventions_function) _PROTO ((ANYARGS));
110
111
112/* Return p advanced to the next multiple of "align" bytes.  "align" must be
113   a power of 2.  Care is taken not to assume sizeof(int)==sizeof(pointer).
114   Using "unsigned long" avoids a warning on hpux.  */
115void *
116align_pointer (void *p, size_t align)
117{
118  unsigned long  d;
119  d = ((unsigned long) p) & (align-1);
120  d = (d != 0 ? align-d : 0);
121  return (void *) (((char *) p) + d);
122}
123
124
125/* Note that memory allocated with this function can never be freed, because
126   the start address of the block allocated is lost. */
127void *
128__gmp_allocate_func_aligned (size_t bytes, size_t align)
129{
130  return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align);
131}
132
133
134void *
135__gmp_allocate_or_reallocate (void *ptr, size_t oldsize, size_t newsize)
136{
137  if (ptr == NULL)
138    return (*__gmp_allocate_func) (newsize);
139  else
140    return (*__gmp_reallocate_func) (ptr, oldsize, newsize);
141}
142
143char *
144__gmp_allocate_strdup (const char *s)
145{
146  size_t  len;
147  char    *t;
148  len = strlen (s);
149  t = (*__gmp_allocate_func) (len+1);
150  memcpy (t, s, len+1);
151  return t;
152}
153
154
155char *
156strtoupper (char *s_orig)
157{
158  char  *s;
159  for (s = s_orig; *s != '\0'; s++)
160    if (isascii (*s))
161      *s = toupper (*s);
162  return s_orig;
163}
164
165
166void
167mpz_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
168{
169  ASSERT (size >= 0);
170  MPN_NORMALIZE (p, size);
171  MPZ_REALLOC (z, size);
172  MPN_COPY (PTR(z), p, size);
173  SIZ(z) = size;
174}
175
176void
177mpz_init_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
178{
179  ASSERT (size >= 0);
180
181  MPN_NORMALIZE (p, size);
182  ALLOC(z) = MAX (size, 1);
183  PTR(z) = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC(z));
184  SIZ(z) = size;
185  MPN_COPY (PTR(z), p, size);
186}
187
188
189/* Find least significant limb position where p1,size and p2,size differ.  */
190mp_size_t
191mpn_diff_lowest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
192{
193  mp_size_t  i;
194
195  for (i = 0; i < size; i++)
196    if (p1[i] != p2[i])
197      return i;
198
199  /* no differences */
200  return -1;
201}
202
203
204/* Find most significant limb position where p1,size and p2,size differ.  */
205mp_size_t
206mpn_diff_highest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
207{
208  mp_size_t  i;
209
210  for (i = size-1; i >= 0; i--)
211    if (p1[i] != p2[i])
212      return i;
213
214  /* no differences */
215  return -1;
216}
217
218
219/* Find least significant byte position where p1,size and p2,size differ.  */
220mp_size_t
221byte_diff_lowest (const void *p1, const void *p2, mp_size_t size)
222{
223  mp_size_t  i;
224
225  for (i = 0; i < size; i++)
226    if (((const char *) p1)[i] != ((const char *) p2)[i])
227      return i;
228
229  /* no differences */
230  return -1;
231}
232
233
234/* Find most significant limb position where p1,size and p2,size differ.  */
235mp_size_t
236byte_diff_highest (const void *p1, const void *p2, mp_size_t size)
237{
238  mp_size_t  i;
239
240  for (i = size-1; i >= 0; i--)
241    if (((const char *) p1)[i] != ((const char *) p2)[i])
242      return i;
243
244  /* no differences */
245  return -1;
246}
247
248
249void
250mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
251{
252  if (mpz_set_str (z, str, base) != 0)
253    {
254      fprintf (stderr, "ERROR: mpz_set_str failed\n");
255      fprintf (stderr, "   str  = \"%s\"\n", str);
256      fprintf (stderr, "   base = %d\n", base);
257      abort();
258    }
259}
260
261void
262mpq_set_str_or_abort (mpq_ptr q, const char *str, int base)
263{
264  if (mpq_set_str (q, str, base) != 0)
265    {
266      fprintf (stderr, "ERROR: mpq_set_str failed\n");
267      fprintf (stderr, "   str  = \"%s\"\n", str);
268      fprintf (stderr, "   base = %d\n", base);
269      abort();
270    }
271}
272
273void
274mpf_set_str_or_abort (mpf_ptr f, const char *str, int base)
275{
276  if (mpf_set_str (f, str, base) != 0)
277    {
278      fprintf (stderr, "ERROR mpf_set_str failed\n");
279      fprintf (stderr, "   str  = \"%s\"\n", str);
280      fprintf (stderr, "   base = %d\n", base);
281      abort();
282    }
283}
284
285
286/* Whether the absolute value of z is a power of 2. */
287int
288mpz_pow2abs_p (mpz_srcptr z)
289{
290  mp_size_t  size, i;
291  mp_srcptr  ptr;
292
293  size = SIZ (z);
294  if (size == 0)
295    return 0;  /* zero is not a power of 2 */
296  size = ABS (size);
297
298  ptr = PTR (z);
299  for (i = 0; i < size-1; i++)
300    if (ptr[i] != 0)
301      return 0;  /* non-zero low limb means not a power of 2 */
302
303  return POW2_P (ptr[i]);  /* high limb power of 2 */
304}
305
306void
307mpz_flipbit (mpz_ptr r, unsigned long bit)
308{
309  if (mpz_tstbit (r, bit))
310    mpz_clrbit (r, bit);
311  else
312    mpz_setbit (r, bit);
313}
314
315
316/* Exponentially distributed between 0 and 2^nbits-1, meaning the number of
317   bits in the result is uniformly distributed between 0 and nbits-1.
318
319   FIXME: This is not a proper exponential distribution, since the
320   probability function will have a stepped shape due to using a uniform
321   distribution after choosing how many bits.  */
322
323void
324mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
325{
326  mpz_urandomb (rop, rstate, urandom () % nbits);
327}
328
329void
330mpz_erandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
331{
332  mpz_erandomb (rop, rstate, nbits);
333  if (mpz_sgn (rop) == 0)
334    mpz_set_ui (rop, 1L);
335}
336
337void
338mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
339{
340  mpz_rrandomb (rop, rstate, urandom () % nbits);
341}
342
343void
344mpz_errandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
345{
346  mpz_errandomb (rop, rstate, nbits);
347  if (mpz_sgn (rop) == 0)
348    mpz_set_ui (rop, 1L);
349}
350
351void
352mpz_negrandom (mpz_ptr rop, gmp_randstate_t rstate)
353{
354  mp_limb_t  n;
355  _gmp_rand (&n, rstate, 1);
356  if (n != 0)
357    mpz_neg (rop, rop);
358}
359
360mp_limb_t
361urandom (void)
362{
363#if GMP_NAIL_BITS == 0
364  mp_limb_t  n;
365  _gmp_rand (&n, RANDS, BITS_PER_MP_LIMB);
366  return n;
367#else
368  mp_limb_t n[2];
369  _gmp_rand (n, RANDS, BITS_PER_MP_LIMB);
370  return n[0] + (n[1] << GMP_NUMB_BITS);
371#endif
372}
Note: See TracBrowser for help on using the repository browser.