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