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