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

     1  /* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_cdiv_qr_ui, mpz_cdiv_q_ui,
     2     mpz_cdiv_r_ui, , mpz_cdiv_ui, mpz_mul_ui.
     3  
     4  Copyright 1993, 1994, 1996, 2000-2002 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 (const char *, mpz_t, unsigned long);
    29  void debug_mp (mpz_t, int);
    30  
    31  int
    32  main (int argc, char **argv)
    33  {
    34    mpz_t dividend;
    35    mpz_t quotient, remainder;
    36    mpz_t quotient2, remainder2;
    37    mpz_t temp;
    38    mp_size_t dividend_size;
    39    unsigned long divisor;
    40    int i;
    41    int reps = 10000;
    42    gmp_randstate_ptr rands;
    43    mpz_t bs;
    44    unsigned long bsi, size_range;
    45    unsigned long r_rq, r_q, r_r, r;
    46  
    47    tests_start ();
    48    rands = RANDS;
    49  
    50    mpz_init (bs);
    51  
    52    if (argc == 2)
    53       reps = atoi (argv[1]);
    54  
    55    mpz_init (dividend);
    56    mpz_init (quotient);
    57    mpz_init (remainder);
    58    mpz_init (quotient2);
    59    mpz_init (remainder2);
    60    mpz_init (temp);
    61  
    62    for (i = 0; i < reps; i++)
    63      {
    64        mpz_urandomb (bs, rands, 32);
    65        size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */
    66  
    67        do
    68  	{
    69  	  mpz_rrandomb (bs, rands, 64);
    70  	  divisor = mpz_get_ui (bs);
    71  	}
    72        while (divisor == 0);
    73  
    74        mpz_urandomb (bs, rands, size_range);
    75        dividend_size = mpz_get_ui (bs);
    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  
    83        /* printf ("%ld\n", SIZ (dividend)); */
    84  
    85        r_rq = mpz_cdiv_qr_ui (quotient, remainder, dividend, divisor);
    86        r_q = mpz_cdiv_q_ui (quotient2, dividend, divisor);
    87        r_r = mpz_cdiv_r_ui (remainder2, dividend, divisor);
    88        r = mpz_cdiv_ui (dividend, divisor);
    89  
    90        /* First determine that the quotients and remainders computed
    91  	 with different functions are equal.  */
    92        if (mpz_cmp (quotient, quotient2) != 0)
    93  	dump_abort ("quotients from mpz_cdiv_qr_ui and mpz_cdiv_q_ui differ",
    94  		    dividend, divisor);
    95        if (mpz_cmp (remainder, remainder2) != 0)
    96  	dump_abort ("remainders from mpz_cdiv_qr_ui and mpz_cdiv_r_ui differ",
    97  		    dividend, divisor);
    98  
    99        /* Check if the sign of the quotient is correct.  */
   100        if (mpz_cmp_ui (quotient, 0) != 0)
   101  	if ((mpz_cmp_ui (quotient, 0) < 0)
   102  	    != (mpz_cmp_ui (dividend, 0) < 0))
   103  	dump_abort ("quotient sign wrong", dividend, divisor);
   104  
   105        /* Check if the remainder has the opposite sign as the (positive) divisor
   106  	 (quotient rounded towards minus infinity).  */
   107        if (mpz_cmp_ui (remainder, 0) != 0)
   108  	if (mpz_cmp_ui (remainder, 0) > 0)
   109  	  dump_abort ("remainder sign wrong", dividend, divisor);
   110  
   111        mpz_mul_ui (temp, quotient, divisor);
   112        mpz_add (temp, temp, remainder);
   113        if (mpz_cmp (temp, dividend) != 0)
   114  	dump_abort ("n mod d != n - [n/d]*d", dividend, divisor);
   115  
   116        mpz_abs (remainder, remainder);
   117        if (mpz_cmp_ui (remainder, divisor) >= 0)
   118  	dump_abort ("remainder greater than divisor", dividend, divisor);
   119  
   120        if (mpz_cmp_ui (remainder, r_rq) != 0)
   121  	dump_abort ("remainder returned from mpz_cdiv_qr_ui is wrong",
   122  		    dividend, divisor);
   123        if (mpz_cmp_ui (remainder, r_q) != 0)
   124  	dump_abort ("remainder returned from mpz_cdiv_q_ui is wrong",
   125  		    dividend, divisor);
   126        if (mpz_cmp_ui (remainder, r_r) != 0)
   127  	dump_abort ("remainder returned from mpz_cdiv_r_ui is wrong",
   128  		    dividend, divisor);
   129        if (mpz_cmp_ui (remainder, r) != 0)
   130  	dump_abort ("remainder returned from mpz_cdiv_ui is wrong",
   131  		    dividend, divisor);
   132      }
   133  
   134    mpz_clear (bs);
   135    mpz_clear (dividend);
   136    mpz_clear (quotient);
   137    mpz_clear (remainder);
   138    mpz_clear (quotient2);
   139    mpz_clear (remainder2);
   140    mpz_clear (temp);
   141  
   142    tests_end ();
   143    exit (0);
   144  }
   145  
   146  void
   147  dump_abort (const char *str, mpz_t dividend, unsigned long divisor)
   148  {
   149    fprintf (stderr, "ERROR: %s\n", str);
   150    fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
   151    fprintf (stderr, "divisor  = %lX\n", divisor);
   152    abort();
   153  }
   154  
   155  void
   156  debug_mp (mpz_t x, int base)
   157  {
   158    mpz_out_str (stderr, base, x); fputc ('\n', stderr);
   159  }