1 /*
2
3 Copyright 2012-2014, 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 <assert.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "testutils.h"
27
28 #define MAXBITS 400
29 #define COUNT 2000
30
31 #define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
32 #define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
33
34 static void
35 test_small (void)
36 {
37 struct {
38 const char *input;
39 const char *decimal;
40 } data[] = {
41 { "183407", "183407" },
42 { " 763959", "763959 " },
43 { "9 81999", "981999" },
44 { "10\t7398 ", "107398" },
45 { "-9585 44", "-00958544" },
46 { "-0", "0000" },
47 { " -000 ", "0" },
48 { "0704436", "231710" },
49 /* Check the case of large number of leading zeros. */
50 { "0000000000000000000000000", "0000000000000000000000000" },
51 { "000000000000000000000000704436", "000000000000000000000000231710" },
52 { " 02503517", "689999" },
53 { "0 1312143", "365667" },
54 { "-03 274062", "-882738" },
55 { "012\t242", "005282" },
56 { "0b11010111110010001111", "883855" },
57 { " 0b11001010010100001", "103585" },
58 { "-0b101010110011101111", "-175343" },
59 { "0b 1111111011011100110", "521958" },
60 { "0b1 1111110111001000011", "1044035" },
61 { " 0x53dfc", "343548" },
62 { "0xfA019", "1024025" },
63 { "0x 642d1", "410321" },
64 { "0x5 8067", "360551" },
65 { "-0xd6Be6", "-879590" },
66 { "\t0B1110000100000000011", "460803" },
67 { "0B\t1111110010010100101", "517285" },
68 { "0B1\t010111101101110100", "359284" },
69 { "-0B101\t1001101111111001", "-367609" },
70 { "0B10001001010111110000", "562672" },
71 { "0Xe4B7e", "936830" },
72 { "0X1E4bf", "124095" },
73 { "-0Xfdb90", "-1039248" },
74 { "0X7fc47", "523335" },
75 { "0X8167c", "530044" },
76 /* Some invalid inputs */
77 { "", NULL },
78 { "0x", NULL },
79 { "0b", NULL },
80 { "0z", NULL },
81 { "-", NULL },
82 { "-0x ", NULL },
83 { "0|1", NULL },
84 { "4+4", NULL },
85 { "0ab", NULL },
86 { "10x0", NULL },
87 { "0xxab", NULL },
88 { "ab", NULL },
89 { "0%#", NULL },
90 { "$foo", NULL },
91 { NULL, NULL }
92 };
93 unsigned i;
94 mpz_t a, b;
95 mpz_init (b);
96
97 for (i = 0; data[i].input; i++)
98 {
99 int res = mpz_init_set_str (a, data[i].input, 0);
100 if (data[i].decimal)
101 {
102 if (res != 0)
103 {
104 fprintf (stderr, "mpz_set_str returned -1, input: %s\n",
105 data[i].input);
106 abort ();
107 }
108 if (mpz_set_str (b, data[i].decimal, 10) != 0)
109 {
110 fprintf (stderr, "mpz_set_str returned -1, decimal input: %s\n",
111 data[i].input);
112 abort ();
113 }
114 if (mpz_cmp (a, b) != 0)
115 {
116 fprintf (stderr, "mpz_set_str failed for input: %s\n",
117 data[i].input);
118
119 dump ("got", a);
120 dump ("ref", b);
121 abort ();
122 }
123 }
124 else if (res != -1)
125 {
126 fprintf (stderr, "mpz_set_str returned %d, invalid input: %s\n",
127 res, data[i].input);
128 abort ();
129 }
130 mpz_clear (a);
131 }
132
133 mpz_clear (b);
134 }
135
136 void
137 testmain (int argc, char **argv)
138 {
139 unsigned i;
140 char *ap;
141 char *bp;
142 char *rp;
143 size_t bn, rn, arn, bps;
144
145 mpz_t a, b;
146
147 FILE *tmp;
148
149 test_small ();
150
151 mpz_init (a);
152 mpz_init (b);
153
154 tmp = tmpfile ();
155 if (!tmp)
156 fprintf (stderr,
157 "Failed to create temporary file. Skipping mpz_out_str tests.\n");
158
159 if (mpz_out_str (tmp, 63, a) != 0)
160 {
161 printf ("mpz_out_str did not return 0 (error) with base > 62\n");
162 abort ();
163 }
164
165 if (mpz_out_str (tmp, -37, a) != 0)
166 {
167 printf ("mpz_out_str did not return 0 (error) with base < -37\n");
168 abort ();
169 }
170
171 for (i = 0; i < COUNT; i++)
172 {
173 int base;
174 for (base = 0; base <= 62; base += 1 + (base == 0))
175 {
176 hex_random_str_op (MAXBITS, (i&1 || base > 36) ? base: -base, &ap, &rp);
177 if (mpz_set_str (a, ap, 16) != 0)
178 {
179 fprintf (stderr, "mpz_set_str failed on input %s\n", ap);
180 abort ();
181 }
182
183 rn = strlen (rp);
184 arn = rn - (rp[0] == '-');
185
186 bn = mpz_sizeinbase (a, base ? base : 10);
187 if (bn < arn || bn > (arn + 1))
188 {
189 fprintf (stderr, "mpz_sizeinbase failed:\n");
190 dump ("a", a);
191 fprintf (stderr, "r = %s\n", rp);
192 fprintf (stderr, " base %d, correct size %u, got %u\n",
193 base, (unsigned) arn, (unsigned)bn);
194 abort ();
195 }
196 bp = mpz_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
197 bps = strlen(bp) + 1;
198 if (strcmp (bp, rp))
199 {
200 fprintf (stderr, "mpz_get_str failed:\n");
201 dump ("a", a);
202 fprintf (stderr, "b = %s\n", bp);
203 fprintf (stderr, " base = %d\n", base);
204 fprintf (stderr, "r = %s\n", rp);
205 abort ();
206 }
207
208 /* Just a few tests with file i/o. */
209 if (tmp && i < 20)
210 {
211 size_t tn;
212 rewind (tmp);
213 tn = mpz_out_str (tmp, (i&1 || base > 36) ? base: -base, a);
214 if (tn != rn)
215 {
216 fprintf (stderr, "mpz_out_str, bad return value:\n");
217 dump ("a", a);
218 fprintf (stderr, "r = %s\n", rp);
219 fprintf (stderr, " base %d, correct size %u, got %u\n",
220 base, (unsigned) rn, (unsigned)tn);
221 abort ();
222 }
223 rewind (tmp);
224 memset (bp, 0, rn);
225 tn = fread (bp, 1, rn, tmp);
226 if (tn != rn)
227 {
228 fprintf (stderr,
229 "fread failed, expected %lu bytes, got only %lu.\n",
230 (unsigned long) rn, (unsigned long) tn);
231 abort ();
232 }
233
234 if (memcmp (bp, rp, rn) != 0)
235 {
236 fprintf (stderr, "mpz_out_str failed:\n");
237 dump ("a", a);
238 fprintf (stderr, "b = %s\n", bp);
239 fprintf (stderr, " base = %d\n", base);
240 fprintf (stderr, "r = %s\n", rp);
241 abort ();
242 }
243 }
244
245 mpz_set_str (b, rp, base);
246
247 if (mpz_cmp (a, b))
248 {
249 fprintf (stderr, "mpz_set_str failed:\n");
250 fprintf (stderr, "r = %s\n", rp);
251 fprintf (stderr, " base = %d\n", base);
252 fprintf (stderr, "r = %s\n", ap);
253 fprintf (stderr, " base = 16\n");
254 dump ("b", b);
255 dump ("r", a);
256 abort ();
257 }
258
259 /* Test mpn interface */
260 if (base && mpz_sgn (a))
261 {
262 size_t i;
263 const char *absr;
264 mp_limb_t t[MAXLIMBS];
265 size_t tn = mpz_size (a);
266
267 assert (tn <= MAXLIMBS);
268 mpn_copyi (t, a->_mp_d, tn);
269
270 bn = mpn_get_str ((unsigned char *) bp, base, t, tn);
271 if (bn != arn)
272 {
273 fprintf (stderr, "mpn_get_str failed:\n");
274 fprintf (stderr, "returned length: %lu (bad)\n", (unsigned long) bn);
275 fprintf (stderr, "expected: %lu\n", (unsigned long) arn);
276 fprintf (stderr, " base = %d\n", base);
277 fprintf (stderr, "r = %s\n", ap);
278 fprintf (stderr, " base = 16\n");
279 dump ("b", b);
280 dump ("r", a);
281 abort ();
282 }
283 absr = rp + (rp[0] == '-');
284
285 for (i = 0; i < bn; i++)
286 {
287 unsigned char digit = absr[i];
288 char value;
289 if (digit >= '0' && digit <= '9')
290 value = digit - '0';
291 else if (digit >= 'a' && digit <= 'z')
292 value = digit - 'a' + ((base > 36) ? 36 : 10);
293 else if (digit >= 'A' && digit <= 'Z')
294 value = digit - 'A' + 10;
295 else
296 {
297 fprintf (stderr, "Internal error in test.\n");
298 abort();
299 }
300 if (bp[i] != value)
301 {
302 fprintf (stderr, "mpn_get_str failed:\n");
303 fprintf (stderr, "digit %lu: %d (bad)\n", (unsigned long) i, bp[i]);
304 fprintf (stderr, "expected: %d\n", value);
305 fprintf (stderr, " base = %d\n", base);
306 fprintf (stderr, "r = %s\n", ap);
307 fprintf (stderr, " base = 16\n");
308 dump ("b", b);
309 dump ("r", a);
310 abort ();
311 }
312 }
313 tn = mpn_set_str (t, (unsigned char *) bp, bn, base);
314 if (tn != mpz_size (a) || mpn_cmp (t, a->_mp_d, tn))
315 {
316 fprintf (stderr, "mpn_set_str failed:\n");
317 fprintf (stderr, "r = %s\n", rp);
318 fprintf (stderr, " base = %d\n", base);
319 fprintf (stderr, "r = %s\n", ap);
320 fprintf (stderr, " base = 16\n");
321 dump ("r", a);
322 abort ();
323 }
324 }
325 free (ap);
326 free (rp);
327 testfree (bp, bps);
328 }
329 }
330 mpz_clear (a);
331 mpz_clear (b);
332 }