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