t-sqrt.c revision 1.1.1.3 1 1.1 mrg /*
2 1.1 mrg
3 1.1.1.2 mrg Copyright 2012, 2014, Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library test suite.
6 1.1 mrg
7 1.1 mrg The GNU MP Library test suite is free software; you can redistribute it
8 1.1 mrg and/or modify it under the terms of the GNU General Public License as
9 1.1 mrg published by the Free Software Foundation; either version 3 of the License,
10 1.1 mrg or (at your option) any later version.
11 1.1 mrg
12 1.1 mrg The GNU MP Library test suite is distributed in the hope that it will be
13 1.1 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 1.1 mrg Public License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU General Public License along with
18 1.1.1.2 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19 1.1 mrg
20 1.1 mrg #include <limits.h>
21 1.1 mrg #include <stdlib.h>
22 1.1 mrg #include <stdio.h>
23 1.1 mrg
24 1.1 mrg #include "testutils.h"
25 1.1 mrg
26 1.1 mrg #define MAXBITS 400
27 1.1.1.2 mrg #define COUNT 9000
28 1.1 mrg
29 1.1 mrg /* Called when s is supposed to be floor(sqrt(u)), and r = u - s^2 */
30 1.1 mrg static int
31 1.1 mrg sqrtrem_valid_p (const mpz_t u, const mpz_t s, const mpz_t r)
32 1.1 mrg {
33 1.1 mrg mpz_t t;
34 1.1 mrg
35 1.1 mrg mpz_init (t);
36 1.1 mrg mpz_mul (t, s, s);
37 1.1 mrg mpz_sub (t, u, t);
38 1.1 mrg if (mpz_sgn (t) < 0 || mpz_cmp (t, r) != 0)
39 1.1 mrg {
40 1.1 mrg mpz_clear (t);
41 1.1 mrg return 0;
42 1.1 mrg }
43 1.1 mrg mpz_add_ui (t, s, 1);
44 1.1 mrg mpz_mul (t, t, t);
45 1.1 mrg if (mpz_cmp (t, u) <= 0)
46 1.1 mrg {
47 1.1 mrg mpz_clear (t);
48 1.1 mrg return 0;
49 1.1 mrg }
50 1.1 mrg
51 1.1 mrg mpz_clear (t);
52 1.1 mrg return 1;
53 1.1 mrg }
54 1.1 mrg
55 1.1 mrg void
56 1.1.1.2 mrg mpz_mpn_sqrtrem (mpz_t s, mpz_t r, const mpz_t u)
57 1.1.1.2 mrg {
58 1.1.1.2 mrg mp_limb_t *sp, *rp;
59 1.1.1.2 mrg mp_size_t un, sn, ret;
60 1.1.1.2 mrg
61 1.1.1.2 mrg un = mpz_size (u);
62 1.1.1.2 mrg
63 1.1.1.2 mrg mpz_xor (s, s, u);
64 1.1.1.2 mrg sn = (un + 1) / 2;
65 1.1.1.2 mrg sp = mpz_limbs_write (s, sn + 1);
66 1.1.1.2 mrg sp [sn] = 11;
67 1.1.1.2 mrg
68 1.1.1.2 mrg if (un & 1)
69 1.1.1.2 mrg rp = NULL; /* Exploits the fact that r already is correct. */
70 1.1.1.2 mrg else {
71 1.1.1.2 mrg mpz_add (r, u, s);
72 1.1.1.2 mrg rp = mpz_limbs_write (r, un + 1);
73 1.1.1.2 mrg rp [un] = 19;
74 1.1.1.2 mrg }
75 1.1.1.2 mrg
76 1.1.1.2 mrg ret = mpn_sqrtrem (sp, rp, mpz_limbs_read (u), un);
77 1.1.1.2 mrg
78 1.1.1.2 mrg if (sp [sn] != 11)
79 1.1.1.2 mrg {
80 1.1.1.2 mrg fprintf (stderr, "mpn_sqrtrem buffer overrun on sp.\n");
81 1.1.1.2 mrg abort ();
82 1.1.1.2 mrg }
83 1.1.1.2 mrg if (un & 1) {
84 1.1.1.2 mrg if ((ret != 0) != (mpz_size (r) != 0)) {
85 1.1.1.2 mrg fprintf (stderr, "mpn_sqrtrem wrong return value with NULL.\n");
86 1.1.1.2 mrg abort ();
87 1.1.1.2 mrg }
88 1.1.1.2 mrg } else {
89 1.1.1.2 mrg mpz_limbs_finish (r, ret);
90 1.1.1.3 mrg if ((size_t) ret != mpz_size (r)) {
91 1.1.1.2 mrg fprintf (stderr, "mpn_sqrtrem wrong return value.\n");
92 1.1.1.2 mrg abort ();
93 1.1.1.2 mrg }
94 1.1.1.2 mrg if (rp [un] != 19)
95 1.1.1.2 mrg {
96 1.1.1.2 mrg fprintf (stderr, "mpn_sqrtrem buffer overrun on rp.\n");
97 1.1.1.2 mrg abort ();
98 1.1.1.2 mrg }
99 1.1.1.2 mrg }
100 1.1.1.2 mrg
101 1.1.1.2 mrg mpz_limbs_finish (s, (un + 1) / 2);
102 1.1.1.2 mrg }
103 1.1.1.2 mrg
104 1.1.1.2 mrg void
105 1.1 mrg testmain (int argc, char **argv)
106 1.1 mrg {
107 1.1 mrg unsigned i;
108 1.1 mrg mpz_t u, s, r;
109 1.1 mrg
110 1.1 mrg mpz_init (s);
111 1.1 mrg mpz_init (r);
112 1.1 mrg
113 1.1.1.2 mrg mpz_init_set_si (u, -1);
114 1.1.1.2 mrg if (mpz_perfect_square_p (u))
115 1.1.1.2 mrg {
116 1.1.1.2 mrg fprintf (stderr, "mpz_perfect_square_p failed on -1.\n");
117 1.1.1.2 mrg abort ();
118 1.1.1.2 mrg }
119 1.1.1.2 mrg
120 1.1.1.2 mrg if (!mpz_perfect_square_p (s))
121 1.1.1.2 mrg {
122 1.1.1.2 mrg fprintf (stderr, "mpz_perfect_square_p failed on 0.\n");
123 1.1.1.2 mrg abort ();
124 1.1.1.2 mrg }
125 1.1.1.2 mrg
126 1.1 mrg for (i = 0; i < COUNT; i++)
127 1.1 mrg {
128 1.1.1.2 mrg mini_rrandomb (u, MAXBITS - (i & 0xFF));
129 1.1 mrg mpz_sqrtrem (s, r, u);
130 1.1 mrg
131 1.1 mrg if (!sqrtrem_valid_p (u, s, r))
132 1.1 mrg {
133 1.1 mrg fprintf (stderr, "mpz_sqrtrem failed:\n");
134 1.1 mrg dump ("u", u);
135 1.1 mrg dump ("sqrt", s);
136 1.1 mrg dump ("rem", r);
137 1.1 mrg abort ();
138 1.1 mrg }
139 1.1.1.2 mrg
140 1.1.1.2 mrg mpz_mpn_sqrtrem (s, r, u);
141 1.1.1.2 mrg
142 1.1.1.2 mrg if (!sqrtrem_valid_p (u, s, r))
143 1.1.1.2 mrg {
144 1.1.1.2 mrg fprintf (stderr, "mpn_sqrtrem failed:\n");
145 1.1.1.2 mrg dump ("u", u);
146 1.1.1.2 mrg dump ("sqrt", s);
147 1.1.1.2 mrg dump ("rem", r);
148 1.1.1.2 mrg abort ();
149 1.1.1.2 mrg }
150 1.1.1.2 mrg
151 1.1.1.2 mrg if (mpz_sgn (r) == 0) {
152 1.1.1.2 mrg mpz_neg (u, u);
153 1.1.1.2 mrg mpz_sub_ui (u, u, 1);
154 1.1.1.2 mrg }
155 1.1.1.2 mrg
156 1.1.1.2 mrg if ((mpz_sgn (u) <= 0 || (i & 1)) ?
157 1.1.1.2 mrg mpz_perfect_square_p (u) :
158 1.1.1.2 mrg mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u)))
159 1.1.1.2 mrg {
160 1.1.1.2 mrg fprintf (stderr, "mp%s_perfect_square_p failed on non square:\n",
161 1.1.1.2 mrg (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
162 1.1.1.2 mrg dump ("u", u);
163 1.1.1.2 mrg abort ();
164 1.1.1.2 mrg }
165 1.1.1.2 mrg
166 1.1.1.2 mrg mpz_mul (u, s, s);
167 1.1.1.2 mrg if (!((mpz_sgn (u) <= 0 || (i & 1)) ?
168 1.1.1.2 mrg mpz_perfect_square_p (u) :
169 1.1.1.2 mrg mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u))))
170 1.1.1.2 mrg {
171 1.1.1.2 mrg fprintf (stderr, "mp%s_perfect_square_p failed on square:\n",
172 1.1.1.2 mrg (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
173 1.1.1.2 mrg dump ("u", u);
174 1.1.1.2 mrg abort ();
175 1.1.1.2 mrg }
176 1.1.1.2 mrg
177 1.1 mrg }
178 1.1 mrg mpz_clear (u);
179 1.1 mrg mpz_clear (s);
180 1.1 mrg mpz_clear (r);
181 1.1 mrg }
182