t-root.c revision 1.1.1.3 1 /* Test mpz_root, mpz_rootrem, and mpz_perfect_power_p.
2
3 Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2009, 2015 Free Software
4 Foundation, Inc.
5
6 This file is part of the GNU MP Library test suite.
7
8 The GNU MP Library test suite is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 3 of the License,
11 or (at your option) any later version.
12
13 The GNU MP Library test suite is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 Public License for more details.
17
18 You should have received a copy of the GNU General Public License along with
19 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "gmp.h"
25 #include "gmp-impl.h"
26 #include "tests.h"
27
28 void debug_mp (mpz_t, int);
29
30 void
31 check_one (mpz_t root1, mpz_t x2, unsigned long nth, int res, int i)
32 {
33 mpz_t temp, temp2;
34 mpz_t root2, rem2;
35
36 mpz_init (root2);
37 mpz_init (rem2);
38 mpz_init (temp);
39 mpz_init (temp2);
40
41 MPZ_CHECK_FORMAT (root1);
42
43 mpz_rootrem (root2, rem2, x2, nth);
44 MPZ_CHECK_FORMAT (root2);
45 MPZ_CHECK_FORMAT (rem2);
46
47 mpz_pow_ui (temp, root1, nth);
48 MPZ_CHECK_FORMAT (temp);
49
50 mpz_add (temp2, temp, rem2);
51
52 /* Is power of result > argument? */
53 if (mpz_cmp (root1, root2) != 0 || mpz_cmp (x2, temp2) != 0 || mpz_cmpabs (temp, x2) > 0 || res == mpz_cmp_ui (rem2, 0))
54 {
55 fprintf (stderr, "ERROR after test %d\n", i);
56 debug_mp (x2, 10);
57 debug_mp (root1, 10);
58 debug_mp (root2, 10);
59 fprintf (stderr, "nth: %lu ,res: %i\n", nth, res);
60 abort ();
61 }
62
63 if (nth > 1 && mpz_cmp_ui (temp, 1L) > 0 && ! mpz_perfect_power_p (temp))
64 {
65 fprintf (stderr, "ERROR in mpz_perfect_power_p after test %d\n", i);
66 debug_mp (temp, 10);
67 debug_mp (root1, 10);
68 fprintf (stderr, "nth: %lu\n", nth);
69 abort ();
70 }
71
72 if (nth <= 10000 && mpz_sgn(x2) > 0) /* skip too expensive test */
73 {
74 mpz_add_ui (temp2, root1, 1L);
75 mpz_pow_ui (temp2, temp2, nth);
76 MPZ_CHECK_FORMAT (temp2);
77
78 /* Is square of (result + 1) <= argument? */
79 if (mpz_cmp (temp2, x2) <= 0)
80 {
81 fprintf (stderr, "ERROR after test %d\n", i);
82 debug_mp (x2, 10);
83 debug_mp (root1, 10);
84 fprintf (stderr, "nth: %lu\n", nth);
85 abort ();
86 }
87 }
88
89 mpz_clear (root2);
90 mpz_clear (rem2);
91 mpz_clear (temp);
92 mpz_clear (temp2);
93 }
94
95 int
96 main (int argc, char **argv)
97 {
98 mpz_t x2;
99 mpz_t root1;
100 mp_size_t x2_size;
101 int i, res;
102 int reps = 500;
103 unsigned long nth;
104 gmp_randstate_ptr rands;
105 mpz_t bs;
106 unsigned long bsi, size_range;
107
108 tests_start ();
109 TESTS_REPS (reps, argv, argc);
110
111 rands = RANDS;
112
113 mpz_init (bs);
114
115 mpz_init (x2);
116 mpz_init (root1);
117
118 /* This triggers a gcc 4.3.2 bug */
119 mpz_set_str (x2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002", 16);
120 res = mpz_root (root1, x2, 2);
121 check_one (root1, x2, 2, res, -1);
122
123 for (i = 0; i < reps; i++)
124 {
125 mpz_urandomb (bs, rands, 32);
126 size_range = mpz_get_ui (bs) % 17 + 2;
127
128 mpz_urandomb (bs, rands, size_range);
129 x2_size = mpz_get_ui (bs) + 10;
130 mpz_rrandomb (x2, rands, x2_size);
131
132 mpz_urandomb (bs, rands, 15);
133 nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2;
134
135 res = mpz_root (root1, x2, nth);
136
137 mpz_urandomb (bs, rands, 4);
138 bsi = mpz_get_ui (bs);
139 if ((bsi & 1) != 0)
140 {
141 /* With 50% probability, set x2 near a perfect power. */
142 mpz_pow_ui (x2, root1, nth);
143 if ((bsi & 2) != 0)
144 {
145 mpz_sub_ui (x2, x2, bsi >> 2);
146 mpz_abs (x2, x2);
147 }
148 else
149 mpz_add_ui (x2, x2, bsi >> 2);
150 res = mpz_root (root1, x2, nth);
151 }
152
153 check_one (root1, x2, nth, res, i);
154
155 if (((nth & 1) != 0) && ((bsi & 2) != 0))
156 {
157 mpz_neg (x2, x2);
158 mpz_neg (root1, root1);
159 check_one (root1, x2, nth, res, i);
160 }
161 }
162
163 mpz_clear (bs);
164 mpz_clear (x2);
165 mpz_clear (root1);
166
167 tests_end ();
168 exit (0);
169 }
170
171 void
172 debug_mp (mpz_t x, int base)
173 {
174 mpz_out_str (stderr, base, x); fputc ('\n', stderr);
175 }
176