source: trunk/third/gmp/tests/mpz/reuse.c @ 18191

Revision 18191, 15.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18190, which included commits to RCS files with non-trunk default branches.
Line 
1/* Test that routines allow reusing a source variable as destination.
2
3   Test all relevant functions except:
4        mpz_bin_ui
5        mpz_nextprime
6        mpz_mul_si
7        mpz_addmul_ui (should this really allow a+=a*c?)
8
9Copyright 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
10
11This file is part of the GNU MP Library.
12
13The GNU MP Library is free software; you can redistribute it and/or modify
14it under the terms of the GNU Lesser General Public License as published by
15the Free Software Foundation; either version 2.1 of the License, or (at your
16option) any later version.
17
18The GNU MP Library is distributed in the hope that it will be useful, but
19WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
21License for more details.
22
23You should have received a copy of the GNU Lesser General Public License
24along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
25the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26MA 02111-1307, USA. */
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#include "gmp.h"
33#include "gmp-impl.h"
34#include "tests.h"
35
36#if __GMP_LIBGMP_DLL
37
38/* FIXME: When linking to a DLL libgmp, mpz_add etc can't be used as
39   initializers for global variables because they're effectively global
40   variables (function pointers) themselves.  Perhaps calling a test
41   function successively with mpz_add etc would be better.  */
42
43int
44main (void)
45{
46  printf ("Test suppressed for windows DLL\n");
47  exit (0);
48}
49
50
51#else /* ! DLL_EXPORT */
52
53void dump _PROTO ((char *, mpz_t, mpz_t, mpz_t));
54
55typedef void (*dss_func) _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
56typedef void (*dsi_func) _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
57typedef unsigned long int (*dsi_div_func) _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
58typedef unsigned long int (*ddsi_div_func) _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
59typedef void (*ddss_div_func) _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
60typedef void (*ds_func) _PROTO ((mpz_ptr, mpz_srcptr));
61
62
63void
64mpz_xinvert (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
65{
66  int res;
67  res = mpz_invert (r, a, b);
68  if (res == 0)
69    mpz_set_ui (r, 0);
70}
71
72dss_func dss_funcs[] =
73{
74  mpz_add, mpz_sub, mpz_mul,
75  mpz_cdiv_q, mpz_cdiv_r, mpz_fdiv_q, mpz_fdiv_r, mpz_tdiv_q, mpz_tdiv_r,
76  mpz_xinvert,
77  mpz_gcd, mpz_lcm, mpz_and, mpz_ior, mpz_xor
78};
79char *dss_func_names[] =
80{
81  "mpz_add", "mpz_sub", "mpz_mul",
82  "mpz_cdiv_q", "mpz_cdiv_r", "mpz_fdiv_q", "mpz_fdiv_r", "mpz_tdiv_q", "mpz_tdiv_r",
83  "mpz_xinvert",
84  "mpz_gcd", "mpz_lcm", "mpz_and", "mpz_ior", "mpz_xor"
85};
86char dss_func_division[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
87
88dsi_func dsi_funcs[] =
89{
90  /* Don't change order here without changing the code in main(). */
91  mpz_add_ui, mpz_mul_ui, mpz_sub_ui,
92  mpz_fdiv_q_2exp, mpz_fdiv_r_2exp,
93  mpz_cdiv_q_2exp, mpz_cdiv_r_2exp,
94  mpz_tdiv_q_2exp, mpz_tdiv_r_2exp,
95  mpz_mul_2exp,
96  mpz_pow_ui
97};
98char *dsi_func_names[] =
99{
100  "mpz_add_ui", "mpz_mul_ui", "mpz_sub_ui",
101  "mpz_fdiv_q_2exp", "mpz_fdiv_r_2exp",
102  "mpz_cdiv_q_2exp", "mpz_cdiv_r_2exp",
103  "mpz_tdiv_q_2exp", "mpz_tdiv_r_2exp",
104  "mpz_mul_2exp",
105  "mpz_pow_ui"
106};
107
108dsi_div_func dsi_div_funcs[] =
109{
110  mpz_cdiv_q_ui, mpz_cdiv_r_ui,
111  mpz_fdiv_q_ui, mpz_fdiv_r_ui,
112  mpz_tdiv_q_ui, mpz_tdiv_r_ui
113};
114char *dsi_div_func_names[] =
115{
116  "mpz_cdiv_q_ui", "mpz_cdiv_r_ui",
117  "mpz_fdiv_q_ui", "mpz_fdiv_r_ui",
118  "mpz_tdiv_q_ui", "mpz_tdiv_r_ui"
119};
120
121ddsi_div_func ddsi_div_funcs[] =
122{
123  mpz_cdiv_qr_ui,
124  mpz_fdiv_qr_ui,
125  mpz_tdiv_qr_ui
126};
127char *ddsi_div_func_names[] =
128{
129  "mpz_cdiv_qr_ui",
130  "mpz_fdiv_qr_ui",
131  "mpz_tdiv_qr_ui"
132};
133
134ddss_div_func ddss_div_funcs[] =
135{
136  mpz_cdiv_qr,
137  mpz_fdiv_qr,
138  mpz_tdiv_qr
139};
140char *ddss_div_func_names[] =
141{
142  "mpz_cdiv_qr",
143  "mpz_fdiv_qr",
144  "mpz_tdiv_qr"
145};
146
147ds_func ds_funcs[] =
148{
149  mpz_abs, mpz_com, mpz_neg, mpz_sqrt
150};
151char *ds_func_names[] =
152{
153  "mpz_abs", "mpz_com", "mpz_neg", "mpz_sqrt"
154};
155
156
157/* Really use `defined (__STDC__)' here; we want it to be true for Sun C */
158#if defined (__STDC__) || defined (__cplusplus)
159#define FAIL(class,indx,op1,op2,op3) \
160  do {                                                                  \
161  class##_funcs[indx] = 0;                                              \
162  dump (class##_func_names[indx], op1, op2, op3);                       \
163  failures++;                                                           \
164  } while (0)
165#define FAIL2(fname,op1,op2,op3) \
166  do {                                                                  \
167  dump (#fname, op1, op2, op3);                                 \
168  failures++;                                                           \
169  } while (0)
170#else
171#define FAIL(class,indx,op1,op2,op3) \
172  do {                                                                  \
173  class/**/_funcs[indx] = 0;                                            \
174  dump (class/**/_func_names[indx], op1, op2, op3);             \
175  failures++;                                                           \
176  } while (0)
177#define FAIL2(fname,op1,op2,op3) \
178  do {                                                                  \
179  dump ("fname", op1, op2, op3);                                        \
180  failures++;                                                           \
181  } while (0)
182#endif
183
184
185int
186main (int argc, char **argv)
187{
188  int i;
189  int pass, reps = 1000;
190  mpz_t in1, in2, in3;
191  unsigned long int in2i;
192  mp_size_t size;
193  mpz_t res1, res2, res3;
194  mpz_t ref1, ref2, ref3;
195  mpz_t t;
196  unsigned long int r1, r2;
197  long failures = 0;
198  gmp_randstate_ptr rands;
199  mpz_t bs;
200  unsigned long bsi, size_range;
201
202  tests_start ();
203  rands = RANDS;
204
205  mpz_init (bs);
206
207  if (argc == 2)
208     reps = atoi (argv[1]);
209
210  mpz_init (in1);
211  mpz_init (in2);
212  mpz_init (in3);
213  mpz_init (ref1);
214  mpz_init (ref2);
215  mpz_init (ref3);
216  mpz_init (res1);
217  mpz_init (res2);
218  mpz_init (res3);
219  mpz_init (t);
220
221  for (pass = 1; pass <= reps; pass++)
222    {
223      mpz_urandomb (bs, rands, 32);
224      size_range = mpz_get_ui (bs) % 10 + 2;
225
226      mpz_urandomb (bs, rands, size_range);
227      size = mpz_get_ui (bs);
228      mpz_rrandomb (in1, rands, size);
229
230      mpz_urandomb (bs, rands, size_range);
231      size = mpz_get_ui (bs);
232      mpz_rrandomb (in2, rands, size);
233
234      mpz_urandomb (bs, rands, size_range);
235      size = mpz_get_ui (bs);
236      mpz_rrandomb (in3, rands, size);
237
238      mpz_urandomb (bs, rands, 3);
239      bsi = mpz_get_ui (bs);
240      if ((bsi & 1) != 0)
241        mpz_neg (in1, in1);
242      if ((bsi & 1) != 0)
243        mpz_neg (in2, in2);
244      if ((bsi & 1) != 0)
245        mpz_neg (in3, in3);
246
247      for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
248        {
249          if (dss_funcs[i] == 0)
250            continue;
251          if (dss_func_division[i] && mpz_sgn (in2) == 0)
252            continue;
253
254          (dss_funcs[i]) (ref1, in1, in2);
255
256          mpz_set (res1, in1);
257          (dss_funcs[i]) (res1, res1, in2);
258          if (mpz_cmp (ref1, res1) != 0)
259            FAIL (dss, i, in1, in2, NULL);
260
261          mpz_set (res1, in2);
262          (dss_funcs[i]) (res1, in1, res1);
263          if (mpz_cmp (ref1, res1) != 0)
264            FAIL (dss, i, in1, in2, NULL);
265        }
266
267      for (i = 0; i < sizeof (ddss_div_funcs) / sizeof (ddss_div_func); i++)
268        {
269          if (ddss_div_funcs[i] == 0)
270            continue;
271          if (mpz_sgn (in2) == 0)
272            continue;
273
274          (ddss_div_funcs[i]) (ref1, ref2, in1, in2);
275
276          mpz_set (res1, in1);
277          (ddss_div_funcs[i]) (res1, res2, res1, in2);
278          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
279            FAIL (ddss_div, i, in1, in2, NULL);
280
281          mpz_set (res2, in1);
282          (ddss_div_funcs[i]) (res1, res2, res2, in2);
283          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
284            FAIL (ddss_div, i, in1, in2, NULL);
285
286          mpz_set (res1, in2);
287          (ddss_div_funcs[i]) (res1, res2, in1, res1);
288          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
289            FAIL (ddss_div, i, in1, in2, NULL);
290
291          mpz_set (res2, in2);
292          (ddss_div_funcs[i]) (res1, res2, in1, res2);
293          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
294            FAIL (ddss_div, i, in1, in2, NULL);
295        }
296
297      for (i = 0; i < sizeof (ds_funcs) / sizeof (ds_func); i++)
298        {
299          if (ds_funcs[i] == 0)
300            continue;
301          if (strcmp (ds_func_names[i], "mpz_sqrt") == 0
302              && mpz_sgn (in1) < 0)
303            continue;
304
305          (ds_funcs[i]) (ref1, in1);
306
307          mpz_set (res1, in1);
308          (ds_funcs[i]) (res1, res1);
309          if (mpz_cmp (ref1, res1) != 0)
310            FAIL (ds, i, in1, in2, NULL);
311        }
312
313      in2i = mpz_get_ui (in2);
314
315      for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
316        {
317          if (dsi_funcs[i] == 0)
318            continue;
319          if (strcmp (dsi_func_names[i], "mpz_fdiv_q_2exp") == 0)
320            /* Limit exponent to something reasonable for the division
321               functions.  Without this, we'd  normally shift things off
322               the end and just generate the trivial values 1, 0, -1.  */
323            in2i %= 0x1000;
324          if (strcmp (dsi_func_names[i], "mpz_mul_2exp") == 0)
325            /* Limit exponent more for mpz_mul_2exp to save time.  */
326            in2i %= 0x100;
327          if (strcmp (dsi_func_names[i], "mpz_pow_ui") == 0)
328            /* Limit exponent yet more for mpz_pow_ui to save time.  */
329            in2i %= 0x10;
330
331          (dsi_funcs[i]) (ref1, in1, in2i);
332
333          mpz_set (res1, in1);
334          (dsi_funcs[i]) (res1, res1, in2i);
335          if (mpz_cmp (ref1, res1) != 0)
336            FAIL (dsi, i, in1, in2, NULL);
337        }
338
339      if (in2i != 0)      /* Don't divide by 0.  */
340        {
341          for (i = 0; i < sizeof (dsi_div_funcs) / sizeof (dsi_div_funcs); i++)
342            {
343              r1 = (dsi_div_funcs[i]) (ref1, in1, in2i);
344
345              mpz_set (res1, in1);
346              r2 = (dsi_div_funcs[i]) (res1, res1, in2i);
347              if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
348                FAIL (dsi_div, i, in1, in2, NULL);
349            }
350
351          for (i = 0; i < sizeof (ddsi_div_funcs) / sizeof (ddsi_div_funcs); i++)
352            {
353              r1 = (ddsi_div_funcs[i]) (ref1, ref2, in1, in2i);
354
355              mpz_set (res1, in1);
356              r2 = (ddsi_div_funcs[i]) (res1, res2, res1, in2i);
357              if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
358                FAIL (ddsi_div, i, in1, in2, NULL);
359
360              mpz_set (res2, in1);
361              (ddsi_div_funcs[i]) (res1, res2, res2, in2i);
362              if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
363                FAIL (ddsi_div, i, in1, in2, NULL);
364            }
365        }
366
367      if (mpz_sgn (in1) >= 0)
368        {
369          mpz_sqrtrem (ref1, ref2, in1);
370
371          mpz_set (res1, in1);
372          mpz_sqrtrem (res1, res2, res1);
373          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
374            FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
375
376          mpz_set (res2, in1);
377          mpz_sqrtrem (res1, res2, res2);
378          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
379            FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
380        }
381
382      if (mpz_sgn (in1) >= 0)
383        {
384          mpz_root (ref1, in1, in2i % 0x100 + 1);
385
386          mpz_set (res1, in1);
387          mpz_root (res1, res1, in2i % 0x100 + 1);
388          if (mpz_cmp (ref1, res1) != 0)
389            FAIL2 (mpz_root, in1, in2, NULL);
390        }
391
392      if (pass < reps / 2)      /* run fewer tests since gcdext lots of time */
393        {
394          mpz_gcdext (ref1, ref2, ref3, in1, in2);
395
396          mpz_set (res1, in1);
397          mpz_gcdext (res1, res2, res3, res1, in2);
398          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
399              || mpz_cmp (ref3, res3) != 0)
400            FAIL2 (mpz_gcdext, in1, in2, NULL);
401
402          mpz_set (res2, in1);
403          mpz_gcdext (res1, res2, res3, res2, in2);
404          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
405              || mpz_cmp (ref3, res3) != 0)
406            FAIL2 (mpz_gcdext, in1, in2, NULL);
407
408          mpz_set (res3, in1);
409          mpz_gcdext (res1, res2, res3, res3, in2);
410          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
411              || mpz_cmp (ref3, res3) != 0)
412            FAIL2 (mpz_gcdext, in1, in2, NULL);
413
414          mpz_set (res1, in2);
415          mpz_gcdext (res1, res2, res3, in1, res1);
416          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
417              || mpz_cmp (ref3, res3) != 0)
418            FAIL2 (mpz_gcdext, in1, in2, NULL);
419
420          mpz_set (res2, in2);
421          mpz_gcdext (res1, res2, res3, in1, res2);
422          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
423              || mpz_cmp (ref3, res3) != 0)
424            FAIL2 (mpz_gcdext, in1, in2, NULL);
425
426          mpz_set (res3, in2);
427          mpz_gcdext (res1, res2, res3, in1, res3);
428          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
429              || mpz_cmp (ref3, res3) != 0)
430            FAIL2 (mpz_gcdext, in1, in2, NULL);
431
432          mpz_set (res1, in1);
433          mpz_gcdext (res1, res2, NULL, res1, in2);
434          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
435              || mpz_cmp (ref3, res3) != 0)
436            FAIL2 (mpz_gcdext, in1, in2, NULL);
437
438          mpz_set (res2, in1);
439          mpz_gcdext (res1, res2, NULL, res2, in2);
440          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
441              || mpz_cmp (ref3, res3) != 0)
442            FAIL2 (mpz_gcdext, in1, in2, NULL);
443
444          mpz_set (res1, in2);
445          mpz_gcdext (res1, res2, NULL, in1, res1);
446          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
447              || mpz_cmp (ref3, res3) != 0)
448            FAIL2 (mpz_gcdext, in1, in2, NULL);
449
450          mpz_set (res2, in2);
451          mpz_gcdext (res1, res2, NULL, in1, res2);
452          if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
453              || mpz_cmp (ref3, res3) != 0)
454            FAIL2 (mpz_gcdext, in1, in2, NULL);
455        }
456
457      /* Don't run mpz_powm for huge exponents or when undefined.  */
458      if (mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
459          && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
460        {
461          mpz_powm (ref1, in1, in2, in3);
462
463          mpz_set (res1, in1);
464          mpz_powm (res1, res1, in2, in3);
465          if (mpz_cmp (ref1, res1) != 0)
466            FAIL2 (mpz_powm, in1, in2, in3);
467
468          mpz_set (res1, in2);
469          mpz_powm (res1, in1, res1, in3);
470          if (mpz_cmp (ref1, res1) != 0)
471            FAIL2 (mpz_powm, in1, in2, in3);
472
473          mpz_set (res1, in3);
474          mpz_powm (res1, in1, in2, res1);
475          if (mpz_cmp (ref1, res1) != 0)
476            FAIL2 (mpz_powm, in1, in2, in3);
477        }
478
479      /* Don't run mpz_powm_ui when undefined.  */
480      if (mpz_sgn (in3) != 0)
481        {
482          mpz_powm_ui (ref1, in1, in2i, in3);
483
484          mpz_set (res1, in1);
485          mpz_powm_ui (res1, res1, in2i, in3);
486          if (mpz_cmp (ref1, res1) != 0)
487            FAIL2 (mpz_powm_ui, in1, in2, in3);
488
489          mpz_set (res1, in3);
490          mpz_powm_ui (res1, in1, in2i, res1);
491          if (mpz_cmp (ref1, res1) != 0)
492            FAIL2 (mpz_powm_ui, in1, in2, in3);
493        }
494
495      {
496        r1 = mpz_gcd_ui (ref1, in1, in2i);
497
498        mpz_set (res1, in1);
499        r2 = mpz_gcd_ui (res1, res1, in2i);
500        if (mpz_cmp (ref1, res1) != 0)
501          FAIL2 (mpz_gcd_ui, in1, in2, NULL);
502      }
503
504      if (mpz_cmp_ui (in2, 1L) > 0 && mpz_sgn (in1) != 0)
505        {
506          /* Test mpz_remove */
507          mpz_remove (ref1, in1, in2);
508
509          mpz_set (res1, in1);
510          mpz_remove (res1, res1, in2);
511          if (mpz_cmp (ref1, res1) != 0)
512            FAIL2 (mpz_remove, in1, in2, NULL);
513
514          mpz_set (res1, in2);
515          mpz_remove (res1, in1, res1);
516          if (mpz_cmp (ref1, res1) != 0)
517            FAIL2 (mpz_remove, in1, in2, NULL);
518        }
519
520      if (mpz_sgn (in2) != 0)
521        {
522          /* Test mpz_divexact */
523          mpz_mul (t, in1, in2);
524          mpz_divexact (ref1, t, in2);
525
526          mpz_set (res1, t);
527          mpz_divexact (res1, res1, in2);
528          if (mpz_cmp (ref1, res1) != 0)
529            FAIL2 (mpz_divexact, t, in2, NULL);
530
531          mpz_set (res1, in2);
532          mpz_divexact (res1, t, res1);
533          if (mpz_cmp (ref1, res1) != 0)
534            FAIL2 (mpz_divexact, t, in2, NULL);
535        }
536
537      if (mpz_sgn (in2) > 0)
538        {
539          /* Test mpz_divexact_gcd, same as mpz_divexact */
540          mpz_mul (t, in1, in2);
541          mpz_divexact_gcd (ref1, t, in2);
542
543          mpz_set (res1, t);
544          mpz_divexact_gcd (res1, res1, in2);
545          if (mpz_cmp (ref1, res1) != 0)
546            FAIL2 (mpz_divexact_gcd, t, in2, NULL);
547
548          mpz_set (res1, in2);
549          mpz_divexact_gcd (res1, t, res1);
550          if (mpz_cmp (ref1, res1) != 0)
551            FAIL2 (mpz_divexact_gcd, t, in2, NULL);
552        }
553    }
554
555  if (failures != 0)
556    {
557      fprintf (stderr, "mpz/reuse: %ld error%s\n", failures, "s" + (failures == 1));
558      exit (1);
559    }
560
561  mpz_clear (bs);
562  mpz_clear (in1);
563  mpz_clear (in2);
564  mpz_clear (in3);
565  mpz_clear (ref1);
566  mpz_clear (ref2);
567  mpz_clear (ref3);
568  mpz_clear (res1);
569  mpz_clear (res2);
570  mpz_clear (res3);
571  mpz_clear (t);
572
573  tests_end ();
574  exit (0);
575}
576
577void
578dump (char *name, mpz_t in1, mpz_t in2, mpz_t in3)
579{
580  printf ("failure in %s (", name);
581  mpz_out_str (stdout, -16, in1);
582  if (in2 != NULL)
583    {
584      printf (" ");
585      mpz_out_str (stdout, -16, in2);
586    }
587  if (in3 != NULL)
588    {
589      printf (" ");
590      mpz_out_str (stdout, -16, in3);
591    }
592  printf (")\n");
593}
594
595#endif /* ! DLL_EXPORT */
Note: See TracBrowser for help on using the repository browser.