1 /*
2
3 Copyright 2012, 2013, 2018 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 <assert.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23
24 #include "testutils.h"
25 #include "../mini-mpq.h"
26
27 #define MAXBITS 300
28 #define COUNT 10000
29
30 static void
31 _mpq_set_zz (mpq_t q, mpz_t n, mpz_t d)
32 {
33 if (mpz_fits_ulong_p (d) && mpz_fits_slong_p (n))
34 {
35 mpq_set_si (q, mpz_get_si (n), mpz_get_ui (d));
36 }
37 else if (mpz_fits_ulong_p (d) && mpz_fits_ulong_p (n))
38 {
39 mpq_set_ui (q, mpz_get_ui (n), mpz_get_ui (d));
40 }
41 else
42 {
43 mpq_set_num (q, n);
44 mpq_set_den (q, d);
45 }
46 mpq_canonicalize (q);
47 }
48
49 void
50 testcmpui ()
51 {
52 unsigned d1, d2, n1, n2;
53 mpq_t q1, q2;
54
55 mpq_init (q1);
56 mpq_init (q2);
57
58 for (d1 = 1; d1 < 6; d1 += 2)
59 for (n1 = 1; n1 < 6; n1 *= 2)
60 {
61 mpq_set_ui (q1, n1, d1);
62 for (d2 = 1; d2 < 6; d2 += 2)
63 for (n2 = 1; n2 < 6; n2 *= 2)
64 {
65 int fres = mpq_cmp_ui (q1, n2, d2);
66 int ref = (d1*n2 < d2*n1) - (d1*n2 > d2*n1);
67
68 mpq_set_ui (q2, n2, d2);
69
70 if ((!ref) != mpq_equal (q1, q2))
71 {
72 fprintf (stderr, "mpz_equal failed: %i / %i = %i / %i ? %i\n", n1, d1, n2, d2, ref);
73 abort ();
74 }
75
76 if (ref != fres)
77 {
78 fprintf (stderr, "mpz_cmp_ui failed: %i / %i = %i / %i ? %i != %i\n", n1, d1, n2, d2, ref, fres);
79 abort ();
80 }
81 }
82 }
83
84 mpq_clear (q1);
85 mpq_clear (q2);
86 }
87
88 void
89 testmain (int argc, char **argv)
90 {
91 unsigned i;
92 mpz_t a, b, q, r, c;
93 mpq_t rr, ii, ff;
94 int tst;
95
96 testcmpui ();
97 mpz_init (a);
98 mpz_init (b);
99 mpz_init (r);
100 mpz_init (q);
101 mpz_init (c);
102 mpq_init (rr);
103 mpq_init (ff);
104 mpq_init (ii);
105
106 for (i = 0; i < COUNT; i++)
107 {
108 mini_random_op4 (OP_TDIV, MAXBITS, a, b, q, r);
109
110 _mpq_set_zz (rr, a, b);
111 _mpq_set_zz (ff, r, b);
112
113 mpq_set_z (ii, q);
114
115 mpz_set_q (c, rr);
116 if (mpz_cmp (c, q))
117 {
118 fprintf (stderr, "mpz_set_q failed:\n");
119 dump ("a", a);
120 dump ("b", b);
121 dump ("c", c);
122 dump ("q", q);
123 abort ();
124 }
125
126 if ((mpz_sgn (r) != 0) ^ (mpz_cmp_ui (mpq_denref (rr), 1) != 0))
127 {
128 fprintf (stderr, "mpq_canonicalize failed:\n");
129 dump ("a", a);
130 dump ("b", b);
131 dump ("r", r);
132 dump ("D", mpq_denref (rr));
133 abort ();
134 }
135
136 if (i & 1)
137 {
138 if (mpz_fits_slong_p (q))
139 tst = mpq_cmp_si (rr, mpz_get_si (q), 1);
140 else if (mpz_fits_ulong_p (q))
141 tst = mpq_cmp_ui (rr, mpz_get_ui (q), 1);
142 else
143 tst = mpq_cmp_z (rr, q);
144 if (mpz_sgn (b) < 0)
145 tst = - tst;
146 if ((tst != mpz_sgn (r)) && ((tst < 0 && mpz_sgn (r) >= 0) || (tst > 0 && mpz_sgn (r) <= 0)))
147 {
148 fprintf (stderr, "mpq_cmp ii failed: %i %i\n", tst, mpz_sgn (r));
149 dump ("a", a);
150 dump ("b", b);
151 dump ("r", r);
152 dump ("q", q);
153 abort ();
154 }
155 }
156 else
157 {
158 if (mpz_fits_ulong_p (b) && mpz_fits_slong_p (r))
159 tst = mpq_cmp_si (rr, mpz_get_si (r), mpz_get_ui (b));
160 else if (mpz_fits_ulong_p (b) && mpz_fits_ulong_p (r))
161 tst = mpq_cmp_ui (rr, mpz_get_ui (r), mpz_get_ui (b));
162 else
163 tst = mpq_cmp (rr, ff);
164 if ((tst != mpz_sgn (q)) && ((tst < 0 && mpz_sgn (q) >= 0) || (tst > 0 && mpz_sgn (q) <= 0)))
165 {
166 fprintf (stderr, "mpq_cmp ff failed: %i %i\n", tst, mpz_sgn (q));
167 dump ("a", a);
168 dump ("b", b);
169 dump ("r", r);
170 dump ("q", q);
171 abort ();
172 }
173 }
174
175 if (i & 1)
176 {
177 mpq_sub (rr, rr, ff);
178 }
179 else
180 {
181 mpq_neg (ff, ff);
182 mpq_add (rr, ff, rr);
183 }
184
185 if (!mpq_equal (ii, rr))
186 {
187 fprintf (stderr, "mpq_%s failed:\n", (i & 1) ? "sub" : "add");
188 dump ("a", a);
189 dump ("b", b);
190 dump ("r", r);
191 dump ("q", q);
192 abort ();
193 }
194 }
195
196 mpz_clear (a);
197 mpz_clear (b);
198 mpz_clear (r);
199 mpz_clear (q);
200 mpz_clear (c);
201 mpq_clear (rr);
202 mpq_clear (ff);
203 mpq_clear (ii);
204 }