xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-div.c (revision 212397c69a103ae7e5eafa8731ddfae671d2dee7)
1 /*
2 
3 Copyright 2012, 2013 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 http://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 static void
30 dump (const char *label, const mpz_t x)
31 {
32   char *buf = mpz_get_str (NULL, 16, x);
33   fprintf (stderr, "%s: %s\n", label, buf);
34   testfree (buf);
35 }
36 
37 typedef void div_qr_func (mpz_t, mpz_t, const mpz_t, const mpz_t);
38 typedef unsigned long div_qr_ui_func (mpz_t, mpz_t, const mpz_t, unsigned long);
39 typedef void div_func (mpz_t, const mpz_t, const mpz_t);
40 typedef unsigned long div_x_ui_func (mpz_t, const mpz_t, unsigned long);
41 typedef unsigned long div_ui_func (const mpz_t, unsigned long);
42 
43 void
44 testmain (int argc, char **argv)
45 {
46   unsigned i;
47   mpz_t a, b, q, r, rq, rr;
48   int div_p;
49 
50   mpz_init (a);
51   mpz_init (b);
52   mpz_init (r);
53   mpz_init (q);
54   mpz_init (rr);
55   mpz_init (rq);
56 
57   for (i = 0; i < COUNT; i++)
58     {
59       unsigned j;
60       for (j = 0; j < 3; j++)
61 	{
62 	  static const enum hex_random_op ops[3] = { OP_CDIV, OP_FDIV, OP_TDIV };
63 	  static const char name[3] = { 'c', 'f', 't'};
64 	  static div_qr_func * const div_qr [3] =
65 	    {
66 	      mpz_cdiv_qr, mpz_fdiv_qr, mpz_tdiv_qr
67 	    };
68 	  static div_qr_ui_func  *div_qr_ui[3] =
69 	    {
70 	      mpz_cdiv_qr_ui, mpz_fdiv_qr_ui, mpz_tdiv_qr_ui
71 	    };
72 	  static div_func * const div_q [3] =
73 	    {
74 	      mpz_cdiv_q, mpz_fdiv_q, mpz_tdiv_q
75 	    };
76 	  static div_x_ui_func  *div_q_ui[3] =
77 	    {
78 	      mpz_cdiv_q_ui, mpz_fdiv_q_ui, mpz_tdiv_q_ui
79 	    };
80 	  static div_func * const div_r [3] =
81 	    {
82 	      mpz_cdiv_r, mpz_fdiv_r, mpz_tdiv_r
83 	    };
84 	  static div_x_ui_func  *div_r_ui[3] =
85 	    {
86 	      mpz_cdiv_r_ui, mpz_fdiv_r_ui, mpz_tdiv_r_ui
87 	    };
88 	  static div_ui_func  *div_ui[3] =
89 	    {
90 	      mpz_cdiv_ui, mpz_fdiv_ui, mpz_tdiv_ui
91 	    };
92 
93 	  mini_random_op4 (ops[j], MAXBITS, a, b, rq, rr);
94 	  div_qr[j] (q, r, a, b);
95 	  if (mpz_cmp (r, rr) || mpz_cmp (q, rq))
96 	    {
97 	      fprintf (stderr, "mpz_%cdiv_qr failed:\n", name[j]);
98 	      dump ("a", a);
99 	      dump ("b", b);
100 	      dump ("r   ", r);
101 	      dump ("rref", rr);
102 	      dump ("q   ", q);
103 	      dump ("qref", rq);
104 	      abort ();
105 	    }
106 	  mpz_set_si (q, -5);
107 	  div_q[j] (q, a, b);
108 	  if (mpz_cmp (q, rq))
109 	    {
110 	      fprintf (stderr, "mpz_%cdiv_q failed:\n", name[j]);
111 	      dump ("a", a);
112 	      dump ("b", b);
113 	      dump ("q   ", q);
114 	      dump ("qref", rq);
115 	      abort ();
116 	    }
117 	  mpz_set_ui (r, ~5);
118 	  div_r[j] (r, a, b);
119 	  if (mpz_cmp (r, rr))
120 	    {
121 	      fprintf (stderr, "mpz_%cdiv_r failed:\n", name[j]);
122 	      dump ("a", a);
123 	      dump ("b", b);
124 	      dump ("r   ", r);
125 	      dump ("rref", rr);
126 	      abort ();
127 	    }
128 
129 	  if (j == 0)		/* do this once, not for all roundings */
130 	    {
131 	      div_p = mpz_divisible_p (a, b);
132 	      if ((mpz_sgn (r) == 0) ^ (div_p != 0))
133 		{
134 		  fprintf (stderr, "mpz_divisible_p failed:\n");
135 		  dump ("a", a);
136 		  dump ("b", b);
137 		  dump ("r   ", r);
138 		  abort ();
139 		}
140 	    }
141 
142 	  if (j == 0 && mpz_sgn (b) < 0)  /* ceil, negative divisor */
143 	    {
144 	      mpz_mod (r, a, b);
145 	      if (mpz_cmp (r, rr))
146 		{
147 		  fprintf (stderr, "mpz_mod failed:\n");
148 		  dump ("a", a);
149 		  dump ("b", b);
150 		  dump ("r   ", r);
151 		  dump ("rref", rr);
152 		  abort ();
153 		}
154 	    }
155 
156 	  if (j == 1 && mpz_sgn (b) > 0) /* floor, positive divisor */
157 	    {
158 	      mpz_mod (r, a, b);
159 	      if (mpz_cmp (r, rr))
160 		{
161 		  fprintf (stderr, "mpz_mod failed:\n");
162 		  dump ("a", a);
163 		  dump ("b", b);
164 		  dump ("r   ", r);
165 		  dump ("rref", rr);
166 		  abort ();
167 		}
168 	    }
169 
170 	  if (mpz_fits_ulong_p (b))
171 	    {
172 	      mp_limb_t rl;
173 
174 	      rl = div_qr_ui[j] (q, r, a, mpz_get_ui (b));
175 	      if (rl != mpz_get_ui (rr)
176 		  || mpz_cmp (r, rr) || mpz_cmp (q, rq))
177 		{
178 		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
179 		  dump ("a", a);
180 		  dump ("b", b);
181 		  fprintf(stderr, "rl   = %lx\n", rl);
182 		  dump ("r   ", r);
183 		  dump ("rref", rr);
184 		  dump ("q   ", q);
185 		  dump ("qref", rq);
186 		  abort ();
187 		}
188 
189 	      mpz_set_si (q, 3);
190 	      rl = div_q_ui[j] (q, a, mpz_get_ui (b));
191 	      if (rl != mpz_get_ui (rr) || mpz_cmp (q, rq))
192 		{
193 		  fprintf (stderr, "mpz_%cdiv_q_ui failed:\n", name[j]);
194 		  dump ("a", a);
195 		  dump ("b", b);
196 		  fprintf(stderr, "rl   = %lx\n", rl);
197 		  dump ("rref", rr);
198 		  dump ("q   ", q);
199 		  dump ("qref", rq);
200 		  abort ();
201 		}
202 
203 	      mpz_set_ui (r, 7);
204 	      rl = div_r_ui[j] (r, a, mpz_get_ui (b));
205 	      if (rl != mpz_get_ui (rr) || mpz_cmp (r, rr))
206 		{
207 		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
208 		  dump ("a", a);
209 		  dump ("b", b);
210 		  fprintf(stderr, "rl   = %lx\n", rl);
211 		  dump ("r   ", r);
212 		  dump ("rref", rr);
213 		  abort ();
214 		}
215 
216 	      rl = div_ui[j] (a, mpz_get_ui (b));
217 	      if (rl != mpz_get_ui (rr))
218 		{
219 		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
220 		  dump ("a", a);
221 		  dump ("b", b);
222 		  fprintf(stderr, "rl   = %lx\n", rl);
223 		  dump ("rref", rr);
224 		  abort ();
225 		}
226 
227 	      if (j == 0)	/* do this once, not for all roundings */
228 		{
229 		  div_p = mpz_divisible_ui_p (a, mpz_get_ui (b));
230 		  if ((mpz_sgn (r) == 0) ^ (div_p != 0))
231 		    {
232 		      fprintf (stderr, "mpz_divisible_ui_p failed:\n");
233 		      dump ("a", a);
234 		      dump ("b", b);
235 		      dump ("r   ", r);
236 		      abort ();
237 		    }
238 		}
239 
240 	      if (j == 1)	/* floor */
241 		{
242 		  mpz_mod_ui (r, a, mpz_get_ui (b));
243 		  if (mpz_cmp (r, rr))
244 		    {
245 		      fprintf (stderr, "mpz_mod failed:\n");
246 		      dump ("a", a);
247 		      dump ("b", b);
248 		      dump ("r   ", r);
249 		      dump ("rref", rr);
250 		      abort ();
251 		    }
252 		}
253 	    }
254 	}
255     }
256   mpz_clear (a);
257   mpz_clear (b);
258   mpz_clear (r);
259   mpz_clear (q);
260   mpz_clear (rr);
261   mpz_clear (rq);
262 }
263