Tizen 2.1 base
[external/gmp.git] / tests / misc.c
1 /* Miscellaneous test program support routines.
2
3 Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP 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 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP 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 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. */
49 void
50 tests_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 }
59 void
60 tests_end (void)
61 {
62   tests_rand_end ();
63   tests_memory_end ();
64 }
65
66
67 void
68 tests_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 }
118 void
119 tests_rand_end (void)
120 {
121   RANDS_CLEAR ();
122 }
123
124
125 /* Only used if CPU calling conventions checking is available. */
126 mp_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.  */
132 void *
133 align_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. */
144 void *
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
151 void *
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
160 char *
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
172 char *
173 strtoupper (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
183 void
184 mpz_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
193 void
194 mpz_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.  */
207 mp_size_t
208 mpn_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.  */
222 mp_size_t
223 mpn_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.  */
237 mp_size_t
238 byte_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.  */
252 mp_size_t
253 byte_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
266 void
267 mpz_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
278 void
279 mpq_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
290 void
291 mpf_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. */
304 int
305 mpz_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
331 void
332 mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
333 {
334   mpz_urandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
335 }
336
337 void
338 mpz_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
345 void
346 mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
347 {
348   mpz_rrandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
349 }
350
351 void
352 mpz_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
359 void
360 mpz_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
368 mp_limb_t
369 urandom (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. */
384 void
385 call_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.  */
431 double
432 tests_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.  */
449 int
450 tests_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.  */
465 int
466 tests_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. */
486 int
487 tests_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
511 int
512 tests_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
553 jmp_buf    tests_sigfpe_target;
554
555 RETSIGTYPE
556 tests_sigfpe_handler (int sig)
557 {
558   longjmp (tests_sigfpe_target, 1);
559 }
560
561 void
562 tests_sigfpe_done (void)
563 {
564   signal (SIGFPE, SIG_DFL);
565 }