Upload Tizen:Base source
[external/gmp.git] / tests / mpz / t-pow.c
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 }