xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-aorsmul.c (revision 8450a7c42673d65e3b1f6560d3b6ecd317a6cbe8)
1 /* Test mpz_addmul, mpz_addmul_ui, mpz_submul, mpz_submul_ui.
2 
3 Copyright 2001, 2002 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 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "gmp.h"
26 #include "gmp-impl.h"
27 #include "tests.h"
28 
29 
30 #define M GMP_NUMB_MAX
31 
32 
33 void
34 check_one_inplace (mpz_srcptr w, mpz_srcptr y)
35 {
36   mpz_t  want, got;
37 
38   mpz_init (want);
39   mpz_init (got);
40 
41   mpz_mul (want, w, y);
42   mpz_add (want, w, want);
43   mpz_set (got, w);
44   mpz_addmul (got, got, y);
45   MPZ_CHECK_FORMAT (got);
46   if (mpz_cmp (want, got) != 0)
47     {
48       printf ("mpz_addmul inplace fail\n");
49     fail:
50       mpz_trace ("w", w);
51       mpz_trace ("y", y);
52       mpz_trace ("want", want);
53       mpz_trace ("got ", got);
54       abort ();
55     }
56 
57   mpz_mul (want, w, y);
58   mpz_sub (want, w, want);
59   mpz_set (got, w);
60   mpz_submul (got, got, y);
61   MPZ_CHECK_FORMAT (got);
62   if (mpz_cmp (want, got) != 0)
63     {
64       printf ("mpz_submul inplace fail\n");
65       goto fail;
66     }
67 
68   mpz_clear (want);
69   mpz_clear (got);
70 }
71 
72 void
73 check_one_ui_inplace (mpz_ptr w, unsigned long y)
74 {
75   mpz_t  want, got;
76 
77   mpz_init (want);
78   mpz_init (got);
79 
80   mpz_mul_ui (want, w, (unsigned long) y);
81   mpz_add (want, w, want);
82   mpz_set (got, w);
83   mpz_addmul_ui (got, got, (unsigned long) y);
84   MPZ_CHECK_FORMAT (got);
85   if (mpz_cmp (want, got) != 0)
86     {
87       printf ("mpz_addmul_ui fail\n");
88     fail:
89       mpz_trace ("w", w);
90       printf    ("y=0x%lX   %lu\n", y, y);
91       mpz_trace ("want", want);
92       mpz_trace ("got ", got);
93       abort ();
94     }
95 
96   mpz_mul_ui (want, w, y);
97   mpz_sub (want, w, want);
98   mpz_set (got, w);
99   mpz_submul_ui (got, got, y);
100   MPZ_CHECK_FORMAT (got);
101   if (mpz_cmp (want, got) != 0)
102     {
103       printf ("mpz_submul_ui fail\n");
104       goto fail;
105     }
106 
107   mpz_clear (want);
108   mpz_clear (got);
109 }
110 
111 void
112 check_all_inplace (mpz_ptr w, mpz_ptr y)
113 {
114   int  wneg, yneg;
115 
116   MPZ_CHECK_FORMAT (w);
117   MPZ_CHECK_FORMAT (y);
118 
119   for (wneg = 0; wneg < 2; wneg++)
120     {
121       for (yneg = 0; yneg < 2; yneg++)
122         {
123           check_one_inplace (w, y);
124 
125           if (mpz_fits_ulong_p (y))
126             check_one_ui_inplace (w, mpz_get_ui (y));
127 
128           mpz_neg (y, y);
129         }
130       mpz_neg (w, w);
131     }
132 }
133 
134 void
135 check_one (mpz_srcptr w, mpz_srcptr x, mpz_srcptr y)
136 {
137   mpz_t  want, got;
138 
139   mpz_init (want);
140   mpz_init (got);
141 
142   mpz_mul (want, x, y);
143   mpz_add (want, w, want);
144   mpz_set (got, w);
145   mpz_addmul (got, x, y);
146   MPZ_CHECK_FORMAT (got);
147   if (mpz_cmp (want, got) != 0)
148     {
149       printf ("mpz_addmul fail\n");
150     fail:
151       mpz_trace ("w", w);
152       mpz_trace ("x", x);
153       mpz_trace ("y", y);
154       mpz_trace ("want", want);
155       mpz_trace ("got ", got);
156       abort ();
157     }
158 
159   mpz_mul (want, x, y);
160   mpz_sub (want, w, want);
161   mpz_set (got, w);
162   mpz_submul (got, x, y);
163   MPZ_CHECK_FORMAT (got);
164   if (mpz_cmp (want, got) != 0)
165     {
166       printf ("mpz_submul fail\n");
167       goto fail;
168     }
169 
170   mpz_clear (want);
171   mpz_clear (got);
172 }
173 
174 void
175 check_one_ui (mpz_ptr w, mpz_ptr x, unsigned long y)
176 {
177   mpz_t  want, got;
178 
179   mpz_init (want);
180   mpz_init (got);
181 
182   mpz_mul_ui (want, x, (unsigned long) y);
183   mpz_add (want, w, want);
184   mpz_set (got, w);
185   mpz_addmul_ui (got, x, (unsigned long) y);
186   MPZ_CHECK_FORMAT (got);
187   if (mpz_cmp (want, got) != 0)
188     {
189       printf ("mpz_addmul_ui fail\n");
190     fail:
191       mpz_trace ("w", w);
192       mpz_trace ("x", x);
193       printf    ("y=0x%lX   %lu\n", y, y);
194       mpz_trace ("want", want);
195       mpz_trace ("got ", got);
196       abort ();
197     }
198 
199   mpz_mul_ui (want, x, y);
200   mpz_sub (want, w, want);
201   mpz_set (got, w);
202   mpz_submul_ui (got, x, y);
203   MPZ_CHECK_FORMAT (got);
204   if (mpz_cmp (want, got) != 0)
205     {
206       printf ("mpz_submul_ui fail\n");
207       goto fail;
208     }
209 
210   mpz_clear (want);
211   mpz_clear (got);
212 }
213 
214 
215 void
216 check_all (mpz_ptr w, mpz_ptr x, mpz_ptr y)
217 {
218   int    swap, wneg, xneg, yneg;
219 
220   MPZ_CHECK_FORMAT (w);
221   MPZ_CHECK_FORMAT (x);
222   MPZ_CHECK_FORMAT (y);
223 
224   for (swap = 0; swap < 2; swap++)
225     {
226       for (wneg = 0; wneg < 2; wneg++)
227         {
228           for (xneg = 0; xneg < 2; xneg++)
229             {
230               for (yneg = 0; yneg < 2; yneg++)
231                 {
232                   check_one (w, x, y);
233 
234                   if (mpz_fits_ulong_p (y))
235                     check_one_ui (w, x, mpz_get_ui (y));
236 
237                   mpz_neg (y, y);
238                 }
239               mpz_neg (x, x);
240             }
241           mpz_neg (w, w);
242         }
243       mpz_swap (x, y);
244     }
245 }
246 
247 void
248 check_data_inplace_ui (void)
249 {
250   static const struct {
251     mp_limb_t      w[6];
252     unsigned long  y;
253 
254   } data[] = {
255 
256     { { 0 }, 0 },
257     { { 0 }, 1 },
258     { { 1 }, 1 },
259     { { 2 }, 1 },
260 
261     { { 123 }, 1 },
262     { { 123 }, ULONG_MAX },
263     { { M }, 1 },
264     { { M }, ULONG_MAX },
265 
266     { { 123, 456 }, 1 },
267     { { M, M }, 1 },
268     { { 123, 456 }, ULONG_MAX },
269     { { M, M }, ULONG_MAX },
270 
271     { { 123, 456, 789 }, 1 },
272     { { M, M, M }, 1 },
273     { { 123, 456, 789 }, ULONG_MAX },
274     { { M, M, M }, ULONG_MAX },
275   };
276 
277   mpz_t  w, y;
278   int    i;
279 
280   mpz_init (w);
281   mpz_init (y);
282 
283   for (i = 0; i < numberof (data); i++)
284     {
285       mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
286       mpz_set_ui (y, data[i].y);
287       check_all_inplace (w, y);
288     }
289 
290   mpz_clear (w);
291   mpz_clear (y);
292 }
293 
294 void
295 check_data (void)
296 {
297   static const struct {
298     mp_limb_t  w[6];
299     mp_limb_t  x[6];
300     mp_limb_t  y[6];
301 
302   } data[] = {
303 
304     /* reducing to zero */
305     { { 1 }, { 1 }, { 1 } },
306     { { 2 }, { 1 }, { 2 } },
307     { { 0,1 }, { 0,1 }, { 1 } },
308 
309     /* reducing to 1 */
310     { { 0,1 },       { M },       { 1 } },
311     { { 0,0,1 },     { M,M },     { 1 } },
312     { { 0,0,0,1 },   { M,M,M },   { 1 } },
313     { { 0,0,0,0,1 }, { M,M,M,M }, { 1 } },
314 
315     /* reducing to -1 */
316     { { M },       { 0,1 },       { 1 } },
317     { { M,M },     { 0,0,1 },     { 1 } },
318     { { M,M,M },   { 0,0,0,1 },   { 1 } },
319     { { M,M,M,M }, { 0,0,0,0,1 }, { 1 } },
320 
321     /* carry out of addmul */
322     { { M },     { 1 }, { 1 } },
323     { { M,M },   { 1 }, { 1 } },
324     { { M,M,M }, { 1 }, { 1 } },
325 
326     /* borrow from submul */
327     { { 0,1 },     { 1 }, { 1 } },
328     { { 0,0,1 },   { 1 }, { 1 } },
329     { { 0,0,0,1 }, { 1 }, { 1 } },
330 
331     /* borrow from submul */
332     { { 0,0,1 },     { 0,1 }, { 1 } },
333     { { 0,0,0,1 },   { 0,1 }, { 1 } },
334     { { 0,0,0,0,1 }, { 0,1 }, { 1 } },
335 
336     /* more borrow from submul */
337     { { M }, { 0,1 },       { 1 } },
338     { { M }, { 0,0,1 },     { 1 } },
339     { { M }, { 0,0,0,1 },   { 1 } },
340     { { M }, { 0,0,0,0,1 }, { 1 } },
341 
342     /* big borrow from submul */
343     { { 0,0,1 },     { M,M }, { M } },
344     { { 0,0,0,1 },   { M,M }, { M } },
345     { { 0,0,0,0,1 }, { M,M }, { M } },
346 
347     /* small w */
348     { { 0,1 }, { M,M },       { M } },
349     { { 0,1 }, { M,M,M },     { M } },
350     { { 0,1 }, { M,M,M,M },   { M } },
351     { { 0,1 }, { M,M,M,M,M }, { M } },
352   };
353 
354   mpz_t  w, x, y;
355   int    i;
356 
357   mpz_init (w);
358   mpz_init (x);
359   mpz_init (y);
360 
361   for (i = 0; i < numberof (data); i++)
362     {
363       mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
364       mpz_set_n (x, data[i].x, (mp_size_t) numberof(data[i].x));
365       mpz_set_n (y, data[i].y, (mp_size_t) numberof(data[i].y));
366       check_all (w, x, y);
367     }
368 
369   mpz_clear (w);
370   mpz_clear (x);
371   mpz_clear (y);
372 }
373 
374 
375 void
376 check_random (int argc, char *argv[])
377 {
378   gmp_randstate_ptr rands = RANDS;
379   mpz_t  w, x, y;
380   int    i, reps = 2000;
381 
382   mpz_init (w);
383   mpz_init (x);
384   mpz_init (y);
385 
386   if (argc == 2)
387     reps = atoi (argv[1]);
388 
389   for (i = 0; i < reps; i++)
390     {
391       mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
392       mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
393       mpz_errandomb (y, rands, 5*GMP_LIMB_BITS);
394       check_all (w, x, y);
395       check_all_inplace (w, y);
396 
397       mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
398       mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
399       mpz_errandomb (y, rands, BITS_PER_ULONG);
400       check_all (w, x, y);
401       check_all_inplace (w, y);
402     }
403 
404   mpz_clear (w);
405   mpz_clear (x);
406   mpz_clear (y);
407 }
408 
409 
410 int
411 main (int argc, char *argv[])
412 {
413   tests_start ();
414   mp_trace_base = -16;
415 
416   check_data ();
417   check_data_inplace_ui ();
418   check_random (argc, argv);
419 
420   tests_end ();
421   exit (0);
422 }
423