xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/convert.c (revision 1daf83e636cd998f45e5597a8f995a540e2d5b4a)
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
string_urandomb(char * bp,size_t len,int base,gmp_randstate_ptr rands)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
main(int argc,char ** argv)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
str_casecmp(const char * s1,const char * s2)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
debug_mp(mpz_t x,int base)183 debug_mp (mpz_t x, int base)
184 {
185   mpz_out_str (stderr, base, x); fputc ('\n', stderr);
186 }
187