github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/cxx/t-istream.cc (about)

     1  /* Test istream formatted input.
     2  
     3  Copyright 2001-2004 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  #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  bool option_check_standard = false;
    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  bool putback_tellg_works = true;
    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 = false;
    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    bool       got_ok, want_ok;
   136    bool       got_eof, want_eof;
   137    long       got_si, want_si;
   138    streampos  init_tellg, got_pos, want_pos;
   139  
   140    mpz_init (got);
   141    mpz_init (want);
   142  
   143    for (size_t i = 0; i < numberof (data); i++)
   144      {
   145        size_t input_length = strlen (data[i].input);
   146        want_pos = (data[i].want_pos == -1
   147                    ? input_length : data[i].want_pos);
   148        want_eof = (want_pos == streampos(input_length));
   149  
   150        want_ok = (data[i].want != NULL);
   151  
   152        if (data[i].want != NULL)
   153          mpz_set_str_or_abort (want, data[i].want, 0);
   154        else
   155          mpz_set_ui (want, 0L);
   156  
   157        if (option_check_standard && mpz_fits_slong_p (want))
   158          {
   159            istringstream  input (data[i].input);
   160            input.flags (data[i].flags);
   161            init_tellg = input.tellg();
   162            want_si = mpz_get_si (want);
   163  
   164            input >> got_si;
   165            got_ok = !input.fail();
   166            got_eof = input.eof();
   167            input.clear();
   168            got_pos = input.tellg() - init_tellg;
   169  
   170            if (got_ok != want_ok)
   171              {
   172                WRONG ("stdc++ operator>> wrong status, check_mpz");
   173                cout << "  want_ok: " << want_ok << "\n";
   174                cout << "  got_ok:  " << got_ok << "\n";
   175              }
   176            if (want_ok && got_si != want_si)
   177              {
   178                WRONG ("stdc++ operator>> wrong result, check_mpz");
   179                cout << "  got_si:  " << got_si << "\n";
   180                cout << "  want_si: " << want_si << "\n";
   181              }
   182            if (want_ok && got_eof != want_eof)
   183              {
   184                WRONG ("stdc++ operator>> wrong EOF state, check_mpz");
   185                cout << "  got_eof:  " << got_eof << "\n";
   186                cout << "  want_eof: " << want_eof << "\n";
   187              }
   188            if (putback_tellg_works && got_pos != want_pos)
   189              {
   190                WRONG ("stdc++ operator>> wrong position, check_mpz");
   191                cout << "  want_pos: " << want_pos << "\n";
   192                cout << "  got_pos:  " << got_pos << "\n";
   193              }
   194          }
   195  
   196        {
   197          istringstream  input (data[i].input);
   198          input.flags (data[i].flags);
   199          init_tellg = input.tellg();
   200  
   201          mpz_set_ui (got, 0xDEAD);
   202          input >> got;
   203          got_ok = !input.fail();
   204  	got_eof = input.eof();
   205          input.clear();
   206          got_pos = input.tellg() - init_tellg;
   207  
   208          if (got_ok != want_ok)
   209            {
   210              WRONG ("mpz operator>> wrong status");
   211              cout << "  want_ok: " << want_ok << "\n";
   212              cout << "  got_ok:  " << got_ok << "\n";
   213              abort ();
   214            }
   215          if (want_ok && mpz_cmp (got, want) != 0)
   216            {
   217              WRONG ("mpz operator>> wrong result");
   218              mpz_trace ("  got ", got);
   219              mpz_trace ("  want", want);
   220              abort ();
   221            }
   222          if (want_ok && got_eof != want_eof)
   223            {
   224              WRONG ("mpz operator>> wrong EOF state");
   225              cout << "  want_eof: " << want_eof << "\n";
   226              cout << "  got_eof:  " << got_eof << "\n";
   227              abort ();
   228            }
   229          if (putback_tellg_works && got_pos != want_pos)
   230            {
   231              WRONG ("mpz operator>> wrong position");
   232              cout << "  want_pos: " << want_pos << "\n";
   233              cout << "  got_pos:  " << got_pos << "\n";
   234              abort ();
   235            }
   236        }
   237      }
   238  
   239    mpz_clear (got);
   240    mpz_clear (want);
   241  }
   242  
   243  void
   244  check_mpq (void)
   245  {
   246    static const struct {
   247      const char     *input;
   248      int            want_pos;
   249      const char     *want;
   250      ios::fmtflags  flags;
   251  
   252    } data[] = {
   253  
   254      { "0",   -1, "0", (ios::fmtflags) 0 },
   255      { "00",  -1, "0", (ios::fmtflags) 0 },
   256      { "0x0", -1, "0", (ios::fmtflags) 0 },
   257  
   258      { "123/456",   -1, "123/456", ios::dec },
   259      { "0123/456",  -1, "123/456", ios::dec },
   260      { "123/0456",  -1, "123/456", ios::dec },
   261      { "0123/0456", -1, "123/456", ios::dec },
   262  
   263      { "123/456",   -1, "83/302", ios::oct },
   264      { "0123/456",  -1, "83/302", ios::oct },
   265      { "123/0456",  -1, "83/302", ios::oct },
   266      { "0123/0456", -1, "83/302", ios::oct },
   267  
   268      { "ab",   -1, "171",  ios::hex },
   269      { "cd",   -1, "205",  ios::hex },
   270      { "ef",   -1, "239",  ios::hex },
   271  
   272      { "0/0",     -1, "0/0", (ios::fmtflags) 0 },
   273      { "5/8",     -1, "5/8", (ios::fmtflags) 0 },
   274      { "0x5/0x8", -1, "5/8", (ios::fmtflags) 0 },
   275  
   276      { "123/456",   -1, "123/456",  (ios::fmtflags) 0 },
   277      { "123/0456",  -1, "123/302",  (ios::fmtflags) 0 },
   278      { "123/0x456", -1, "123/1110", (ios::fmtflags) 0 },
   279      { "123/0X456", -1, "123/1110", (ios::fmtflags) 0 },
   280  
   281      { "0123/123",   -1, "83/123", (ios::fmtflags) 0 },
   282      { "0123/0123",  -1, "83/83",  (ios::fmtflags) 0 },
   283      { "0123/0x123", -1, "83/291", (ios::fmtflags) 0 },
   284      { "0123/0X123", -1, "83/291", (ios::fmtflags) 0 },
   285  
   286      { "0x123/123",   -1, "291/123", (ios::fmtflags) 0 },
   287      { "0X123/0123",  -1, "291/83",  (ios::fmtflags) 0 },
   288      { "0x123/0x123", -1, "291/291", (ios::fmtflags) 0 },
   289  
   290      { " 123",  0, NULL,  (ios::fmtflags) 0 },   // not without skipws
   291      { " 123", -1, "123", ios::skipws },
   292  
   293      { "123 /456",    3, "123",  (ios::fmtflags) 0 },
   294      { "123/ 456",    4,  NULL,  (ios::fmtflags) 0 },
   295      { "123/"    ,   -1,  NULL,  (ios::fmtflags) 0 },
   296      { "123 /456",    3, "123",  ios::skipws },
   297      { "123/ 456",    4,  NULL,  ios::skipws },
   298    };
   299  
   300    mpq_t      got, want;
   301    bool       got_ok, want_ok;
   302    bool       got_eof, want_eof;
   303    long       got_si, want_si;
   304    streampos  init_tellg, got_pos, want_pos;
   305  
   306    mpq_init (got);
   307    mpq_init (want);
   308  
   309    for (size_t i = 0; i < numberof (data); i++)
   310      {
   311        size_t input_length = strlen (data[i].input);
   312        want_pos = (data[i].want_pos == -1
   313                    ? input_length : data[i].want_pos);
   314        want_eof = (want_pos == streampos(input_length));
   315  
   316        want_ok = (data[i].want != NULL);
   317  
   318        if (data[i].want != NULL)
   319          mpq_set_str_or_abort (want, data[i].want, 0);
   320        else
   321          mpq_set_ui (want, 0L, 1L);
   322  
   323        if (option_check_standard
   324            && mpz_fits_slong_p (mpq_numref(want))
   325            && mpz_cmp_ui (mpq_denref(want), 1L) == 0
   326            && strchr (data[i].input, '/') == NULL)
   327          {
   328            istringstream  input (data[i].input);
   329            input.flags (data[i].flags);
   330            init_tellg = input.tellg();
   331            want_si = mpz_get_si (mpq_numref(want));
   332  
   333            input >> got_si;
   334            got_ok = !input.fail();
   335            got_eof = input.eof();
   336            input.clear();
   337            got_pos = input.tellg() - init_tellg;
   338  
   339            if (got_ok != want_ok)
   340              {
   341                WRONG ("stdc++ operator>> wrong status, check_mpq");
   342                cout << "  want_ok: " << want_ok << "\n";
   343                cout << "  got_ok:  " << got_ok << "\n";
   344              }
   345            if (want_ok && want_si != got_si)
   346              {
   347                WRONG ("stdc++ operator>> wrong result, check_mpq");
   348                cout << "  got_si:  " << got_si << "\n";
   349                cout << "  want_si: " << want_si << "\n";
   350              }
   351            if (want_ok && got_eof != want_eof)
   352              {
   353                WRONG ("stdc++ operator>> wrong EOF state, check_mpq");
   354                cout << "  got_eof:  " << got_eof << "\n";
   355                cout << "  want_eof: " << want_eof << "\n";
   356              }
   357            if (putback_tellg_works && got_pos != want_pos)
   358              {
   359                WRONG ("stdc++ operator>> wrong position, check_mpq");
   360                cout << "  want_pos: " << want_pos << "\n";
   361                cout << "  got_pos:  " << got_pos << "\n";
   362              }
   363          }
   364  
   365        {
   366          istringstream  input (data[i].input);
   367          input.flags (data[i].flags);
   368          init_tellg = input.tellg();
   369          mpq_set_si (got, 0xDEAD, 0xBEEF);
   370  
   371          input >> got;
   372          got_ok = !input.fail();
   373  	got_eof = input.eof();
   374          input.clear();
   375          got_pos = input.tellg() - init_tellg;
   376  
   377          if (got_ok != want_ok)
   378            {
   379              WRONG ("mpq operator>> wrong status");
   380              cout << "  want_ok: " << want_ok << "\n";
   381              cout << "  got_ok:  " << got_ok << "\n";
   382              abort ();
   383            }
   384          // don't use mpq_equal, since we allow non-normalized values to be
   385          // read, which can trigger ASSERTs in mpq_equal
   386          if (want_ok && (mpz_cmp (mpq_numref (got), mpq_numref(want)) != 0
   387                          || mpz_cmp (mpq_denref (got), mpq_denref(want)) != 0))
   388            {
   389              WRONG ("mpq operator>> wrong result");
   390              mpq_trace ("  got ", got);
   391              mpq_trace ("  want", want);
   392              abort ();
   393            }
   394          if (want_ok && got_eof != want_eof)
   395            {
   396              WRONG ("mpq operator>> wrong EOF state");
   397              cout << "  want_eof: " << want_eof << "\n";
   398              cout << "  got_eof:  " << got_eof << "\n";
   399              abort ();
   400            }
   401          if (putback_tellg_works && got_pos != want_pos)
   402            {
   403              WRONG ("mpq operator>> wrong position");
   404              cout << "  want_pos: " << want_pos << "\n";
   405              cout << "  got_pos:  " << got_pos << "\n";
   406              abort ();
   407            }
   408        }
   409      }
   410  
   411    mpq_clear (got);
   412    mpq_clear (want);
   413  }
   414  
   415  
   416  void
   417  check_mpf (void)
   418  {
   419    static const struct {
   420      const char     *input;
   421      int            want_pos;
   422      const char     *want;
   423      ios::fmtflags  flags;
   424  
   425    } data[] = {
   426  
   427      { "0",      -1, "0", (ios::fmtflags) 0 },
   428      { "+0",     -1, "0", (ios::fmtflags) 0 },
   429      { "-0",     -1, "0", (ios::fmtflags) 0 },
   430      { "0.0",    -1, "0", (ios::fmtflags) 0 },
   431      { "0.",     -1, "0", (ios::fmtflags) 0 },
   432      { ".0",     -1, "0", (ios::fmtflags) 0 },
   433      { "+.0",    -1, "0", (ios::fmtflags) 0 },
   434      { "-.0",    -1, "0", (ios::fmtflags) 0 },
   435      { "+0.00",  -1, "0", (ios::fmtflags) 0 },
   436      { "-0.000", -1, "0", (ios::fmtflags) 0 },
   437      { "+0.00",  -1, "0", (ios::fmtflags) 0 },
   438      { "-0.000", -1, "0", (ios::fmtflags) 0 },
   439      { "0.0e0",  -1, "0", (ios::fmtflags) 0 },
   440      { "0.e0",   -1, "0", (ios::fmtflags) 0 },
   441      { ".0e0",   -1, "0", (ios::fmtflags) 0 },
   442      { "0.0e-0", -1, "0", (ios::fmtflags) 0 },
   443      { "0.e-0",  -1, "0", (ios::fmtflags) 0 },
   444      { ".0e-0",  -1, "0", (ios::fmtflags) 0 },
   445      { "0.0e+0", -1, "0", (ios::fmtflags) 0 },
   446      { "0.e+0",  -1, "0", (ios::fmtflags) 0 },
   447      { ".0e+0",  -1, "0", (ios::fmtflags) 0 },
   448  
   449      { "1",  -1,  "1", (ios::fmtflags) 0 },
   450      { "+1", -1,  "1", (ios::fmtflags) 0 },
   451      { "-1", -1, "-1", (ios::fmtflags) 0 },
   452  
   453      { " 0",  0,  NULL, (ios::fmtflags) 0 },  // not without skipws
   454      { " 0",  -1, "0", ios::skipws },
   455      { " +0", -1, "0", ios::skipws },
   456      { " -0", -1, "0", ios::skipws },
   457  
   458      { "+-123", 1, NULL, (ios::fmtflags) 0 },
   459      { "-+123", 1, NULL, (ios::fmtflags) 0 },
   460      { "1e+-123", 3, NULL, (ios::fmtflags) 0 },
   461      { "1e-+123", 3, NULL, (ios::fmtflags) 0 },
   462  
   463      { "e123",   0, NULL, (ios::fmtflags) 0 }, // at least one mantissa digit
   464      { ".e123",  1, NULL, (ios::fmtflags) 0 },
   465      { "+.e123", 2, NULL, (ios::fmtflags) 0 },
   466      { "-.e123", 2, NULL, (ios::fmtflags) 0 },
   467  
   468      { "123e",   4, NULL, (ios::fmtflags) 0 }, // at least one exponent digit
   469      { "123e-",  5, NULL, (ios::fmtflags) 0 },
   470      { "123e+",  5, NULL, (ios::fmtflags) 0 },
   471    };
   472  
   473    mpf_t      got, want;
   474    bool       got_ok, want_ok;
   475    bool       got_eof, want_eof;
   476    double     got_d, want_d;
   477    streampos  init_tellg, got_pos, want_pos;
   478  
   479    mpf_init (got);
   480    mpf_init (want);
   481  
   482    for (size_t i = 0; i < numberof (data); i++)
   483      {
   484        size_t input_length = strlen (data[i].input);
   485        want_pos = (data[i].want_pos == -1
   486                    ? input_length : data[i].want_pos);
   487        want_eof = (want_pos == streampos(input_length));
   488  
   489        want_ok = (data[i].want != NULL);
   490  
   491        if (data[i].want != NULL)
   492          mpf_set_str_or_abort (want, data[i].want, 0);
   493        else
   494          mpf_set_ui (want, 0L);
   495  
   496        want_d = mpf_get_d (want);
   497        if (option_check_standard && mpf_cmp_d (want, want_d) == 0)
   498          {
   499            istringstream  input (data[i].input);
   500            input.flags (data[i].flags);
   501            init_tellg = input.tellg();
   502  
   503            input >> got_d;
   504            got_ok = !input.fail();
   505            got_eof = input.eof();
   506            input.clear();
   507            got_pos = input.tellg() - init_tellg;
   508  
   509            if (got_ok != want_ok)
   510              {
   511                WRONG ("stdc++ operator>> wrong status, check_mpf");
   512                cout << "  want_ok: " << want_ok << "\n";
   513                cout << "  got_ok:  " << got_ok << "\n";
   514              }
   515            if (want_ok && want_d != got_d)
   516              {
   517                WRONG ("stdc++ operator>> wrong result, check_mpf");
   518                cout << "  got:   " << got_d << "\n";
   519                cout << "  want:  " << want_d << "\n";
   520              }
   521            if (want_ok && got_eof != want_eof)
   522              {
   523                WRONG ("stdc++ operator>> wrong EOF state, check_mpf");
   524                cout << "  got_eof:  " << got_eof << "\n";
   525                cout << "  want_eof: " << want_eof << "\n";
   526              }
   527            if (putback_tellg_works && got_pos != want_pos)
   528              {
   529                WRONG ("stdc++ operator>> wrong position, check_mpf");
   530                cout << "  want_pos: " << want_pos << "\n";
   531                cout << "  got_pos:  " << got_pos << "\n";
   532              }
   533          }
   534  
   535        {
   536          istringstream  input (data[i].input);
   537          input.flags (data[i].flags);
   538          init_tellg = input.tellg();
   539  
   540          mpf_set_ui (got, 0xDEAD);
   541          input >> got;
   542          got_ok = !input.fail();
   543  	got_eof = input.eof();
   544          input.clear();
   545          got_pos = input.tellg() - init_tellg;
   546  
   547          if (got_ok != want_ok)
   548            {
   549              WRONG ("mpf operator>> wrong status");
   550              cout << "  want_ok: " << want_ok << "\n";
   551              cout << "  got_ok:  " << got_ok << "\n";
   552              abort ();
   553            }
   554          if (want_ok && mpf_cmp (got, want) != 0)
   555            {
   556              WRONG ("mpf operator>> wrong result");
   557              mpf_trace ("  got ", got);
   558              mpf_trace ("  want", want);
   559              abort ();
   560            }
   561          if (want_ok && got_eof != want_eof)
   562            {
   563              WRONG ("mpf operator>> wrong EOF state");
   564              cout << "  want_eof: " << want_eof << "\n";
   565              cout << "  got_eof:  " << got_eof << "\n";
   566              abort ();
   567            }
   568          if (putback_tellg_works && got_pos != want_pos)
   569            {
   570              WRONG ("mpf operator>> wrong position");
   571              cout << "  want_pos: " << want_pos << "\n";
   572              cout << "  got_pos:  " << got_pos << "\n";
   573              abort ();
   574            }
   575        }
   576      }
   577  
   578    mpf_clear (got);
   579    mpf_clear (want);
   580  }
   581  
   582  
   583  
   584  int
   585  main (int argc, char *argv[])
   586  {
   587    if (argc > 1 && strcmp (argv[1], "-s") == 0)
   588      option_check_standard = true;
   589  
   590    tests_start ();
   591  
   592    check_putback_tellg ();
   593    check_mpz ();
   594    check_mpq ();
   595    check_mpf ();
   596  
   597    tests_end ();
   598    return 0;
   599  }