xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-powm_ui.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /* Test mpz_powm_ui, mpz_mul, mpz_mod.
2 
3 Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2002, 2013 Free Software
4 Foundation, Inc.
5 
6 This file is part of the GNU MP Library test suite.
7 
8 The GNU MP Library test suite is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 3 of the License,
11 or (at your option) any later version.
12 
13 The GNU MP Library test suite is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
16 Public License for more details.
17 
18 You should have received a copy of the GNU General Public License along with
19 the GNU MP Library test suite.  If not, see http://www.gnu.org/licenses/.  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include "gmp.h"
25 #include "gmp-impl.h"
26 #include "tests.h"
27 
28 void debug_mp (mpz_t, int);
29 
30 int
31 main (int argc, char **argv)
32 {
33   mpz_t base, exp, mod;
34   mpz_t r1, r2, base2;
35   mp_size_t base_size, exp_size, mod_size;
36   unsigned long int exp2;
37   int i;
38   int reps = 100;
39   gmp_randstate_ptr rands;
40   mpz_t bs;
41   unsigned long bsi, size_range;
42 
43   tests_start ();
44   rands = RANDS;
45 
46   mpz_init (bs);
47 
48   if (argc == 2)
49      reps = atoi (argv[1]);
50 
51   mpz_init (base);
52   mpz_init (exp);
53   mpz_init (mod);
54   mpz_init (r1);
55   mpz_init (r2);
56   mpz_init (base2);
57 
58   for (i = 0; i < reps; i++)
59     {
60       mpz_urandomb (bs, rands, 32);
61       size_range = mpz_get_ui (bs) % 18 + 2;
62 
63       do  /* Loop until mathematically well-defined.  */
64 	{
65 	  mpz_urandomb (bs, rands, size_range);
66 	  base_size = mpz_get_ui (bs);
67 	  mpz_rrandomb (base, rands, base_size);
68 
69 	  mpz_urandomb (bs, rands, 6L);
70 	  exp_size = mpz_get_ui (bs);
71 	  mpz_rrandomb (exp, rands, exp_size);
72 	  exp2 = mpz_getlimbn (exp, (mp_size_t) 0);
73 	}
74       while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0);
75 
76       do
77         {
78 	  mpz_urandomb (bs, rands, size_range);
79 	  mod_size = mpz_get_ui (bs);
80 	  mpz_rrandomb (mod, rands, mod_size);
81 	}
82       while (mpz_cmp_ui (mod, 0) == 0);
83 
84       mpz_urandomb (bs, rands, 2);
85       bsi = mpz_get_ui (bs);
86       if ((bsi & 1) != 0)
87 	mpz_neg (base, base);
88 
89       /* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */
90 
91 #if 0
92       putc ('\n', stderr);
93       debug_mp (base, -16);
94       debug_mp (mod, -16);
95 #endif
96 
97       mpz_powm_ui (r1, base, exp2, mod);
98       MPZ_CHECK_FORMAT (r1);
99 
100       mpz_set_ui (r2, 1);
101       mpz_set (base2, base);
102 
103       mpz_mod (r2, r2, mod);	/* needed when exp==0 and mod==1 */
104       while (exp2 != 0)
105 	{
106 	  if (exp2 % 2 != 0)
107 	    {
108 	      mpz_mul (r2, r2, base2);
109 	      mpz_mod (r2, r2, mod);
110 	    }
111 	  mpz_mul (base2, base2, base2);
112 	  mpz_mod (base2, base2, mod);
113 	  exp2 = exp2 / 2;
114 	}
115 
116 #if 0
117       debug_mp (r1, -16);
118       debug_mp (r2, -16);
119 #endif
120 
121       if (mpz_cmp (r1, r2) != 0)
122 	{
123 	  fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i);
124 	  debug_mp (base, -16);
125 	  debug_mp (exp, -16);
126 	  debug_mp (mod, -16);
127 	  fprintf (stderr, "mpz_powm_ui result:\n");
128 	  debug_mp (r1, -16);
129 	  fprintf (stderr, "reference result:\n");
130 	  debug_mp (r2, -16);
131 	  abort ();
132 	}
133     }
134 
135   mpz_clear (bs);
136   mpz_clear (base);
137   mpz_clear (exp);
138   mpz_clear (mod);
139   mpz_clear (r1);
140   mpz_clear (r2);
141   mpz_clear (base2);
142 
143   tests_end ();
144   exit (0);
145 }
146 
147 void
148 debug_mp (mpz_t x, int base)
149 {
150   mpz_out_str (stderr, base, x); fputc ('\n', stderr);
151 }
152