X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gmp%2Ftests%2Fcxx%2Ft-istream.cc;fp=gmp%2Ftests%2Fcxx%2Ft-istream.cc;h=59600be16695e21c37f33c39d334787c9359aa5a;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gmp/tests/cxx/t-istream.cc b/gmp/tests/cxx/t-istream.cc new file mode 100644 index 00000000..59600be1 --- /dev/null +++ b/gmp/tests/cxx/t-istream.cc @@ -0,0 +1,538 @@ +/* Test istream formatted input. + +Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser 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 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include +#include +#include + +#include "gmp.h" +#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. + +int option_check_standard = 0; + + +// 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. + +int putback_tellg_works = 1; + +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 = 0; + } +} + + +#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; + int got_ok, want_ok; + 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++) + { + want_pos = (data[i].want_pos == -1 + ? strlen (data[i].input) : data[i].want_pos); + + 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 ? 1 : 0); + 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 (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 ? 1 : 0); + 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 (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 }, + }; + + mpq_t got, want; + int got_ok, want_ok; + 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++) + { + want_pos = (data[i].want_pos == -1 + ? strlen (data[i].input) : data[i].want_pos); + + 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) + { + 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 ? 1 : 0); + 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 (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 ? 1 : 0); + 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 (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; + int got_ok, want_ok; + 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++) + { + want_pos = (data[i].want_pos == -1 + ? strlen (data[i].input) : data[i].want_pos); + + 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 ? 1 : 0); + 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 (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 ? 1 : 0); + 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 (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 = 1; + + tests_start (); + + check_putback_tellg (); + check_mpz (); + check_mpq (); + check_mpf (); + + tests_end (); + return 0; +}