xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-fdiv.c (revision 212397c69a103ae7e5eafa8731ddfae671d2dee7)
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 http://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 }
148