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