1 /* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr, mpz_tdiv_q,
2    mpz_tdiv_r, mpz_mul.
3 
4 Copyright 1991, 1993, 1994, 1996, 1997, 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-impl.h"
25 #include "tests.h"
26 
27 void dump_abort (mpz_t, mpz_t);
28 void debug_mp (mpz_t, int);
29 
30 int
main(int argc,char ** argv)31 main (int argc, char **argv)
32 {
33   mpz_t dividend, divisor;
34   mpz_t quotient, remainder;
35   mpz_t quotient2, remainder2;
36   mpz_t temp;
37   mp_size_t dividend_size, divisor_size;
38   int i;
39   int reps = 1000;
40   gmp_randstate_ptr rands;
41   mpz_t bs;
42   unsigned long bsi, size_range;
43 
44   tests_start ();
45   TESTS_REPS (reps, argv, argc);
46 
47   rands = RANDS;
48 
49   mpz_init (bs);
50 
51   mpz_init (dividend);
52   mpz_init (divisor);
53   mpz_init (quotient);
54   mpz_init (remainder);
55   mpz_init (quotient2);
56   mpz_init (remainder2);
57   mpz_init (temp);
58 
59   for (i = 0; i < reps; i++)
60     {
61       mpz_urandomb (bs, rands, 32);
62       size_range = mpz_get_ui (bs) % 18 + 2; /* 0..524288 bit operands */
63 
64       do
65 	{
66 	  mpz_urandomb (bs, rands, size_range);
67 	  divisor_size = mpz_get_ui (bs);
68 	  mpz_rrandomb (divisor, rands, divisor_size);
69 	}
70       while (mpz_sgn (divisor) == 0);
71 
72       mpz_urandomb (bs, rands, size_range);
73       dividend_size = mpz_get_ui (bs) + divisor_size;
74       mpz_rrandomb (dividend, rands, dividend_size);
75 
76       mpz_urandomb (bs, rands, 2);
77       bsi = mpz_get_ui (bs);
78       if ((bsi & 1) != 0)
79 	mpz_neg (dividend, dividend);
80       if ((bsi & 2) != 0)
81 	mpz_neg (divisor, divisor);
82 
83       /* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */
84 
85       mpz_tdiv_qr (quotient, remainder, dividend, divisor);
86       mpz_tdiv_q (quotient2, dividend, divisor);
87       mpz_tdiv_r (remainder2, dividend, divisor);
88 
89       /* First determine that the quotients and remainders computed
90 	 with different functions are equal.  */
91       if (mpz_cmp (quotient, quotient2) != 0)
92 	dump_abort (dividend, divisor);
93       if (mpz_cmp (remainder, remainder2) != 0)
94 	dump_abort (dividend, divisor);
95 
96       /* Check if the sign of the quotient is correct.  */
97       if (mpz_cmp_ui (quotient, 0) != 0)
98 	if ((mpz_cmp_ui (quotient, 0) < 0)
99 	    != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
100 	dump_abort (dividend, divisor);
101 
102       /* Check if the remainder has the same sign as the dividend
103 	 (quotient rounded towards 0).  */
104       if (mpz_cmp_ui (remainder, 0) != 0)
105 	if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
106 	  dump_abort (dividend, divisor);
107 
108       mpz_mul (temp, quotient, divisor);
109       mpz_add (temp, temp, remainder);
110       if (mpz_cmp (temp, dividend) != 0)
111 	dump_abort (dividend, divisor);
112 
113       mpz_abs (temp, divisor);
114       mpz_abs (remainder, remainder);
115       if (mpz_cmp (remainder, temp) >= 0)
116 	dump_abort (dividend, divisor);
117     }
118 
119   mpz_clear (bs);
120   mpz_clear (dividend);
121   mpz_clear (divisor);
122   mpz_clear (quotient);
123   mpz_clear (remainder);
124   mpz_clear (quotient2);
125   mpz_clear (remainder2);
126   mpz_clear (temp);
127 
128   tests_end ();
129   exit (0);
130 }
131 
132 void
dump_abort(mpz_t dividend,mpz_t divisor)133 dump_abort (mpz_t dividend, mpz_t divisor)
134 {
135   fprintf (stderr, "ERROR\n");
136   fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
137   fprintf (stderr, "divisor  = "); debug_mp (divisor, -16);
138   abort();
139 }
140 
141 void
debug_mp(mpz_t x,int base)142 debug_mp (mpz_t x, int base)
143 {
144   mpz_out_str (stderr, base, x); fputc ('\n', stderr);
145 }
146