1/* Miscellaneous test program support routines.
2
3Copyright 2000, 2001, 2002, 2003, 2005 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 3 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.  If not, see http://www.gnu.org/licenses/.  */
19
20#include "config.h"
21
22#include <ctype.h>
23#include <signal.h>
24#include <stdio.h>
25#include <stdlib.h>     /* for getenv */
26#include <string.h>
27
28#if HAVE_FLOAT_H
29#include <float.h>      /* for DBL_MANT_DIG */
30#endif
31
32#if TIME_WITH_SYS_TIME
33# include <sys/time.h>  /* for struct timeval */
34# include <time.h>
35#else
36# if HAVE_SYS_TIME_H
37#  include <sys/time.h>
38# else
39#  include <time.h>
40# endif
41#endif
42
43#include "gmp.h"
44#include "gmp-impl.h"
45#include "tests.h"
46
47
48/* The various tests setups and final checks, collected up together. */
49void
50tests_start (void)
51{
52  /* don't buffer, so output is not lost if a test causes a segv etc */
53  setbuf (stdout, NULL);
54  setbuf (stderr, NULL);
55
56  tests_memory_start ();
57  tests_rand_start ();
58}
59void
60tests_end (void)
61{
62  tests_rand_end ();
63  tests_memory_end ();
64}
65
66
67void
68tests_rand_start (void)
69{
70  gmp_randstate_ptr  rands;
71  char           *perform_seed;
72  unsigned long  seed;
73
74  if (__gmp_rands_initialized)
75    {
76      printf ("Please let tests_start() initialize the global __gmp_rands.\n");
77      printf ("ie. ensure that function is called before the first use of RANDS.\n");
78      abort ();
79    }
80
81  gmp_randinit_default (__gmp_rands);
82  __gmp_rands_initialized = 1;
83  rands = __gmp_rands;
84
85  perform_seed = getenv ("GMP_CHECK_RANDOMIZE");
86  if (perform_seed != NULL)
87    {
88#ifdef HAVE_STRTOUL
89      seed = strtoul (perform_seed, 0, 0);
90#else
91      /* This will not work right for seeds >= 2^31 on 64-bit machines.
92	 Perhaps use atol unconditionally?  Is that ubiquitous?  */
93      seed = atoi (perform_seed);
94#endif
95      if (! (seed == 0 || seed == 1))
96        {
97          printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
98          gmp_randseed_ui (rands, seed);
99        }
100      else
101        {
102#if HAVE_GETTIMEOFDAY
103          struct timeval  tv;
104          gettimeofday (&tv, NULL);
105          seed = tv.tv_sec ^ (tv.tv_usec << 12);
106	  seed &= 0xffffffff;
107#else
108          time_t  tv;
109          time (&tv);
110          seed = tv;
111#endif
112          gmp_randseed_ui (rands, seed);
113          printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed);
114        }
115      fflush (stdout);
116    }
117}
118void
119tests_rand_end (void)
120{
121  RANDS_CLEAR ();
122}
123
124
125/* Only used if CPU calling conventions checking is available. */
126mp_limb_t (*calling_conventions_function) __GMP_PROTO ((ANYARGS));
127
128
129/* Return p advanced to the next multiple of "align" bytes.  "align" must be
130   a power of 2.  Care is taken not to assume sizeof(int)==sizeof(pointer).
131   Using "unsigned long" avoids a warning on hpux.  */
132void *
133align_pointer (void *p, size_t align)
134{
135  gmp_intptr_t d;
136  d = ((gmp_intptr_t) p) & (align-1);
137  d = (d != 0 ? align-d : 0);
138  return (void *) (((char *) p) + d);
139}
140
141
142/* Note that memory allocated with this function can never be freed, because
143   the start address of the block allocated is lost. */
144void *
145__gmp_allocate_func_aligned (size_t bytes, size_t align)
146{
147  return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align);
148}
149
150
151void *
152__gmp_allocate_or_reallocate (void *ptr, size_t oldsize, size_t newsize)
153{
154  if (ptr == NULL)
155    return (*__gmp_allocate_func) (newsize);
156  else
157    return (*__gmp_reallocate_func) (ptr, oldsize, newsize);
158}
159
160char *
161__gmp_allocate_strdup (const char *s)
162{
163  size_t  len;
164  char    *t;
165  len = strlen (s);
166  t = (*__gmp_allocate_func) (len+1);
167  memcpy (t, s, len+1);
168  return t;
169}
170
171
172char *
173strtoupper (char *s_orig)
174{
175  char  *s;
176  for (s = s_orig; *s != '\0'; s++)
177    if (isascii (*s))
178      *s = toupper (*s);
179  return s_orig;
180}
181
182
183void
184mpz_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
185{
186  ASSERT (size >= 0);
187  MPN_NORMALIZE (p, size);
188  MPZ_REALLOC (z, size);
189  MPN_COPY (PTR(z), p, size);
190  SIZ(z) = size;
191}
192
193void
194mpz_init_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
195{
196  ASSERT (size >= 0);
197
198  MPN_NORMALIZE (p, size);
199  ALLOC(z) = MAX (size, 1);
200  PTR(z) = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC(z));
201  SIZ(z) = size;
202  MPN_COPY (PTR(z), p, size);
203}
204
205
206/* Find least significant limb position where p1,size and p2,size differ.  */
207mp_size_t
208mpn_diff_lowest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
209{
210  mp_size_t  i;
211
212  for (i = 0; i < size; i++)
213    if (p1[i] != p2[i])
214      return i;
215
216  /* no differences */
217  return -1;
218}
219
220
221/* Find most significant limb position where p1,size and p2,size differ.  */
222mp_size_t
223mpn_diff_highest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
224{
225  mp_size_t  i;
226
227  for (i = size-1; i >= 0; i--)
228    if (p1[i] != p2[i])
229      return i;
230
231  /* no differences */
232  return -1;
233}
234
235
236/* Find least significant byte position where p1,size and p2,size differ.  */
237mp_size_t
238byte_diff_lowest (const void *p1, const void *p2, mp_size_t size)
239{
240  mp_size_t  i;
241
242  for (i = 0; i < size; i++)
243    if (((const char *) p1)[i] != ((const char *) p2)[i])
244      return i;
245
246  /* no differences */
247  return -1;
248}
249
250
251/* Find most significant limb position where p1,size and p2,size differ.  */
252mp_size_t
253byte_diff_highest (const void *p1, const void *p2, mp_size_t size)
254{
255  mp_size_t  i;
256
257  for (i = size-1; i >= 0; i--)
258    if (((const char *) p1)[i] != ((const char *) p2)[i])
259      return i;
260
261  /* no differences */
262  return -1;
263}
264
265
266void
267mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
268{
269  if (mpz_set_str (z, str, base) != 0)
270    {
271      fprintf (stderr, "ERROR: mpz_set_str failed\n");
272      fprintf (stderr, "   str  = \"%s\"\n", str);
273      fprintf (stderr, "   base = %d\n", base);
274      abort();
275    }
276}
277
278void
279mpq_set_str_or_abort (mpq_ptr q, const char *str, int base)
280{
281  if (mpq_set_str (q, str, base) != 0)
282    {
283      fprintf (stderr, "ERROR: mpq_set_str failed\n");
284      fprintf (stderr, "   str  = \"%s\"\n", str);
285      fprintf (stderr, "   base = %d\n", base);
286      abort();
287    }
288}
289
290void
291mpf_set_str_or_abort (mpf_ptr f, const char *str, int base)
292{
293  if (mpf_set_str (f, str, base) != 0)
294    {
295      fprintf (stderr, "ERROR mpf_set_str failed\n");
296      fprintf (stderr, "   str  = \"%s\"\n", str);
297      fprintf (stderr, "   base = %d\n", base);
298      abort();
299    }
300}
301
302
303/* Whether the absolute value of z is a power of 2. */
304int
305mpz_pow2abs_p (mpz_srcptr z)
306{
307  mp_size_t  size, i;
308  mp_srcptr  ptr;
309
310  size = SIZ (z);
311  if (size == 0)
312    return 0;  /* zero is not a power of 2 */
313  size = ABS (size);
314
315  ptr = PTR (z);
316  for (i = 0; i < size-1; i++)
317    if (ptr[i] != 0)
318      return 0;  /* non-zero low limb means not a power of 2 */
319
320  return POW2_P (ptr[i]);  /* high limb power of 2 */
321}
322
323
324/* Exponentially distributed between 0 and 2^nbits-1, meaning the number of
325   bits in the result is uniformly distributed between 0 and nbits-1.
326
327   FIXME: This is not a proper exponential distribution, since the
328   probability function will have a stepped shape due to using a uniform
329   distribution after choosing how many bits.  */
330
331void
332mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
333{
334  mpz_urandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
335}
336
337void
338mpz_erandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
339{
340  mpz_erandomb (rop, rstate, nbits);
341  if (mpz_sgn (rop) == 0)
342    mpz_set_ui (rop, 1L);
343}
344
345void
346mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
347{
348  mpz_rrandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
349}
350
351void
352mpz_errandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
353{
354  mpz_errandomb (rop, rstate, nbits);
355  if (mpz_sgn (rop) == 0)
356    mpz_set_ui (rop, 1L);
357}
358
359void
360mpz_negrandom (mpz_ptr rop, gmp_randstate_t rstate)
361{
362  mp_limb_t  n;
363  _gmp_rand (&n, rstate, 1);
364  if (n != 0)
365    mpz_neg (rop, rop);
366}
367
368mp_limb_t
369urandom (void)
370{
371#if GMP_NAIL_BITS == 0
372  mp_limb_t  n;
373  _gmp_rand (&n, RANDS, GMP_LIMB_BITS);
374  return n;
375#else
376  mp_limb_t n[2];
377  _gmp_rand (n, RANDS, GMP_LIMB_BITS);
378  return n[0] + (n[1] << GMP_NUMB_BITS);
379#endif
380}
381
382
383/* Call (*func)() with various random number generators. */
384void
385call_rand_algs (void (*func) __GMP_PROTO ((const char *, gmp_randstate_ptr)))
386{
387  gmp_randstate_t  rstate;
388  mpz_t            a;
389
390  mpz_init (a);
391
392  gmp_randinit_default (rstate);
393  (*func) ("gmp_randinit_default", rstate);
394  gmp_randclear (rstate);
395
396  gmp_randinit_mt (rstate);
397  (*func) ("gmp_randinit_mt", rstate);
398  gmp_randclear (rstate);
399
400  gmp_randinit_lc_2exp_size (rstate, 8L);
401  (*func) ("gmp_randinit_lc_2exp_size 8", rstate);
402  gmp_randclear (rstate);
403
404  gmp_randinit_lc_2exp_size (rstate, 16L);
405  (*func) ("gmp_randinit_lc_2exp_size 16", rstate);
406  gmp_randclear (rstate);
407
408  gmp_randinit_lc_2exp_size (rstate, 128L);
409  (*func) ("gmp_randinit_lc_2exp_size 128", rstate);
410  gmp_randclear (rstate);
411
412  /* degenerate always zeros */
413  mpz_set_ui (a, 0L);
414  gmp_randinit_lc_2exp (rstate, a, 0L, 8L);
415  (*func) ("gmp_randinit_lc_2exp a=0 c=0 m=8", rstate);
416  gmp_randclear (rstate);
417
418  /* degenerate always FFs */
419  mpz_set_ui (a, 0L);
420  gmp_randinit_lc_2exp (rstate, a, 0xFFL, 8L);
421  (*func) ("gmp_randinit_lc_2exp a=0 c=0xFF m=8", rstate);
422  gmp_randclear (rstate);
423
424  mpz_clear (a);
425}
426
427
428/* Return +infinity if available, or 0 if not.
429   We don't want to use libm, so INFINITY or other system values are not
430   used here.  */
431double
432tests_infinity_d (void)
433{
434#if _GMP_IEEE_FLOATS
435  union ieee_double_extract x;
436  x.s.exp = 2047;
437  x.s.manl = 0;
438  x.s.manh = 0;
439  x.s.sig = 0;
440  return x.d;
441#else
442  return 0;
443#endif
444}
445
446
447/* Return non-zero if d is an infinity (either positive or negative).
448   Don't want libm, so don't use isinf() or other system tests.  */
449int
450tests_isinf (double d)
451{
452#if _GMP_IEEE_FLOATS
453  union ieee_double_extract x;
454  x.d = d;
455  return (x.s.exp == 2047 && x.s.manl == 0 && x.s.manh == 0);
456#else
457  return 0;
458#endif
459}
460
461
462/* Set the hardware floating point rounding mode.  Same mode values as mpfr,
463   namely 0=nearest, 1=tozero, 2=up, 3=down.  Return 1 if successful, 0 if
464   not.  */
465int
466tests_hardware_setround (int mode)
467{
468#if HAVE_HOST_CPU_FAMILY_x86
469  int  rc;
470  switch (mode) {
471  case 0: rc = 0; break;  /* nearest */
472  case 1: rc = 3; break;  /* tozero  */
473  case 2: rc = 2; break;  /* up      */
474  case 3: rc = 1; break;  /* down    */
475  default:
476    return 0;
477  }
478  x86_fldcw ((x86_fstcw () & ~0xC00) | (rc << 10));
479  return 1;
480#endif
481
482  return 0;
483}
484
485/* Return the hardware floating point rounding mode, or -1 if unknown. */
486int
487tests_hardware_getround (void)
488{
489#if HAVE_HOST_CPU_FAMILY_x86
490  switch ((x86_fstcw () & ~0xC00) >> 10) {
491  case 0: return 0; break;  /* nearest */
492  case 1: return 3; break;  /* down    */
493  case 2: return 2; break;  /* up      */
494  case 3: return 1; break;  /* tozero  */
495  }
496#endif
497
498  return -1;
499}
500
501
502/* tests_dbl_mant_bits() determines by experiment the number of bits in the
503   mantissa of a "double".  If it's not possible to find a value (perhaps
504   due to the compiler optimizing too aggressively), then return 0.
505
506   This code is used rather than DBL_MANT_DIG from <float.h> since ancient
507   systems like SunOS don't have that file, and since one GNU/Linux ARM
508   system was seen where the float emulation seemed to have only 32 working
509   bits, not the 53 float.h claimed.  */
510
511int
512tests_dbl_mant_bits (void)
513{
514  static int n = -1;
515  volatile double x, y, d;
516
517  if (n != -1)
518    return n;
519
520  n = 1;
521  x = 2.0;
522  for (;;)
523    {
524      /* see if 2^(n+1)+1 can be formed without rounding, if so then
525         continue, if not then "n" is the answer */
526      y = x + 1.0;
527      d = y - x;
528      if (d != 1.0)
529        {
530#if defined (DBL_MANT_DIG) && DBL_RADIX == 2
531          if (n != DBL_MANT_DIG)
532            printf ("Warning, tests_dbl_mant_bits got %d but DBL_MANT_DIG says %d\n", n, DBL_MANT_DIG);
533#endif
534          break;
535        }
536
537      x *= 2;
538      n++;
539
540      if (n > 1000)
541        {
542          printf ("Oops, tests_dbl_mant_bits can't determine mantissa size\n");
543          n = 0;
544          break;
545        }
546    }
547  return n;
548}
549
550
551/* See tests_setjmp_sigfpe in tests.h. */
552
553jmp_buf    tests_sigfpe_target;
554
555RETSIGTYPE
556tests_sigfpe_handler (int sig)
557{
558  longjmp (tests_sigfpe_target, 1);
559}
560
561void
562tests_sigfpe_done (void)
563{
564  signal (SIGFPE, SIG_DFL);
565}
566