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

     1  /* Test mpz_[cft]div_[qr]_2exp.
     2  
     3  Copyright 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  
    23  #include "gmp.h"
    24  #include "gmp-impl.h"
    25  #include "tests.h"
    26  
    27  
    28  /* If the remainder is in the correct range and q*d+r is correct, then q
    29     must have rounded correctly.  */
    30  
    31  void
    32  check_one (mpz_srcptr a, unsigned long d)
    33  {
    34    mpz_t  q, r, p, d2exp;
    35    int    inplace;
    36  
    37    mpz_init (d2exp);
    38    mpz_init (q);
    39    mpz_init (r);
    40    mpz_init (p);
    41  
    42    mpz_set_ui (d2exp, 1L);
    43    mpz_mul_2exp (d2exp, d2exp, d);
    44  
    45  #define INPLACE(fun,dst,src,d)  \
    46    if (inplace)                  \
    47      {                           \
    48        mpz_set (dst, src);       \
    49        fun (dst, dst, d);        \
    50      }                           \
    51    else                          \
    52      fun (dst, src, d);
    53  
    54    for (inplace = 0; inplace <= 1; inplace++)
    55      {
    56        INPLACE (mpz_fdiv_q_2exp, q, a, d);
    57        INPLACE (mpz_fdiv_r_2exp, r, a, d);
    58  
    59        mpz_mul_2exp (p, q, d);
    60        mpz_add (p, p, r);
    61        if (mpz_sgn (r) < 0 || mpz_cmp (r, d2exp) >= 0)
    62  	{
    63  	  printf ("mpz_fdiv_r_2exp result out of range\n");
    64  	  goto error;
    65  	}
    66        if (mpz_cmp (p, a) != 0)
    67  	{
    68  	  printf ("mpz_fdiv_[qr]_2exp doesn't multiply back\n");
    69  	  goto error;
    70  	}
    71  
    72  
    73        INPLACE (mpz_cdiv_q_2exp, q, a, d);
    74        INPLACE (mpz_cdiv_r_2exp, r, a, d);
    75  
    76        mpz_mul_2exp (p, q, d);
    77        mpz_add (p, p, r);
    78        if (mpz_sgn (r) > 0 || mpz_cmpabs (r, d2exp) >= 0)
    79  	{
    80  	  printf ("mpz_cdiv_r_2exp result out of range\n");
    81  	  goto error;
    82  	}
    83        if (mpz_cmp (p, a) != 0)
    84  	{
    85  	  printf ("mpz_cdiv_[qr]_2exp doesn't multiply back\n");
    86  	  goto error;
    87  	}
    88  
    89  
    90        INPLACE (mpz_tdiv_q_2exp, q, a, d);
    91        INPLACE (mpz_tdiv_r_2exp, r, a, d);
    92  
    93        mpz_mul_2exp (p, q, d);
    94        mpz_add (p, p, r);
    95        if (mpz_sgn (r) != 0 && mpz_sgn (r) != mpz_sgn (a))
    96  	{
    97  	  printf ("mpz_tdiv_r_2exp result wrong sign\n");
    98  	  goto error;
    99  	}
   100        if (mpz_cmpabs (r, d2exp) >= 0)
   101  	{
   102  	  printf ("mpz_tdiv_r_2exp result out of range\n");
   103  	  goto error;
   104  	}
   105        if (mpz_cmp (p, a) != 0)
   106  	{
   107  	  printf ("mpz_tdiv_[qr]_2exp doesn't multiply back\n");
   108  	  goto error;
   109  	}
   110      }
   111  
   112    mpz_clear (d2exp);
   113    mpz_clear (q);
   114    mpz_clear (r);
   115    mpz_clear (p);
   116    return;
   117  
   118  
   119   error:
   120    mpz_trace ("a", a);
   121    printf    ("d=%lu\n", d);
   122    mpz_trace ("q", q);
   123    mpz_trace ("r", r);
   124    mpz_trace ("p", p);
   125  
   126    mp_trace_base = -16;
   127    mpz_trace ("a", a);
   128    printf    ("d=0x%lX\n", d);
   129    mpz_trace ("q", q);
   130    mpz_trace ("r", r);
   131    mpz_trace ("p", p);
   132  
   133    abort ();
   134  }
   135  
   136  
   137  void
   138  check_all (mpz_ptr a, unsigned long d)
   139  {
   140    check_one (a, d);
   141    mpz_neg (a, a);
   142    check_one (a, d);
   143  }
   144  
   145  
   146  void
   147  check_various (void)
   148  {
   149    static const unsigned long  table[] = {
   150      0, 1, 2, 3, 4, 5,
   151      GMP_NUMB_BITS-1, GMP_NUMB_BITS, GMP_NUMB_BITS+1,
   152      2*GMP_NUMB_BITS-1, 2*GMP_NUMB_BITS, 2*GMP_NUMB_BITS+1,
   153      3*GMP_NUMB_BITS-1, 3*GMP_NUMB_BITS, 3*GMP_NUMB_BITS+1,
   154      4*GMP_NUMB_BITS-1, 4*GMP_NUMB_BITS, 4*GMP_NUMB_BITS+1
   155    };
   156  
   157    int            i, j;
   158    unsigned long  n, d;
   159    mpz_t          a;
   160  
   161    mpz_init (a);
   162  
   163    /* a==0, and various d */
   164    mpz_set_ui (a, 0L);
   165    for (i = 0; i < numberof (table); i++)
   166      check_one (a, table[i]);
   167  
   168    /* a==2^n, and various d */
   169    for (i = 0; i < numberof (table); i++)
   170      {
   171        n = table[i];
   172        mpz_set_ui (a, 1L);
   173        mpz_mul_2exp (a, a, n);
   174  
   175        for (j = 0; j < numberof (table); j++)
   176  	{
   177  	  d = table[j];
   178  	  check_all (a, d);
   179  	}
   180      }
   181  
   182    mpz_clear (a);
   183  }
   184  
   185  
   186  void
   187  check_random (int argc, char *argv[])
   188  {
   189    gmp_randstate_ptr  rands = RANDS;
   190    int            reps = 100;
   191    mpz_t          a;
   192    unsigned long  d;
   193    int            i;
   194  
   195    if (argc == 2)
   196      reps = atoi (argv[1]);
   197  
   198    mpz_init (a);
   199  
   200    for (i = 0; i < reps; i++)
   201      {
   202        /* exponentially within 2 to 257 bits */
   203        mpz_erandomb (a, rands, urandom () % 8 + 2);
   204  
   205        d = urandom () % 256;
   206  
   207        check_all (a, d);
   208      }
   209  
   210    mpz_clear (a);
   211  }
   212  
   213  
   214  int
   215  main (int argc, char *argv[])
   216  {
   217    tests_start ();
   218  
   219    check_various ();
   220    check_random (argc, argv);
   221  
   222    tests_end ();
   223    exit (0);
   224  }