1 /* Exercise some mpz_..._si functions.
2
3 Copyright 2013, 2016 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
check_si(const mpz_t sz,long si)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
check_si_cmp(const mpz_t sz,const mpz_t oz,long si,long oi,int c)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
try_op_si(int c)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
try_fits_slong_p(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
testmain(int argc,char * argv[])200 testmain (int argc, char *argv[])
201 {
202 try_fits_slong_p ();
203 try_op_si (-1);
204 try_op_si (1);
205 }
206