]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gmp/tests/cxx/t-istream.cc
Imported gcc-4.4.3
[msp430-gcc.git] / gmp / tests / cxx / t-istream.cc
diff --git a/gmp/tests/cxx/t-istream.cc b/gmp/tests/cxx/t-istream.cc
new file mode 100644 (file)
index 0000000..59600be
--- /dev/null
@@ -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 <iostream>
+#include <cstdlib>
+#include <cstring>
+
+#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;
+}