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-impl.h"
24 #include "tests.h"
25
26 using namespace std;
27
28
29 bool 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
71 void
check_mpz(void)72 check_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
174 void
check_mpq(void)175 check_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
255 void
check_mpf(void)256 check_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
435 int
main(int argc,char * argv[])436 main (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 }
450