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