1 /* Exercise some mpz_..._si functions.
2
3 Copyright 2013, 2016, 2020 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 <stdio.h>
22 #include <stdlib.h>
23
24 #include "testutils.h"
25
26 /* Always called with sz fitting in a signed long, and si is the
27 corresponding value. */
28 int
29 check_si (const mpz_t sz, long si)
30 {
31 mpz_t t;
32
33 /* Checks on sz/si */
34 if ((mpz_cmp_si (sz, si)) != 0)
35 {
36 printf ("mpz_cmp_si (sz, %ld) != 0.\n", si);
37 return 0;
38 }
39 if (mpz_get_si (sz) != si)
40 {
41 printf ("mpz_get_si (sz) != %ld.\n", si);
42 return 0;
43 }
44
45 mpz_init_set_si (t, si);
46
47 if (mpz_cmp (t, sz) != 0)
48 {
49 printf ("mpz_init_set_si (%ld) failed.\n", si);
50 printf (" got="); mpz_out_str (stdout, 10, t); printf ("\n");
51 return 0;
52 }
53
54 mpz_clear (t);
55 return 1;
56 }
57
58 /* Called with mpz_cmp (sz, oz) == c. If sz fits in a signed long,
59 si is the coresponding value, and similarly for oz and oi. */
60 void
61 check_si_cmp (const mpz_t sz, const mpz_t oz, long si, long oi, int c)
62 {
63 if (mpz_cmp (sz, oz) != c)
64 {
65 printf ("mpz_cmp (sz, oz) != %i.\n", c);
66 goto fail;
67 }
68
69 if (mpz_fits_slong_p (sz))
70 {
71 if (!check_si (sz, si))
72 goto fail;
73 if (mpz_cmp_si (oz, si) != -c)
74 {
75 printf ("mpz_cmp_si (oz, %ld) != %i.\n", si, -c);
76 goto fail;
77 }
78 }
79 else
80 {
81 if (mpz_cmp_si (sz, si) != c)
82 {
83 printf ("mpz_cmp_si (sz, %ld) != %i.\n", si, c);
84 goto fail;
85 }
86 if (mpz_cmp_si (sz, -c) != c)
87 {
88 printf ("mpz_cmp_si (sz, %i) != %i.\n", -c, c);
89 goto fail;
90 }
91 }
92 if (mpz_fits_slong_p (oz))
93 {
94 if (!check_si (oz, oi))
95 goto fail;
96 if (mpz_cmp_si (sz, oi) != c)
97 {
98 printf ("mpz_cmp_si (sz, %ld) != %i.\n", oi, c);
99 goto fail;
100 }
101 }
102 return;
103
104 fail:
105 printf (" sz="); mpz_out_str (stdout, 10, sz); printf ("\n");
106 printf (" si=%ld\n", si);
107 printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
108 printf (" oi=%ld\n", si);
109 abort ();
110 }
111
112 void
113 try_op_si (int c)
114 {
115 long si, oi;
116 mpz_t sz, oz;
117 unsigned overflow_count;
118
119 si = c;
120 mpz_init_set_si (sz, si);
121
122 oi = si;
123 mpz_init_set (oz, sz);
124
125 /* To get a few tests with operands straddling the border, don't
126 stop at the very first operand exceeding a signed long. */
127 for (overflow_count = 0; overflow_count < 10; )
128 {
129 /* c * 2^k */
130 mpz_mul_2exp (sz, sz, 1);
131 if (mpz_fits_slong_p (sz))
132 si *= 2;
133 else
134 overflow_count++;
135
136 check_si_cmp (sz, oz, si, oi, c);
137
138 /* c * (2^k + 1) */
139 if (c == -1)
140 mpz_sub_ui (oz, sz, 1);
141 else
142 mpz_add_ui (oz, sz, 1);
143 if (mpz_fits_slong_p (oz))
144 oi = si + c;
145 else
146 overflow_count++;
147 check_si_cmp (oz, sz, oi, si, c);
148
149 /* c * (2^K - 1) */
150 mpz_mul_si (oz, sz, 2*c);
151 if (c == -1)
152 mpz_ui_sub (oz, 1, oz); /* oz = sz * 2 + 1 */
153 else
154 mpz_sub_ui (oz, oz, 1); /* oz = sz * 2 - 1 */
155 if (mpz_fits_slong_p (oz))
156 oi = (si - c) * 2 + c;
157 else
158 overflow_count++;
159
160 check_si_cmp (oz, sz, oi, si, c);
161 };
162
163 mpz_clear (sz);
164 mpz_clear (oz);
165 }
166
167 void
168 try_fits_slong_p (void)
169 {
170 mpz_t x;
171 mpz_init_set_si (x, LONG_MAX);
172 if (!mpz_fits_slong_p (x))
173 {
174 printf ("mpz_fits_slong_p (LONG_MAX) false!\n");
175 abort ();
176 }
177 mpz_add_ui (x, x, 1);
178 if (mpz_fits_slong_p (x))
179 {
180 printf ("mpz_fits_slong_p (LONG_MAX + 1) true!\n");
181 abort ();
182 }
183 mpz_set_si (x, LONG_MIN);
184 if (!mpz_fits_slong_p (x))
185 {
186 printf ("mpz_fits_slong_p (LONG_MIN) false!\n");
187 abort ();
188 }
189 mpz_sub_ui (x, x, 1);
190 if (mpz_fits_slong_p (x))
191 {
192 printf ("mpz_fits_slong_p (LONG_MIN - 1) true!\n");
193 abort ();
194 }
195
196 mpz_clear (x);
197 }
198
199 void
200 try_fits_utype_p (void)
201 {
202 mpz_t x;
203 mpz_init (x);
204 if (!mpz_fits_ulong_p (x))
205 {
206 printf ("mpz_fits_ulong_p (0) false!\n");
207 abort ();
208 }
209 if (!mpz_fits_uint_p (x))
210 {
211 printf ("mpz_fits_uint_p (0) false!\n");
212 abort ();
213 }
214 if (!mpz_fits_ushort_p (x))
215 {
216 printf ("mpz_fits_udhort_p (0) false!\n");
217 abort ();
218 }
219 mpz_set_si (x, -1);
220 if (mpz_fits_ulong_p (x))
221 {
222 printf ("mpz_fits_ulong_p (- 1) true!\n");
223 abort ();
224 }
225 if (mpz_fits_uint_p (x))
226 {
227 printf ("mpz_fits_uint_p (- 1) true!\n");
228 abort ();
229 }
230 if (mpz_fits_ushort_p (x))
231 {
232 printf ("mpz_fits_ushort_p (- 1) true!\n");
233 abort ();
234 }
235 mpz_set_ui (x, ULONG_MAX);
236 if (!mpz_fits_ulong_p (x))
237 {
238 printf ("mpz_fits_ulong_p (ULONG_MAX) false!\n");
239 abort ();
240 }
241 mpz_add_ui (x, x, 1);
242 if (mpz_fits_ulong_p (x))
243 {
244 printf ("mpz_fits_ulong_p (ULONG_MAX + 1) true!\n");
245 abort ();
246 }
247 mpz_set_ui (x, UINT_MAX);
248 if (!mpz_fits_uint_p (x))
249 {
250 printf ("mpz_fits_uint_p (UINT_MAX) false!\n");
251 abort ();
252 }
253 mpz_add_ui (x, x, 1);
254 if (mpz_fits_uint_p (x))
255 {
256 printf ("mpz_fits_uint_p (UINT_MAX + 1) true!\n");
257 abort ();
258 }
259 mpz_set_ui (x, USHRT_MAX);
260 if (!mpz_fits_ushort_p (x))
261 {
262 printf ("mpz_fits_ushort_p (USHRT_MAX) false!\n");
263 abort ();
264 }
265 mpz_add_ui (x, x, 1);
266 if (mpz_fits_ushort_p (x))
267 {
268 printf ("mpz_fits_ushort_p (USHRT_MAX + 1) true!\n");
269 abort ();
270 }
271
272 mpz_clear (x);
273 }
274
275 void
276 try_fits_sint_p (void)
277 {
278 mpz_t x;
279 mpz_init_set_si (x, INT_MAX);
280 if (!mpz_fits_sint_p (x))
281 {
282 printf ("mpz_fits_sint_p (INT_MAX) false!\n");
283 abort ();
284 }
285 mpz_add_ui (x, x, 1);
286 if (mpz_fits_sint_p (x))
287 {
288 printf ("mpz_fits_sint_p (INT_MAX + 1) true!\n");
289 abort ();
290 }
291 mpz_set_si (x, INT_MIN);
292 if (!mpz_fits_sint_p (x))
293 {
294 printf ("mpz_fits_sint_p (INT_MIN) false!\n");
295 abort ();
296 }
297 mpz_sub_ui (x, x, 1);
298 if (mpz_fits_sint_p (x))
299 {
300 printf ("mpz_fits_sint_p (INT_MIN - 1) true!\n");
301 abort ();
302 }
303
304 mpz_clear (x);
305 }
306
307 void
308 try_fits_sshort_p (void)
309 {
310 mpz_t x;
311 mpz_init_set_si (x, SHRT_MAX);
312 if (!mpz_fits_sshort_p (x))
313 {
314 printf ("mpz_fits_sshort_p (SHRT_MAX) false!\n");
315 abort ();
316 }
317 mpz_add_ui (x, x, 1);
318 if (mpz_fits_sshort_p (x))
319 {
320 printf ("mpz_fits_sshort_p (SHRT_MAX + 1) true!\n");
321 abort ();
322 }
323 mpz_set_si (x, SHRT_MIN);
324 if (!mpz_fits_sshort_p (x))
325 {
326 printf ("mpz_fits_sshort_p (SHRT_MIN) false!\n");
327 abort ();
328 }
329 mpz_sub_ui (x, x, 1);
330 if (mpz_fits_sshort_p (x))
331 {
332 printf ("mpz_fits_sshort_p (SHRT_MIN - 1) true!\n");
333 abort ();
334 }
335
336 mpz_clear (x);
337 }
338
339 void
340 testmain (int argc, char *argv[])
341 {
342 try_fits_slong_p ();
343 try_fits_sint_p ();
344 try_fits_sshort_p ();
345 try_fits_utype_p ();
346 try_op_si (-1);
347 try_op_si (1);
348 }