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

     1  /* Test mpn_get_d.
     2  
     3  Copyright 2002-2004 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 <setjmp.h>
    23  #include <signal.h>
    24  #include <stdio.h>
    25  #include <stdlib.h>
    26  
    27  #include "gmp.h"
    28  #include "gmp-impl.h"
    29  #include "tests.h"
    30  
    31  
    32  #ifndef _GMP_IEEE_FLOATS
    33  #define _GMP_IEEE_FLOATS 0
    34  #endif
    35  
    36  
    37  /* Exercise various 2^n values, with various exponents and positive and
    38     negative.  */
    39  void
    40  check_onebit (void)
    41  {
    42    static const int bit_table[] = {
    43      0, 1, 2, 3,
    44      GMP_NUMB_BITS - 2, GMP_NUMB_BITS - 1,
    45      GMP_NUMB_BITS,
    46      GMP_NUMB_BITS + 1, GMP_NUMB_BITS + 2,
    47      2 * GMP_NUMB_BITS - 2, 2 * GMP_NUMB_BITS - 1,
    48      2 * GMP_NUMB_BITS,
    49      2 * GMP_NUMB_BITS + 1, 2 * GMP_NUMB_BITS + 2,
    50      3 * GMP_NUMB_BITS - 2, 3 * GMP_NUMB_BITS - 1,
    51      3 * GMP_NUMB_BITS,
    52      3 * GMP_NUMB_BITS + 1, 3 * GMP_NUMB_BITS + 2,
    53      4 * GMP_NUMB_BITS - 2, 4 * GMP_NUMB_BITS - 1,
    54      4 * GMP_NUMB_BITS,
    55      4 * GMP_NUMB_BITS + 1, 4 * GMP_NUMB_BITS + 2,
    56      5 * GMP_NUMB_BITS - 2, 5 * GMP_NUMB_BITS - 1,
    57      5 * GMP_NUMB_BITS,
    58      5 * GMP_NUMB_BITS + 1, 5 * GMP_NUMB_BITS + 2,
    59      6 * GMP_NUMB_BITS - 2, 6 * GMP_NUMB_BITS - 1,
    60      6 * GMP_NUMB_BITS,
    61      6 * GMP_NUMB_BITS + 1, 6 * GMP_NUMB_BITS + 2,
    62    };
    63    static const int exp_table[] = {
    64      0, -100, -10, -1, 1, 10, 100,
    65    };
    66  
    67    /* FIXME: It'd be better to base this on the float format. */
    68  #if defined (__vax) || defined (__vax__)
    69    int     limit = 127;  /* vax fp numbers have limited range */
    70  #else
    71    int     limit = 511;
    72  #endif
    73  
    74    int        bit_i, exp_i, i;
    75    double     got, want;
    76    mp_size_t  nsize, sign;
    77    long       bit, exp, want_bit;
    78    mp_limb_t  np[20];
    79  
    80    for (bit_i = 0; bit_i < numberof (bit_table); bit_i++)
    81      {
    82        bit = bit_table[bit_i];
    83  
    84        nsize = BITS_TO_LIMBS (bit+1);
    85        refmpn_zero (np, nsize);
    86        np[bit/GMP_NUMB_BITS] = CNST_LIMB(1) << (bit % GMP_NUMB_BITS);
    87  
    88        for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
    89          {
    90            exp = exp_table[exp_i];
    91  
    92            want_bit = bit + exp;
    93            if (want_bit >= limit || want_bit <= -limit)
    94              continue;
    95  
    96            want = 1.0;
    97            for (i = 0; i < want_bit; i++)
    98              want *= 2.0;
    99            for (i = 0; i > want_bit; i--)
   100              want *= 0.5;
   101  
   102            for (sign = 0; sign >= -1; sign--, want = -want)
   103              {
   104                got = mpn_get_d (np, nsize, sign, exp);
   105                if (got != want)
   106                  {
   107                    printf    ("mpn_get_d wrong on 2^n\n");
   108                    printf    ("   bit      %ld\n", bit);
   109                    printf    ("   exp      %ld\n", exp);
   110                    printf    ("   want_bit %ld\n", want_bit);
   111                    printf    ("   sign     %ld\n", (long) sign);
   112                    mpn_trace ("   n        ", np, nsize);
   113                    printf    ("   nsize    %ld\n", (long) nsize);
   114                    d_trace   ("   want     ", want);
   115                    d_trace   ("   got      ", got);
   116                    abort();
   117                  }
   118              }
   119          }
   120      }
   121  }
   122  
   123  
   124  /* Exercise values 2^n+1, while such a value fits the mantissa of a double. */
   125  void
   126  check_twobit (void)
   127  {
   128    int        i, mant_bits;
   129    double     got, want;
   130    mp_size_t  nsize, sign;
   131    mp_ptr     np;
   132  
   133    mant_bits = tests_dbl_mant_bits ();
   134    if (mant_bits == 0)
   135      return;
   136  
   137    np = refmpn_malloc_limbs (BITS_TO_LIMBS (mant_bits));
   138    want = 3.0;
   139    for (i = 1; i < mant_bits; i++)
   140      {
   141        nsize = BITS_TO_LIMBS (i+1);
   142        refmpn_zero (np, nsize);
   143        np[i/GMP_NUMB_BITS] = CNST_LIMB(1) << (i % GMP_NUMB_BITS);
   144        np[0] |= 1;
   145  
   146        for (sign = 0; sign >= -1; sign--)
   147          {
   148            got = mpn_get_d (np, nsize, sign, 0);
   149            if (got != want)
   150              {
   151                printf    ("mpn_get_d wrong on 2^%d + 1\n", i);
   152                printf    ("   sign     %ld\n", (long) sign);
   153                mpn_trace ("   n        ", np, nsize);
   154                printf    ("   nsize    %ld\n", (long) nsize);
   155                d_trace   ("   want     ", want);
   156                d_trace   ("   got      ", got);
   157                abort();
   158              }
   159            want = -want;
   160          }
   161  
   162        want = 2.0 * want - 1.0;
   163      }
   164  
   165    free (np);
   166  }
   167  
   168  
   169  /* Expect large negative exponents to underflow to 0.0.
   170     Some systems might have hardware traps for such an underflow (though
   171     usually it's not the default), so watch out for SIGFPE. */
   172  void
   173  check_underflow (void)
   174  {
   175    static const long exp_table[] = {
   176      -999999L, LONG_MIN,
   177    };
   178    static const mp_limb_t  np[1] = { 1 };
   179  
   180    static long exp;
   181    mp_size_t  nsize, sign;
   182    double     got;
   183    int        exp_i;
   184  
   185    nsize = numberof (np);
   186  
   187    if (tests_setjmp_sigfpe() == 0)
   188      {
   189        for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
   190          {
   191            exp = exp_table[exp_i];
   192  
   193            for (sign = 0; sign >= -1; sign--)
   194              {
   195                got = mpn_get_d (np, nsize, sign, exp);
   196                if (got != 0.0)
   197                  {
   198                    printf  ("mpn_get_d wrong, didn't get 0.0 on underflow\n");
   199                    printf  ("  nsize    %ld\n", (long) nsize);
   200                    printf  ("  exp      %ld\n", exp);
   201                    printf  ("  sign     %ld\n", (long) sign);
   202                    d_trace ("  got      ", got);
   203                    abort ();
   204                  }
   205              }
   206          }
   207      }
   208    else
   209      {
   210        printf ("Warning, underflow to zero tests skipped due to SIGFPE (exp=%ld)\n", exp);
   211      }
   212    tests_sigfpe_done ();
   213  }
   214  
   215  
   216  /* Expect large values to result in +/-inf, on IEEE systems. */
   217  void
   218  check_inf (void)
   219  {
   220    static const long exp_table[] = {
   221      999999L, LONG_MAX,
   222    };
   223    static const mp_limb_t  np[4] = { 1, 1, 1, 1 };
   224    long       exp;
   225    mp_size_t  nsize, sign, got_sign;
   226    double     got;
   227    int        exp_i;
   228  
   229    if (! _GMP_IEEE_FLOATS)
   230      return;
   231  
   232    for (nsize = 1; nsize <= numberof (np); nsize++)
   233      {
   234        for (exp_i = 0; exp_i < numberof (exp_table); exp_i++)
   235          {
   236            exp = exp_table[exp_i];
   237  
   238            for (sign = 0; sign >= -1; sign--)
   239              {
   240                got = mpn_get_d (np, nsize, sign, exp);
   241                got_sign = (got >= 0 ? 0 : -1);
   242                if (! tests_isinf (got))
   243                  {
   244                    printf  ("mpn_get_d wrong, didn't get infinity\n");
   245                  bad:
   246                    printf  ("  nsize    %ld\n", (long) nsize);
   247                    printf  ("  exp      %ld\n", exp);
   248                    printf  ("  sign     %ld\n", (long) sign);
   249                    d_trace ("  got      ", got);
   250                    printf  ("  got sign %ld\n", (long) got_sign);
   251                    abort ();
   252                  }
   253                if (got_sign != sign)
   254                  {
   255                    printf  ("mpn_get_d wrong sign on infinity\n");
   256                    goto bad;
   257                  }
   258              }
   259          }
   260      }
   261  }
   262  
   263  /* Check values 2^n approaching and into IEEE denorm range.
   264     Some systems might not support denorms, or might have traps setup, so
   265     watch out for SIGFPE.  */
   266  void
   267  check_ieee_denorm (void)
   268  {
   269    static long exp;
   270    mp_limb_t  n = 1;
   271    long       i;
   272    mp_size_t  sign;
   273    double     want, got;
   274  
   275    if (! _GMP_IEEE_FLOATS)
   276      return;
   277  
   278    if (tests_setjmp_sigfpe() == 0)
   279      {
   280        exp = -1020;
   281        want = 1.0;
   282        for (i = 0; i > exp; i--)
   283          want *= 0.5;
   284  
   285        for ( ; exp > -1500 && want != 0.0; exp--)
   286          {
   287            for (sign = 0; sign >= -1; sign--)
   288              {
   289                got = mpn_get_d (&n, (mp_size_t) 1, sign, exp);
   290                if (got != want)
   291                  {
   292                    printf  ("mpn_get_d wrong on denorm\n");
   293                    printf  ("  n=1\n");
   294                    printf  ("  exp   %ld\n", exp);
   295                    printf  ("  sign  %ld\n", (long) sign);
   296                    d_trace ("  got   ", got);
   297                    d_trace ("  want  ", want);
   298                    abort ();
   299                  }
   300                want = -want;
   301              }
   302            want *= 0.5;
   303            FORCE_DOUBLE (want);
   304          }
   305      }
   306    else
   307      {
   308        printf ("Warning, IEEE denorm tests skipped due to SIGFPE (exp=%ld)\n", exp);
   309      }
   310    tests_sigfpe_done ();
   311  }
   312  
   313  
   314  /* Check values 2^n approaching exponent overflow.
   315     Some systems might trap on overflow, so watch out for SIGFPE.  */
   316  void
   317  check_ieee_overflow (void)
   318  {
   319    static long exp;
   320    mp_limb_t  n = 1;
   321    long       i;
   322    mp_size_t  sign;
   323    double     want, got;
   324  
   325    if (! _GMP_IEEE_FLOATS)
   326      return;
   327  
   328    if (tests_setjmp_sigfpe() == 0)
   329      {
   330        exp = 1010;
   331        want = 1.0;
   332        for (i = 0; i < exp; i++)
   333          want *= 2.0;
   334  
   335        for ( ; exp < 1050; exp++)
   336          {
   337            for (sign = 0; sign >= -1; sign--)
   338              {
   339                got = mpn_get_d (&n, (mp_size_t) 1, sign, exp);
   340                if (got != want)
   341                  {
   342                    printf  ("mpn_get_d wrong on overflow\n");
   343                    printf  ("  n=1\n");
   344                    printf  ("  exp   %ld\n", exp);
   345                    printf  ("  sign  %ld\n", (long) sign);
   346                    d_trace ("  got   ", got);
   347                    d_trace ("  want  ", want);
   348                    abort ();
   349                  }
   350                want = -want;
   351              }
   352            want *= 2.0;
   353            FORCE_DOUBLE (want);
   354          }
   355      }
   356    else
   357      {
   358        printf ("Warning, IEEE overflow tests skipped due to SIGFPE (exp=%ld)\n", exp);
   359      }
   360    tests_sigfpe_done ();
   361  }
   362  
   363  
   364  /* ARM gcc 2.95.4 was seen generating bad code for ulong->double
   365     conversions, resulting in for instance 0x81c25113 incorrectly converted.
   366     This test exercises that value, to see mpn_get_d has avoided the
   367     problem.  */
   368  void
   369  check_0x81c25113 (void)
   370  {
   371  #if GMP_NUMB_BITS >= 32
   372    double     want = 2176995603.0;
   373    double     got;
   374    mp_limb_t  np[4];
   375    mp_size_t  nsize;
   376    long       exp;
   377  
   378    if (tests_dbl_mant_bits() < 32)
   379      return;
   380  
   381    for (nsize = 1; nsize <= numberof (np); nsize++)
   382      {
   383        refmpn_zero (np, nsize-1);
   384        np[nsize-1] = CNST_LIMB(0x81c25113);
   385        exp = - (nsize-1) * GMP_NUMB_BITS;
   386        got = mpn_get_d (np, nsize, (mp_size_t) 0, exp);
   387        if (got != want)
   388          {
   389            printf  ("mpn_get_d wrong on 2176995603 (0x81c25113)\n");
   390            printf  ("  nsize  %ld\n", (long) nsize);
   391            printf  ("  exp    %ld\n", exp);
   392            d_trace ("  got    ", got);
   393            d_trace ("  want   ", want);
   394            abort ();
   395          }
   396      }
   397  #endif
   398  }
   399  
   400  
   401  void
   402  check_rand (void)
   403  {
   404    gmp_randstate_ptr rands = RANDS;
   405    int            rep, i;
   406    unsigned long  mant_bits;
   407    long           exp, exp_min, exp_max;
   408    double         got, want, d;
   409    mp_size_t      nalloc, nsize, sign;
   410    mp_limb_t      nhigh_mask;
   411    mp_ptr         np;
   412  
   413    mant_bits = tests_dbl_mant_bits ();
   414    if (mant_bits == 0)
   415      return;
   416  
   417    /* Allow for vax D format with exponent 127 to -128 only.
   418       FIXME: Do something to probe for a valid exponent range.  */
   419    exp_min = -100 - mant_bits;
   420    exp_max =  100 - mant_bits;
   421  
   422    /* space for mant_bits */
   423    nalloc = BITS_TO_LIMBS (mant_bits);
   424    np = refmpn_malloc_limbs (nalloc);
   425    nhigh_mask = MP_LIMB_T_MAX
   426      >> (GMP_NAIL_BITS + nalloc * GMP_NUMB_BITS - mant_bits);
   427  
   428    for (rep = 0; rep < 200; rep++)
   429      {
   430        /* random exp_min to exp_max, inclusive */
   431        exp = exp_min + (long) gmp_urandomm_ui (rands, exp_max - exp_min + 1);
   432  
   433        /* mant_bits worth of random at np */
   434        if (rep & 1)
   435          mpn_random (np, nalloc);
   436        else
   437          mpn_random2 (np, nalloc);
   438        nsize = nalloc;
   439        np[nsize-1] &= nhigh_mask;
   440        MPN_NORMALIZE (np, nsize);
   441        if (nsize == 0)
   442          continue;
   443  
   444        sign = (mp_size_t) gmp_urandomb_ui (rands, 1L) - 1;
   445  
   446        /* want = {np,nsize}, converting one bit at a time */
   447        want = 0.0;
   448        for (i = 0, d = 1.0; i < mant_bits; i++, d *= 2.0)
   449          if (np[i/GMP_NUMB_BITS] & (CNST_LIMB(1) << (i%GMP_NUMB_BITS)))
   450            want += d;
   451        if (sign < 0)
   452          want = -want;
   453  
   454        /* want = want * 2^exp */
   455        for (i = 0; i < exp; i++)
   456          want *= 2.0;
   457        for (i = 0; i > exp; i--)
   458          want *= 0.5;
   459  
   460        got = mpn_get_d (np, nsize, sign, exp);
   461  
   462        if (got != want)
   463          {
   464            printf    ("mpn_get_d wrong on random data\n");
   465            printf    ("   sign     %ld\n", (long) sign);
   466            mpn_trace ("   n        ", np, nsize);
   467            printf    ("   nsize    %ld\n", (long) nsize);
   468            printf    ("   exp      %ld\n", exp);
   469            d_trace   ("   want     ", want);
   470            d_trace   ("   got      ", got);
   471            abort();
   472          }
   473      }
   474  
   475    free (np);
   476  }
   477  
   478  
   479  int
   480  main (void)
   481  {
   482    tests_start ();
   483    mp_trace_base = -16;
   484  
   485    check_onebit ();
   486    check_twobit ();
   487    check_inf ();
   488    check_underflow ();
   489    check_ieee_denorm ();
   490    check_ieee_overflow ();
   491    check_0x81c25113 ();
   492  #if ! (defined (__vax) || defined (__vax__))
   493    check_rand ();
   494  #endif
   495  
   496    tests_end ();
   497    exit (0);
   498  }