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
test_small(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
testmain(int argc,char ** argv)141 testmain (int argc, char **argv)
142 {
143 unsigned i;
144 char *ap;
145 char *bp;
146 char *rp;
147 size_t rn, arn;
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 arn = rn - (rp[0] == '-');
189
190 bp = mpq_get_str (NULL, (i&1 || base > 36) ? base: -base, a);
191 if (strcmp (bp, rp))
192 {
193 fprintf (stderr, "mpz_get_str failed:\n");
194 dump ("a_num", mpq_numref (a));
195 dump ("a_den", mpq_denref (a));
196 fprintf (stderr, "b = %s\n", bp);
197 fprintf (stderr, " base = %d\n", base);
198 fprintf (stderr, "r = %s\n", rp);
199 abort ();
200 }
201
202 /* Just a few tests with file i/o. */
203 if (tmp && i < 20)
204 {
205 size_t tn;
206 rewind (tmp);
207 tn = mpq_out_str (tmp, (i&1 || base > 36) ? base: -base, a);
208 if (tn != rn)
209 {
210 fprintf (stderr, "mpq_out_str, bad return value:\n");
211 dump ("a_num", mpq_numref (a));
212 dump ("a_den", mpq_denref (a));
213 fprintf (stderr, "r = %s\n", rp);
214 fprintf (stderr, " base %d, correct size %u, got %u\n",
215 base, (unsigned) rn, (unsigned)tn);
216 abort ();
217 }
218 rewind (tmp);
219 memset (bp, 0, rn);
220 tn = fread (bp, 1, rn, tmp);
221 if (tn != rn)
222 {
223 fprintf (stderr,
224 "fread failed, expected %lu bytes, got only %lu.\n",
225 (unsigned long) rn, (unsigned long) tn);
226 abort ();
227 }
228
229 if (memcmp (bp, rp, rn) != 0)
230 {
231 fprintf (stderr, "mpq_out_str failed:\n");
232 dump ("a_num", mpq_numref (a));
233 dump ("a_den", mpq_denref (a));
234 fprintf (stderr, "b = %s\n", bp);
235 fprintf (stderr, " base = %d\n", base);
236 fprintf (stderr, "r = %s\n", rp);
237 abort ();
238 }
239 }
240
241 mpq_set_str (b, rp, base);
242
243 if (!mpq_equal (a, b))
244 {
245 fprintf (stderr, "mpq_set_str failed:\n");
246 fprintf (stderr, "r = %s\n", rp);
247 fprintf (stderr, " base = %d\n", base);
248 fprintf (stderr, "r = %s\n", ap);
249 fprintf (stderr, " base = 16\n");
250 dump ("b_num", mpq_numref (b));
251 dump ("b_den", mpq_denref (b));
252 dump ("r_num", mpq_numref (a));
253 dump ("r_den", mpq_denref (a));
254 abort ();
255 }
256
257 free (ap);
258 free (rp);
259 testfree (bp);
260 }
261 }
262 mpq_clear (a);
263 mpq_clear (b);
264 }
265