xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-cong.c (revision fdd524d4ccd2bb0c6f67401e938dabf773eb0372)
1 /* test mpz_congruent_p and mpz_congruent_ui_p
2 
3 Copyright 2001, 2002, 2012 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 <stdio.h>
21 #include <stdlib.h>
22 #include "gmp.h"
23 #include "gmp-impl.h"
24 #include "tests.h"
25 
26 
27 void
28 check_one (mpz_srcptr a, mpz_srcptr c, mpz_srcptr d, int want)
29 {
30   int   got;
31   int   swap;
32 
33   for (swap = 0; swap <= 1; swap++)
34     {
35       got = (mpz_congruent_p (a, c, d) != 0);
36       if (want != got)
37 	{
38 	  printf ("mpz_congruent_p wrong\n");
39 	  printf ("   expected %d got %d\n", want, got);
40 	  mpz_trace ("	 a", a);
41 	  mpz_trace ("	 c", c);
42 	  mpz_trace ("	 d", d);
43 	  mp_trace_base = -16;
44 	  mpz_trace ("	 a", a);
45 	  mpz_trace ("	 c", c);
46 	  mpz_trace ("	 d", d);
47 	  abort ();
48 	}
49 
50       if (mpz_fits_ulong_p (c) && mpz_fits_ulong_p (d))
51 	{
52 	  unsigned long	 uc = mpz_get_ui (c);
53 	  unsigned long	 ud = mpz_get_ui (d);
54 	  got = (mpz_congruent_ui_p (a, uc, ud) != 0);
55 	  if (want != got)
56 	    {
57 	      printf	("mpz_congruent_ui_p wrong\n");
58 	      printf	("   expected %d got %d\n", want, got);
59 	      mpz_trace ("   a", a);
60 	      printf	("   c=%lu\n", uc);
61 	      printf	("   d=%lu\n", ud);
62 	      mp_trace_base = -16;
63 	      mpz_trace ("   a", a);
64 	      printf	("   c=0x%lX\n", uc);
65 	      printf	("   d=0x%lX\n", ud);
66 	      abort ();
67 	    }
68 	}
69 
70       MPZ_SRCPTR_SWAP (a, c);
71     }
72 }
73 
74 
75 void
76 check_data (void)
77 {
78   static const struct {
79     const char *a;
80     const char *c;
81     const char *d;
82     int        want;
83 
84   } data[] = {
85 
86     /* strict equality mod 0 */
87     { "0", "0", "0", 1 },
88     { "11", "11", "0", 1 },
89     { "3", "11", "0", 0 },
90 
91     /* anything congruent mod 1 */
92     { "0", "0", "1", 1 },
93     { "1", "0", "1", 1 },
94     { "0", "1", "1", 1 },
95     { "123", "456", "1", 1 },
96     { "0x123456789123456789", "0x987654321987654321", "1", 1 },
97 
98     /* csize==1, dsize==2 changing to 1 after stripping 2s */
99     { "0x3333333333333333",  "0x33333333",
100       "0x180000000", 1 },
101     { "0x33333333333333333333333333333333", "0x3333333333333333",
102       "0x18000000000000000", 1 },
103 
104     /* another dsize==2 becoming 1, with opposite signs this time */
105     {  "0x444444441",
106       "-0x22222221F",
107        "0x333333330", 1 },
108     {  "0x44444444444444441",
109       "-0x2222222222222221F",
110        "0x33333333333333330", 1 },
111   };
112 
113   mpz_t   a, c, d;
114   int     i;
115 
116   mpz_init (a);
117   mpz_init (c);
118   mpz_init (d);
119 
120   for (i = 0; i < numberof (data); i++)
121     {
122       mpz_set_str_or_abort (a, data[i].a, 0);
123       mpz_set_str_or_abort (c, data[i].c, 0);
124       mpz_set_str_or_abort (d, data[i].d, 0);
125       check_one (a, c, d, data[i].want);
126     }
127 
128   mpz_clear (a);
129   mpz_clear (c);
130   mpz_clear (d);
131 }
132 
133 
134 void
135 check_random (int argc, char *argv[])
136 {
137   gmp_randstate_ptr rands = RANDS;
138   mpz_t   a, c, d, ra, rc;
139   int     i;
140   int     want;
141   int     reps = 10000;
142   mpz_t bs;
143   unsigned long size_range, size;
144 
145   if (argc >= 2)
146     reps = atoi (argv[1]);
147 
148   mpz_init (bs);
149 
150   mpz_init (a);
151   mpz_init (c);
152   mpz_init (d);
153   mpz_init (ra);
154   mpz_init (rc);
155 
156   for (i = 0; i < reps; i++)
157     {
158       mpz_urandomb (bs, rands, 32);
159       size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */
160 
161       mpz_urandomb (bs, rands, size_range);
162       size = mpz_get_ui (bs);
163       mpz_rrandomb (a, rands, size);
164 
165       mpz_urandomb (bs, rands, 32);
166       size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */
167 
168       mpz_urandomb (bs, rands, size_range);
169       size = mpz_get_ui (bs);
170       mpz_rrandomb (c, rands, size);
171 
172       do
173 	{
174 	  mpz_urandomb (bs, rands, 32);
175 	  size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */
176 
177 	  mpz_urandomb (bs, rands, size_range);
178 	  size = mpz_get_ui (bs);
179 	  mpz_rrandomb (d, rands, size);
180 	}
181       while (SIZ(d) == 0);
182 
183       mpz_negrandom (a, rands);
184       MPZ_CHECK_FORMAT (a);
185       mpz_negrandom (c, rands);
186       MPZ_CHECK_FORMAT (c);
187       mpz_negrandom (d, rands);
188 
189       mpz_fdiv_r (ra, a, d);
190       mpz_fdiv_r (rc, c, d);
191 
192       want = (mpz_cmp (ra, rc) == 0);
193       check_one (a, c, d, want);
194 
195       mpz_sub (ra, ra, rc);
196       mpz_sub (a, a, ra);
197       MPZ_CHECK_FORMAT (a);
198       check_one (a, c, d, 1);
199 
200       if (! mpz_pow2abs_p (d))
201         {
202 	  refmpz_combit (a, urandom() % (8*GMP_LIMB_BITS));
203 	  check_one (a, c, d, 0);
204         }
205     }
206 
207   mpz_clear (bs);
208 
209   mpz_clear (a);
210   mpz_clear (c);
211   mpz_clear (d);
212   mpz_clear (ra);
213   mpz_clear (rc);
214 }
215 
216 
217 int
218 main (int argc, char *argv[])
219 {
220   tests_start ();
221 
222   check_data ();
223   check_random (argc, argv);
224 
225   tests_end ();
226   exit (0);
227 }
228