Upload Tizen:Base source
[external/gmp.git] / tests / cxx / t-istream.cc
1 /* Test istream formatted input.
2
3 Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
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.
11
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.
16
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/.  */
19
20 #include <iostream>
21 #include <cstdlib>
22 #include <cstring>
23
24 #include "gmp.h"
25 #include "gmp-impl.h"
26 #include "tests.h"
27
28 using namespace std;
29
30
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.
34 //
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.
39
40 int   option_check_standard = 0;
41
42
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.
47
48 int putback_tellg_works = 1;
49
50 void
51 check_putback_tellg (void)
52 {
53   istringstream input ("hello");
54   streampos  old_pos, new_pos;
55   char  c;
56
57   input.get(c);
58   old_pos = input.tellg();
59   input.putback(c);
60   new_pos = input.tellg();
61
62   if (old_pos == new_pos)
63     {
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;
67     }
68 }
69
70
71 #define WRONG(str)                                              \
72   do {                                                          \
73     cout << str ", data[" << i << "]\n";                        \
74     cout << "  input: \"" << data[i].input << "\"\n";           \
75     cout << "  flags: " << hex << input.flags() << dec << "\n"; \
76   } while (0)
77
78 void
79 check_mpz (void)
80 {
81   static const struct {
82     const char     *input;
83     int            want_pos;
84     const char     *want;
85     ios::fmtflags  flags;
86
87   } data[] = {
88
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 },
99
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 },
110
111     { "0",    -1, "0",   ios::oct },
112     { "123",  -1, "83",  ios::oct },
113     { "-123", -1, "-83", ios::oct },
114     { "+123", -1, "83",  ios::oct },
115
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 },
129
130     { " 123",  0, NULL,  (ios::fmtflags) 0 },   // not without skipws
131     { " 123", -1, "123", ios::skipws },
132   };
133
134   mpz_t      got, want;
135   int        got_ok, want_ok;
136   long       got_si, want_si;
137   streampos  init_tellg, got_pos, want_pos;
138
139   mpz_init (got);
140   mpz_init (want);
141
142   for (size_t i = 0; i < numberof (data); i++)
143     {
144       want_pos = (data[i].want_pos == -1
145                   ? strlen (data[i].input) : data[i].want_pos);
146
147       want_ok = (data[i].want != NULL);
148
149       if (data[i].want != NULL)
150         mpz_set_str_or_abort (want, data[i].want, 0);
151       else
152         mpz_set_ui (want, 0L);
153
154       if (option_check_standard && mpz_fits_slong_p (want))
155         {
156           istringstream  input (data[i].input);
157           input.flags (data[i].flags);
158           init_tellg = input.tellg();
159           want_si = mpz_get_si (want);
160
161           input >> got_si;
162           got_ok = (input ? 1 : 0);
163           input.clear();
164           got_pos = input.tellg() - init_tellg;
165
166           if (got_ok != want_ok)
167             {
168               WRONG ("stdc++ operator>> wrong status, check_mpz");
169               cout << "  want_ok: " << want_ok << "\n";
170               cout << "  got_ok:  " << got_ok << "\n";
171             }
172           if (want_ok && got_si != want_si)
173             {
174               WRONG ("stdc++ operator>> wrong result, check_mpz");
175               cout << "  got_si:  " << got_si << "\n";
176               cout << "  want_si: " << want_si << "\n";
177             }
178           if (putback_tellg_works && got_pos != want_pos)
179             {
180               WRONG ("stdc++ operator>> wrong position, check_mpz");
181               cout << "  want_pos: " << want_pos << "\n";
182               cout << "  got_pos:  " << got_pos << "\n";
183             }
184         }
185
186       {
187         istringstream  input (data[i].input);
188         input.flags (data[i].flags);
189         init_tellg = input.tellg();
190
191         mpz_set_ui (got, 0xDEAD);
192         input >> got;
193         got_ok = (input ? 1 : 0);
194         input.clear();
195         got_pos = input.tellg() - init_tellg;
196
197         if (got_ok != want_ok)
198           {
199             WRONG ("mpz operator>> wrong status");
200             cout << "  want_ok: " << want_ok << "\n";
201             cout << "  got_ok:  " << got_ok << "\n";
202             abort ();
203           }
204         if (want_ok && mpz_cmp (got, want) != 0)
205           {
206             WRONG ("mpz operator>> wrong result");
207             mpz_trace ("  got ", got);
208             mpz_trace ("  want", want);
209             abort ();
210           }
211         if (putback_tellg_works && got_pos != want_pos)
212           {
213             WRONG ("mpz operator>> wrong position");
214             cout << "  want_pos: " << want_pos << "\n";
215             cout << "  got_pos:  " << got_pos << "\n";
216             abort ();
217           }
218       }
219     }
220
221   mpz_clear (got);
222   mpz_clear (want);
223 }
224
225 void
226 check_mpq (void)
227 {
228   static const struct {
229     const char     *input;
230     int            want_pos;
231     const char     *want;
232     ios::fmtflags  flags;
233
234   } data[] = {
235
236     { "0",   -1, "0", (ios::fmtflags) 0 },
237     { "00",  -1, "0", (ios::fmtflags) 0 },
238     { "0x0", -1, "0", (ios::fmtflags) 0 },
239
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 },
244
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 },
249
250     { "ab",   -1, "171",  ios::hex },
251     { "cd",   -1, "205",  ios::hex },
252     { "ef",   -1, "239",  ios::hex },
253
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 },
257
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 },
262
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 },
267
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 },
271
272     { " 123",  0, NULL,  (ios::fmtflags) 0 },   // not without skipws
273     { " 123", -1, "123", ios::skipws },
274   };
275
276   mpq_t      got, want;
277   int        got_ok, want_ok;
278   long       got_si, want_si;
279   streampos  init_tellg, got_pos, want_pos;
280
281   mpq_init (got);
282   mpq_init (want);
283
284   for (size_t i = 0; i < numberof (data); i++)
285     {
286       want_pos = (data[i].want_pos == -1
287                   ? strlen (data[i].input) : data[i].want_pos);
288
289       want_ok = (data[i].want != NULL);
290
291       if (data[i].want != NULL)
292         mpq_set_str_or_abort (want, data[i].want, 0);
293       else
294         mpq_set_ui (want, 0L, 1L);
295
296       if (option_check_standard
297           && mpz_fits_slong_p (mpq_numref(want))
298           && mpz_cmp_ui (mpq_denref(want), 1L) == 0)
299         {
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));
304
305           input >> got_si;
306           got_ok = (input ? 1 : 0);
307           input.clear();
308           got_pos = input.tellg() - init_tellg;
309
310           if (got_ok != want_ok)
311             {
312               WRONG ("stdc++ operator>> wrong status, check_mpq");
313               cout << "  want_ok: " << want_ok << "\n";
314               cout << "  got_ok:  " << got_ok << "\n";
315             }
316           if (want_ok && want_si != got_si)
317             {
318               WRONG ("stdc++ operator>> wrong result, check_mpq");
319               cout << "  got_si:  " << got_si << "\n";
320               cout << "  want_si: " << want_si << "\n";
321             }
322           if (putback_tellg_works && got_pos != want_pos)
323             {
324               WRONG ("stdc++ operator>> wrong position, check_mpq");
325               cout << "  want_pos: " << want_pos << "\n";
326               cout << "  got_pos:  " << got_pos << "\n";
327             }
328         }
329
330       {
331         istringstream  input (data[i].input);
332         input.flags (data[i].flags);
333         init_tellg = input.tellg();
334         mpq_set_si (got, 0xDEAD, 0xBEEF);
335
336         input >> got;
337         got_ok = (input ? 1 : 0);
338         input.clear();
339         got_pos = input.tellg() - init_tellg;
340
341         if (got_ok != want_ok)
342           {
343             WRONG ("mpq operator>> wrong status");
344             cout << "  want_ok: " << want_ok << "\n";
345             cout << "  got_ok:  " << got_ok << "\n";
346             abort ();
347           }
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))
352           {
353             WRONG ("mpq operator>> wrong result");
354             mpq_trace ("  got ", got);
355             mpq_trace ("  want", want);
356             abort ();
357           }
358         if (putback_tellg_works && got_pos != want_pos)
359           {
360             WRONG ("mpq operator>> wrong position");
361             cout << "  want_pos: " << want_pos << "\n";
362             cout << "  got_pos:  " << got_pos << "\n";
363             abort ();
364           }
365       }
366     }
367
368   mpq_clear (got);
369   mpq_clear (want);
370 }
371
372
373 void
374 check_mpf (void)
375 {
376   static const struct {
377     const char     *input;
378     int            want_pos;
379     const char     *want;
380     ios::fmtflags  flags;
381
382   } data[] = {
383
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 },
405
406     { "1",  -1,  "1", (ios::fmtflags) 0 },
407     { "+1", -1,  "1", (ios::fmtflags) 0 },
408     { "-1", -1, "-1", (ios::fmtflags) 0 },
409
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 },
414
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 },
419
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 },
424
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 },
428   };
429
430   mpf_t      got, want;
431   int        got_ok, want_ok;
432   double     got_d, want_d;
433   streampos  init_tellg, got_pos, want_pos;
434
435   mpf_init (got);
436   mpf_init (want);
437
438   for (size_t i = 0; i < numberof (data); i++)
439     {
440       want_pos = (data[i].want_pos == -1
441                   ? strlen (data[i].input) : data[i].want_pos);
442
443       want_ok = (data[i].want != NULL);
444
445       if (data[i].want != NULL)
446         mpf_set_str_or_abort (want, data[i].want, 0);
447       else
448         mpf_set_ui (want, 0L);
449
450       want_d = mpf_get_d (want);
451       if (option_check_standard && mpf_cmp_d (want, want_d) == 0)
452         {
453           istringstream  input (data[i].input);
454           input.flags (data[i].flags);
455           init_tellg = input.tellg();
456
457           input >> got_d;
458           got_ok = (input ? 1 : 0);
459           input.clear();
460           got_pos = input.tellg() - init_tellg;
461
462           if (got_ok != want_ok)
463             {
464               WRONG ("stdc++ operator>> wrong status, check_mpf");
465               cout << "  want_ok: " << want_ok << "\n";
466               cout << "  got_ok:  " << got_ok << "\n";
467             }
468           if (want_ok && want_d != got_d)
469             {
470               WRONG ("stdc++ operator>> wrong result, check_mpf");
471               cout << "  got:   " << got_d << "\n";
472               cout << "  want:  " << want_d << "\n";
473             }
474           if (putback_tellg_works && got_pos != want_pos)
475             {
476               WRONG ("stdc++ operator>> wrong position, check_mpf");
477               cout << "  want_pos: " << want_pos << "\n";
478               cout << "  got_pos:  " << got_pos << "\n";
479             }
480         }
481
482       {
483         istringstream  input (data[i].input);
484         input.flags (data[i].flags);
485         init_tellg = input.tellg();
486
487         mpf_set_ui (got, 0xDEAD);
488         input >> got;
489         got_ok = (input ? 1 : 0);
490         input.clear();
491         got_pos = input.tellg() - init_tellg;
492
493         if (got_ok != want_ok)
494           {
495             WRONG ("mpf operator>> wrong status");
496             cout << "  want_ok: " << want_ok << "\n";
497             cout << "  got_ok:  " << got_ok << "\n";
498             abort ();
499           }
500         if (want_ok && mpf_cmp (got, want) != 0)
501           {
502             WRONG ("mpf operator>> wrong result");
503             mpf_trace ("  got ", got);
504             mpf_trace ("  want", want);
505             abort ();
506           }
507         if (putback_tellg_works && got_pos != want_pos)
508           {
509             WRONG ("mpf operator>> wrong position");
510             cout << "  want_pos: " << want_pos << "\n";
511             cout << "  got_pos:  " << got_pos << "\n";
512             abort ();
513           }
514       }
515     }
516
517   mpf_clear (got);
518   mpf_clear (want);
519 }
520
521
522
523 int
524 main (int argc, char *argv[])
525 {
526   if (argc > 1 && strcmp (argv[1], "-s") == 0)
527     option_check_standard = 1;
528
529   tests_start ();
530
531   check_putback_tellg ();
532   check_mpz ();
533   check_mpq ();
534   check_mpf ();
535
536   tests_end ();
537   return 0;
538 }