(root)/
gmp-6.3.0/
mini-gmp/
tests/
t-mpq_str.c
       1  /*
       2  
       3  Copyright 2012-2014, 2016, 2018, 2020 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  #include "../mini-mpq.h"
      28  
      29  #define MAXBITS 400
      30  #define COUNT 2000
      31  
      32  #define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
      33  #define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS)
      34  
      35  static void
      36  test_small (void)
      37  {
      38    struct {
      39      const char *input;
      40      const char *decimal;
      41    } data[] = {
      42      { "1832407/3", "1832407/3" },
      43      { " 2763959/6", "2763959/6 " },
      44      { "4 981 999 / 1 8", "4981999/18" },
      45      { "10\t73981/30 ", "1073981/30" },
      46      { "958 544 /1", "00958544/01" },
      47      { "-0", "0000" },
      48      { " -000  ", "0/ 1" },
      49      { "0704436/011", "231710/9" },
      50      /* Check the case of large number of leading zeros. */
      51      { "0000000000000000000000000/1", "0/0000000000000000000000001" },
      52      { "000000000000000704436/000011", "0000000000000000231710/00009" },
      53      { " 012/ 02503517", "10/689999" },
      54      { "0b 10/0 1312143", "2/365667" },
      55      { "-03 274062/0x1", "-882738/1" },
      56      { "012\t242", "005282" },
      57      { "9/0b11010111110010001111", "9/883855" },
      58      { "022/ 0b11001010010100001", "18/103585" },
      59      { "-0b101010110011101111/0x12", "-175343/18" },
      60      { "-05/0b 111 1111 0110 1110 0110", "-5/521958" },
      61      { "0b 011 111 110 111 001 000 011/0b00110", "1044035/6" },
      62      { " 0x53dfc", "343548" },
      63      { "-0x00012/0x000fA019", "-18/1024025" },
      64      { "0x 642d1", "410321" },
      65      { "0x5 8067/0Xa", "360551/10" },
      66      { "-0xd6Be6/3", "-879590/3" },
      67      { "\t0B1110000100000000011", "460803" },
      68      { "0B\t1111110010010100101", "517285" },
      69      { "-0x 00 2d/0B1\t010111101101110100", "-45/359284" },
      70      { "-0B101\t1001101111111001", "-367609" },
      71      { "0B10001001010111110000/0xf", "562672/15" },
      72      { "0Xe4B7e/1", "936830" },
      73      { "0X1E4bf/0X1", "124095" },
      74      { "-0Xfdb90/05", "-1039248/5" },
      75      { "0b010/0X7fc47", "2/523335" },
      76      { "15/0X8167c", "15/530044" },
      77      /* Some invalid inputs */
      78      { "", NULL },
      79      { "0x", NULL },
      80      { "0b", NULL },
      81      { "0z", NULL },
      82      { "-", NULL },
      83      { "/0x ", NULL },
      84      { "0|1", NULL },
      85      { "/", NULL },
      86      { "0ab", NULL },
      87      { "10x0", NULL },
      88      { "1/0xxab", NULL },
      89      { "0/ab", NULL },
      90      { "0/#", NULL },
      91      { "$foo/1", NULL },
      92      { NULL, NULL }
      93    };
      94    unsigned i;
      95    mpq_t a, b;
      96    mpq_init (a);
      97    mpq_init (b);
      98  
      99    for (i = 0; data[i].input; i++)
     100      {
     101        int res = mpq_set_str (a, data[i].input, 0);
     102        if (data[i].decimal)
     103  	{
     104  	  if (res != 0)
     105  	    {
     106  	      fprintf (stderr, "mpq_set_str returned -1, input: %s\n",
     107  		       data[i].input);
     108  	      abort ();
     109  	    }
     110  	  if (mpq_set_str (b, data[i].decimal, 10) != 0)
     111  	    {
     112  	      fprintf (stderr, "mpq_set_str returned -1, decimal input: %s\n",
     113  		       data[i].input);
     114  	      abort ();
     115  	    }
     116  	  if (!mpq_equal (a, b))
     117  	    {
     118  	      fprintf (stderr, "mpq_set_str failed for input: %s\n",
     119  		       data[i].input);
     120  
     121  	      dump ("got_num", mpq_numref (a));
     122  	      dump ("got_den", mpq_denref (a));
     123  	      dump ("ref_num", mpq_numref (b));
     124  	      dump ("ref_den", mpq_denref (b));
     125  	      abort ();
     126  	    }
     127  	}
     128        else if (res != -1)
     129  	{
     130  	  fprintf (stderr, "mpq_set_str returned %d, invalid input: %s\n",
     131  		   res, data[i].input);
     132  	  abort ();
     133  	}
     134      }
     135  
     136    mpq_clear (a);
     137    mpq_clear (b);
     138  }
     139  
     140  void
     141  testmain (int argc, char **argv)
     142  {
     143    unsigned i;
     144    char *ap;
     145    char *bp;
     146    char *rp;
     147    size_t rn;
     148  
     149    mpq_t a, b;
     150  
     151    FILE *tmp;
     152  
     153    test_small ();
     154  
     155    mpq_init (a);
     156    mpq_init (b);
     157  
     158    tmp = tmpfile ();
     159    if (!tmp)
     160      fprintf (stderr,
     161  	     "Failed to create temporary file. Skipping mpq_out_str tests.\n");
     162  
     163    if (mpq_out_str (tmp, 63, a) != 0)
     164      {
     165        printf ("mpq_out_str did not return 0 (error) with base > 62\n");
     166        abort ();
     167      }
     168  
     169    if (mpq_out_str (tmp, -37, a) != 0)
     170      {
     171        printf ("mpq_out_str did not return 0 (error) with base < -37\n");
     172        abort ();
     173      }
     174  
     175    for (i = 0; i < COUNT/60; i++)
     176      {
     177        int base;
     178        for (base = 2; base <= 62; ++base)
     179  	{
     180  	  hex_mpq_random_str_op (MAXBITS, (i&1 || base > 36) ? base: -base, &ap, &rp);
     181  	  if (mpq_set_str (a, ap, 16) != 0)
     182  	    {
     183  	      fprintf (stderr, "mpq_set_str failed on input %s\n", ap);
     184  	      abort ();
     185  	    }
     186  
     187  	  rn = strlen (rp);
     188  
     189  	  bp = mpq_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
     190  	  if (strcmp (bp, rp))
     191  	    {
     192  	      fprintf (stderr, "mpz_get_str failed:\n");
     193  	      dump ("a_num", mpq_numref (a));
     194  	      dump ("a_den", mpq_denref (a));
     195  	      fprintf (stderr, "b = %s\n", bp);
     196  	      fprintf (stderr, "  base = %d\n", base);
     197  	      fprintf (stderr, "r = %s\n", rp);
     198  	      abort ();
     199  	    }
     200  
     201  	  /* Just a few tests with file i/o. */
     202  	  if (tmp && i < 20)
     203  	    {
     204  	      size_t tn;
     205  	      rewind (tmp);
     206  	      tn = mpq_out_str (tmp, (i&1 || base > 36) ? base: -base, a);
     207  	      if (tn != rn)
     208  		{
     209  		  fprintf (stderr, "mpq_out_str, bad return value:\n");
     210  		  dump ("a_num", mpq_numref (a));
     211  		  dump ("a_den", mpq_denref (a));
     212  		  fprintf (stderr, "r = %s\n", rp);
     213  		  fprintf (stderr, "  base %d, correct size %u, got %u\n",
     214  			   base, (unsigned) rn, (unsigned)tn);
     215  		  abort ();
     216  		}
     217  	      rewind (tmp);
     218  	      memset (bp, 0, rn);
     219  	      tn = fread (bp, 1, rn, tmp);
     220  	      if (tn != rn)
     221  		{
     222  		  fprintf (stderr,
     223  			   "fread failed, expected %lu bytes, got only %lu.\n",
     224  			   (unsigned long) rn, (unsigned long) tn);
     225  		  abort ();
     226  		}
     227  
     228  	      if (memcmp (bp, rp, rn) != 0)
     229  		{
     230  		  fprintf (stderr, "mpq_out_str failed:\n");
     231  		  dump ("a_num", mpq_numref (a));
     232  		  dump ("a_den", mpq_denref (a));
     233  		  fprintf (stderr, "b = %s\n", bp);
     234  		  fprintf (stderr, "  base = %d\n", base);
     235  		  fprintf (stderr, "r = %s\n", rp);
     236  		  abort ();
     237  		}
     238  	    }
     239  
     240  	  mpq_set_str (b, rp, base);
     241  
     242  	  if (!mpq_equal (a, b))
     243  	    {
     244  	      fprintf (stderr, "mpq_set_str failed:\n");
     245  	      fprintf (stderr, "r = %s\n", rp);
     246  	      fprintf (stderr, "  base = %d\n", base);
     247  	      fprintf (stderr, "r = %s\n", ap);
     248  	      fprintf (stderr, "  base = 16\n");
     249  	      dump ("b_num", mpq_numref (b));
     250  	      dump ("b_den", mpq_denref (b));
     251  	      dump ("r_num", mpq_numref (a));
     252  	      dump ("r_den", mpq_denref (a));
     253  	      abort ();
     254  	    }
     255  
     256  	  free (ap);
     257  	  free (rp);
     258  	  testfree (bp, strlen(bp) + 1);
     259  	}
     260      }
     261    mpq_clear (a);
     262    mpq_clear (b);
     263  }