blob: 8550f676b59574c4f829985be8b10bdf0177986c [file] [log] [blame]
Austin Schuhbb1338c2024-06-15 19:31:16 -07001/* Test ostream formatted output.
2
3Copyright 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20#include <iostream>
21#include <cstdlib>
22
23#include "gmp-impl.h"
24#include "tests.h"
25
26using namespace std;
27
28
29bool option_check_standard = false;
30
31
32#define CALL(expr) \
33 do { \
34 got.flags (data[i].flags); \
35 got.width (data[i].width); \
36 got.precision (data[i].precision); \
37 if (data[i].fill == '\0') \
38 got.fill (' '); \
39 else \
40 got.fill (data[i].fill); \
41 \
42 if (! (expr)) \
43 { \
44 cout << "\"got\" output error\n"; \
45 abort (); \
46 } \
47 if (got.width() != 0) \
48 { \
49 cout << "\"got\" width not reset to 0\n"; \
50 abort (); \
51 } \
52 \
53 } while (0)
54
55
56#define DUMP() \
57 do { \
58 cout << " want: |" << data[i].want << "|\n"; \
59 cout << " got: |" << got.str() << "|\n"; \
60 cout << " width: " << data[i].width << "\n"; \
61 cout << " prec: " << got.precision() << "\n"; \
62 cout << " flags: " << hex << (unsigned long) got.flags() << "\n"; \
63 } while (0)
64
65#define ABORT() \
66 do { \
67 DUMP (); \
68 abort (); \
69 } while (0)
70
71void
72check_mpz (void)
73{
74 static const struct {
75 const char *z;
76 const char *want;
77 ios::fmtflags flags;
78 int width;
79 int precision;
80 char fill;
81
82 } data[] = {
83
84 { "0", "0", ios::dec },
85
86 { "0", "0", ios::oct },
87 { "0", "0", ios::oct | ios::showbase },
88
89 { "0", "0", ios::hex },
90 { "0", "0x0", ios::hex | ios::showbase },
91 { "0", "0X0", ios::hex | ios::showbase | ios::uppercase },
92
93 { "1", "****1", ios::dec, 5, 0, '*' },
94
95 { "-1", " -1", ios::dec | ios::right, 5 },
96 { "-1", "- 1", ios::dec | ios::internal, 5 },
97 { "-1", "-1 ", ios::dec | ios::left, 5 },
98
99 { "1", " 0x1", ios::hex | ios::showbase | ios::right, 6 },
100 { "1", "0x 1", ios::hex | ios::showbase | ios::internal, 6 },
101 { "1", "0x1 ", ios::hex | ios::showbase | ios::left, 6 },
102
103 { "1", " +0x1", ios::hex | ios::showbase | ios::showpos | ios::right,
104 7 },
105 { "1", "+0x 1", ios::hex | ios::showbase | ios::showpos | ios::internal,
106 7 },
107 { "1", "+0x1 ", ios::hex | ios::showbase | ios::showpos | ios::left,
108 7 },
109
110 { "123", "7b", ios::hex },
111 { "123", "7B", ios::hex | ios::uppercase },
112 { "123", "0x7b", ios::hex | ios::showbase },
113 { "123", "0X7B", ios::hex | ios::showbase | ios::uppercase },
114 { "-123", "-0x7b", ios::hex | ios::showbase },
115 { "-123", "-0X7B", ios::hex | ios::showbase | ios::uppercase },
116
117 { "123", "173", ios::oct },
118 { "123", "173", ios::oct | ios::uppercase },
119 { "123", "0173", ios::oct | ios::showbase },
120 { "123", "0173", ios::oct | ios::showbase | ios::uppercase },
121 { "-123", "-0173", ios::oct | ios::showbase },
122 { "-123", "-0173", ios::oct | ios::showbase | ios::uppercase },
123
124 };
125
126 size_t i;
127 mpz_t z;
128
129 mpz_init (z);
130
131 for (i = 0; i < numberof (data); i++)
132 {
133 mpz_set_str_or_abort (z, data[i].z, 0);
134
135 if (option_check_standard
136 && mpz_fits_slong_p (z)
137
138 // no negatives or showpos in hex or oct
139 && (((data[i].flags & ios::basefield) == ios::hex
140 || (data[i].flags & ios::basefield) == ios::oct)
141 ? (mpz_sgn (z) >= 0
142 && ! (data[i].flags & ios::showpos))
143 : 1)
144 )
145 {
146 ostringstream got;
147 long n = mpz_get_si (z);
148 CALL (got << n);
149 if (got.str().compare (data[i].want) != 0)
150 {
151 cout << "check_mpz data[" << i
152 << "] doesn't match standard ostream output\n";
153 cout << " z: " << data[i].z << "\n";
154 cout << " n: " << n << "\n";
155 DUMP ();
156 }
157 }
158
159 {
160 ostringstream got;
161 CALL (got << z);
162 if (got.str().compare (data[i].want) != 0)
163 {
164 cout << "mpz operator<< wrong, data[" << i << "]\n";
165 cout << " z: " << data[i].z << "\n";
166 ABORT ();
167 }
168 }
169 }
170
171 mpz_clear (z);
172}
173
174void
175check_mpq (void)
176{
177 static const struct {
178 const char *q;
179 const char *want;
180 ios::fmtflags flags;
181 int width;
182 int precision;
183 char fill;
184
185 } data[] = {
186
187 { "0", "0", ios::dec },
188 { "0", "0", ios::hex },
189 { "0", "0x0", ios::hex | ios::showbase },
190 { "0", "0X0", ios::hex | ios::showbase | ios::uppercase },
191
192 { "5/8", "5/8", ios::dec },
193 { "5/8", "0X5/0X8", ios::hex | ios::showbase | ios::uppercase },
194
195 // zero denominator with showbase
196 { "0/0", " 0/0", ios::oct | ios::showbase, 10 },
197 { "0/0", " 0/0", ios::dec | ios::showbase, 10 },
198 { "0/0", " 0x0/0x0", ios::hex | ios::showbase, 10 },
199 { "123/0", " 0173/0", ios::oct | ios::showbase, 10 },
200 { "123/0", " 123/0", ios::dec | ios::showbase, 10 },
201 { "123/0", " 0x7b/0x0", ios::hex | ios::showbase, 10 },
202 { "123/0", " 0X7B/0X0", ios::hex | ios::showbase | ios::uppercase, 10 },
203 { "0/123", " 0/0173", ios::oct | ios::showbase, 10 },
204 { "0/123", " 0/123", ios::dec | ios::showbase, 10 },
205 { "0/123", " 0x0/0x7b", ios::hex | ios::showbase, 10 },
206 { "0/123", " 0X0/0X7B", ios::hex | ios::showbase | ios::uppercase, 10 },
207 };
208
209 size_t i;
210 mpq_t q;
211
212 mpq_init (q);
213
214#define mpq_integer_p(q) (mpz_cmp_ui (mpq_denref(q), 1L) == 0)
215
216 for (i = 0; i < numberof (data); i++)
217 {
218 mpq_set_str_or_abort (q, data[i].q, 0);
219 MPZ_CHECK_FORMAT (mpq_numref (q));
220 MPZ_CHECK_FORMAT (mpq_denref (q));
221
222 if (option_check_standard
223 && mpz_fits_slong_p (mpq_numref(q))
224 && mpq_integer_p (q))
225 {
226 ostringstream got;
227 long n = mpz_get_si (mpq_numref(q));
228 CALL (got << n);
229 if (got.str().compare (data[i].want) != 0)
230 {
231 cout << "check_mpq data[" << i
232 << "] doesn't match standard ostream output\n";
233 cout << " q: " << data[i].q << "\n";
234 cout << " n: " << n << "\n";
235 DUMP ();
236 }
237 }
238
239 {
240 ostringstream got;
241 CALL (got << q);
242 if (got.str().compare (data[i].want) != 0)
243 {
244 cout << "mpq operator<< wrong, data[" << i << "]\n";
245 cout << " q: " << data[i].q << "\n";
246 ABORT ();
247 }
248 }
249 }
250
251 mpq_clear (q);
252}
253
254
255void
256check_mpf (void)
257{
258 static const struct {
259 const char *f;
260 const char *want;
261 ios::fmtflags flags;
262 int width;
263 int precision;
264 char fill;
265
266 } data[] = {
267
268 { "0", "0", ios::dec },
269 { "0", "+0", ios::dec | ios::showpos },
270 { "0", "0.00000", ios::dec | ios::showpoint },
271 { "0", "0", ios::dec | ios::fixed },
272 { "0", "0.", ios::dec | ios::fixed | ios::showpoint },
273 { "0", "0.000000e+00", ios::dec | ios::scientific },
274 { "0", "0.000000e+00", ios::dec | ios::scientific | ios::showpoint },
275
276 { "0", "0", ios::dec, 0, 4 },
277 { "0", "0.000", ios::dec | ios::showpoint, 0, 4 },
278 { "0", "0.0000", ios::dec | ios::fixed, 0, 4 },
279 { "0", "0.0000", ios::dec | ios::fixed | ios::showpoint, 0, 4 },
280 { "0", "0.0000e+00", ios::dec | ios::scientific, 0, 4 },
281 { "0", "0.0000e+00", ios::dec | ios::scientific | ios::showpoint, 0, 4 },
282
283 { "1", "1", ios::dec },
284 { "1", "+1", ios::dec | ios::showpos },
285 { "1", "1.00000", ios::dec | ios::showpoint },
286 { "1", "1", ios::dec | ios::fixed },
287 { "1", "1.", ios::dec | ios::fixed | ios::showpoint },
288 { "1", "1.000000e+00", ios::dec | ios::scientific },
289 { "1", "1.000000e+00", ios::dec | ios::scientific | ios::showpoint },
290
291 { "1", "1", ios::dec, 0, 4 },
292 { "1", "1.000", ios::dec | ios::showpoint, 0, 4 },
293 { "1", "1.0000", ios::dec | ios::fixed, 0, 4 },
294 { "1", "1.0000", ios::dec | ios::fixed | ios::showpoint, 0, 4 },
295 { "1", "1.0000e+00", ios::dec | ios::scientific, 0, 4 },
296 { "1", "1.0000e+00", ios::dec | ios::scientific | ios::showpoint, 0, 4 },
297
298 { "-1", "-1", ios::dec | ios::showpos },
299
300 { "-1", " -1", ios::dec, 4 },
301 { "-1", "- 1", ios::dec | ios::internal, 4 },
302 { "-1", "-1 ", ios::dec | ios::left, 4 },
303
304 { "-1", " -0x1", ios::hex | ios::showbase, 6 },
305 { "-1", "-0x 1", ios::hex | ios::showbase | ios::internal, 6 },
306 { "-1", "-0x1 ", ios::hex | ios::showbase | ios::left, 6 },
307
308 { "1", "*********1", ios::dec, 10, 4, '*' },
309 { "1234", "******1234", ios::dec, 10, 4, '*' },
310 { "1234", "*****1234.", ios::dec | ios::showpoint, 10, 4, '*' },
311
312 { "12345", "1.23e+04", ios::dec, 0, 3 },
313
314 { "12345", "12345.", ios::dec | ios::fixed | ios::showpoint },
315
316 { "1.9999999", "2", ios::dec, 0, 1 },
317 { "1.0009999999", "1.001", ios::dec, 0, 4 },
318 { "1.0001", "1", ios::dec, 0, 4 },
319 { "1.0004", "1", ios::dec, 0, 4 },
320 { "1.000555", "1.001", ios::dec, 0, 4 },
321
322 { "1.0002", "1.000", ios::dec | ios::fixed, 0, 3 },
323 { "1.0008", "1.001", ios::dec | ios::fixed, 0, 3 },
324
325 { "0", "0", ios::hex },
326 { "0", "0x0", ios::hex | ios::showbase },
327 { "0", "0X0", ios::hex | ios::showbase | ios::uppercase },
328 { "123", "7b", ios::hex },
329 { "123", "0x7b", ios::hex | ios::showbase },
330 { "123", "0X7B", ios::hex | ios::showbase | ios::uppercase },
331
332 { "0", "0.000@+00", ios::hex | ios::scientific, 0, 3 },
333 { "256", "1.000@+02", ios::hex | ios::scientific, 0, 3 },
334
335 { "123", "7.b@+01", ios::hex | ios::scientific, 0, 1 },
336 { "123", "7.B@+01", ios::hex | ios::scientific | ios::uppercase, 0, 1 },
337 { "123", "0x7.b@+01", ios::hex | ios::scientific | ios::showbase, 0, 1 },
338 { "123", "0X7.B@+01",
339 ios::hex | ios::scientific | ios::showbase | ios::uppercase, 0, 1 },
340
341 { "1099511627776", "1.0@+10", ios::hex | ios::scientific, 0, 1 },
342 { "1099511627776", "1.0@+10",
343 ios::hex | ios::scientific | ios::uppercase, 0, 1 },
344
345 { "0.0625", "1.00@-01", ios::hex | ios::scientific, 0, 2 },
346
347 { "0", "0", ios::oct },
348 { "123", "173", ios::oct },
349 { "123", "0173", ios::oct | ios::showbase },
350
351 // octal showbase suppressed for 0
352 { "0", "0", ios::oct | ios::showbase },
353 { ".125", "00.1", ios::oct | ios::showbase, 0, 1 },
354 { ".015625", "00.01", ios::oct | ios::showbase, 0, 2 },
355 { ".125", "00.1", ios::fixed | ios::oct | ios::showbase, 0, 1 },
356 { ".015625", "0.0", ios::fixed | ios::oct | ios::showbase, 0, 1 },
357 { ".015625", "00.01", ios::fixed | ios::oct | ios::showbase, 0, 2 },
358
359 { "0.125", "1.000000e-01", ios::oct | ios::scientific },
360 { "0.125", "+1.000000e-01", ios::oct | ios::scientific | ios::showpos },
361 { "-0.125", "-1.000000e-01", ios::oct | ios::scientific },
362 { "-0.125", "-1.000000e-01", ios::oct | ios::scientific | ios::showpos },
363
364 { "0", "0.000e+00", ios::oct | ios::scientific, 0, 3 },
365 { "256", "4.000e+02", ios::oct | ios::scientific, 0, 3 },
366 { "256", "04.000e+02", ios::oct | ios::scientific | ios::showbase, 0, 3 },
367 { "256", "4.000E+02", ios::oct | ios::scientific | ios::uppercase, 0, 3 },
368 { "256", "04.000E+02",
369 ios::oct | ios::scientific | ios::showbase | ios::uppercase, 0, 3 },
370
371 { "16777216", "1.000000e+08", ios::oct | ios::scientific },
372 { "16777216", "1.000000E+08",
373 ios::oct | ios::scientific | ios::uppercase },
374 { "16777216", "01.000000e+08",
375 ios::oct | ios::scientific | ios::showbase },
376 { "16777216", "01.000000E+08",
377 ios::oct | ios::scientific | ios::showbase | ios::uppercase },
378 { "16777216", "+01.000000e+08",
379 ios::oct | ios::scientific | ios::showbase | ios::showpos },
380 { "16777216", "+01.000000E+08", ios::oct | ios::scientific
381 | ios::showbase | ios::showpos | ios::uppercase },
382 { "-16777216", "-01.000000e+08",
383 ios::oct | ios::scientific | ios::showbase | ios::showpos },
384 { "-16777216", "-01.000000E+08", ios::oct | ios::scientific
385 | ios::showbase | ios::showpos | ios::uppercase },
386
387 };
388
389 size_t i;
390 mpf_t f, f2;
391 double d;
392
393 mpf_init (f);
394 mpf_init (f2);
395
396 for (i = 0; i < numberof (data); i++)
397 {
398 mpf_set_str_or_abort (f, data[i].f, 0);
399
400 d = mpf_get_d (f);
401 mpf_set_d (f2, d);
402 if (option_check_standard && mpf_cmp (f, f2) == 0
403 && ! (data[i].flags & (ios::hex | ios::oct | ios::showbase)))
404 {
405 ostringstream got;
406 CALL (got << d);
407 if (got.str().compare (data[i].want) != 0)
408 {
409 cout << "check_mpf data[" << i
410 << "] doesn't match standard ostream output\n";
411 cout << " f: " << data[i].f << "\n";
412 cout << " d: " << d << "\n";
413 DUMP ();
414 }
415 }
416
417 {
418 ostringstream got;
419 CALL (got << f);
420 if (got.str().compare (data[i].want) != 0)
421 {
422 cout << "mpf operator<< wrong, data[" << i << "]\n";
423 cout << " f: " << data[i].f << "\n";
424 ABORT ();
425 }
426 }
427 }
428
429 mpf_clear (f);
430 mpf_clear (f2);
431}
432
433
434
435int
436main (int argc, char *argv[])
437{
438 if (argc > 1 && strcmp (argv[1], "-s") == 0)
439 option_check_standard = true;
440
441 tests_start ();
442
443 check_mpz ();
444 check_mpq ();
445 check_mpf ();
446
447 tests_end ();
448 return 0;
449}