(root)/
gmp-6.3.0/
tests/
mpz/
convert.c
       1  /* Test conversion using mpz_get_str and mpz_set_str.
       2  
       3  Copyright 1993, 1994, 1996, 1999-2002, 2006, 2007, 2020 Free Software
       4  Foundation, Inc.
       5  
       6  This file is part of the GNU MP Library test suite.
       7  
       8  The GNU MP Library test suite is free software; you can redistribute it
       9  and/or modify it under the terms of the GNU General Public License as
      10  published by the Free Software Foundation; either version 3 of the License,
      11  or (at your option) any later version.
      12  
      13  The GNU MP Library test suite is distributed in the hope that it will be
      14  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
      15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      16  Public License for more details.
      17  
      18  You should have received a copy of the GNU General Public License along with
      19  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
      20  
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h> /* for strlen */
      24  #include <ctype.h> /* for tolower */
      25  
      26  #include "gmp-impl.h"
      27  #include "tests.h"
      28  
      29  void debug_mp (mpz_t, int);
      30  
      31  static int str_casecmp (const char *, const char *);
      32  
      33  void
      34  string_urandomb (char *bp, size_t len, int base, gmp_randstate_ptr rands)
      35  {
      36    mpz_t bs;
      37    unsigned long bsi;
      38    int d, l;
      39    const char *collseq = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
      40  
      41    mpz_init (bs);
      42  
      43    mpz_urandomb (bs, rands, 32);
      44    bsi = mpz_get_ui (bs);
      45    d = bsi % base;
      46    while (len != 0)
      47      {
      48        l = (bsi >> 16) % 20;
      49        l = MIN (l, len);
      50  
      51        memset (bp, collseq[d], l);
      52  
      53        len -= l;
      54        bp += l;
      55  
      56        mpz_urandomb (bs, rands, 32);
      57        bsi = mpz_get_ui (bs);
      58        d = bsi & 0xfff;
      59        if (d >= base)
      60  	d = 0;
      61      }
      62  
      63    bp[0] = '\0';
      64    mpz_clear (bs);
      65  }
      66  
      67  int
      68  main (int argc, char **argv)
      69  {
      70    mpz_t op1, op2;
      71    mp_size_t size;
      72    int i;
      73    int reps = 2000;
      74    char *str, *buf, *bp;
      75    int base;
      76    gmp_randstate_ptr rands;
      77    mpz_t bs;
      78    unsigned long bsi, size_range;
      79    size_t len;
      80  
      81    tests_start ();
      82    TESTS_REPS (reps, argv, argc);
      83  
      84    rands = RANDS;
      85  
      86    mpz_init (bs);
      87  
      88    mpz_init (op1);
      89    mpz_init (op2);
      90  
      91    for (i = 0; i < reps; i++)
      92      {
      93        /* 1. Generate random mpz_t and convert to a string and back to mpz_t
      94  	 again.  */
      95        mpz_urandomb (bs, rands, 32);
      96        size_range = mpz_get_ui (bs) % 17 + 2;	/* 2..18 */
      97        mpz_urandomb (bs, rands, size_range);	/* 3..262144 bits */
      98        size = mpz_get_ui (bs);
      99        mpz_rrandomb (op1, rands, size);
     100  
     101        mpz_urandomb (bs, rands, 1);
     102        bsi = mpz_get_ui (bs);
     103        if ((bsi & 1) != 0)
     104  	mpz_neg (op1, op1);
     105  
     106        mpz_urandomb (bs, rands, 32);
     107        bsi = mpz_get_ui (bs);
     108        base = bsi % 62 + 1;
     109        if (base == 1)
     110  	base = 0;
     111  
     112        str = mpz_get_str ((char *) 0, base, op1);
     113        mpz_set_str_or_abort (op2, str, base);
     114  
     115        if (mpz_cmp (op1, op2))
     116  	{
     117  	  fprintf (stderr, "ERROR, op1 and op2 different in test %d\n", i);
     118  	  fprintf (stderr, "str  = %s\n", str);
     119  	  fprintf (stderr, "base = %d\n", base);
     120  	  fprintf (stderr, "op1  = "); debug_mp (op1, -16);
     121  	  fprintf (stderr, "op2  = "); debug_mp (op2, -16);
     122  	  abort ();
     123  	}
     124  
     125        (*__gmp_free_func) (str, strlen (str) + 1);
     126  
     127        /* 2. Generate random string and convert to mpz_t and back to a string
     128  	 again.  */
     129        mpz_urandomb (bs, rands, 32);
     130        size_range = mpz_get_ui (bs) % 16 + 1;	/* 1..16 */
     131        mpz_urandomb (bs, rands, size_range);	/* 1..65536 digits */
     132        len = mpz_get_ui (bs) + 1;
     133        buf = (char *) (*__gmp_allocate_func) (len + 1);
     134        if (base == 0)
     135  	base = 10;
     136        string_urandomb (buf, len, base, rands);
     137  
     138        mpz_set_str_or_abort (op1, buf, base);
     139        str = mpz_get_str ((char *) 0, base, op1);
     140  
     141        /* Skip over leading zeros, but don't leave the string at zero length. */
     142        for (bp = buf; bp[0] == '0' && bp[1] != '\0'; bp++)
     143  	;
     144  
     145        if (str_casecmp (str, bp) != 0)
     146  	{
     147  	  fprintf (stderr, "ERROR, str and buf different in test %d\n", i);
     148  	  fprintf (stderr, "str  = %s\n", str);
     149  	  fprintf (stderr, "buf  = %s\n", buf);
     150  	  fprintf (stderr, "base = %d\n", base);
     151  	  fprintf (stderr, "op1  = "); debug_mp (op1, -16);
     152  	  abort ();
     153  	}
     154  
     155        (*__gmp_free_func) (buf, len + 1);
     156        (*__gmp_free_func) (str, strlen (str) + 1);
     157      }
     158  
     159    mpz_clear (bs);
     160    mpz_clear (op1);
     161    mpz_clear (op2);
     162  
     163    tests_end ();
     164    exit (0);
     165  }
     166  
     167  /* This is similar to POSIX strcasecmp except that we don't do the comparison
     168     with unsigned char.  We avoid strcasecmp for C standard conformance.  */
     169  static int
     170  str_casecmp (const char *s1, const char *s2)
     171  {
     172    size_t i;
     173    for (i = 0;; i++)
     174      {
     175        int c1 = s1[i];
     176        int c2 = s2[i];
     177        if (c1 == 0 || tolower (c1) != tolower (c2))
     178  	return c1 - c2;
     179      }
     180  }
     181  
     182  void
     183  debug_mp (mpz_t x, int base)
     184  {
     185    mpz_out_str (stderr, base, x); fputc ('\n', stderr);
     186  }