Home | History | Annotate | Line # | Download | only in cxx
t-istream.cc revision 1.1.1.4
      1      1.1  mrg /* Test istream formatted input.
      2      1.1  mrg 
      3  1.1.1.3  mrg Copyright 2001-2004 Free Software Foundation, Inc.
      4      1.1  mrg 
      5  1.1.1.2  mrg This file is part of the GNU MP Library test suite.
      6      1.1  mrg 
      7  1.1.1.2  mrg The GNU MP Library test suite is free software; you can redistribute it
      8  1.1.1.2  mrg and/or modify it under the terms of the GNU General Public License as
      9  1.1.1.2  mrg published by the Free Software Foundation; either version 3 of the License,
     10  1.1.1.2  mrg or (at your option) any later version.
     11  1.1.1.2  mrg 
     12  1.1.1.2  mrg The GNU MP Library test suite is distributed in the hope that it will be
     13  1.1.1.2  mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1.1.2  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     15  1.1.1.2  mrg Public License for more details.
     16      1.1  mrg 
     17  1.1.1.2  mrg You should have received a copy of the GNU General Public License along with
     18  1.1.1.3  mrg the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
     19      1.1  mrg 
     20      1.1  mrg #include <iostream>
     21      1.1  mrg #include <cstdlib>
     22      1.1  mrg #include <cstring>
     23      1.1  mrg 
     24      1.1  mrg #include "gmp-impl.h"
     25      1.1  mrg #include "tests.h"
     26      1.1  mrg 
     27      1.1  mrg using namespace std;
     28      1.1  mrg 
     29      1.1  mrg 
     30      1.1  mrg // Under option_check_standard, the various test cases for mpz operator>>
     31      1.1  mrg // are put through the standard operator>> for long, and likewise mpf
     32      1.1  mrg // operator>> is put through double.
     33      1.1  mrg //
     34      1.1  mrg // In g++ 3.3 this results in some printouts about the final position
     35      1.1  mrg // indicated for something like ".e123".  Our mpf code stops at the "e"
     36      1.1  mrg // since there's no mantissa digits, but g++ reads the whole thing and only
     37      1.1  mrg // then decides it's bad.
     38      1.1  mrg 
     39  1.1.1.2  mrg bool option_check_standard = false;
     40      1.1  mrg 
     41      1.1  mrg 
     42      1.1  mrg // On some versions of g++ 2.96 it's been observed that putback() may leave
     43      1.1  mrg // tellg() unchanged.  We believe this is incorrect and presumably the
     44      1.1  mrg // result of a bug, since for instance it's ok in g++ 2.95 and g++ 3.3.  We
     45      1.1  mrg // detect the problem at runtime and disable affected checks.
     46      1.1  mrg 
     47  1.1.1.2  mrg bool putback_tellg_works = true;
     48      1.1  mrg 
     49      1.1  mrg void
     50      1.1  mrg check_putback_tellg (void)
     51      1.1  mrg {
     52      1.1  mrg   istringstream input ("hello");
     53      1.1  mrg   streampos  old_pos, new_pos;
     54      1.1  mrg   char  c;
     55      1.1  mrg 
     56      1.1  mrg   input.get(c);
     57      1.1  mrg   old_pos = input.tellg();
     58      1.1  mrg   input.putback(c);
     59      1.1  mrg   new_pos = input.tellg();
     60      1.1  mrg 
     61      1.1  mrg   if (old_pos == new_pos)
     62      1.1  mrg     {
     63      1.1  mrg       cout << "Warning, istringstream has a bug: putback() doesn't update tellg().\n";;
     64      1.1  mrg       cout << "Tests on tellg() will be skipped.\n";
     65  1.1.1.2  mrg       putback_tellg_works = false;
     66      1.1  mrg     }
     67      1.1  mrg }
     68      1.1  mrg 
     69      1.1  mrg 
     70      1.1  mrg #define WRONG(str)                                              \
     71      1.1  mrg   do {                                                          \
     72      1.1  mrg     cout << str ", data[" << i << "]\n";                        \
     73      1.1  mrg     cout << "  input: \"" << data[i].input << "\"\n";           \
     74      1.1  mrg     cout << "  flags: " << hex << input.flags() << dec << "\n"; \
     75      1.1  mrg   } while (0)
     76      1.1  mrg 
     77      1.1  mrg void
     78      1.1  mrg check_mpz (void)
     79      1.1  mrg {
     80      1.1  mrg   static const struct {
     81      1.1  mrg     const char     *input;
     82      1.1  mrg     int            want_pos;
     83      1.1  mrg     const char     *want;
     84      1.1  mrg     ios::fmtflags  flags;
     85      1.1  mrg 
     86      1.1  mrg   } data[] = {
     87      1.1  mrg 
     88      1.1  mrg     { "0",      -1, "0",    (ios::fmtflags) 0 },
     89      1.1  mrg     { "123",    -1, "123",  (ios::fmtflags) 0 },
     90      1.1  mrg     { "0123",   -1, "83",   (ios::fmtflags) 0 },
     91      1.1  mrg     { "0x123",  -1, "291",  (ios::fmtflags) 0 },
     92      1.1  mrg     { "-123",   -1, "-123", (ios::fmtflags) 0 },
     93      1.1  mrg     { "-0123",  -1, "-83",  (ios::fmtflags) 0 },
     94      1.1  mrg     { "-0x123", -1, "-291", (ios::fmtflags) 0 },
     95      1.1  mrg     { "+123",   -1, "123", (ios::fmtflags) 0 },
     96      1.1  mrg     { "+0123",  -1, "83",  (ios::fmtflags) 0 },
     97      1.1  mrg     { "+0x123", -1, "291", (ios::fmtflags) 0 },
     98      1.1  mrg 
     99      1.1  mrg     { "0",     -1, "0",    ios::dec },
    100      1.1  mrg     { "1f",     1, "1",    ios::dec },
    101      1.1  mrg     { "011f",   3, "11",   ios::dec },
    102      1.1  mrg     { "123",   -1, "123",  ios::dec },
    103      1.1  mrg     { "-1f",    2, "-1",   ios::dec },
    104      1.1  mrg     { "-011f",  4, "-11",  ios::dec },
    105      1.1  mrg     { "-123",  -1, "-123", ios::dec },
    106      1.1  mrg     { "+1f",    2, "1",    ios::dec },
    107      1.1  mrg     { "+011f",  4, "11",   ios::dec },
    108      1.1  mrg     { "+123",  -1, "123",  ios::dec },
    109      1.1  mrg 
    110      1.1  mrg     { "0",    -1, "0",   ios::oct },
    111      1.1  mrg     { "123",  -1, "83",  ios::oct },
    112      1.1  mrg     { "-123", -1, "-83", ios::oct },
    113      1.1  mrg     { "+123", -1, "83",  ios::oct },
    114      1.1  mrg 
    115      1.1  mrg     { "0",    -1, "0",    ios::hex },
    116      1.1  mrg     { "123",  -1, "291",  ios::hex },
    117      1.1  mrg     { "ff",   -1, "255",  ios::hex },
    118      1.1  mrg     { "FF",   -1, "255",  ios::hex },
    119      1.1  mrg     { "-123", -1, "-291", ios::hex },
    120      1.1  mrg     { "-ff",  -1, "-255", ios::hex },
    121      1.1  mrg     { "-FF",  -1, "-255", ios::hex },
    122      1.1  mrg     { "+123", -1, "291",  ios::hex },
    123      1.1  mrg     { "+ff",  -1, "255",  ios::hex },
    124      1.1  mrg     { "+FF",  -1, "255",  ios::hex },
    125      1.1  mrg     { "ab",   -1, "171",  ios::hex },
    126      1.1  mrg     { "cd",   -1, "205",  ios::hex },
    127      1.1  mrg     { "ef",   -1, "239",  ios::hex },
    128      1.1  mrg 
    129      1.1  mrg     { " 123",  0, NULL,  (ios::fmtflags) 0 },   // not without skipws
    130      1.1  mrg     { " 123", -1, "123", ios::skipws },
    131      1.1  mrg   };
    132      1.1  mrg 
    133      1.1  mrg   mpz_t      got, want;
    134  1.1.1.2  mrg   bool       got_ok, want_ok;
    135  1.1.1.2  mrg   bool       got_eof, want_eof;
    136      1.1  mrg   long       got_si, want_si;
    137      1.1  mrg   streampos  init_tellg, got_pos, want_pos;
    138      1.1  mrg 
    139      1.1  mrg   mpz_init (got);
    140      1.1  mrg   mpz_init (want);
    141      1.1  mrg 
    142      1.1  mrg   for (size_t i = 0; i < numberof (data); i++)
    143      1.1  mrg     {
    144  1.1.1.2  mrg       size_t input_length = strlen (data[i].input);
    145      1.1  mrg       want_pos = (data[i].want_pos == -1
    146  1.1.1.2  mrg                   ? input_length : data[i].want_pos);
    147  1.1.1.2  mrg       want_eof = (want_pos == streampos(input_length));
    148      1.1  mrg 
    149      1.1  mrg       want_ok = (data[i].want != NULL);
    150      1.1  mrg 
    151      1.1  mrg       if (data[i].want != NULL)
    152      1.1  mrg         mpz_set_str_or_abort (want, data[i].want, 0);
    153      1.1  mrg       else
    154      1.1  mrg         mpz_set_ui (want, 0L);
    155      1.1  mrg 
    156      1.1  mrg       if (option_check_standard && mpz_fits_slong_p (want))
    157      1.1  mrg         {
    158      1.1  mrg           istringstream  input (data[i].input);
    159      1.1  mrg           input.flags (data[i].flags);
    160      1.1  mrg           init_tellg = input.tellg();
    161      1.1  mrg           want_si = mpz_get_si (want);
    162      1.1  mrg 
    163      1.1  mrg           input >> got_si;
    164  1.1.1.2  mrg           got_ok = !input.fail();
    165  1.1.1.2  mrg           got_eof = input.eof();
    166      1.1  mrg           input.clear();
    167      1.1  mrg           got_pos = input.tellg() - init_tellg;
    168      1.1  mrg 
    169      1.1  mrg           if (got_ok != want_ok)
    170      1.1  mrg             {
    171      1.1  mrg               WRONG ("stdc++ operator>> wrong status, check_mpz");
    172      1.1  mrg               cout << "  want_ok: " << want_ok << "\n";
    173      1.1  mrg               cout << "  got_ok:  " << got_ok << "\n";
    174      1.1  mrg             }
    175      1.1  mrg           if (want_ok && got_si != want_si)
    176      1.1  mrg             {
    177      1.1  mrg               WRONG ("stdc++ operator>> wrong result, check_mpz");
    178      1.1  mrg               cout << "  got_si:  " << got_si << "\n";
    179      1.1  mrg               cout << "  want_si: " << want_si << "\n";
    180      1.1  mrg             }
    181  1.1.1.2  mrg           if (want_ok && got_eof != want_eof)
    182  1.1.1.2  mrg             {
    183  1.1.1.2  mrg               WRONG ("stdc++ operator>> wrong EOF state, check_mpz");
    184  1.1.1.2  mrg               cout << "  got_eof:  " << got_eof << "\n";
    185  1.1.1.2  mrg               cout << "  want_eof: " << want_eof << "\n";
    186  1.1.1.2  mrg             }
    187      1.1  mrg           if (putback_tellg_works && got_pos != want_pos)
    188      1.1  mrg             {
    189      1.1  mrg               WRONG ("stdc++ operator>> wrong position, check_mpz");
    190      1.1  mrg               cout << "  want_pos: " << want_pos << "\n";
    191      1.1  mrg               cout << "  got_pos:  " << got_pos << "\n";
    192      1.1  mrg             }
    193      1.1  mrg         }
    194      1.1  mrg 
    195      1.1  mrg       {
    196      1.1  mrg         istringstream  input (data[i].input);
    197      1.1  mrg         input.flags (data[i].flags);
    198      1.1  mrg         init_tellg = input.tellg();
    199      1.1  mrg 
    200      1.1  mrg         mpz_set_ui (got, 0xDEAD);
    201      1.1  mrg         input >> got;
    202  1.1.1.2  mrg         got_ok = !input.fail();
    203  1.1.1.2  mrg 	got_eof = input.eof();
    204      1.1  mrg         input.clear();
    205      1.1  mrg         got_pos = input.tellg() - init_tellg;
    206      1.1  mrg 
    207      1.1  mrg         if (got_ok != want_ok)
    208      1.1  mrg           {
    209      1.1  mrg             WRONG ("mpz operator>> wrong status");
    210      1.1  mrg             cout << "  want_ok: " << want_ok << "\n";
    211      1.1  mrg             cout << "  got_ok:  " << got_ok << "\n";
    212      1.1  mrg             abort ();
    213      1.1  mrg           }
    214      1.1  mrg         if (want_ok && mpz_cmp (got, want) != 0)
    215      1.1  mrg           {
    216      1.1  mrg             WRONG ("mpz operator>> wrong result");
    217      1.1  mrg             mpz_trace ("  got ", got);
    218      1.1  mrg             mpz_trace ("  want", want);
    219      1.1  mrg             abort ();
    220      1.1  mrg           }
    221  1.1.1.2  mrg         if (want_ok && got_eof != want_eof)
    222  1.1.1.2  mrg           {
    223  1.1.1.2  mrg             WRONG ("mpz operator>> wrong EOF state");
    224  1.1.1.2  mrg             cout << "  want_eof: " << want_eof << "\n";
    225  1.1.1.2  mrg             cout << "  got_eof:  " << got_eof << "\n";
    226  1.1.1.2  mrg             abort ();
    227  1.1.1.2  mrg           }
    228      1.1  mrg         if (putback_tellg_works && got_pos != want_pos)
    229      1.1  mrg           {
    230      1.1  mrg             WRONG ("mpz operator>> wrong position");
    231      1.1  mrg             cout << "  want_pos: " << want_pos << "\n";
    232      1.1  mrg             cout << "  got_pos:  " << got_pos << "\n";
    233      1.1  mrg             abort ();
    234      1.1  mrg           }
    235      1.1  mrg       }
    236      1.1  mrg     }
    237      1.1  mrg 
    238      1.1  mrg   mpz_clear (got);
    239      1.1  mrg   mpz_clear (want);
    240      1.1  mrg }
    241      1.1  mrg 
    242      1.1  mrg void
    243      1.1  mrg check_mpq (void)
    244      1.1  mrg {
    245      1.1  mrg   static const struct {
    246      1.1  mrg     const char     *input;
    247      1.1  mrg     int            want_pos;
    248      1.1  mrg     const char     *want;
    249      1.1  mrg     ios::fmtflags  flags;
    250      1.1  mrg 
    251      1.1  mrg   } data[] = {
    252      1.1  mrg 
    253      1.1  mrg     { "0",   -1, "0", (ios::fmtflags) 0 },
    254      1.1  mrg     { "00",  -1, "0", (ios::fmtflags) 0 },
    255      1.1  mrg     { "0x0", -1, "0", (ios::fmtflags) 0 },
    256      1.1  mrg 
    257      1.1  mrg     { "123/456",   -1, "123/456", ios::dec },
    258      1.1  mrg     { "0123/456",  -1, "123/456", ios::dec },
    259      1.1  mrg     { "123/0456",  -1, "123/456", ios::dec },
    260      1.1  mrg     { "0123/0456", -1, "123/456", ios::dec },
    261      1.1  mrg 
    262      1.1  mrg     { "123/456",   -1, "83/302", ios::oct },
    263      1.1  mrg     { "0123/456",  -1, "83/302", ios::oct },
    264      1.1  mrg     { "123/0456",  -1, "83/302", ios::oct },
    265      1.1  mrg     { "0123/0456", -1, "83/302", ios::oct },
    266      1.1  mrg 
    267      1.1  mrg     { "ab",   -1, "171",  ios::hex },
    268      1.1  mrg     { "cd",   -1, "205",  ios::hex },
    269      1.1  mrg     { "ef",   -1, "239",  ios::hex },
    270      1.1  mrg 
    271      1.1  mrg     { "0/0",     -1, "0/0", (ios::fmtflags) 0 },
    272      1.1  mrg     { "5/8",     -1, "5/8", (ios::fmtflags) 0 },
    273      1.1  mrg     { "0x5/0x8", -1, "5/8", (ios::fmtflags) 0 },
    274      1.1  mrg 
    275      1.1  mrg     { "123/456",   -1, "123/456",  (ios::fmtflags) 0 },
    276      1.1  mrg     { "123/0456",  -1, "123/302",  (ios::fmtflags) 0 },
    277      1.1  mrg     { "123/0x456", -1, "123/1110", (ios::fmtflags) 0 },
    278      1.1  mrg     { "123/0X456", -1, "123/1110", (ios::fmtflags) 0 },
    279      1.1  mrg 
    280      1.1  mrg     { "0123/123",   -1, "83/123", (ios::fmtflags) 0 },
    281      1.1  mrg     { "0123/0123",  -1, "83/83",  (ios::fmtflags) 0 },
    282      1.1  mrg     { "0123/0x123", -1, "83/291", (ios::fmtflags) 0 },
    283      1.1  mrg     { "0123/0X123", -1, "83/291", (ios::fmtflags) 0 },
    284      1.1  mrg 
    285      1.1  mrg     { "0x123/123",   -1, "291/123", (ios::fmtflags) 0 },
    286      1.1  mrg     { "0X123/0123",  -1, "291/83",  (ios::fmtflags) 0 },
    287      1.1  mrg     { "0x123/0x123", -1, "291/291", (ios::fmtflags) 0 },
    288      1.1  mrg 
    289      1.1  mrg     { " 123",  0, NULL,  (ios::fmtflags) 0 },   // not without skipws
    290      1.1  mrg     { " 123", -1, "123", ios::skipws },
    291  1.1.1.2  mrg 
    292  1.1.1.2  mrg     { "123 /456",    3, "123",  (ios::fmtflags) 0 },
    293  1.1.1.2  mrg     { "123/ 456",    4,  NULL,  (ios::fmtflags) 0 },
    294  1.1.1.2  mrg     { "123/"    ,   -1,  NULL,  (ios::fmtflags) 0 },
    295  1.1.1.2  mrg     { "123 /456",    3, "123",  ios::skipws },
    296  1.1.1.2  mrg     { "123/ 456",    4,  NULL,  ios::skipws },
    297      1.1  mrg   };
    298      1.1  mrg 
    299      1.1  mrg   mpq_t      got, want;
    300  1.1.1.2  mrg   bool       got_ok, want_ok;
    301  1.1.1.2  mrg   bool       got_eof, want_eof;
    302      1.1  mrg   long       got_si, want_si;
    303      1.1  mrg   streampos  init_tellg, got_pos, want_pos;
    304      1.1  mrg 
    305      1.1  mrg   mpq_init (got);
    306      1.1  mrg   mpq_init (want);
    307      1.1  mrg 
    308      1.1  mrg   for (size_t i = 0; i < numberof (data); i++)
    309      1.1  mrg     {
    310  1.1.1.2  mrg       size_t input_length = strlen (data[i].input);
    311      1.1  mrg       want_pos = (data[i].want_pos == -1
    312  1.1.1.2  mrg                   ? input_length : data[i].want_pos);
    313  1.1.1.2  mrg       want_eof = (want_pos == streampos(input_length));
    314      1.1  mrg 
    315      1.1  mrg       want_ok = (data[i].want != NULL);
    316      1.1  mrg 
    317      1.1  mrg       if (data[i].want != NULL)
    318      1.1  mrg         mpq_set_str_or_abort (want, data[i].want, 0);
    319      1.1  mrg       else
    320      1.1  mrg         mpq_set_ui (want, 0L, 1L);
    321      1.1  mrg 
    322      1.1  mrg       if (option_check_standard
    323      1.1  mrg           && mpz_fits_slong_p (mpq_numref(want))
    324  1.1.1.2  mrg           && mpz_cmp_ui (mpq_denref(want), 1L) == 0
    325  1.1.1.2  mrg           && strchr (data[i].input, '/') == NULL)
    326      1.1  mrg         {
    327      1.1  mrg           istringstream  input (data[i].input);
    328      1.1  mrg           input.flags (data[i].flags);
    329      1.1  mrg           init_tellg = input.tellg();
    330      1.1  mrg           want_si = mpz_get_si (mpq_numref(want));
    331      1.1  mrg 
    332      1.1  mrg           input >> got_si;
    333  1.1.1.2  mrg           got_ok = !input.fail();
    334  1.1.1.2  mrg           got_eof = input.eof();
    335      1.1  mrg           input.clear();
    336      1.1  mrg           got_pos = input.tellg() - init_tellg;
    337      1.1  mrg 
    338      1.1  mrg           if (got_ok != want_ok)
    339      1.1  mrg             {
    340      1.1  mrg               WRONG ("stdc++ operator>> wrong status, check_mpq");
    341      1.1  mrg               cout << "  want_ok: " << want_ok << "\n";
    342      1.1  mrg               cout << "  got_ok:  " << got_ok << "\n";
    343      1.1  mrg             }
    344      1.1  mrg           if (want_ok && want_si != got_si)
    345      1.1  mrg             {
    346      1.1  mrg               WRONG ("stdc++ operator>> wrong result, check_mpq");
    347      1.1  mrg               cout << "  got_si:  " << got_si << "\n";
    348      1.1  mrg               cout << "  want_si: " << want_si << "\n";
    349      1.1  mrg             }
    350  1.1.1.2  mrg           if (want_ok && got_eof != want_eof)
    351  1.1.1.2  mrg             {
    352  1.1.1.2  mrg               WRONG ("stdc++ operator>> wrong EOF state, check_mpq");
    353  1.1.1.2  mrg               cout << "  got_eof:  " << got_eof << "\n";
    354  1.1.1.2  mrg               cout << "  want_eof: " << want_eof << "\n";
    355  1.1.1.2  mrg             }
    356      1.1  mrg           if (putback_tellg_works && got_pos != want_pos)
    357      1.1  mrg             {
    358      1.1  mrg               WRONG ("stdc++ operator>> wrong position, check_mpq");
    359      1.1  mrg               cout << "  want_pos: " << want_pos << "\n";
    360      1.1  mrg               cout << "  got_pos:  " << got_pos << "\n";
    361      1.1  mrg             }
    362      1.1  mrg         }
    363      1.1  mrg 
    364      1.1  mrg       {
    365      1.1  mrg         istringstream  input (data[i].input);
    366      1.1  mrg         input.flags (data[i].flags);
    367      1.1  mrg         init_tellg = input.tellg();
    368      1.1  mrg         mpq_set_si (got, 0xDEAD, 0xBEEF);
    369      1.1  mrg 
    370      1.1  mrg         input >> got;
    371  1.1.1.2  mrg         got_ok = !input.fail();
    372  1.1.1.2  mrg 	got_eof = input.eof();
    373      1.1  mrg         input.clear();
    374      1.1  mrg         got_pos = input.tellg() - init_tellg;
    375      1.1  mrg 
    376      1.1  mrg         if (got_ok != want_ok)
    377      1.1  mrg           {
    378      1.1  mrg             WRONG ("mpq operator>> wrong status");
    379      1.1  mrg             cout << "  want_ok: " << want_ok << "\n";
    380      1.1  mrg             cout << "  got_ok:  " << got_ok << "\n";
    381      1.1  mrg             abort ();
    382      1.1  mrg           }
    383      1.1  mrg         // don't use mpq_equal, since we allow non-normalized values to be
    384      1.1  mrg         // read, which can trigger ASSERTs in mpq_equal
    385      1.1  mrg         if (want_ok && (mpz_cmp (mpq_numref (got), mpq_numref(want)) != 0
    386      1.1  mrg                         || mpz_cmp (mpq_denref (got), mpq_denref(want)) != 0))
    387      1.1  mrg           {
    388      1.1  mrg             WRONG ("mpq operator>> wrong result");
    389      1.1  mrg             mpq_trace ("  got ", got);
    390      1.1  mrg             mpq_trace ("  want", want);
    391      1.1  mrg             abort ();
    392      1.1  mrg           }
    393  1.1.1.2  mrg         if (want_ok && got_eof != want_eof)
    394  1.1.1.2  mrg           {
    395  1.1.1.2  mrg             WRONG ("mpq operator>> wrong EOF state");
    396  1.1.1.2  mrg             cout << "  want_eof: " << want_eof << "\n";
    397  1.1.1.2  mrg             cout << "  got_eof:  " << got_eof << "\n";
    398  1.1.1.2  mrg             abort ();
    399  1.1.1.2  mrg           }
    400      1.1  mrg         if (putback_tellg_works && got_pos != want_pos)
    401      1.1  mrg           {
    402      1.1  mrg             WRONG ("mpq operator>> wrong position");
    403      1.1  mrg             cout << "  want_pos: " << want_pos << "\n";
    404      1.1  mrg             cout << "  got_pos:  " << got_pos << "\n";
    405      1.1  mrg             abort ();
    406      1.1  mrg           }
    407      1.1  mrg       }
    408      1.1  mrg     }
    409      1.1  mrg 
    410      1.1  mrg   mpq_clear (got);
    411      1.1  mrg   mpq_clear (want);
    412      1.1  mrg }
    413      1.1  mrg 
    414      1.1  mrg 
    415      1.1  mrg void
    416      1.1  mrg check_mpf (void)
    417      1.1  mrg {
    418      1.1  mrg   static const struct {
    419      1.1  mrg     const char     *input;
    420      1.1  mrg     int            want_pos;
    421      1.1  mrg     const char     *want;
    422      1.1  mrg     ios::fmtflags  flags;
    423      1.1  mrg 
    424      1.1  mrg   } data[] = {
    425      1.1  mrg 
    426      1.1  mrg     { "0",      -1, "0", (ios::fmtflags) 0 },
    427      1.1  mrg     { "+0",     -1, "0", (ios::fmtflags) 0 },
    428      1.1  mrg     { "-0",     -1, "0", (ios::fmtflags) 0 },
    429      1.1  mrg     { "0.0",    -1, "0", (ios::fmtflags) 0 },
    430      1.1  mrg     { "0.",     -1, "0", (ios::fmtflags) 0 },
    431      1.1  mrg     { ".0",     -1, "0", (ios::fmtflags) 0 },
    432      1.1  mrg     { "+.0",    -1, "0", (ios::fmtflags) 0 },
    433      1.1  mrg     { "-.0",    -1, "0", (ios::fmtflags) 0 },
    434      1.1  mrg     { "+0.00",  -1, "0", (ios::fmtflags) 0 },
    435      1.1  mrg     { "-0.000", -1, "0", (ios::fmtflags) 0 },
    436      1.1  mrg     { "+0.00",  -1, "0", (ios::fmtflags) 0 },
    437      1.1  mrg     { "-0.000", -1, "0", (ios::fmtflags) 0 },
    438      1.1  mrg     { "0.0e0",  -1, "0", (ios::fmtflags) 0 },
    439      1.1  mrg     { "0.e0",   -1, "0", (ios::fmtflags) 0 },
    440      1.1  mrg     { ".0e0",   -1, "0", (ios::fmtflags) 0 },
    441      1.1  mrg     { "0.0e-0", -1, "0", (ios::fmtflags) 0 },
    442      1.1  mrg     { "0.e-0",  -1, "0", (ios::fmtflags) 0 },
    443      1.1  mrg     { ".0e-0",  -1, "0", (ios::fmtflags) 0 },
    444      1.1  mrg     { "0.0e+0", -1, "0", (ios::fmtflags) 0 },
    445      1.1  mrg     { "0.e+0",  -1, "0", (ios::fmtflags) 0 },
    446      1.1  mrg     { ".0e+0",  -1, "0", (ios::fmtflags) 0 },
    447      1.1  mrg 
    448      1.1  mrg     { "1",  -1,  "1", (ios::fmtflags) 0 },
    449      1.1  mrg     { "+1", -1,  "1", (ios::fmtflags) 0 },
    450      1.1  mrg     { "-1", -1, "-1", (ios::fmtflags) 0 },
    451      1.1  mrg 
    452      1.1  mrg     { " 0",  0,  NULL, (ios::fmtflags) 0 },  // not without skipws
    453      1.1  mrg     { " 0",  -1, "0", ios::skipws },
    454      1.1  mrg     { " +0", -1, "0", ios::skipws },
    455      1.1  mrg     { " -0", -1, "0", ios::skipws },
    456      1.1  mrg 
    457      1.1  mrg     { "+-123", 1, NULL, (ios::fmtflags) 0 },
    458      1.1  mrg     { "-+123", 1, NULL, (ios::fmtflags) 0 },
    459      1.1  mrg     { "1e+-123", 3, NULL, (ios::fmtflags) 0 },
    460      1.1  mrg     { "1e-+123", 3, NULL, (ios::fmtflags) 0 },
    461      1.1  mrg 
    462      1.1  mrg     { "e123",   0, NULL, (ios::fmtflags) 0 }, // at least one mantissa digit
    463      1.1  mrg     { ".e123",  1, NULL, (ios::fmtflags) 0 },
    464      1.1  mrg     { "+.e123", 2, NULL, (ios::fmtflags) 0 },
    465      1.1  mrg     { "-.e123", 2, NULL, (ios::fmtflags) 0 },
    466      1.1  mrg 
    467      1.1  mrg     { "123e",   4, NULL, (ios::fmtflags) 0 }, // at least one exponent digit
    468      1.1  mrg     { "123e-",  5, NULL, (ios::fmtflags) 0 },
    469      1.1  mrg     { "123e+",  5, NULL, (ios::fmtflags) 0 },
    470      1.1  mrg   };
    471      1.1  mrg 
    472      1.1  mrg   mpf_t      got, want;
    473  1.1.1.2  mrg   bool       got_ok, want_ok;
    474  1.1.1.2  mrg   bool       got_eof, want_eof;
    475      1.1  mrg   double     got_d, want_d;
    476      1.1  mrg   streampos  init_tellg, got_pos, want_pos;
    477      1.1  mrg 
    478      1.1  mrg   mpf_init (got);
    479      1.1  mrg   mpf_init (want);
    480      1.1  mrg 
    481      1.1  mrg   for (size_t i = 0; i < numberof (data); i++)
    482      1.1  mrg     {
    483  1.1.1.2  mrg       size_t input_length = strlen (data[i].input);
    484      1.1  mrg       want_pos = (data[i].want_pos == -1
    485  1.1.1.2  mrg                   ? input_length : data[i].want_pos);
    486  1.1.1.2  mrg       want_eof = (want_pos == streampos(input_length));
    487      1.1  mrg 
    488      1.1  mrg       want_ok = (data[i].want != NULL);
    489      1.1  mrg 
    490      1.1  mrg       if (data[i].want != NULL)
    491      1.1  mrg         mpf_set_str_or_abort (want, data[i].want, 0);
    492      1.1  mrg       else
    493      1.1  mrg         mpf_set_ui (want, 0L);
    494      1.1  mrg 
    495      1.1  mrg       want_d = mpf_get_d (want);
    496      1.1  mrg       if (option_check_standard && mpf_cmp_d (want, want_d) == 0)
    497      1.1  mrg         {
    498      1.1  mrg           istringstream  input (data[i].input);
    499      1.1  mrg           input.flags (data[i].flags);
    500      1.1  mrg           init_tellg = input.tellg();
    501      1.1  mrg 
    502      1.1  mrg           input >> got_d;
    503  1.1.1.2  mrg           got_ok = !input.fail();
    504  1.1.1.2  mrg           got_eof = input.eof();
    505      1.1  mrg           input.clear();
    506      1.1  mrg           got_pos = input.tellg() - init_tellg;
    507      1.1  mrg 
    508      1.1  mrg           if (got_ok != want_ok)
    509      1.1  mrg             {
    510      1.1  mrg               WRONG ("stdc++ operator>> wrong status, check_mpf");
    511      1.1  mrg               cout << "  want_ok: " << want_ok << "\n";
    512      1.1  mrg               cout << "  got_ok:  " << got_ok << "\n";
    513      1.1  mrg             }
    514      1.1  mrg           if (want_ok && want_d != got_d)
    515      1.1  mrg             {
    516      1.1  mrg               WRONG ("stdc++ operator>> wrong result, check_mpf");
    517      1.1  mrg               cout << "  got:   " << got_d << "\n";
    518      1.1  mrg               cout << "  want:  " << want_d << "\n";
    519      1.1  mrg             }
    520  1.1.1.2  mrg           if (want_ok && got_eof != want_eof)
    521  1.1.1.2  mrg             {
    522  1.1.1.2  mrg               WRONG ("stdc++ operator>> wrong EOF state, check_mpf");
    523  1.1.1.2  mrg               cout << "  got_eof:  " << got_eof << "\n";
    524  1.1.1.2  mrg               cout << "  want_eof: " << want_eof << "\n";
    525  1.1.1.2  mrg             }
    526      1.1  mrg           if (putback_tellg_works && got_pos != want_pos)
    527      1.1  mrg             {
    528      1.1  mrg               WRONG ("stdc++ operator>> wrong position, check_mpf");
    529      1.1  mrg               cout << "  want_pos: " << want_pos << "\n";
    530      1.1  mrg               cout << "  got_pos:  " << got_pos << "\n";
    531      1.1  mrg             }
    532      1.1  mrg         }
    533      1.1  mrg 
    534      1.1  mrg       {
    535      1.1  mrg         istringstream  input (data[i].input);
    536      1.1  mrg         input.flags (data[i].flags);
    537      1.1  mrg         init_tellg = input.tellg();
    538      1.1  mrg 
    539      1.1  mrg         mpf_set_ui (got, 0xDEAD);
    540      1.1  mrg         input >> got;
    541  1.1.1.2  mrg         got_ok = !input.fail();
    542  1.1.1.2  mrg 	got_eof = input.eof();
    543      1.1  mrg         input.clear();
    544      1.1  mrg         got_pos = input.tellg() - init_tellg;
    545      1.1  mrg 
    546      1.1  mrg         if (got_ok != want_ok)
    547      1.1  mrg           {
    548      1.1  mrg             WRONG ("mpf operator>> wrong status");
    549      1.1  mrg             cout << "  want_ok: " << want_ok << "\n";
    550      1.1  mrg             cout << "  got_ok:  " << got_ok << "\n";
    551      1.1  mrg             abort ();
    552      1.1  mrg           }
    553      1.1  mrg         if (want_ok && mpf_cmp (got, want) != 0)
    554      1.1  mrg           {
    555      1.1  mrg             WRONG ("mpf operator>> wrong result");
    556      1.1  mrg             mpf_trace ("  got ", got);
    557      1.1  mrg             mpf_trace ("  want", want);
    558      1.1  mrg             abort ();
    559      1.1  mrg           }
    560  1.1.1.2  mrg         if (want_ok && got_eof != want_eof)
    561  1.1.1.2  mrg           {
    562  1.1.1.2  mrg             WRONG ("mpf operator>> wrong EOF state");
    563  1.1.1.2  mrg             cout << "  want_eof: " << want_eof << "\n";
    564  1.1.1.2  mrg             cout << "  got_eof:  " << got_eof << "\n";
    565  1.1.1.2  mrg             abort ();
    566  1.1.1.2  mrg           }
    567      1.1  mrg         if (putback_tellg_works && got_pos != want_pos)
    568      1.1  mrg           {
    569      1.1  mrg             WRONG ("mpf operator>> wrong position");
    570      1.1  mrg             cout << "  want_pos: " << want_pos << "\n";
    571      1.1  mrg             cout << "  got_pos:  " << got_pos << "\n";
    572      1.1  mrg             abort ();
    573      1.1  mrg           }
    574      1.1  mrg       }
    575      1.1  mrg     }
    576      1.1  mrg 
    577      1.1  mrg   mpf_clear (got);
    578      1.1  mrg   mpf_clear (want);
    579      1.1  mrg }
    580      1.1  mrg 
    581      1.1  mrg 
    582      1.1  mrg 
    583      1.1  mrg int
    584      1.1  mrg main (int argc, char *argv[])
    585      1.1  mrg {
    586      1.1  mrg   if (argc > 1 && strcmp (argv[1], "-s") == 0)
    587  1.1.1.2  mrg     option_check_standard = true;
    588      1.1  mrg 
    589      1.1  mrg   tests_start ();
    590      1.1  mrg 
    591      1.1  mrg   check_putback_tellg ();
    592      1.1  mrg   check_mpz ();
    593      1.1  mrg   check_mpq ();
    594      1.1  mrg   check_mpf ();
    595      1.1  mrg 
    596      1.1  mrg   tests_end ();
    597      1.1  mrg   return 0;
    598      1.1  mrg }
    599