xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-str.c (revision 4d342c046e3288fb5a1edcd33cfec48c41c80664)
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;
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   for (i = 0; i < COUNT; i++)
160     {
161       int base;
162       for (base = 0; base <= 36; base += 1 + (base == 0))
163 	{
164 	  hex_random_str_op (MAXBITS, i&1 ? base: -base, &ap, &rp);
165 	  if (mpz_set_str (a, ap, 16) != 0)
166 	    {
167 	      fprintf (stderr, "mpz_set_str failed on input %s\n", ap);
168 	      abort ();
169 	    }
170 
171 	  rn = strlen (rp);
172 	  arn = rn - (rp[0] == '-');
173 
174 	  bn = mpz_sizeinbase (a, base ? base : 10);
175 	  if (bn < arn || bn > (arn + 1))
176 	    {
177 	      fprintf (stderr, "mpz_sizeinbase failed:\n");
178 	      dump ("a", a);
179 	      fprintf (stderr, "r = %s\n", rp);
180 	      fprintf (stderr, "  base %d, correct size %u, got %u\n",
181 		       base, (unsigned) arn, (unsigned)bn);
182 	      abort ();
183 	    }
184 	  bp = mpz_get_str (NULL, i&1 ? base: -base, a);
185 	  if (strcmp (bp, rp))
186 	    {
187 	      fprintf (stderr, "mpz_get_str failed:\n");
188 	      dump ("a", a);
189 	      fprintf (stderr, "b = %s\n", bp);
190 	      fprintf (stderr, "  base = %d\n", base);
191 	      fprintf (stderr, "r = %s\n", rp);
192 	      abort ();
193 	    }
194 
195 	  /* Just a few tests with file i/o. */
196 	  if (tmp && i < 20)
197 	    {
198 	      size_t tn;
199 	      rewind (tmp);
200 	      tn = mpz_out_str (tmp, i&1 ? base: -base, a);
201 	      if (tn != rn)
202 		{
203 		  fprintf (stderr, "mpz_out_str, bad return value:\n");
204 		  dump ("a", a);
205 		  fprintf (stderr, "r = %s\n", rp);
206 		  fprintf (stderr, "  base %d, correct size %u, got %u\n",
207 			   base, (unsigned) rn, (unsigned)tn);
208 		  abort ();
209 		}
210 	      rewind (tmp);
211 	      memset (bp, 0, rn);
212 	      tn = fread (bp, 1, rn, tmp);
213 	      if (tn != rn)
214 		{
215 		  fprintf (stderr,
216 			   "fread failed, expected %lu bytes, got only %lu.\n",
217 			   (unsigned long) rn, (unsigned long) tn);
218 		  abort ();
219 		}
220 
221 	      if (memcmp (bp, rp, rn) != 0)
222 		{
223 		  fprintf (stderr, "mpz_out_str failed:\n");
224 		  dump ("a", a);
225 		  fprintf (stderr, "b = %s\n", bp);
226 		  fprintf (stderr, "  base = %d\n", base);
227 		  fprintf (stderr, "r = %s\n", rp);
228 		  abort ();
229 		}
230 	    }
231 
232 	  mpz_set_str (b, rp, base);
233 
234 	  if (mpz_cmp (a, b))
235 	    {
236 	      fprintf (stderr, "mpz_set_str failed:\n");
237 	      fprintf (stderr, "r = %s\n", rp);
238 	      fprintf (stderr, "  base = %d\n", base);
239 	      fprintf (stderr, "r = %s\n", ap);
240 	      fprintf (stderr, "  base = 16\n");
241 	      dump ("b", b);
242 	      dump ("r", a);
243 	      abort ();
244 	    }
245 
246 	  /* Test mpn interface */
247 	  if (base && mpz_sgn (a))
248 	    {
249 	      size_t i;
250 	      const char *absr;
251 	      mp_limb_t t[MAXLIMBS];
252 	      mp_size_t tn = mpz_size (a);
253 
254 	      assert (tn <= MAXLIMBS);
255 	      mpn_copyi (t, a->_mp_d, tn);
256 
257 	      bn = mpn_get_str ((unsigned char *) bp, base, t, tn);
258 	      if (bn != arn)
259 		{
260 		  fprintf (stderr, "mpn_get_str failed:\n");
261 		  fprintf (stderr, "returned length: %lu (bad)\n", (unsigned long) bn);
262 		  fprintf (stderr, "expected: %lu\n", (unsigned long) arn);
263 		  fprintf (stderr, "  base = %d\n", base);
264 		  fprintf (stderr, "r = %s\n", ap);
265 		  fprintf (stderr, "  base = 16\n");
266 		  dump ("b", b);
267 		  dump ("r", a);
268 		  abort ();
269 		}
270 	      absr = rp + (rp[0] == '-');
271 
272 	      for (i = 0; i < bn; i++)
273 		{
274 		  unsigned char digit = absr[i];
275 		  unsigned value;
276 		  if (digit >= '0' && digit <= '9')
277 		    value = digit - '0';
278 		  else if (digit >= 'a' && digit <= 'z')
279 		    value = digit - 'a' + 10;
280 		  else if (digit >= 'A' && digit <= 'Z')
281 		    value = digit - 'A' + 10;
282 		  else
283 		    {
284 		      fprintf (stderr, "Internal error in test.\n");
285 		      abort();
286 		    }
287 		  if (bp[i] != value)
288 		    {
289 		      fprintf (stderr, "mpn_get_str failed:\n");
290 		      fprintf (stderr, "digit %lu: %d (bad)\n", (unsigned long) i, bp[i]);
291 		      fprintf (stderr, "expected: %d\n", value);
292 		      fprintf (stderr, "  base = %d\n", base);
293 		      fprintf (stderr, "r = %s\n", ap);
294 		      fprintf (stderr, "  base = 16\n");
295 		      dump ("b", b);
296 		      dump ("r", a);
297 		      abort ();
298 		    }
299 		}
300 	      tn = mpn_set_str (t, (unsigned char *) bp, bn, base);
301 	      if (tn != mpz_size (a) || mpn_cmp (t, a->_mp_d, tn))
302 		{
303 		  fprintf (stderr, "mpn_set_str failed:\n");
304 		  fprintf (stderr, "r = %s\n", rp);
305 		  fprintf (stderr, "  base = %d\n", base);
306 		  fprintf (stderr, "r = %s\n", ap);
307 		  fprintf (stderr, "  base = 16\n");
308 		  dump ("r", a);
309 		  abort ();
310 		}
311 	    }
312 	  free (ap);
313 	  free (rp);
314 	  testfree (bp);
315 	}
316     }
317   mpz_clear (a);
318   mpz_clear (b);
319 }
320