1 /*
2
3 Copyright 2012, 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 <limits.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23
24 #include "testutils.h"
25
26 #define MAXBITS 400
27 #define COUNT 10000
28
29 /* Called when g is supposed to be gcd(a,b), and g = s a + t b. */
30 static int
gcdext_valid_p(const mpz_t a,const mpz_t b,const mpz_t g,const mpz_t s,const mpz_t t)31 gcdext_valid_p (const mpz_t a, const mpz_t b,
32 const mpz_t g, const mpz_t s, const mpz_t t)
33 {
34 mpz_t ta, tb, r;
35
36 /* It's not clear that gcd(0,0) is well defined, but we allow it and
37 require that gcd(0,0) = 0. */
38 if (mpz_sgn (g) < 0)
39 return 0;
40
41 if (mpz_sgn (a) == 0)
42 {
43 /* Must have g == abs (b). Any value for s is in some sense "correct",
44 but it makes sense to require that s == 0, t = sgn (b)*/
45 return mpz_cmpabs (g, b) == 0
46 && mpz_sgn (s) == 0 && mpz_cmp_si (t, mpz_sgn (b)) == 0;
47 }
48 else if (mpz_sgn (b) == 0)
49 {
50 /* Must have g == abs (a), s == sign (a), t = 0 */
51 return mpz_cmpabs (g, a) == 0
52 && mpz_cmp_si (s, mpz_sgn (a)) == 0 && mpz_sgn (t) == 0;
53 }
54
55 if (mpz_sgn (g) <= 0)
56 return 0;
57
58 mpz_init (ta);
59 mpz_init (tb);
60 mpz_init (r);
61
62 mpz_mul (ta, s, a);
63 mpz_mul (tb, t, b);
64 mpz_add (ta, ta, tb);
65
66 if (mpz_cmp (ta, g) != 0)
67 {
68 fail:
69 mpz_clear (ta);
70 mpz_clear (tb);
71 mpz_clear (r);
72 return 0;
73 }
74 mpz_tdiv_qr (ta, r, a, g);
75 if (mpz_sgn (r) != 0)
76 goto fail;
77
78 mpz_tdiv_qr (tb, r, b, g);
79 if (mpz_sgn (r) != 0)
80 goto fail;
81
82 /* Require that 2 |s| < |b/g|, or |s| == 1. */
83 if (mpz_cmpabs_ui (s, 1) > 0)
84 {
85 mpz_mul_2exp (r, s, 1);
86 if (mpz_cmpabs (r, tb) > 0)
87 goto fail;
88 }
89
90 /* Require that 2 |t| < |a/g| or |t| == 1*/
91 if (mpz_cmpabs_ui (t, 1) > 0)
92 {
93 mpz_mul_2exp (r, t, 1);
94 if (mpz_cmpabs (r, ta) > 0)
95 return 0;
96 }
97
98 mpz_clear (ta);
99 mpz_clear (tb);
100 mpz_clear (r);
101
102 return 1;
103 }
104
105 void
testmain(int argc,char ** argv)106 testmain (int argc, char **argv)
107 {
108 unsigned i;
109 mpz_t a, b, g, s, t;
110
111 mpz_init (a);
112 mpz_init (b);
113 mpz_init (g);
114 mpz_init (s);
115 mpz_init (t);
116
117 for (i = 0; i < COUNT; i++)
118 {
119 mini_random_op3 (OP_GCD, MAXBITS, a, b, s);
120 mpz_gcd (g, a, b);
121 if (mpz_cmp (g, s))
122 {
123 fprintf (stderr, "mpz_gcd failed:\n");
124 dump ("a", a);
125 dump ("b", b);
126 dump ("r", g);
127 dump ("ref", s);
128 abort ();
129 }
130 }
131
132 for (i = 0; i < COUNT; i++)
133 {
134 unsigned flags;
135 mini_urandomb (a, 32);
136 flags = mpz_get_ui (a);
137 mini_rrandomb (a, MAXBITS);
138 mini_rrandomb (b, MAXBITS);
139
140 if (flags % 37 == 0)
141 mpz_mul (a, a, b);
142 if (flags % 37 == 1)
143 mpz_mul (b, a, b);
144
145 if (flags & 1)
146 mpz_neg (a, a);
147 if (flags & 2)
148 mpz_neg (b, b);
149
150 mpz_gcdext (g, s, t, a, b);
151 if (!gcdext_valid_p (a, b, g, s, t))
152 {
153 fprintf (stderr, "mpz_gcdext failed:\n");
154 dump ("a", a);
155 dump ("b", b);
156 dump ("g", g);
157 dump ("s", s);
158 dump ("t", t);
159 abort ();
160 }
161
162 mpz_gcd (s, a, b);
163 if (mpz_cmp (g, s))
164 {
165 fprintf (stderr, "mpz_gcd failed:\n");
166 dump ("a", a);
167 dump ("b", b);
168 dump ("r", g);
169 dump ("ref", s);
170 abort ();
171 }
172 }
173 mpz_clear (a);
174 mpz_clear (b);
175 mpz_clear (g);
176 mpz_clear (s);
177 mpz_clear (t);
178 }
179