Import upstream 5.1.3.
[platform/upstream/gmp.git] / mini-gmp / tests / t-div.c
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 }