xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-div.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
1 /*
2 
3 Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 
24 #include "testutils.h"
25 
26 #define MAXBITS 400
27 #define COUNT 10000
28 
29 typedef void div_qr_func (mpz_t, mpz_t, const mpz_t, const mpz_t);
30 typedef unsigned long div_qr_ui_func (mpz_t, mpz_t, const mpz_t, unsigned long);
31 typedef void div_func (mpz_t, const mpz_t, const mpz_t);
32 typedef unsigned long div_x_ui_func (mpz_t, const mpz_t, unsigned long);
33 typedef unsigned long div_ui_func (const mpz_t, unsigned long);
34 
35 void
testmain(int argc,char ** argv)36 testmain (int argc, char **argv)
37 {
38   unsigned i;
39   mpz_t a, b, q, r, rq, rr;
40   int div_p;
41 
42   mpz_init (a);
43   mpz_init (b);
44   mpz_init (r);
45   mpz_init (q);
46   mpz_init (rr);
47   mpz_init (rq);
48 
49   for (i = 0; i < COUNT; i++)
50     {
51       unsigned j;
52       for (j = 0; j < 3; j++)
53 	{
54 	  static const enum hex_random_op ops[3] = { OP_CDIV, OP_FDIV, OP_TDIV };
55 	  static const char name[3] = { 'c', 'f', 't'};
56 	  static div_qr_func * const div_qr [3] =
57 	    {
58 	      mpz_cdiv_qr, mpz_fdiv_qr, mpz_tdiv_qr
59 	    };
60 	  static div_qr_ui_func * const div_qr_ui[3] =
61 	    {
62 	      mpz_cdiv_qr_ui, mpz_fdiv_qr_ui, mpz_tdiv_qr_ui
63 	    };
64 	  static div_func * const div_q [3] =
65 	    {
66 	      mpz_cdiv_q, mpz_fdiv_q, mpz_tdiv_q
67 	    };
68 	  static div_x_ui_func * const div_q_ui[3] =
69 	    {
70 	      mpz_cdiv_q_ui, mpz_fdiv_q_ui, mpz_tdiv_q_ui
71 	    };
72 	  static div_func * const div_r [3] =
73 	    {
74 	      mpz_cdiv_r, mpz_fdiv_r, mpz_tdiv_r
75 	    };
76 	  static div_x_ui_func * const div_r_ui[3] =
77 	    {
78 	      mpz_cdiv_r_ui, mpz_fdiv_r_ui, mpz_tdiv_r_ui
79 	    };
80 	  static div_ui_func * const div_ui[3] =
81 	    {
82 	      mpz_cdiv_ui, mpz_fdiv_ui, mpz_tdiv_ui
83 	    };
84 
85 	  mini_random_op4 (ops[j], MAXBITS, a, b, rq, rr);
86 	  div_qr[j] (q, r, a, b);
87 	  if (mpz_cmp (r, rr) || mpz_cmp (q, rq))
88 	    {
89 	      fprintf (stderr, "mpz_%cdiv_qr failed:\n", name[j]);
90 	      dump ("a", a);
91 	      dump ("b", b);
92 	      dump ("r   ", r);
93 	      dump ("rref", rr);
94 	      dump ("q   ", q);
95 	      dump ("qref", rq);
96 	      abort ();
97 	    }
98 	  mpz_set_si (q, -5);
99 	  div_q[j] (q, a, b);
100 	  if (mpz_cmp (q, rq))
101 	    {
102 	      fprintf (stderr, "mpz_%cdiv_q failed:\n", name[j]);
103 	      dump ("a", a);
104 	      dump ("b", b);
105 	      dump ("q   ", q);
106 	      dump ("qref", rq);
107 	      abort ();
108 	    }
109 	  mpz_set_ui (r, ~5);
110 	  div_r[j] (r, a, b);
111 	  if (mpz_cmp (r, rr))
112 	    {
113 	      fprintf (stderr, "mpz_%cdiv_r failed:\n", name[j]);
114 	      dump ("a", a);
115 	      dump ("b", b);
116 	      dump ("r   ", r);
117 	      dump ("rref", rr);
118 	      abort ();
119 	    }
120 
121 	  if (j == 0)		/* do this once, not for all roundings */
122 	    {
123 	      div_p = mpz_divisible_p (a, b);
124 	      if ((mpz_sgn (r) == 0) ^ (div_p != 0))
125 		{
126 		  fprintf (stderr, "mpz_divisible_p failed:\n");
127 		  dump ("a", a);
128 		  dump ("b", b);
129 		  dump ("r   ", r);
130 		  abort ();
131 		}
132 	    }
133 
134 	  mpz_set_si (r, -6);
135 	  if (j == 0 && mpz_sgn (b) < 0)  /* ceil, negative divisor */
136 	    {
137 	      mpz_mod (r, a, b);
138 	      if (mpz_cmp (r, rr))
139 		{
140 		  fprintf (stderr, "mpz_mod failed:\n");
141 		  dump ("a", a);
142 		  dump ("b", b);
143 		  dump ("r   ", r);
144 		  dump ("rref", rr);
145 		  abort ();
146 		}
147 	    }
148 
149 	  if (j == 1 && mpz_sgn (b) > 0) /* floor, positive divisor */
150 	    {
151 	      mpz_mod (r, a, b);
152 	      if (mpz_cmp (r, rr))
153 		{
154 		  fprintf (stderr, "mpz_mod failed:\n");
155 		  dump ("a", a);
156 		  dump ("b", b);
157 		  dump ("r   ", r);
158 		  dump ("rref", rr);
159 		  abort ();
160 		}
161 	    }
162 
163 	  if (mpz_fits_ulong_p (b))
164 	    {
165 	      unsigned long rl;
166 
167 	      mpz_set_si (r, -7);
168 	      mpz_set_ui (q, ~7);
169 	      rl = div_qr_ui[j] (q, r, a, mpz_get_ui (b));
170 	      if (rl != mpz_get_ui (rr)
171 		  || mpz_cmp (r, rr) || mpz_cmp (q, rq))
172 		{
173 		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
174 		  dump ("a", a);
175 		  dump ("b", b);
176 		  fprintf(stderr, "rl   = %lx\n", rl);
177 		  dump ("r   ", r);
178 		  dump ("rref", rr);
179 		  dump ("q   ", q);
180 		  dump ("qref", rq);
181 		  abort ();
182 		}
183 
184 	      mpz_set_si (q, 3);
185 	      rl = div_q_ui[j] (q, a, mpz_get_ui (b));
186 	      if (rl != mpz_get_ui (rr) || mpz_cmp (q, rq))
187 		{
188 		  fprintf (stderr, "mpz_%cdiv_q_ui failed:\n", name[j]);
189 		  dump ("a", a);
190 		  dump ("b", b);
191 		  fprintf(stderr, "rl   = %lx\n", rl);
192 		  dump ("rref", rr);
193 		  dump ("q   ", q);
194 		  dump ("qref", rq);
195 		  abort ();
196 		}
197 
198 	      mpz_set_ui (r, 7);
199 	      rl = div_r_ui[j] (r, a, mpz_get_ui (b));
200 	      if (rl != mpz_get_ui (rr) || mpz_cmp (r, rr))
201 		{
202 		  fprintf (stderr, "mpz_%cdiv_r_ui failed:\n", name[j]);
203 		  dump ("a", a);
204 		  dump ("b", b);
205 		  fprintf(stderr, "rl   = %lx\n", rl);
206 		  dump ("r   ", r);
207 		  dump ("rref", rr);
208 		  abort ();
209 		}
210 
211 	      rl = div_ui[j] (a, mpz_get_ui (b));
212 	      if (rl != mpz_get_ui (rr))
213 		{
214 		  fprintf (stderr, "mpz_%cdiv_ui failed:\n", name[j]);
215 		  dump ("a", a);
216 		  dump ("b", b);
217 		  fprintf(stderr, "rl   = %lx\n", rl);
218 		  dump ("rref", rr);
219 		  abort ();
220 		}
221 
222 	      if (j == 0)	/* do this once, not for all roundings */
223 		{
224 		  div_p = mpz_divisible_ui_p (a, mpz_get_ui (b));
225 		  if ((mpz_sgn (r) == 0) ^ (div_p != 0))
226 		    {
227 		      fprintf (stderr, "mpz_divisible_ui_p failed:\n");
228 		      dump ("a", a);
229 		      dump ("b", b);
230 		      dump ("r   ", r);
231 		      abort ();
232 		    }
233 		}
234 
235 	      if (j == 1)	/* floor */
236 		{
237 		  mpz_set_si (r, -2);
238 		  mpz_mod_ui (r, a, mpz_get_ui (b));
239 		  if (mpz_cmp (r, rr))
240 		    {
241 		      fprintf (stderr, "mpz_mod failed:\n");
242 		      dump ("a", a);
243 		      dump ("b", b);
244 		      dump ("r   ", r);
245 		      dump ("rref", rr);
246 		      abort ();
247 		    }
248 		}
249 	    }
250 	}
251     }
252   mpz_clear (a);
253   mpz_clear (b);
254   mpz_clear (r);
255   mpz_clear (q);
256   mpz_clear (rr);
257   mpz_clear (rq);
258 }
259