xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-pow.c (revision b49cc1491953ef2348eff9c84520ffd0678a5c8d)
1 /* Test mpz_pow_ui and mpz_ui_pow_ui.
2 
3 Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library.
6 
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see http://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