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

     1  /* Test mpz_get_d_2exp.
     2  
     3  Copyright 2002, 2003, 2012 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 <stdio.h>
    21  #include <stdlib.h>
    22  #include "gmp.h"
    23  #include "gmp-impl.h"
    24  #include "tests.h"
    25  
    26  
    27  static void
    28  check_zero (void)
    29  {
    30    mpz_t   z;
    31    double  got, want;
    32    long    got_exp, want_exp;
    33  
    34    mpz_init_set_ui (z, 0);
    35  
    36    want = 0.0;
    37    want_exp = 0;
    38    got = mpz_get_d_2exp (&got_exp, z);
    39    if (got != want || got_exp != want_exp)
    40      {
    41        printf    ("mpz_get_d_2exp wrong on zero\n");
    42        mpz_trace ("   z    ", z);
    43        d_trace   ("   want ", want);
    44        d_trace   ("   got  ", got);
    45        printf    ("   want exp %ld\n", want_exp);
    46        printf    ("   got exp  %ld\n", got_exp);
    47        abort();
    48      }
    49  
    50    mpz_clear (z);
    51  }
    52  
    53  static void
    54  check_onebit (void)
    55  {
    56    static const unsigned long data[] = {
    57      1, 32, 52, 53, 54, 63, 64, 65, 128, 256, 511, 512, 513
    58    };
    59    mpz_t   z;
    60    double  got, want;
    61    long    got_exp, want_exp;
    62    int     i;
    63  
    64    mpz_init (z);
    65  
    66    for (i = 0; i < numberof (data); i++)
    67      {
    68        mpz_set_ui (z, 1L);
    69        mpz_mul_2exp (z, z, data[i]);
    70        want = 0.5;
    71        want_exp = data[i] + 1;
    72        got = mpz_get_d_2exp (&got_exp, z);
    73        if (got != want || got_exp != want_exp)
    74          {
    75            printf    ("mpz_get_d_2exp wrong on 2**%ld\n", data[i]);
    76            mpz_trace ("   z    ", z);
    77            d_trace   ("   want ", want);
    78            d_trace   ("   got  ", got);
    79            printf    ("   want exp %ld\n", want_exp);
    80            printf    ("   got exp  %ld\n", got_exp);
    81            abort();
    82          }
    83  
    84        mpz_set_si (z, -1L);
    85        mpz_mul_2exp (z, z, data[i]);
    86        want = -0.5;
    87        want_exp = data[i] + 1;
    88        got = mpz_get_d_2exp (&got_exp, z);
    89        if (got != want || got_exp != want_exp)
    90          {
    91            printf    ("mpz_get_d_2exp wrong on -2**%ld\n", data[i]);
    92            mpz_trace ("   z    ", z);
    93            d_trace   ("   want ", want);
    94            d_trace   ("   got  ", got);
    95            printf    ("   want exp %ld\n", want_exp);
    96            printf    ("   got exp  %ld\n", got_exp);
    97            abort();
    98          }
    99      }
   100    mpz_clear (z);
   101  }
   102  
   103  /* Check that hardware rounding doesn't make mpz_get_d_2exp return a value
   104     outside its defined range. */
   105  static void
   106  check_round (void)
   107  {
   108    static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 };
   109    mpz_t   z;
   110    double  got;
   111    long    got_exp;
   112    int     i, rnd_mode, old_rnd_mode;
   113  
   114    mpz_init (z);
   115    old_rnd_mode = tests_hardware_getround ();
   116  
   117    for (rnd_mode = 0; rnd_mode < 4; rnd_mode++)
   118      {
   119        tests_hardware_setround (rnd_mode);
   120  
   121        for (i = 0; i < numberof (data); i++)
   122          {
   123            mpz_set_ui (z, 1L);
   124            mpz_mul_2exp (z, z, data[i]);
   125            mpz_sub_ui (z, z, 1L);
   126  
   127            got = mpz_get_d_2exp (&got_exp, z);
   128            if (got < 0.5 || got >= 1.0)
   129              {
   130                printf    ("mpz_get_d_2exp wrong on 2**%lu-1\n", data[i]);
   131                printf    ("result out of range, expect 0.5 <= got < 1.0\n");
   132                printf    ("   rnd_mode = %d\n", rnd_mode);
   133                printf    ("   data[i]  = %lu\n", data[i]);
   134                mpz_trace ("   z    ", z);
   135                d_trace   ("   got  ", got);
   136                printf    ("   got exp  %ld\n", got_exp);
   137                abort();
   138              }
   139  
   140            mpz_neg (z, z);
   141            got = mpz_get_d_2exp (&got_exp, z);
   142            if (got <= -1.0 || got > -0.5)
   143              {
   144                printf    ("mpz_get_d_2exp wrong on -2**%lu-1\n", data[i]);
   145                printf    ("result out of range, expect -1.0 < got <= -0.5\n");
   146                printf    ("   rnd_mode = %d\n", rnd_mode);
   147                printf    ("   data[i]  = %lu\n", data[i]);
   148                mpz_trace ("   z    ", z);
   149                d_trace   ("   got  ", got);
   150                printf    ("   got exp  %ld\n", got_exp);
   151                abort();
   152              }
   153          }
   154      }
   155  
   156    mpz_clear (z);
   157    tests_hardware_setround (old_rnd_mode);
   158  }
   159  
   160  static void
   161  check_rand (void)
   162  {
   163    gmp_randstate_ptr rands = RANDS;
   164    int     i;
   165    mpz_t   z;
   166    double  got;
   167    long    got_exp;
   168    unsigned long  bits;
   169  
   170    mpz_init (z);
   171  
   172    for (i = 0; i < 200; i++)
   173      {
   174        bits = gmp_urandomm_ui (rands, 512L);
   175        mpz_urandomb (z, rands, bits);
   176  
   177        got = mpz_get_d_2exp (&got_exp, z);
   178        if (mpz_sgn (z) == 0)
   179          continue;
   180        bits = mpz_sizeinbase (z, 2);
   181  
   182        if (got < 0.5 || got >= 1.0)
   183          {
   184            printf    ("mpz_get_d_2exp out of range, expect 0.5 <= got < 1.0\n");
   185            mpz_trace ("   z    ", z);
   186            d_trace   ("   got  ", got);
   187            printf    ("   got exp  %ld\n", got_exp);
   188            abort();
   189          }
   190  
   191        /* FIXME: If mpz_get_d_2exp rounds upwards we might have got_exp ==
   192           bits+1, so leave this test disabled until we decide if that's what
   193           should happen, or not.  */
   194  #if 0
   195        if (got_exp != bits)
   196          {
   197            printf    ("mpz_get_d_2exp wrong exponent\n", i);
   198            mpz_trace ("   z    ", z);
   199            d_trace   ("   bits ", bits);
   200            d_trace   ("   got  ", got);
   201            printf    ("   got exp  %ld\n", got_exp);
   202            abort();
   203          }
   204  #endif
   205      }
   206    mpz_clear (z);
   207  }
   208  
   209  
   210  int
   211  main (void)
   212  {
   213    tests_start ();
   214    mp_trace_base = -16;
   215  
   216    check_zero ();
   217    check_onebit ();
   218    check_round ();
   219    check_rand ();
   220  
   221    tests_end ();
   222    exit (0);
   223  }