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