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

     1  /* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr, mpz_fdiv_q,
     2     mpz_fdiv_r, mpz_mul.
     3  
     4  Copyright 1993, 1994, 1996, 2000, 2001 Free Software Foundation, Inc.
     5  
     6  This file is part of the GNU MP Library test suite.
     7  
     8  The GNU MP Library test suite is free software; you can redistribute it
     9  and/or modify it under the terms of the GNU General Public License as
    10  published by the Free Software Foundation; either version 3 of the License,
    11  or (at your option) any later version.
    12  
    13  The GNU MP Library test suite is distributed in the hope that it will be
    14  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    16  Public License for more details.
    17  
    18  You should have received a copy of the GNU General Public License along with
    19  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
    20  
    21  #include <stdio.h>
    22  #include <stdlib.h>
    23  
    24  #include "gmp.h"
    25  #include "gmp-impl.h"
    26  #include "tests.h"
    27  
    28  void dump_abort (mpz_t, mpz_t);
    29  void debug_mp (mpz_t, int);
    30  
    31  int
    32  main (int argc, char **argv)
    33  {
    34    mpz_t dividend, divisor;
    35    mpz_t quotient, remainder;
    36    mpz_t quotient2, remainder2;
    37    mpz_t temp;
    38    mp_size_t dividend_size, divisor_size;
    39    int i;
    40    int reps = 1000;
    41    gmp_randstate_ptr rands;
    42    mpz_t bs;
    43    unsigned long bsi, size_range;
    44  
    45    tests_start ();
    46    rands = RANDS;
    47  
    48    mpz_init (bs);
    49  
    50    if (argc == 2)
    51       reps = atoi (argv[1]);
    52  
    53    mpz_init (dividend);
    54    mpz_init (divisor);
    55    mpz_init (quotient);
    56    mpz_init (remainder);
    57    mpz_init (quotient2);
    58    mpz_init (remainder2);
    59    mpz_init (temp);
    60  
    61    for (i = 0; i < reps; i++)
    62      {
    63        mpz_urandomb (bs, rands, 32);
    64        size_range = mpz_get_ui (bs) % 16 + 2; /* 0..131071 bit operands */
    65  
    66        do
    67  	{
    68  	  mpz_urandomb (bs, rands, size_range);
    69  	  divisor_size = mpz_get_ui (bs);
    70  	  mpz_rrandomb (divisor, rands, divisor_size);
    71  	}
    72        while (mpz_sgn (divisor) == 0);
    73  
    74        mpz_urandomb (bs, rands, size_range);
    75        dividend_size = mpz_get_ui (bs) + divisor_size;
    76        mpz_rrandomb (dividend, rands, dividend_size);
    77  
    78        mpz_urandomb (bs, rands, 2);
    79        bsi = mpz_get_ui (bs);
    80        if ((bsi & 1) != 0)
    81  	mpz_neg (dividend, dividend);
    82        if ((bsi & 2) != 0)
    83  	mpz_neg (divisor, divisor);
    84  
    85        /* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */
    86  
    87        mpz_fdiv_qr (quotient, remainder, dividend, divisor);
    88        mpz_fdiv_q (quotient2, dividend, divisor);
    89        mpz_fdiv_r (remainder2, dividend, divisor);
    90  
    91        /* First determine that the quotients and remainders computed
    92  	 with different functions are equal.  */
    93        if (mpz_cmp (quotient, quotient2) != 0)
    94  	dump_abort (dividend, divisor);
    95        if (mpz_cmp (remainder, remainder2) != 0)
    96  	dump_abort (dividend, divisor);
    97  
    98        /* Check if the sign of the quotient is correct.  */
    99        if (mpz_cmp_ui (quotient, 0) != 0)
   100  	if ((mpz_cmp_ui (quotient, 0) < 0)
   101  	    != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
   102  	dump_abort (dividend, divisor);
   103  
   104        /* Check if the remainder has the same sign as the divisor
   105  	 (quotient rounded towards minus infinity).  */
   106        if (mpz_cmp_ui (remainder, 0) != 0)
   107  	if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (divisor, 0) < 0))
   108  	  dump_abort (dividend, divisor);
   109  
   110        mpz_mul (temp, quotient, divisor);
   111        mpz_add (temp, temp, remainder);
   112        if (mpz_cmp (temp, dividend) != 0)
   113  	dump_abort (dividend, divisor);
   114  
   115        mpz_abs (temp, divisor);
   116        mpz_abs (remainder, remainder);
   117        if (mpz_cmp (remainder, temp) >= 0)
   118  	dump_abort (dividend, divisor);
   119      }
   120  
   121    mpz_clear (bs);
   122    mpz_clear (dividend);
   123    mpz_clear (divisor);
   124    mpz_clear (quotient);
   125    mpz_clear (remainder);
   126    mpz_clear (quotient2);
   127    mpz_clear (remainder2);
   128    mpz_clear (temp);
   129  
   130    tests_end ();
   131    exit (0);
   132  }
   133  
   134  void
   135  dump_abort (mpz_t dividend, mpz_t divisor)
   136  {
   137    fprintf (stderr, "ERROR\n");
   138    fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
   139    fprintf (stderr, "divisor  = "); debug_mp (divisor, -16);
   140    abort();
   141  }
   142  
   143  void
   144  debug_mp (mpz_t x, int base)
   145  {
   146    mpz_out_str (stderr, base, x); fputc ('\n', stderr);
   147  }