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

     1  /* Test mpq_mul_2exp and mpq_div_2exp.
     2  
     3  Copyright 2000, 2001 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  struct pair_t {
    28    const char     *num;
    29    const char     *den;
    30  };
    31  
    32  void
    33  check_random ()
    34  {
    35    gmp_randstate_ptr rands;
    36    mpz_t bs;
    37    unsigned long arg_size, size_range;
    38    mpq_t q, r;
    39    int i;
    40    mp_bitcnt_t shift;
    41    int reps = 10000;
    42  
    43    rands = RANDS;
    44  
    45    mpz_init (bs);
    46    mpq_init (q);
    47    mpq_init (r);
    48  
    49    for (i = 0; i < reps; i++)
    50      {
    51        mpz_urandomb (bs, rands, 32);
    52        size_range = mpz_get_ui (bs) % 11 + 2; /* 0..4096 bit operands */
    53  
    54        mpz_urandomb (bs, rands, size_range);
    55        arg_size = mpz_get_ui (bs);
    56        mpz_rrandomb (mpq_numref (q), rands, arg_size);
    57        do
    58  	{
    59  	  mpz_urandomb (bs, rands, size_range);
    60  	  arg_size = mpz_get_ui (bs);
    61  	  mpz_rrandomb (mpq_denref (q), rands, arg_size);
    62  	}
    63        while (mpz_sgn (mpq_denref (q)) == 0);
    64  
    65        /* We now have a random rational in q, albeit an unnormalised one.  The
    66  	 lack of normalisation should not matter here, so let's save the time a
    67  	 gcd would require.  */
    68  
    69        mpz_urandomb (bs, rands, 32);
    70        shift = mpz_get_ui (bs) % 4096;
    71  
    72        mpq_mul_2exp (r, q, shift);
    73  
    74        if (mpq_cmp (r, q) < 0)
    75  	{
    76  	  printf ("mpq_mul_2exp wrong on random\n");
    77  	  abort ();
    78  	}
    79  
    80        mpq_div_2exp (r, r, shift);
    81  
    82        if (mpq_cmp (r, q) != 0)
    83  	{
    84  	  printf ("mpq_mul_2exp or mpq_div_2exp wrong on random\n");
    85  	  abort ();
    86  	}
    87      }
    88    mpq_clear (q);
    89    mpq_clear (r);
    90    mpz_clear (bs);
    91  }
    92  
    93  int
    94  main (int argc, char **argv)
    95  {
    96    static const struct {
    97      struct pair_t  left;
    98      unsigned long  n;
    99      struct pair_t  right;
   100  
   101    } data[] = {
   102      { {"0","1"}, 0, {"0","1"} },
   103      { {"0","1"}, 1, {"0","1"} },
   104      { {"0","1"}, 2, {"0","1"} },
   105  
   106      { {"1","1"}, 0, {"1","1"} },
   107      { {"1","1"}, 1, {"2","1"} },
   108      { {"1","1"}, 2, {"4","1"} },
   109      { {"1","1"}, 3, {"8","1"} },
   110  
   111      { {"1","1"}, 31, {"0x80000000","1"} },
   112      { {"1","1"}, 32, {"0x100000000","1"} },
   113      { {"1","1"}, 33, {"0x200000000","1"} },
   114      { {"1","1"}, 63, {"0x8000000000000000","1"} },
   115      { {"1","1"}, 64, {"0x10000000000000000","1"} },
   116      { {"1","1"}, 65, {"0x20000000000000000","1"} },
   117      { {"1","1"}, 95, {"0x800000000000000000000000","1"} },
   118      { {"1","1"}, 96, {"0x1000000000000000000000000","1"} },
   119      { {"1","1"}, 97, {"0x2000000000000000000000000","1"} },
   120      { {"1","1"}, 127, {"0x80000000000000000000000000000000","1"} },
   121      { {"1","1"}, 128, {"0x100000000000000000000000000000000","1"} },
   122      { {"1","1"}, 129, {"0x200000000000000000000000000000000","1"} },
   123  
   124      { {"1","2"}, 31, {"0x40000000","1"} },
   125      { {"1","2"}, 32, {"0x80000000","1"} },
   126      { {"1","2"}, 33, {"0x100000000","1"} },
   127      { {"1","2"}, 63, {"0x4000000000000000","1"} },
   128      { {"1","2"}, 64, {"0x8000000000000000","1"} },
   129      { {"1","2"}, 65, {"0x10000000000000000","1"} },
   130      { {"1","2"}, 95, {"0x400000000000000000000000","1"} },
   131      { {"1","2"}, 96, {"0x800000000000000000000000","1"} },
   132      { {"1","2"}, 97, {"0x1000000000000000000000000","1"} },
   133      { {"1","2"}, 127, {"0x40000000000000000000000000000000","1"} },
   134      { {"1","2"}, 128, {"0x80000000000000000000000000000000","1"} },
   135      { {"1","2"}, 129, {"0x100000000000000000000000000000000","1"} },
   136  
   137      { {"1","0x80000000"}, 30, {"1","2"} },
   138      { {"1","0x80000000"}, 31, {"1","1"} },
   139      { {"1","0x80000000"}, 32, {"2","1"} },
   140      { {"1","0x80000000"}, 33, {"4","1"} },
   141      { {"1","0x80000000"}, 62, {"0x80000000","1"} },
   142      { {"1","0x80000000"}, 63, {"0x100000000","1"} },
   143      { {"1","0x80000000"}, 64, {"0x200000000","1"} },
   144      { {"1","0x80000000"}, 94, {"0x8000000000000000","1"} },
   145      { {"1","0x80000000"}, 95, {"0x10000000000000000","1"} },
   146      { {"1","0x80000000"}, 96, {"0x20000000000000000","1"} },
   147      { {"1","0x80000000"}, 126, {"0x800000000000000000000000","1"} },
   148      { {"1","0x80000000"}, 127, {"0x1000000000000000000000000","1"} },
   149      { {"1","0x80000000"}, 128, {"0x2000000000000000000000000","1"} },
   150  
   151      { {"1","0x100000000"}, 1, {"1","0x80000000"} },
   152      { {"1","0x100000000"}, 2, {"1","0x40000000"} },
   153      { {"1","0x100000000"}, 3, {"1","0x20000000"} },
   154  
   155      { {"1","0x10000000000000000"}, 1, {"1","0x8000000000000000"} },
   156      { {"1","0x10000000000000000"}, 2, {"1","0x4000000000000000"} },
   157      { {"1","0x10000000000000000"}, 3, {"1","0x2000000000000000"} },
   158    };
   159  
   160    void (*fun) (mpq_ptr, mpq_srcptr, unsigned long);
   161    const struct pair_t  *p_start, *p_want;
   162    const char  *name;
   163    mpq_t    sep, got, want;
   164    mpq_ptr  q;
   165    int      i, muldiv, sign, overlap;
   166  
   167    tests_start ();
   168  
   169    mpq_init (sep);
   170    mpq_init (got);
   171    mpq_init (want);
   172  
   173    for (i = 0; i < numberof (data); i++)
   174      {
   175        for (muldiv = 0; muldiv < 2; muldiv++)
   176          {
   177            if (muldiv == 0)
   178              {
   179                fun = mpq_mul_2exp;
   180                name = "mpq_mul_2exp";
   181                p_start = &data[i].left;
   182                p_want = &data[i].right;
   183              }
   184            else
   185              {
   186                fun = mpq_div_2exp;
   187                name = "mpq_div_2exp";
   188                p_start = &data[i].right;
   189                p_want = &data[i].left;
   190              }
   191  
   192            for (sign = 0; sign <= 1; sign++)
   193              {
   194                mpz_set_str_or_abort (mpq_numref(want), p_want->num, 0);
   195                mpz_set_str_or_abort (mpq_denref(want), p_want->den, 0);
   196                if (sign)
   197                  mpq_neg (want, want);
   198  
   199                for (overlap = 0; overlap <= 1; overlap++)
   200                  {
   201                    q = overlap ? got : sep;
   202  
   203                    /* initial garbage in "got" */
   204                    mpq_set_ui (got, 123L, 456L);
   205  
   206                    mpz_set_str_or_abort (mpq_numref(q), p_start->num, 0);
   207                    mpz_set_str_or_abort (mpq_denref(q), p_start->den, 0);
   208                    if (sign)
   209                      mpq_neg (q, q);
   210  
   211                    (*fun) (got, q, data[i].n);
   212                    MPQ_CHECK_FORMAT (got);
   213  
   214                    if (! mpq_equal (got, want))
   215                      {
   216                        printf ("%s wrong at data[%d], sign %d, overlap %d\n",
   217                                name, i, sign, overlap);
   218                        printf ("   num \"%s\"\n", p_start->num);
   219                        printf ("   den \"%s\"\n", p_start->den);
   220                        printf ("   n   %lu\n", data[i].n);
   221  
   222                        printf ("   got  ");
   223                        mpq_out_str (stdout, 16, got);
   224                        printf (" (hex)\n");
   225  
   226                        printf ("   want ");
   227                        mpq_out_str (stdout, 16, want);
   228                        printf (" (hex)\n");
   229  
   230                        abort ();
   231                      }
   232                  }
   233              }
   234          }
   235      }
   236  
   237    check_random ();
   238  
   239    mpq_clear (sep);
   240    mpq_clear (got);
   241    mpq_clear (want);
   242  
   243    tests_end ();
   244    exit (0);
   245  }