xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-pow.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Test mpz_pow_ui and mpz_ui_pow_ui.
2 
3 Copyright 1997, 1999-2001 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 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include "gmp.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 
28 void
29 check_one (mpz_srcptr want, mpz_srcptr base, unsigned long exp)
30 {
31   mpz_t  got;
32 
33   mpz_init (got);
34 
35   MPZ_CHECK_FORMAT (want);
36 
37   mpz_pow_ui (got, base, exp);
38   if (mpz_cmp (got, want))
39     {
40       printf ("mpz_pow_ui wrong\n");
41       mpz_trace ("  base", base);
42       printf    ("  exp = %lu (0x%lX)\n", exp, exp);
43       mpz_trace ("  got ", got);
44       mpz_trace ("  want", want);
45       abort ();
46     }
47 
48   mpz_set (got, base);
49   mpz_pow_ui (got, got, exp);
50   if (mpz_cmp (got, want))
51     {
52       printf ("mpz_pow_ui wrong\n");
53       mpz_trace ("  base", base);
54       printf    ("  exp = %lu (0x%lX)\n", exp, exp);
55       mpz_trace ("  got ", got);
56       mpz_trace ("  want", want);
57       abort ();
58     }
59 
60   if (mpz_fits_ulong_p (base))
61     {
62       unsigned long  base_u = mpz_get_ui (base);
63       mpz_ui_pow_ui (got, base_u, exp);
64       if (mpz_cmp (got, want))
65 	{
66 	  printf    ("mpz_ui_pow_ui wrong\n");
67 	  printf    ("  base=%lu (0x%lX)\n", base_u, base_u);
68 	  printf    ("  exp = %lu (0x%lX)\n", exp, exp);
69 	  mpz_trace ("  got ", got);
70 	  mpz_trace ("  want", want);
71 	  abort ();
72 	}
73     }
74 
75   mpz_clear (got);
76 }
77 
78 void
79 check_base (mpz_srcptr base)
80 {
81   unsigned long  exp;
82   mpz_t          want;
83 
84   mpz_init (want);
85   mpz_set_ui (want, 1L);
86 
87   for (exp = 0; exp < 20; exp++)
88     {
89       check_one (want, base, exp);
90       mpz_mul (want, want, base);
91     }
92 
93   mpz_clear (want);
94 }
95 
96 void
97 check_various (void)
98 {
99   static const struct {
100     const char *base;
101   } data[] = {
102     { "0" },
103     { "1" },
104     { "2" },
105     { "3" },
106     { "4" },
107     { "5" },
108     { "6" },
109     { "10" },
110     { "15" },
111     { "16" },
112 
113     { "0x1F" },
114     { "0xFF" },
115     { "0x1001" },
116     { "0xFFFF" },
117     { "0x10000001" },
118     { "0x1000000000000001" },
119 
120     /* actual size closest to estimate */
121     { "0xFFFFFFFF" },
122     { "0xFFFFFFFFFFFFFFFF" },
123 
124     /* same after rshift */
125     { "0xFFFFFFFF0" },
126     { "0xFFFFFFFF00" },
127     { "0xFFFFFFFFFFFFFFFF0" },
128     { "0xFFFFFFFFFFFFFFFF00" },
129 
130     /* change from 2 limbs to 1 after rshift */
131     { "0x180000000" },
132     { "0x18000000000000000" },
133 
134     /* change from 3 limbs to 2 after rshift */
135     { "0x18000000100000000" },
136     { "0x180000000000000010000000000000000" },
137 
138     /* handling of absolute value */
139     { "-0x80000000" },
140     { "-0x8000000000000000" },
141 
142     /* low zero limb, and size>2, checking argument overlap detection */
143     { "0x3000000000000000300000000000000030000000000000000" },
144   };
145 
146   mpz_t  base;
147   int    i;
148 
149   mpz_init (base);
150 
151   for (i = 0; i < numberof (data); i++)
152     {
153       mpz_set_str_or_abort (base, data[i].base, 0);
154       check_base (base);
155     }
156 
157   mpz_clear (base);
158 }
159 
160 void
161 check_random (int reps)
162 {
163   mpz_t              base, want;
164   mp_size_t          base_size;
165   int                i;
166   unsigned long      size_range, exp;
167   gmp_randstate_ptr  rands = RANDS;
168 
169   mpz_init (base);
170   mpz_init (want);
171 
172   for (i = 0; i < reps; i++)
173     {
174       /* exponentially random 0 to 2^13 bits for base */
175       mpz_urandomb (want, rands, 32);
176       size_range = mpz_get_ui (want) % 12 + 2;
177       mpz_urandomb (want, rands, size_range);
178       base_size = mpz_get_ui (want);
179       mpz_rrandomb (base, rands, base_size);
180 
181       /* randomly signed base */
182       mpz_urandomb (want, rands, 2);
183       if ((mpz_get_ui (want) & 1) != 0)
184 	mpz_neg (base, base);
185 
186       /* random 5 bits for exponent */
187       mpz_urandomb (want, rands, 5L);
188       exp = mpz_get_ui (want);
189 
190       refmpz_pow_ui (want, base, exp);
191       check_one (want, base, exp);
192     }
193 
194   mpz_clear (base);
195   mpz_clear (want);
196 }
197 
198 int
199 main (int argc, char **argv)
200 {
201   int reps = 5000;
202 
203   /* dummy call to drag in refmpn.o for testing mpz/n_pow_ui.c with
204      refmpn_mul_2 */
205   refmpn_zero_p (NULL, (mp_size_t) 0);
206 
207   tests_start ();
208   mp_trace_base = -16;
209 
210   if (argc == 2)
211      reps = atoi (argv[1]);
212 
213   check_various ();
214   check_random (reps);
215 
216   tests_end ();
217   exit (0);
218 }
219