xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/hex-random.c (revision 80d9064ac03cbb6a4174695f0d5b237c8766d3d0)
1 /*
2 
3 Copyright 2011, 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 
23 #include <time.h>
24 #include <unistd.h>
25 
26 #include "gmp.h"
27 
28 #include "hex-random.h"
29 
30 static gmp_randstate_t state;
31 
32 void
33 hex_random_init (void)
34 {
35   unsigned long seed;
36   char *env_seed;
37 
38   env_seed = getenv("GMP_CHECK_RANDOMIZE");
39   if (env_seed && env_seed[0])
40     {
41       seed = strtoul (env_seed, NULL, 0);
42       if (seed)
43 	printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
44       else
45 	{
46 	  seed = time(NULL) + getpid();
47 	  printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed);
48 	}
49     }
50   else
51     seed = 4711;
52 
53   gmp_randinit_default (state);
54   gmp_randseed_ui (state, seed);
55 }
56 
57 char *
58 hex_urandomb (unsigned long bits)
59 {
60   char *res;
61   mpz_t x;
62 
63   mpz_init (x);
64   mpz_urandomb (x, state, bits);
65   gmp_asprintf (&res, "%Zx", x);
66   mpz_clear (x);
67   return res;
68 }
69 
70 char *
71 hex_rrandomb (unsigned long bits)
72 {
73   char *res;
74   mpz_t x;
75 
76   mpz_init (x);
77   mpz_rrandomb (x, state, bits);
78   gmp_asprintf (&res, "%Zx", x);
79   mpz_clear (x);
80   return res;
81 }
82 
83 char *
84 hex_rrandomb_export (void *dst, size_t *countp,
85 		     int order, size_t size, int endian, unsigned long bits)
86 {
87   char *res;
88   mpz_t x;
89   mpz_init (x);
90   mpz_rrandomb (x, state, bits);
91   gmp_asprintf (&res, "%Zx", x);
92   mpz_export (dst, countp, order, size, endian, 0, x);
93   mpz_clear (x);
94   return res;
95 }
96 
97 void hex_random_op2 (enum hex_random_op op,  unsigned long maxbits,
98 		     char **ap, char **rp)
99 {
100   mpz_t a, r;
101   unsigned long abits;
102   unsigned signs;
103 
104   mpz_init (a);
105   mpz_init (r);
106 
107   abits = gmp_urandomb_ui (state, 32) % maxbits;
108 
109   mpz_rrandomb (a, state, abits);
110 
111   signs = gmp_urandomb_ui (state, 1);
112   if (signs & 1)
113     mpz_neg (a, a);
114 
115   switch (op)
116     {
117     default:
118       abort ();
119     case OP_SQR:
120       mpz_mul (r, a, a);
121       break;
122     }
123 
124   gmp_asprintf (ap, "%Zx", a);
125   gmp_asprintf (rp, "%Zx", r);
126 
127   mpz_clear (a);
128   mpz_clear (r);
129 }
130 
131 void
132 hex_random_op3 (enum hex_random_op op,  unsigned long maxbits,
133 		char **ap, char **bp, char **rp)
134 {
135   mpz_t a, b, r;
136   unsigned long abits, bbits;
137   unsigned signs;
138 
139   mpz_init (a);
140   mpz_init (b);
141   mpz_init (r);
142 
143   abits = gmp_urandomb_ui (state, 32) % maxbits;
144   bbits = gmp_urandomb_ui (state, 32) % maxbits;
145 
146   mpz_rrandomb (a, state, abits);
147   mpz_rrandomb (b, state, bbits);
148 
149   signs = gmp_urandomb_ui (state, 3);
150   if (signs & 1)
151     mpz_neg (a, a);
152   if (signs & 2)
153     mpz_neg (b, b);
154 
155   switch (op)
156     {
157     default:
158       abort ();
159     case OP_ADD:
160       mpz_add (r, a, b);
161       break;
162     case OP_SUB:
163       mpz_sub (r, a, b);
164       break;
165     case OP_MUL:
166       mpz_mul (r, a, b);
167       break;
168     case OP_GCD:
169       if (signs & 4)
170 	{
171 	  /* Produce a large gcd */
172 	  unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
173 	  mpz_rrandomb (r, state, gbits);
174 	  mpz_mul (a, a, r);
175 	  mpz_mul (b, b, r);
176 	}
177       mpz_gcd (r, a, b);
178       break;
179     case OP_LCM:
180       if (signs & 4)
181 	{
182 	  /* Produce a large gcd */
183 	  unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
184 	  mpz_rrandomb (r, state, gbits);
185 	  mpz_mul (a, a, r);
186 	  mpz_mul (b, b, r);
187 	}
188       mpz_lcm (r, a, b);
189       break;
190     case OP_AND:
191       mpz_and (r, a, b);
192       break;
193     case OP_IOR:
194       mpz_ior (r, a, b);
195       break;
196     case OP_XOR:
197       mpz_xor (r, a, b);
198       break;
199     }
200 
201   gmp_asprintf (ap, "%Zx", a);
202   gmp_asprintf (bp, "%Zx", b);
203   gmp_asprintf (rp, "%Zx", r);
204 
205   mpz_clear (a);
206   mpz_clear (b);
207   mpz_clear (r);
208 }
209 
210 void
211 hex_random_op4 (enum hex_random_op op, unsigned long maxbits,
212 		char **ap, char **bp, char **cp, char **dp)
213 {
214   mpz_t a, b, c, d;
215   unsigned long abits, bbits;
216   unsigned signs;
217 
218   mpz_init (a);
219   mpz_init (b);
220   mpz_init (c);
221   mpz_init (d);
222 
223   if (op == OP_POWM)
224     {
225       unsigned long cbits;
226       abits = gmp_urandomb_ui (state, 32) % maxbits;
227       bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
228       cbits = 2 + gmp_urandomb_ui (state, 32) % maxbits;
229 
230       mpz_rrandomb (a, state, abits);
231       mpz_rrandomb (b, state, bbits);
232       mpz_rrandomb (c, state, cbits);
233 
234       signs = gmp_urandomb_ui (state, 3);
235       if (signs & 1)
236 	mpz_neg (a, a);
237       if (signs & 2)
238 	{
239 	  mpz_t g;
240 
241 	  /* If we negate the exponent, must make sure that gcd(a, c) = 1 */
242 	  if (mpz_sgn (a) == 0)
243 	    mpz_set_ui (a, 1);
244 	  else
245 	    {
246 	      mpz_init (g);
247 
248 	      for (;;)
249 		{
250 		  mpz_gcd (g, a, c);
251 		  if (mpz_cmp_ui (g, 1) == 0)
252 		    break;
253 		  mpz_divexact (a, a, g);
254 		}
255 	      mpz_clear (g);
256 	    }
257 	  mpz_neg (b, b);
258 	}
259       if (signs & 4)
260 	mpz_neg (c, c);
261 
262       mpz_powm (d, a, b, c);
263     }
264   else
265     {
266       unsigned long qbits;
267       bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
268       qbits = gmp_urandomb_ui (state, 32) % maxbits;
269       abits = bbits + qbits;
270       if (abits > 30)
271 	abits -= 30;
272       else
273 	abits = 0;
274 
275       mpz_rrandomb (a, state, abits);
276       mpz_rrandomb (b, state, bbits);
277 
278       signs = gmp_urandomb_ui (state, 2);
279       if (signs & 1)
280 	mpz_neg (a, a);
281       if (signs & 2)
282 	mpz_neg (b, b);
283 
284       switch (op)
285 	{
286 	default:
287 	  abort ();
288 	case OP_CDIV:
289 	  mpz_cdiv_qr (c, d, a, b);
290 	  break;
291 	case OP_FDIV:
292 	  mpz_fdiv_qr (c, d, a, b);
293 	  break;
294 	case OP_TDIV:
295 	  mpz_tdiv_qr (c, d, a, b);
296 	  break;
297 	}
298     }
299   gmp_asprintf (ap, "%Zx", a);
300   gmp_asprintf (bp, "%Zx", b);
301   gmp_asprintf (cp, "%Zx", c);
302   gmp_asprintf (dp, "%Zx", d);
303 
304   mpz_clear (a);
305   mpz_clear (b);
306   mpz_clear (c);
307   mpz_clear (d);
308 }
309 
310 void
311 hex_random_bit_op (enum hex_random_op op, unsigned long maxbits,
312 		   char **ap, unsigned long *b, char **rp)
313 {
314   mpz_t a, r;
315   unsigned long abits, bbits;
316   unsigned signs;
317 
318   mpz_init (a);
319   mpz_init (r);
320 
321   abits = gmp_urandomb_ui (state, 32) % maxbits;
322   bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
323 
324   mpz_rrandomb (a, state, abits);
325 
326   signs = gmp_urandomb_ui (state, 1);
327   if (signs & 1)
328     mpz_neg (a, a);
329 
330   switch (op)
331     {
332     default:
333       abort ();
334 
335     case OP_SETBIT:
336       mpz_set (r, a);
337       mpz_setbit (r, bbits);
338       break;
339     case OP_CLRBIT:
340       mpz_set (r, a);
341       mpz_clrbit (r, bbits);
342       break;
343     case OP_COMBIT:
344       mpz_set (r, a);
345       mpz_combit (r, bbits);
346       break;
347     case OP_CDIV_Q_2:
348       mpz_cdiv_q_2exp (r, a, bbits);
349       break;
350     case OP_CDIV_R_2:
351       mpz_cdiv_r_2exp (r, a, bbits);
352       break;
353     case OP_FDIV_Q_2:
354       mpz_fdiv_q_2exp (r, a, bbits);
355       break;
356     case OP_FDIV_R_2:
357       mpz_fdiv_r_2exp (r, a, bbits);
358       break;
359     case OP_TDIV_Q_2:
360       mpz_tdiv_q_2exp (r, a, bbits);
361       break;
362     case OP_TDIV_R_2:
363       mpz_tdiv_r_2exp (r, a, bbits);
364       break;
365     }
366 
367   gmp_asprintf (ap, "%Zx", a);
368   *b = bbits;
369   gmp_asprintf (rp, "%Zx", r);
370 
371   mpz_clear (a);
372   mpz_clear (r);
373 }
374 
375 void
376 hex_random_scan_op (enum hex_random_op op, unsigned long maxbits,
377 		    char **ap, unsigned long *b, unsigned long *r)
378 {
379   mpz_t a;
380   unsigned long abits, bbits;
381   unsigned signs;
382 
383   mpz_init (a);
384 
385   abits = gmp_urandomb_ui (state, 32) % maxbits;
386   bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
387 
388   mpz_rrandomb (a, state, abits);
389 
390   signs = gmp_urandomb_ui (state, 1);
391   if (signs & 1)
392     mpz_neg (a, a);
393 
394   switch (op)
395     {
396     default:
397       abort ();
398 
399     case OP_SCAN0:
400       *r = mpz_scan0 (a, bbits);
401       break;
402     case OP_SCAN1:
403       *r = mpz_scan1 (a, bbits);
404       break;
405     }
406   gmp_asprintf (ap, "%Zx", a);
407   *b = bbits;
408 
409   mpz_clear (a);
410 }
411 
412 void
413 hex_random_str_op (unsigned long maxbits,
414 		   int base, char **ap, char **rp)
415 {
416   mpz_t a;
417   unsigned long abits;
418   unsigned signs;
419 
420   mpz_init (a);
421 
422   abits = gmp_urandomb_ui (state, 32) % maxbits;
423 
424   mpz_rrandomb (a, state, abits);
425 
426   signs = gmp_urandomb_ui (state, 2);
427   if (signs & 1)
428     mpz_neg (a, a);
429 
430   *ap = mpz_get_str (NULL, 16, a);
431   *rp = mpz_get_str (NULL, base, a);
432 
433   mpz_clear (a);
434 }
435