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