(root)/
gmp-6.3.0/
mini-gmp/
tests/
t-str.c
       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  }