1 /* Test istream formatted input.
3 Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
31 // Under option_check_standard, the various test cases for mpz operator>>
32 // are put through the standard operator>> for long, and likewise mpf
33 // operator>> is put through double.
35 // In g++ 3.3 this results in some printouts about the final position
36 // indicated for something like ".e123". Our mpf code stops at the "e"
37 // since there's no mantissa digits, but g++ reads the whole thing and only
38 // then decides it's bad.
40 int option_check_standard = 0;
43 // On some versions of g++ 2.96 it's been observed that putback() may leave
44 // tellg() unchanged. We believe this is incorrect and presumably the
45 // result of a bug, since for instance it's ok in g++ 2.95 and g++ 3.3. We
46 // detect the problem at runtime and disable affected checks.
48 int putback_tellg_works = 1;
51 check_putback_tellg (void)
53 istringstream input ("hello");
54 streampos old_pos, new_pos;
58 old_pos = input.tellg();
60 new_pos = input.tellg();
62 if (old_pos == new_pos)
64 cout << "Warning, istringstream has a bug: putback() doesn't update tellg().\n";;
65 cout << "Tests on tellg() will be skipped.\n";
66 putback_tellg_works = 0;
73 cout << str ", data[" << i << "]\n"; \
74 cout << " input: \"" << data[i].input << "\"\n"; \
75 cout << " flags: " << hex << input.flags() << dec << "\n"; \
89 { "0", -1, "0", (ios::fmtflags) 0 },
90 { "123", -1, "123", (ios::fmtflags) 0 },
91 { "0123", -1, "83", (ios::fmtflags) 0 },
92 { "0x123", -1, "291", (ios::fmtflags) 0 },
93 { "-123", -1, "-123", (ios::fmtflags) 0 },
94 { "-0123", -1, "-83", (ios::fmtflags) 0 },
95 { "-0x123", -1, "-291", (ios::fmtflags) 0 },
96 { "+123", -1, "123", (ios::fmtflags) 0 },
97 { "+0123", -1, "83", (ios::fmtflags) 0 },
98 { "+0x123", -1, "291", (ios::fmtflags) 0 },
100 { "0", -1, "0", ios::dec },
101 { "1f", 1, "1", ios::dec },
102 { "011f", 3, "11", ios::dec },
103 { "123", -1, "123", ios::dec },
104 { "-1f", 2, "-1", ios::dec },
105 { "-011f", 4, "-11", ios::dec },
106 { "-123", -1, "-123", ios::dec },
107 { "+1f", 2, "1", ios::dec },
108 { "+011f", 4, "11", ios::dec },
109 { "+123", -1, "123", ios::dec },
111 { "0", -1, "0", ios::oct },
112 { "123", -1, "83", ios::oct },
113 { "-123", -1, "-83", ios::oct },
114 { "+123", -1, "83", ios::oct },
116 { "0", -1, "0", ios::hex },
117 { "123", -1, "291", ios::hex },
118 { "ff", -1, "255", ios::hex },
119 { "FF", -1, "255", ios::hex },
120 { "-123", -1, "-291", ios::hex },
121 { "-ff", -1, "-255", ios::hex },
122 { "-FF", -1, "-255", ios::hex },
123 { "+123", -1, "291", ios::hex },
124 { "+ff", -1, "255", ios::hex },
125 { "+FF", -1, "255", ios::hex },
126 { "ab", -1, "171", ios::hex },
127 { "cd", -1, "205", ios::hex },
128 { "ef", -1, "239", ios::hex },
130 { " 123", 0, NULL, (ios::fmtflags) 0 }, // not without skipws
131 { " 123", -1, "123", ios::skipws },
136 long got_si, want_si;
137 streampos init_tellg, got_pos, want_pos;
142 for (size_t i = 0; i < numberof (data); i++)
144 want_pos = (data[i].want_pos == -1
145 ? strlen (data[i].input) : data[i].want_pos);
147 want_ok = (data[i].want != NULL);
149 if (data[i].want != NULL)
150 mpz_set_str_or_abort (want, data[i].want, 0);
152 mpz_set_ui (want, 0L);
154 if (option_check_standard && mpz_fits_slong_p (want))
156 istringstream input (data[i].input);
157 input.flags (data[i].flags);
158 init_tellg = input.tellg();
159 want_si = mpz_get_si (want);
162 got_ok = (input ? 1 : 0);
164 got_pos = input.tellg() - init_tellg;
166 if (got_ok != want_ok)
168 WRONG ("stdc++ operator>> wrong status, check_mpz");
169 cout << " want_ok: " << want_ok << "\n";
170 cout << " got_ok: " << got_ok << "\n";
172 if (want_ok && got_si != want_si)
174 WRONG ("stdc++ operator>> wrong result, check_mpz");
175 cout << " got_si: " << got_si << "\n";
176 cout << " want_si: " << want_si << "\n";
178 if (putback_tellg_works && got_pos != want_pos)
180 WRONG ("stdc++ operator>> wrong position, check_mpz");
181 cout << " want_pos: " << want_pos << "\n";
182 cout << " got_pos: " << got_pos << "\n";
187 istringstream input (data[i].input);
188 input.flags (data[i].flags);
189 init_tellg = input.tellg();
191 mpz_set_ui (got, 0xDEAD);
193 got_ok = (input ? 1 : 0);
195 got_pos = input.tellg() - init_tellg;
197 if (got_ok != want_ok)
199 WRONG ("mpz operator>> wrong status");
200 cout << " want_ok: " << want_ok << "\n";
201 cout << " got_ok: " << got_ok << "\n";
204 if (want_ok && mpz_cmp (got, want) != 0)
206 WRONG ("mpz operator>> wrong result");
207 mpz_trace (" got ", got);
208 mpz_trace (" want", want);
211 if (putback_tellg_works && got_pos != want_pos)
213 WRONG ("mpz operator>> wrong position");
214 cout << " want_pos: " << want_pos << "\n";
215 cout << " got_pos: " << got_pos << "\n";
228 static const struct {
236 { "0", -1, "0", (ios::fmtflags) 0 },
237 { "00", -1, "0", (ios::fmtflags) 0 },
238 { "0x0", -1, "0", (ios::fmtflags) 0 },
240 { "123/456", -1, "123/456", ios::dec },
241 { "0123/456", -1, "123/456", ios::dec },
242 { "123/0456", -1, "123/456", ios::dec },
243 { "0123/0456", -1, "123/456", ios::dec },
245 { "123/456", -1, "83/302", ios::oct },
246 { "0123/456", -1, "83/302", ios::oct },
247 { "123/0456", -1, "83/302", ios::oct },
248 { "0123/0456", -1, "83/302", ios::oct },
250 { "ab", -1, "171", ios::hex },
251 { "cd", -1, "205", ios::hex },
252 { "ef", -1, "239", ios::hex },
254 { "0/0", -1, "0/0", (ios::fmtflags) 0 },
255 { "5/8", -1, "5/8", (ios::fmtflags) 0 },
256 { "0x5/0x8", -1, "5/8", (ios::fmtflags) 0 },
258 { "123/456", -1, "123/456", (ios::fmtflags) 0 },
259 { "123/0456", -1, "123/302", (ios::fmtflags) 0 },
260 { "123/0x456", -1, "123/1110", (ios::fmtflags) 0 },
261 { "123/0X456", -1, "123/1110", (ios::fmtflags) 0 },
263 { "0123/123", -1, "83/123", (ios::fmtflags) 0 },
264 { "0123/0123", -1, "83/83", (ios::fmtflags) 0 },
265 { "0123/0x123", -1, "83/291", (ios::fmtflags) 0 },
266 { "0123/0X123", -1, "83/291", (ios::fmtflags) 0 },
268 { "0x123/123", -1, "291/123", (ios::fmtflags) 0 },
269 { "0X123/0123", -1, "291/83", (ios::fmtflags) 0 },
270 { "0x123/0x123", -1, "291/291", (ios::fmtflags) 0 },
272 { " 123", 0, NULL, (ios::fmtflags) 0 }, // not without skipws
273 { " 123", -1, "123", ios::skipws },
278 long got_si, want_si;
279 streampos init_tellg, got_pos, want_pos;
284 for (size_t i = 0; i < numberof (data); i++)
286 want_pos = (data[i].want_pos == -1
287 ? strlen (data[i].input) : data[i].want_pos);
289 want_ok = (data[i].want != NULL);
291 if (data[i].want != NULL)
292 mpq_set_str_or_abort (want, data[i].want, 0);
294 mpq_set_ui (want, 0L, 1L);
296 if (option_check_standard
297 && mpz_fits_slong_p (mpq_numref(want))
298 && mpz_cmp_ui (mpq_denref(want), 1L) == 0)
300 istringstream input (data[i].input);
301 input.flags (data[i].flags);
302 init_tellg = input.tellg();
303 want_si = mpz_get_si (mpq_numref(want));
306 got_ok = (input ? 1 : 0);
308 got_pos = input.tellg() - init_tellg;
310 if (got_ok != want_ok)
312 WRONG ("stdc++ operator>> wrong status, check_mpq");
313 cout << " want_ok: " << want_ok << "\n";
314 cout << " got_ok: " << got_ok << "\n";
316 if (want_ok && want_si != got_si)
318 WRONG ("stdc++ operator>> wrong result, check_mpq");
319 cout << " got_si: " << got_si << "\n";
320 cout << " want_si: " << want_si << "\n";
322 if (putback_tellg_works && got_pos != want_pos)
324 WRONG ("stdc++ operator>> wrong position, check_mpq");
325 cout << " want_pos: " << want_pos << "\n";
326 cout << " got_pos: " << got_pos << "\n";
331 istringstream input (data[i].input);
332 input.flags (data[i].flags);
333 init_tellg = input.tellg();
334 mpq_set_si (got, 0xDEAD, 0xBEEF);
337 got_ok = (input ? 1 : 0);
339 got_pos = input.tellg() - init_tellg;
341 if (got_ok != want_ok)
343 WRONG ("mpq operator>> wrong status");
344 cout << " want_ok: " << want_ok << "\n";
345 cout << " got_ok: " << got_ok << "\n";
348 // don't use mpq_equal, since we allow non-normalized values to be
349 // read, which can trigger ASSERTs in mpq_equal
350 if (want_ok && (mpz_cmp (mpq_numref (got), mpq_numref(want)) != 0
351 || mpz_cmp (mpq_denref (got), mpq_denref(want)) != 0))
353 WRONG ("mpq operator>> wrong result");
354 mpq_trace (" got ", got);
355 mpq_trace (" want", want);
358 if (putback_tellg_works && got_pos != want_pos)
360 WRONG ("mpq operator>> wrong position");
361 cout << " want_pos: " << want_pos << "\n";
362 cout << " got_pos: " << got_pos << "\n";
376 static const struct {
384 { "0", -1, "0", (ios::fmtflags) 0 },
385 { "+0", -1, "0", (ios::fmtflags) 0 },
386 { "-0", -1, "0", (ios::fmtflags) 0 },
387 { "0.0", -1, "0", (ios::fmtflags) 0 },
388 { "0.", -1, "0", (ios::fmtflags) 0 },
389 { ".0", -1, "0", (ios::fmtflags) 0 },
390 { "+.0", -1, "0", (ios::fmtflags) 0 },
391 { "-.0", -1, "0", (ios::fmtflags) 0 },
392 { "+0.00", -1, "0", (ios::fmtflags) 0 },
393 { "-0.000", -1, "0", (ios::fmtflags) 0 },
394 { "+0.00", -1, "0", (ios::fmtflags) 0 },
395 { "-0.000", -1, "0", (ios::fmtflags) 0 },
396 { "0.0e0", -1, "0", (ios::fmtflags) 0 },
397 { "0.e0", -1, "0", (ios::fmtflags) 0 },
398 { ".0e0", -1, "0", (ios::fmtflags) 0 },
399 { "0.0e-0", -1, "0", (ios::fmtflags) 0 },
400 { "0.e-0", -1, "0", (ios::fmtflags) 0 },
401 { ".0e-0", -1, "0", (ios::fmtflags) 0 },
402 { "0.0e+0", -1, "0", (ios::fmtflags) 0 },
403 { "0.e+0", -1, "0", (ios::fmtflags) 0 },
404 { ".0e+0", -1, "0", (ios::fmtflags) 0 },
406 { "1", -1, "1", (ios::fmtflags) 0 },
407 { "+1", -1, "1", (ios::fmtflags) 0 },
408 { "-1", -1, "-1", (ios::fmtflags) 0 },
410 { " 0", 0, NULL, (ios::fmtflags) 0 }, // not without skipws
411 { " 0", -1, "0", ios::skipws },
412 { " +0", -1, "0", ios::skipws },
413 { " -0", -1, "0", ios::skipws },
415 { "+-123", 1, NULL, (ios::fmtflags) 0 },
416 { "-+123", 1, NULL, (ios::fmtflags) 0 },
417 { "1e+-123", 3, NULL, (ios::fmtflags) 0 },
418 { "1e-+123", 3, NULL, (ios::fmtflags) 0 },
420 { "e123", 0, NULL, (ios::fmtflags) 0 }, // at least one mantissa digit
421 { ".e123", 1, NULL, (ios::fmtflags) 0 },
422 { "+.e123", 2, NULL, (ios::fmtflags) 0 },
423 { "-.e123", 2, NULL, (ios::fmtflags) 0 },
425 { "123e", 4, NULL, (ios::fmtflags) 0 }, // at least one exponent digit
426 { "123e-", 5, NULL, (ios::fmtflags) 0 },
427 { "123e+", 5, NULL, (ios::fmtflags) 0 },
432 double got_d, want_d;
433 streampos init_tellg, got_pos, want_pos;
438 for (size_t i = 0; i < numberof (data); i++)
440 want_pos = (data[i].want_pos == -1
441 ? strlen (data[i].input) : data[i].want_pos);
443 want_ok = (data[i].want != NULL);
445 if (data[i].want != NULL)
446 mpf_set_str_or_abort (want, data[i].want, 0);
448 mpf_set_ui (want, 0L);
450 want_d = mpf_get_d (want);
451 if (option_check_standard && mpf_cmp_d (want, want_d) == 0)
453 istringstream input (data[i].input);
454 input.flags (data[i].flags);
455 init_tellg = input.tellg();
458 got_ok = (input ? 1 : 0);
460 got_pos = input.tellg() - init_tellg;
462 if (got_ok != want_ok)
464 WRONG ("stdc++ operator>> wrong status, check_mpf");
465 cout << " want_ok: " << want_ok << "\n";
466 cout << " got_ok: " << got_ok << "\n";
468 if (want_ok && want_d != got_d)
470 WRONG ("stdc++ operator>> wrong result, check_mpf");
471 cout << " got: " << got_d << "\n";
472 cout << " want: " << want_d << "\n";
474 if (putback_tellg_works && got_pos != want_pos)
476 WRONG ("stdc++ operator>> wrong position, check_mpf");
477 cout << " want_pos: " << want_pos << "\n";
478 cout << " got_pos: " << got_pos << "\n";
483 istringstream input (data[i].input);
484 input.flags (data[i].flags);
485 init_tellg = input.tellg();
487 mpf_set_ui (got, 0xDEAD);
489 got_ok = (input ? 1 : 0);
491 got_pos = input.tellg() - init_tellg;
493 if (got_ok != want_ok)
495 WRONG ("mpf operator>> wrong status");
496 cout << " want_ok: " << want_ok << "\n";
497 cout << " got_ok: " << got_ok << "\n";
500 if (want_ok && mpf_cmp (got, want) != 0)
502 WRONG ("mpf operator>> wrong result");
503 mpf_trace (" got ", got);
504 mpf_trace (" want", want);
507 if (putback_tellg_works && got_pos != want_pos)
509 WRONG ("mpf operator>> wrong position");
510 cout << " want_pos: " << want_pos << "\n";
511 cout << " got_pos: " << got_pos << "\n";
524 main (int argc, char *argv[])
526 if (argc > 1 && strcmp (argv[1], "-s") == 0)
527 option_check_standard = 1;
531 check_putback_tellg ();