/* Test istream formatted input.
Copyright 2001-2004 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "gmp-impl.h"
#include "tests.h"
using namespace std;
// Under option_check_standard, the various test cases for mpz operator>>
// are put through the standard operator>> for long, and likewise mpf
// operator>> is put through double.
//
// In g++ 3.3 this results in some printouts about the final position
// indicated for something like ".e123". Our mpf code stops at the "e"
// since there's no mantissa digits, but g++ reads the whole thing and only
// then decides it's bad.
bool option_check_standard =
false ;
// On some versions of g++ 2.96 it's been observed that putback() may leave
// tellg() unchanged. We believe this is incorrect and presumably the
// result of a bug, since for instance it's ok in g++ 2.95 and g++ 3.3. We
// detect the problem at runtime and disable affected checks.
bool putback_tellg_works =
true ;
void
check_putback_tellg (
void )
{
istringstream input (
"hello" );
streampos old_pos, new_pos;
char c;
input.get(c);
old_pos = input.tellg();
input.putback(c);
new_pos = input.tellg();
if (old_pos == new_pos)
{
cout <<
"Warning, istringstream has a bug: putback() doesn't update tellg().\n" ;;
cout <<
"Tests on tellg() will be skipped.\n" ;
putback_tellg_works =
false ;
}
}
#define WRONG(str) \
do { \
cout << str
", data[" << i <<
"]\n" ; \
cout <<
" input: \" " << data[i].input << " \
"\n" ; \
cout <<
" flags: " << hex << input.flags() << dec <<
"\n" ; \
}
while (0)
void
check_mpz (
void )
{
static const struct {
const char *input;
int want_pos;
const char *want;
ios::fmtflags flags;
} data[] = {
{
"0" , -1,
"0" , (ios::fmtflags) 0 },
{
"123" , -1,
"123" , (ios::fmtflags) 0 },
{
"0123" , -1,
"83" , (ios::fmtflags) 0 },
{
"0x123" , -1,
"291" , (ios::fmtflags) 0 },
{
"-123" , -1,
"-123" , (ios::fmtflags) 0 },
{
"-0123" , -1,
"-83" , (ios::fmtflags) 0 },
{
"-0x123" , -1,
"-291" , (ios::fmtflags) 0 },
{
"+123" , -1,
"123" , (ios::fmtflags) 0 },
{
"+0123" , -1,
"83" , (ios::fmtflags) 0 },
{
"+0x123" , -1,
"291" , (ios::fmtflags) 0 },
{
"0" , -1,
"0" , ios::dec },
{
"1f" , 1,
"1" , ios::dec },
{
"011f" , 3,
"11" , ios::dec },
{
"123" , -1,
"123" , ios::dec },
{
"-1f" , 2,
"-1" , ios::dec },
{
"-011f" , 4,
"-11" , ios::dec },
{
"-123" , -1,
"-123" , ios::dec },
{
"+1f" , 2,
"1" , ios::dec },
{
"+011f" , 4,
"11" , ios::dec },
{
"+123" , -1,
"123" , ios::dec },
{
"0" , -1,
"0" , ios::oct },
{
"123" , -1,
"83" , ios::oct },
{
"-123" , -1,
"-83" , ios::oct },
{
"+123" , -1,
"83" , ios::oct },
{
"0" , -1,
"0" , ios::hex },
{
"123" , -1,
"291" , ios::hex },
{
"ff" , -1,
"255" , ios::hex },
{
"FF" , -1,
"255" , ios::hex },
{
"-123" , -1,
"-291" , ios::hex },
{
"-ff" , -1,
"-255" , ios::hex },
{
"-FF" , -1,
"-255" , ios::hex },
{
"+123" , -1,
"291" , ios::hex },
{
"+ff" , -1,
"255" , ios::hex },
{
"+FF" , -1,
"255" , ios::hex },
{
"ab" , -1,
"171" , ios::hex },
{
"cd" , -1,
"205" , ios::hex },
{
"ef" , -1,
"239" , ios::hex },
{
" 123" , 0, NULL, (ios::fmtflags) 0 },
// not without skipws
{
" 123" , -1,
"123" , ios::skipws },
};
mpz_t got, want;
bool got_ok, want_ok;
bool got_eof, want_eof;
long got_si, want_si;
streampos init_tellg, got_pos, want_pos;
mpz_init (got);
mpz_init (want);
for (size_t i = 0; i < numberof (data); i++)
{
size_t input_length = strlen (data[i].input);
want_pos = (data[i].want_pos == -1
? input_length : data[i].want_pos);
want_eof = (want_pos == streampos(input_length));
want_ok = (data[i].want != NULL);
if (data[i].want != NULL)
mpz_set_str_or_abort (want, data[i].want, 0);
else
mpz_set_ui (want, 0L);
if (option_check_standard && mpz_fits_slong_p (want))
{
istringstream input (data[i].input);
input.flags (data[i].flags);
init_tellg = input.tellg();
want_si = mpz_get_si (want);
input >> got_si;
got_ok = !input.fail();
got_eof = input.eof();
input.clear();
got_pos = input.tellg() - init_tellg;
if (got_ok != want_ok)
{
WRONG (
"stdc++ operator>> wrong status, check_mpz" );
cout <<
" want_ok: " << want_ok <<
"\n" ;
cout <<
" got_ok: " << got_ok <<
"\n" ;
}
if (want_ok && got_si != want_si)
{
WRONG (
"stdc++ operator>> wrong result, check_mpz" );
cout <<
" got_si: " << got_si <<
"\n" ;
cout <<
" want_si: " << want_si <<
"\n" ;
}
if (want_ok && got_eof != want_eof)
{
WRONG (
"stdc++ operator>> wrong EOF state, check_mpz" );
cout <<
" got_eof: " << got_eof <<
"\n" ;
cout <<
" want_eof: " << want_eof <<
"\n" ;
}
if (putback_tellg_works && got_pos != want_pos)
{
WRONG (
"stdc++ operator>> wrong position, check_mpz" );
cout <<
" want_pos: " << want_pos <<
"\n" ;
cout <<
" got_pos: " << got_pos <<
"\n" ;
}
}
{
istringstream input (data[i].input);
input.flags (data[i].flags);
init_tellg = input.tellg();
mpz_set_ui (got, 0xDEAD);
input >> got;
got_ok = !input.fail();
got_eof = input.eof();
input.clear();
got_pos = input.tellg() - init_tellg;
if (got_ok != want_ok)
{
WRONG (
"mpz operator>> wrong status" );
cout <<
" want_ok: " << want_ok <<
"\n" ;
cout <<
" got_ok: " << got_ok <<
"\n" ;
abort ();
}
if (want_ok && mpz_cmp (got, want) != 0)
{
WRONG (
"mpz operator>> wrong result" );
mpz_trace (
" got " , got);
mpz_trace (
" want" , want);
abort ();
}
if (want_ok && got_eof != want_eof)
{
WRONG (
"mpz operator>> wrong EOF state" );
cout <<
" want_eof: " << want_eof <<
"\n" ;
cout <<
" got_eof: " << got_eof <<
"\n" ;
abort ();
}
if (putback_tellg_works && got_pos != want_pos)
{
WRONG (
"mpz operator>> wrong position" );
cout <<
" want_pos: " << want_pos <<
"\n" ;
cout <<
" got_pos: " << got_pos <<
"\n" ;
abort ();
}
}
}
mpz_clear (got);
mpz_clear (want);
}
void
check_mpq (
void )
{
static const struct {
const char *input;
int want_pos;
const char *want;
ios::fmtflags flags;
} data[] = {
{
"0" , -1,
"0" , (ios::fmtflags) 0 },
{
"00" , -1,
"0" , (ios::fmtflags) 0 },
{
"0x0" , -1,
"0" , (ios::fmtflags) 0 },
{
"123/456" , -1,
"123/456" , ios::dec },
{
"0123/456" , -1,
"123/456" , ios::dec },
{
"123/0456" , -1,
"123/456" , ios::dec },
{
"0123/0456" , -1,
"123/456" , ios::dec },
{
"123/456" , -1,
"83/302" , ios::oct },
{
"0123/456" , -1,
"83/302" , ios::oct },
{
"123/0456" , -1,
"83/302" , ios::oct },
{
"0123/0456" , -1,
"83/302" , ios::oct },
{
"ab" , -1,
"171" , ios::hex },
{
"cd" , -1,
"205" , ios::hex },
{
"ef" , -1,
"239" , ios::hex },
{
"0/0" , -1,
"0/0" , (ios::fmtflags) 0 },
{
"5/8" , -1,
"5/8" , (ios::fmtflags) 0 },
{
"0x5/0x8" , -1,
"5/8" , (ios::fmtflags) 0 },
{
"123/456" , -1,
"123/456" , (ios::fmtflags) 0 },
{
"123/0456" , -1,
"123/302" , (ios::fmtflags) 0 },
{
"123/0x456" , -1,
"123/1110" , (ios::fmtflags) 0 },
{
"123/0X456" , -1,
"123/1110" , (ios::fmtflags) 0 },
{
"0123/123" , -1,
"83/123" , (ios::fmtflags) 0 },
{
"0123/0123" , -1,
"83/83" , (ios::fmtflags) 0 },
{
"0123/0x123" , -1,
"83/291" , (ios::fmtflags) 0 },
{
"0123/0X123" , -1,
"83/291" , (ios::fmtflags) 0 },
{
"0x123/123" , -1,
"291/123" , (ios::fmtflags) 0 },
{
"0X123/0123" , -1,
"291/83" , (ios::fmtflags) 0 },
{
"0x123/0x123" , -1,
"291/291" , (ios::fmtflags) 0 },
{
" 123" , 0, NULL, (ios::fmtflags) 0 },
// not without skipws
{
" 123" , -1,
"123" , ios::skipws },
{
"123 /456" , 3,
"123" , (ios::fmtflags) 0 },
{
"123/ 456" , 4, NULL, (ios::fmtflags) 0 },
{
"123/" , -1, NULL, (ios::fmtflags) 0 },
{
"123 /456" , 3,
"123" , ios::skipws },
{
"123/ 456" , 4, NULL, ios::skipws },
};
mpq_t got, want;
bool got_ok, want_ok;
bool got_eof, want_eof;
long got_si, want_si;
streampos init_tellg, got_pos, want_pos;
mpq_init (got);
mpq_init (want);
for (size_t i = 0; i < numberof (data); i++)
{
size_t input_length = strlen (data[i].input);
want_pos = (data[i].want_pos == -1
? input_length : data[i].want_pos);
want_eof = (want_pos == streampos(input_length));
want_ok = (data[i].want != NULL);
if (data[i].want != NULL)
mpq_set_str_or_abort (want, data[i].want, 0);
else
mpq_set_ui (want, 0L, 1L);
if (option_check_standard
&& mpz_fits_slong_p (mpq_numref(want))
&& mpz_cmp_ui (mpq_denref(want), 1L) == 0
&& strchr (data[i].input,
'/' ) == NULL)
{
istringstream input (data[i].input);
input.flags (data[i].flags);
init_tellg = input.tellg();
want_si = mpz_get_si (mpq_numref(want));
input >> got_si;
got_ok = !input.fail();
got_eof = input.eof();
input.clear();
got_pos = input.tellg() - init_tellg;
if (got_ok != want_ok)
{
WRONG (
"stdc++ operator>> wrong status, check_mpq" );
cout <<
" want_ok: " << want_ok <<
"\n" ;
cout <<
" got_ok: " << got_ok <<
"\n" ;
}
if (want_ok && want_si != got_si)
{
WRONG (
"stdc++ operator>> wrong result, check_mpq" );
cout <<
" got_si: " << got_si <<
"\n" ;
cout <<
" want_si: " << want_si <<
"\n" ;
}
if (want_ok && got_eof != want_eof)
{
WRONG (
"stdc++ operator>> wrong EOF state, check_mpq" );
cout <<
" got_eof: " << got_eof <<
"\n" ;
cout <<
" want_eof: " << want_eof <<
"\n" ;
}
if (putback_tellg_works && got_pos != want_pos)
{
WRONG (
"stdc++ operator>> wrong position, check_mpq" );
cout <<
" want_pos: " << want_pos <<
"\n" ;
cout <<
" got_pos: " << got_pos <<
"\n" ;
}
}
{
istringstream input (data[i].input);
input.flags (data[i].flags);
init_tellg = input.tellg();
mpq_set_si (got, 0xDEAD, 0xBEEF);
input >> got;
got_ok = !input.fail();
got_eof = input.eof();
input.clear();
got_pos = input.tellg() - init_tellg;
if (got_ok != want_ok)
{
WRONG (
"mpq operator>> wrong status" );
cout <<
" want_ok: " << want_ok <<
"\n" ;
cout <<
" got_ok: " << got_ok <<
"\n" ;
abort ();
}
// don't use mpq_equal, since we allow non-normalized values to be
// read, which can trigger ASSERTs in mpq_equal
if (want_ok && (mpz_cmp (mpq_numref (got), mpq_numref(want)) != 0
|| mpz_cmp (mpq_denref (got), mpq_denref(want)) != 0))
{
WRONG (
"mpq operator>> wrong result" );
mpq_trace (
" got " , got);
mpq_trace (
" want" , want);
abort ();
}
if (want_ok && got_eof != want_eof)
{
WRONG (
"mpq operator>> wrong EOF state" );
cout <<
" want_eof: " << want_eof <<
"\n" ;
cout <<
" got_eof: " << got_eof <<
"\n" ;
abort ();
}
if (putback_tellg_works && got_pos != want_pos)
{
WRONG (
"mpq operator>> wrong position" );
cout <<
" want_pos: " << want_pos <<
"\n" ;
cout <<
" got_pos: " << got_pos <<
"\n" ;
abort ();
}
}
}
mpq_clear (got);
mpq_clear (want);
}
void
check_mpf (
void )
{
static const struct {
const char *input;
int want_pos;
const char *want;
ios::fmtflags flags;
} data[] = {
{
"0" , -1,
"0" , (ios::fmtflags) 0 },
{
"+0" , -1,
"0" , (ios::fmtflags) 0 },
{
"-0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0." , -1,
"0" , (ios::fmtflags) 0 },
{
".0" , -1,
"0" , (ios::fmtflags) 0 },
{
"+.0" , -1,
"0" , (ios::fmtflags) 0 },
{
"-.0" , -1,
"0" , (ios::fmtflags) 0 },
{
"+0.00" , -1,
"0" , (ios::fmtflags) 0 },
{
"-0.000" , -1,
"0" , (ios::fmtflags) 0 },
{
"+0.00" , -1,
"0" , (ios::fmtflags) 0 },
{
"-0.000" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.0e0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.e0" , -1,
"0" , (ios::fmtflags) 0 },
{
".0e0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.0e-0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.e-0" , -1,
"0" , (ios::fmtflags) 0 },
{
".0e-0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.0e+0" , -1,
"0" , (ios::fmtflags) 0 },
{
"0.e+0" , -1,
"0" , (ios::fmtflags) 0 },
{
".0e+0" , -1,
"0" , (ios::fmtflags) 0 },
{
"1" , -1,
"1" , (ios::fmtflags) 0 },
{
"+1" , -1,
"1" , (ios::fmtflags) 0 },
{
"-1" , -1,
"-1" , (ios::fmtflags) 0 },
{
" 0" , 0, NULL, (ios::fmtflags) 0 },
// not without skipws
{
" 0" , -1,
"0" , ios::skipws },
{
" +0" , -1,
"0" , ios::skipws },
{
" -0" , -1,
"0" , ios::skipws },
{
"+-123" , 1, NULL, (ios::fmtflags) 0 },
{
"-+123" , 1, NULL, (ios::fmtflags) 0 },
{
"1e+-123" , 3, NULL, (ios::fmtflags) 0 },
{
"1e-+123" , 3, NULL, (ios::fmtflags) 0 },
{
"e123" , 0, NULL, (ios::fmtflags) 0 },
// at least one mantissa digit
{
".e123" , 1, NULL, (ios::fmtflags) 0 },
{
"+.e123" , 2, NULL, (ios::fmtflags) 0 },
{
"-.e123" , 2, NULL, (ios::fmtflags) 0 },
{
"123e" , 4, NULL, (ios::fmtflags) 0 },
// at least one exponent digit
{
"123e-" , 5, NULL, (ios::fmtflags) 0 },
{
"123e+" , 5, NULL, (ios::fmtflags) 0 },
};
mpf_t got, want;
bool got_ok, want_ok;
bool got_eof, want_eof;
double got_d, want_d;
streampos init_tellg, got_pos, want_pos;
mpf_init (got);
mpf_init (want);
for (size_t i = 0; i < numberof (data); i++)
{
size_t input_length = strlen (data[i].input);
want_pos = (data[i].want_pos == -1
? input_length : data[i].want_pos);
want_eof = (want_pos == streampos(input_length));
want_ok = (data[i].want != NULL);
if (data[i].want != NULL)
mpf_set_str_or_abort (want, data[i].want, 0);
else
mpf_set_ui (want, 0L);
want_d = mpf_get_d (want);
if (option_check_standard && mpf_cmp_d (want, want_d) == 0)
{
istringstream input (data[i].input);
input.flags (data[i].flags);
init_tellg = input.tellg();
input >> got_d;
got_ok = !input.fail();
got_eof = input.eof();
input.clear();
got_pos = input.tellg() - init_tellg;
if (got_ok != want_ok)
{
WRONG (
"stdc++ operator>> wrong status, check_mpf" );
cout <<
" want_ok: " << want_ok <<
"\n" ;
cout <<
" got_ok: " << got_ok <<
"\n" ;
}
if (want_ok && want_d != got_d)
{
WRONG (
"stdc++ operator>> wrong result, check_mpf" );
cout <<
" got: " << got_d <<
"\n" ;
cout <<
" want: " << want_d <<
"\n" ;
}
if (want_ok && got_eof != want_eof)
{
WRONG (
"stdc++ operator>> wrong EOF state, check_mpf" );
cout <<
" got_eof: " << got_eof <<
"\n" ;
cout <<
" want_eof: " << want_eof <<
"\n" ;
}
if (putback_tellg_works && got_pos != want_pos)
{
WRONG (
"stdc++ operator>> wrong position, check_mpf" );
cout <<
" want_pos: " << want_pos <<
"\n" ;
cout <<
" got_pos: " << got_pos <<
"\n" ;
}
}
{
istringstream input (data[i].input);
input.flags (data[i].flags);
init_tellg = input.tellg();
mpf_set_ui (got, 0xDEAD);
input >> got;
got_ok = !input.fail();
got_eof = input.eof();
input.clear();
got_pos = input.tellg() - init_tellg;
if (got_ok != want_ok)
{
WRONG (
"mpf operator>> wrong status" );
cout <<
" want_ok: " << want_ok <<
"\n" ;
cout <<
" got_ok: " << got_ok <<
"\n" ;
abort ();
}
if (want_ok && mpf_cmp (got, want) != 0)
{
WRONG (
"mpf operator>> wrong result" );
mpf_trace (
" got " , got);
mpf_trace (
" want" , want);
abort ();
}
if (want_ok && got_eof != want_eof)
{
WRONG (
"mpf operator>> wrong EOF state" );
cout <<
" want_eof: " << want_eof <<
"\n" ;
cout <<
" got_eof: " << got_eof <<
"\n" ;
abort ();
}
if (putback_tellg_works && got_pos != want_pos)
{
WRONG (
"mpf operator>> wrong position" );
cout <<
" want_pos: " << want_pos <<
"\n" ;
cout <<
" got_pos: " << got_pos <<
"\n" ;
abort ();
}
}
}
mpf_clear (got);
mpf_clear (want);
}
int
main (
int argc,
char *argv[])
{
if (argc > 1 && strcmp (argv[1],
"-s" ) == 0)
option_check_standard =
true ;
tests_start ();
check_putback_tellg ();
check_mpz ();
check_mpq ();
check_mpf ();
tests_end ();
return 0;
}
Messung V0.5 C=94 H=99 G=96
¤ Dauer der Verarbeitung: 0.8 Sekunden
¤
*© Formatika GbR, Deutschland