Blame mini-gmp/tests/t-str.c

Packit 5c3484
/*
Packit 5c3484
Packit 5c3484
Copyright 2012-2014, 2016 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library test suite.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is free software; you can redistribute it
Packit 5c3484
and/or modify it under the terms of the GNU General Public License as
Packit 5c3484
published by the Free Software Foundation; either version 3 of the License,
Packit 5c3484
or (at your option) any later version.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is distributed in the hope that it will be
Packit 5c3484
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5c3484
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit 5c3484
Public License for more details.
Packit 5c3484
Packit 5c3484
You should have received a copy of the GNU General Public License along with
Packit 5c3484
the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <assert.h>
Packit 5c3484
#include <limits.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include <string.h>
Packit 5c3484
Packit 5c3484
#include "testutils.h"
Packit 5c3484
Packit 5c3484
#define MAXBITS 400
Packit 5c3484
#define COUNT 2000
Packit 5c3484
Packit 5c3484
#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
Packit 5c3484
#define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
Packit 5c3484
Packit 5c3484
static void
Packit 5c3484
test_small (void)
Packit 5c3484
{
Packit 5c3484
  struct {
Packit 5c3484
    const char *input;
Packit 5c3484
    const char *decimal;
Packit 5c3484
  } data[] = {
Packit 5c3484
    { "183407", "183407" },
Packit 5c3484
    { " 763959", "763959 " },
Packit 5c3484
    { "9 81999", "981999" },
Packit 5c3484
    { "10\t7398 ", "107398" },
Packit 5c3484
    { "-9585 44", "-00958544" },
Packit 5c3484
    { "-0", "0000" },
Packit 5c3484
    { " -000  ", "0" },
Packit 5c3484
    { "0704436", "231710" },
Packit 5c3484
    /* Check the case of large number of leading zeros. */
Packit 5c3484
    { "0000000000000000000000000", "0000000000000000000000000" },
Packit 5c3484
    { "000000000000000000000000704436", "000000000000000000000000231710" },
Packit 5c3484
    { " 02503517", "689999" },
Packit 5c3484
    { "0 1312143", "365667" },
Packit 5c3484
    { "-03 274062", "-882738" },
Packit 5c3484
    { "012\t242", "005282" },
Packit 5c3484
    { "0b11010111110010001111", "883855" },
Packit 5c3484
    { " 0b11001010010100001", "103585" },
Packit 5c3484
    { "-0b101010110011101111", "-175343" },
Packit 5c3484
    { "0b 1111111011011100110", "521958" },
Packit 5c3484
    { "0b1 1111110111001000011", "1044035" },
Packit 5c3484
    { " 0x53dfc", "343548" },
Packit 5c3484
    { "0xfA019", "1024025" },
Packit 5c3484
    { "0x 642d1", "410321" },
Packit 5c3484
    { "0x5 8067", "360551" },
Packit 5c3484
    { "-0xd6Be6", "-879590" },
Packit 5c3484
    { "\t0B1110000100000000011", "460803" },
Packit 5c3484
    { "0B\t1111110010010100101", "517285" },
Packit 5c3484
    { "0B1\t010111101101110100", "359284" },
Packit 5c3484
    { "-0B101\t1001101111111001", "-367609" },
Packit 5c3484
    { "0B10001001010111110000", "562672" },
Packit 5c3484
    { "0Xe4B7e", "936830" },
Packit 5c3484
    { "0X1E4bf", "124095" },
Packit 5c3484
    { "-0Xfdb90", "-1039248" },
Packit 5c3484
    { "0X7fc47", "523335" },
Packit 5c3484
    { "0X8167c", "530044" },
Packit 5c3484
    /* Some invalid inputs */
Packit 5c3484
    { "", NULL },
Packit 5c3484
    { "0x", NULL },
Packit 5c3484
    { "0b", NULL },
Packit 5c3484
    { "0z", NULL },
Packit 5c3484
    { "-", NULL },
Packit 5c3484
    { "-0x ", NULL },
Packit 5c3484
    { "0|1", NULL },
Packit 5c3484
    { "4+4", NULL },
Packit 5c3484
    { "0ab", NULL },
Packit 5c3484
    { "10x0", NULL },
Packit 5c3484
    { "0xxab", NULL },
Packit 5c3484
    { "ab", NULL },
Packit 5c3484
    { "0%#", NULL },
Packit 5c3484
    { "$foo", NULL },
Packit 5c3484
    { NULL, NULL }
Packit 5c3484
  };
Packit 5c3484
  unsigned i;
Packit 5c3484
  mpz_t a, b;
Packit 5c3484
  mpz_init (b);
Packit 5c3484
Packit 5c3484
  for (i = 0; data[i].input; i++)
