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