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