Packit 5c3484
    {
Packit 5c3484
      int res = mpz_init_set_str (a, data[i].input, 0);
Packit 5c3484
      if (data[i].decimal)
Packit 5c3484
	{
Packit 5c3484
	  if (res != 0)
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_set_str returned -1, input: %s\n",
Packit 5c3484
		       data[i].input);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
	  if (mpz_set_str (b, data[i].decimal, 10) != 0)
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_set_str returned -1, decimal input: %s\n",
Packit 5c3484
		       data[i].input);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
	  if (mpz_cmp (a, b) != 0)
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_set_str failed for input: %s\n",
Packit 5c3484
		       data[i].input);
Packit 5c3484
Packit 5c3484
	      dump ("got", a);
Packit 5c3484
	      dump ("ref", b);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
	}
Packit 5c3484
      else if (res != -1)
Packit 5c3484
	{
Packit 5c3484
	  fprintf (stderr, "mpz_set_str returned %d, invalid input: %s\n",
Packit 5c3484
		   res, data[i].input);
Packit 5c3484
	  abort ();
Packit 5c3484
	}
Packit 5c3484
      mpz_clear (a);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (b);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
testmain (int argc, char **argv)
Packit 5c3484
{
Packit 5c3484
  unsigned i;
Packit 5c3484
  char *ap;
Packit 5c3484
  char *bp;
Packit 5c3484
  char *rp;
Packit 5c3484
  size_t bn, rn, arn;
Packit 5c3484
Packit 5c3484
  mpz_t a, b;
Packit 5c3484
Packit 5c3484
  FILE *tmp;
Packit 5c3484
Packit 5c3484
  test_small ();
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
  mpz_init (b);
Packit 5c3484
Packit 5c3484
  tmp = tmpfile ();
Packit 5c3484
  if (!tmp)
Packit 5c3484
    fprintf (stderr,
Packit 5c3484
	     "Failed to create temporary file. Skipping mpz_out_str tests.\n");
Packit 5c3484
Packit 5c3484
  for (i = 0; i < COUNT; i++)
Packit 5c3484
    {
Packit 5c3484
      int base;
Packit 5c3484
      for (base = 0; base <= 36; base += 1 + (base == 0))
Packit 5c3484
	{
Packit 5c3484
	  hex_random_str_op (MAXBITS, i&1 ? base: -base, &ap, &rp);
Packit 5c3484
	  if (mpz_set_str (a, ap, 16) != 0)
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_set_str failed on input %s\n", ap);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  rn = strlen (rp);
Packit 5c3484
	  arn = rn - (rp[0] == '-');
Packit 5c3484
Packit 5c3484
	  bn = mpz_sizeinbase (a, base ? base : 10);
Packit 5c3484
	  if (bn < arn || bn > (arn + 1))
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_sizeinbase failed:\n");
Packit 5c3484
	      dump ("a", a);
Packit 5c3484
	      fprintf (stderr, "r = %s\n", rp);
Packit 5c3484
	      fprintf (stderr, "  base %d, correct size %u, got %u\n",
Packit 5c3484
		       base, (unsigned) arn, (unsigned)bn);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
	  bp = mpz_get_str (NULL, i&1 ? base: -base, a);
Packit 5c3484
	  if (strcmp (bp, rp))
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_get_str failed:\n");
Packit 5c3484
	      dump ("a", a);
Packit 5c3484
	      fprintf (stderr, "b = %s\n", bp);
Packit 5c3484
	      fprintf (stderr, "  base = %d\n", base);
Packit 5c3484
	      fprintf (stderr, "r = %s\n", rp);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  /* Just a few tests with file i/o. */
Packit 5c3484
	  if (tmp && i < 20)
Packit 5c3484
	    {
Packit 5c3484
	      size_t tn;
Packit 5c3484
	      rewind (tmp);
Packit 5c3484
	      tn = mpz_out_str (tmp, i&1 ? base: -base, a);
Packit 5c3484
	      if (tn != rn)
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_out_str, bad return value:\n");
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  fprintf (stderr, "r = %s\n", rp);
Packit 5c3484
		  fprintf (stderr, "  base %d, correct size %u, got %u\n",
Packit 5c3484
			   base, (unsigned) rn, (unsigned)tn);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	      rewind (tmp);
Packit 5c3484
	      memset (bp, 0, rn);
Packit 5c3484
	      tn = fread (bp, 1, rn, tmp);
Packit 5c3484
	      if (tn != rn)
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr,
Packit 5c3484
			   "fread failed, expected %lu bytes, got only %lu.\n",
Packit 5c3484
			   (unsigned long) rn, (unsigned long) tn);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
Packit 5c3484
	      if (memcmp (bp, rp, rn) != 0)
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_out_str failed:\n");
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  fprintf (stderr, "b = %s\n", bp);
Packit 5c3484
		  fprintf (stderr, "  base = %d\n", base);
Packit 5c3484
		  fprintf (stderr, "r = %s\n", rp);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  mpz_set_str (b, rp, base);
Packit 5c3484
Packit 5c3484
	  if (mpz_cmp (a, b))
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_set_str failed:\n");
Packit 5c3484
	      fprintf (stderr, "r = %s\n", rp);
Packit 5c3484
	      fprintf (stderr, "  base = %d\n", base);
Packit 5c3484
	      fprintf (stderr, "r = %s\n", ap);
Packit 5c3484
	      fprintf (stderr, "  base = 16\n");
Packit 5c3484
	      dump ("b", b);
Packit 5c3484
	      dump ("r", a);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  /* Test mpn interface */
Packit 5c3484
	  if (base && mpz_sgn (a))
Packit 5c3484
	    {
Packit 5c3484
	      size_t i;
Packit 5c3484
	      const char *absr;
Packit 5c3484
	      mp_limb_t t[MAXLIMBS];
Packit 5c3484
	      mp_size_t tn = mpz_size (a);
Packit 5c3484
Packit 5c3484
	      assert (tn <= MAXLIMBS);
Packit 5c3484
	      mpn_copyi (t, a->_mp_d, tn);
Packit 5c3484
Packit 5c3484
	      bn = mpn_get_str ((unsigned char *) bp, base, t, tn);
Packit 5c3484
	      if (bn != arn)
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpn_get_str failed:\n");
Packit 5c3484
		  fprintf (stderr, "returned length: %lu (bad)\n", (unsigned long) bn);
Packit 5c3484
		  fprintf (stderr, "expected: %lu\n", (unsigned long) arn);
Packit 5c3484
		  fprintf (stderr, "  base = %d\n", base);
Packit 5c3484
		  fprintf (stderr, "r = %s\n", ap);
Packit 5c3484
		  fprintf (stderr, "  base = 16\n");
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  dump ("r", a);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	      absr = rp + (rp[0] == '-');
Packit 5c3484
Packit 5c3484
	      for (i = 0; i < bn; i++)
Packit 5c3484
		{
Packit 5c3484
		  unsigned char digit = absr[i];
Packit 5c3484
		  unsigned value;
Packit 5c3484
		  if (digit >= '0' && digit <= '9')
Packit 5c3484
		    value = digit - '0';
Packit 5c3484
		  else if (digit >= 'a' && digit <= 'z')
Packit 5c3484
		    value = digit - 'a' + 10;
Packit 5c3484
		  else if (digit >= 'A' && digit <= 'Z')
Packit 5c3484
		    value = digit - 'A' + 10;
Packit 5c3484
		  else
Packit 5c3484
		    {
Packit 5c3484
		      fprintf (stderr, "Internal error in test.\n");
Packit 5c3484
		      abort();
Packit 5c3484
		    }
Packit 5c3484
		  if (bp[i] != value)
Packit 5c3484
		    {
Packit 5c3484
		      fprintf (stderr, "mpn_get_str failed:\n");
Packit 5c3484
		      fprintf (stderr, "digit %lu: %d (bad)\n", (unsigned long) i, bp[i]);
Packit 5c3484
		      fprintf (stderr, "expected: %d\n", value);
Packit 5c3484
		      fprintf (stderr, "  base = %d\n", base);
Packit 5c3484
		      fprintf (stderr, "r = %s\n", ap);
Packit 5c3484
		      fprintf (stderr, "  base = 16\n");
Packit 5c3484
		      dump ("b", b);
Packit 5c3484
		      dump ("r", a);
Packit 5c3484
		      abort ();
Packit 5c3484
		    }
Packit 5c3484
		}
Packit 5c3484
	      tn = mpn_set_str (t, (unsigned char *) bp, bn, base);
Packit 5c3484
	      if (tn != mpz_size (a) || mpn_cmp (t, a->_mp_d, tn))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpn_set_str failed:\n");
Packit 5c3484
		  fprintf (stderr, "r = %s\n", rp);
Packit 5c3484
		  fprintf (stderr, "  base = %d\n", base);
Packit 5c3484
		  fprintf (stderr, "r = %s\n", ap);
Packit 5c3484
		  fprintf (stderr, "  base = 16\n");
Packit 5c3484
		  dump ("r", a);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	    }
Packit 5c3484
	  free (ap);
Packit 5c3484
	  free (rp);
Packit 5c3484
	  testfree (bp);
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
  mpz_clear (b);
Packit 5c3484
}