github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/misc.c (about)

     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
    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
    74  tests_end (void)
    75  {
    76    tests_rand_end ();
    77    tests_memory_end ();
    78  }
    79  
    80  
    81  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
   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 *
   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 *
   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 *
   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 *
   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 *
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   570  tests_sigfpe_handler (int sig)
   571  {
   572    longjmp (tests_sigfpe_target, 1);
   573  }
   574  
   575  void
   576  tests_sigfpe_done (void)
   577  {
   578    signal (SIGFPE, SIG_DFL);
   579  }