xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-str.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /*
2 
3 Copyright 2012-2014, 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 <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;
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 	  if (strcmp (bp, rp))
198 	    {
199 	      fprintf (stderr, "mpz_get_str failed:\n");
200 	      dump ("a", a);
201 	      fprintf (stderr, "b = %s\n", bp);
202 	      fprintf (stderr, "  base = %d\n", base);
203 	      fprintf (stderr, "r = %s\n", rp);
204 	      abort ();
205 	    }
206 
207 	  /* Just a few tests with file i/o. */
208 	  if (tmp && i < 20)
209 	    {
210 	      size_t tn;
211 	      rewind (tmp);
212 	      tn = mpz_out_str (tmp, (i&1 || base > 36) ? base: -base, a);
213 	      if (tn != rn)
214 		{
215 		  fprintf (stderr, "mpz_out_str, bad return value:\n");
216 		  dump ("a", a);
217 		  fprintf (stderr, "r = %s\n", rp);
218 		  fprintf (stderr, "  base %d, correct size %u, got %u\n",
219 			   base, (unsigned) rn, (unsigned)tn);
220 		  abort ();
221 		}
222 	      rewind (tmp);
223 	      memset (bp, 0, rn);
224 	      tn = fread (bp, 1, rn, tmp);
225 	      if (tn != rn)
226 		{
227 		  fprintf (stderr,
228 			   "fread failed, expected %lu bytes, got only %lu.\n",
229 			   (unsigned long) rn, (unsigned long) tn);
230 		  abort ();
231 		}
232 
233 	      if (memcmp (bp, rp, rn) != 0)
234 		{
235 		  fprintf (stderr, "mpz_out_str failed:\n");
236 		  dump ("a", a);
237 		  fprintf (stderr, "b = %s\n", bp);
238 		  fprintf (stderr, "  base = %d\n", base);
239 		  fprintf (stderr, "r = %s\n", rp);
240 		  abort ();
241 		}
242 	    }
243 
244 	  mpz_set_str (b, rp, base);
245 
246 	  if (mpz_cmp (a, b))
247 	    {
248 	      fprintf (stderr, "mpz_set_str failed:\n");
249 	      fprintf (stderr, "r = %s\n", rp);
250 	      fprintf (stderr, "  base = %d\n", base);
251 	      fprintf (stderr, "r = %s\n", ap);
252 	      fprintf (stderr, "  base = 16\n");
253 	      dump ("b", b);
254 	      dump ("r", a);
255 	      abort ();
256 	    }
257 
258 	  /* Test mpn interface */
259 	  if (base && mpz_sgn (a))
260 	    {
261 	      size_t i;
262 	      const char *absr;
263 	      mp_limb_t t[MAXLIMBS];
264 	      size_t tn = mpz_size (a);
265 
266 	      assert (tn <= MAXLIMBS);
267 	      mpn_copyi (t, a->_mp_d, tn);
268 
269 	      bn = mpn_get_str ((unsigned char *) bp, base, t, tn);
270 	      if (bn != arn)
271 		{
272 		  fprintf (stderr, "mpn_get_str failed:\n");
273 		  fprintf (stderr, "returned length: %lu (bad)\n", (unsigned long) bn);
274 		  fprintf (stderr, "expected: %lu\n", (unsigned long) arn);
275 		  fprintf (stderr, "  base = %d\n", base);
276 		  fprintf (stderr, "r = %s\n", ap);
277 		  fprintf (stderr, "  base = 16\n");
278 		  dump ("b", b);
279 		  dump ("r", a);
280 		  abort ();
281 		}
282 	      absr = rp + (rp[0] == '-');
283 
284 	      for (i = 0; i < bn; i++)
285 		{
286 		  unsigned char digit = absr[i];
287 		  char value;
288 		  if (digit >= '0' && digit <= '9')
289 		    value = digit - '0';
290 		  else if (digit >= 'a' && digit <= 'z')
291 		    value = digit - 'a' + ((base > 36) ? 36 : 10);
292 		  else if (digit >= 'A' && digit <= 'Z')
293 		    value = digit - 'A' + 10;
294 		  else
295 		    {
296 		      fprintf (stderr, "Internal error in test.\n");
297 		      abort();
298 		    }
299 		  if (bp[i] != value)
300 		    {
301 		      fprintf (stderr, "mpn_get_str failed:\n");
302 		      fprintf (stderr, "digit %lu: %d (bad)\n", (unsigned long) i, bp[i]);
303 		      fprintf (stderr, "expected: %d\n", value);
304 		      fprintf (stderr, "  base = %d\n", base);
305 		      fprintf (stderr, "r = %s\n", ap);
306 		      fprintf (stderr, "  base = 16\n");
307 		      dump ("b", b);
308 		      dump ("r", a);
309 		      abort ();
310 		    }
311 		}
312 	      tn = mpn_set_str (t, (unsigned char *) bp, bn, base);
313 	      if (tn != mpz_size (a) || mpn_cmp (t, a->_mp_d, tn))
314 		{
315 		  fprintf (stderr, "mpn_set_str failed:\n");
316 		  fprintf (stderr, "r = %s\n", rp);
317 		  fprintf (stderr, "  base = %d\n", base);
318 		  fprintf (stderr, "r = %s\n", ap);
319 		  fprintf (stderr, "  base = 16\n");
320 		  dump ("r", a);
321 		  abort ();
322 		}
323 	    }
324 	  free (ap);
325 	  free (rp);
326 	  testfree (bp);
327 	}
328     }
329   mpz_clear (a);
330   mpz_clear (b);
331 }
332