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