/* tsprintf.c -- test file for mpfr_sprintf, mpfr_vsprintf, mpfr_snprintf, and mpfr_vsnprintf Copyright 2007-2015 Free Software Foundation, Inc. Contributed by the AriC and Caramel projects, INRIA. This file is part of the GNU MPFR Library. The GNU MPFR 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 MPFR 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 MPFR Library; see the file COPYING.LESSER. If not, see http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_STDARG #include #include #include #ifdef HAVE_LOCALE_H #include #endif #include "mpfr-test.h" #if MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0) const int prec_max_printf = 5000; /* limit for random precision in random_double() */ #define BUF_SIZE 65536 const char pinf_str[] = "inf"; const char pinf_uc_str[] = "INF"; const char minf_str[] = "-inf"; const char minf_uc_str[] = "-INF"; const char nan_str[] = "nan"; const char nan_uc_str[] = "NAN"; /* 1. compare expected string with the string BUFFER returned by mpfr_sprintf(buffer, fmt, x) 2. then test mpfr_snprintf (buffer, p, fmt, x) with a random p. */ static int check_sprintf (const char *expected, const char *fmt, mpfr_srcptr x) { int n0, n1, p; char buffer[BUF_SIZE]; /* test mpfr_sprintf */ n0 = mpfr_sprintf (buffer, fmt, x); if (strcmp (buffer, expected) != 0) { printf ("Error in mpfr_sprintf (s, \"%s\", x);\n", fmt); printf ("expected: \"%s\"\ngot: \"%s\"\n", expected, buffer); exit (1); } /* test mpfr_snprintf */ p = (int) (randlimb () % n0); if (p == 0 && (randlimb () & 1) == 0) { n1 = mpfr_snprintf (NULL, 0, fmt, x); } else { buffer[p] = 17; n1 = mpfr_snprintf (buffer, p, fmt, x); if (buffer[p] != 17) { printf ("Buffer overflow in mpfr_snprintf for p = %d!\n", p); exit (1); } } if (n0 != n1) { printf ("Error in mpfr_snprintf (s, %d, \"%s\", x) return value\n", p, fmt); printf ("expected: %d\ngot: %d\n", n0, n1); exit (1); } if ((p > 1 && strncmp (expected, buffer, p-1) != 0) || (p == 1 && buffer[0] != '\0')) { char part_expected[BUF_SIZE]; strncpy (part_expected, expected, p); part_expected[p-1] = '\0'; printf ("Error in mpfr_vsnprintf (s, %d, \"%s\", ...);\n", p, fmt); printf ("expected: \"%s\"\ngot: \"%s\"\n", part_expected, buffer); exit (1); } return n0; } /* 1. compare expected string with the string BUFFER returned by mpfr_vsprintf(buffer, fmt, ...) 2. then, test mpfr_vsnprintf. */ static int check_vsprintf (const char *expected, const char *fmt, ...) { int n0, n1, p; char buffer[BUF_SIZE]; va_list ap0, ap1; va_start (ap0, fmt); va_start (ap1, fmt); n0 = mpfr_vsprintf (buffer, fmt, ap0); if (strcmp (buffer, expected) != 0) { printf ("Error in mpfr_vsprintf (s, \"%s\", ...);\n", fmt); printf ("expected: \"%s\"\ngot: \"%s\"\n", expected, buffer); va_end (ap0); va_end (ap1); exit (1); } va_end (ap0); /* test mpfr_snprintf */ p = (int) (randlimb () % n0); if (p == 0 && (randlimb () & 1) == 0) { n1 = mpfr_vsnprintf (NULL, 0, fmt, ap1); } else { buffer[p] = 17; n1 = mpfr_vsnprintf (buffer, p, fmt, ap1); if (buffer[p] != 17) { printf ("Buffer overflow in mpfr_vsnprintf for p = %d!\n", p); exit (1); } } if (n0 != n1) { printf ("Error in mpfr_vsnprintf (s, %d, \"%s\", ...) return value\n", p, fmt); printf ("expected: %d\ngot: %d\n", n0, n1); va_end (ap1); exit (1); } if ((p > 1 && strncmp (expected, buffer, p-1) != 0) || (p == 1 && buffer[0] != '\0')) { char part_expected[BUF_SIZE]; strncpy (part_expected, expected, p); part_expected[p-1] = '\0'; printf ("Error in mpfr_vsnprintf (s, %d, \"%s\", ...);\n", p, fmt); printf ("expected: \"%s\"\ngot: \"%s\"\n", part_expected, buffer); va_end (ap1); exit (1); } va_end (ap1); return n0; } static void native_types (void) { int c = 'a'; int i = -1; unsigned int ui = 1; double d = -1.25; char s[] = "test"; char buf[255]; sprintf (buf, "%c", c); check_vsprintf (buf, "%c", c); sprintf (buf, "%d", i); check_vsprintf (buf, "%d", i); sprintf (buf, "%e", d); check_vsprintf (buf, "%e", d); sprintf (buf, "%f", d); check_vsprintf (buf, "%f", d); sprintf (buf, "%i", i); check_vsprintf (buf, "%i", i); sprintf (buf, "%g", d); check_vsprintf (buf, "%g", d); sprintf (buf, "%o", i); check_vsprintf (buf, "%o", i); sprintf (buf, "%s", s); check_vsprintf (buf, "%s", s); sprintf (buf, "--%s++", ""); check_vsprintf (buf, "--%s++", ""); sprintf (buf, "%u", ui); check_vsprintf (buf, "%u", ui); sprintf (buf, "%x", ui); check_vsprintf (buf, "%x", ui); } static int decimal (void) { mpfr_prec_t p = 128; mpfr_t x; mpfr_t z; mpfr_init (z); mpfr_init2 (x, p); /* specifier 'P' for precision */ check_vsprintf ("128", "%Pu", p); check_vsprintf ("00128", "%.5Pu", p); /* special numbers */ mpfr_set_inf (x, 1); check_sprintf (pinf_str, "%Re", x); check_sprintf (pinf_str, "%RUe", x); check_sprintf (pinf_uc_str, "%RE", x); check_sprintf (pinf_uc_str, "%RDE", x); check_sprintf (pinf_str, "%Rf", x); check_sprintf (pinf_str, "%RYf", x); check_sprintf (pinf_uc_str, "%RF", x); check_sprintf (pinf_uc_str, "%RZF", x); check_sprintf (pinf_str, "%Rg", x); check_sprintf (pinf_str, "%RNg", x); check_sprintf (pinf_uc_str, "%RG", x); check_sprintf (pinf_uc_str, "%RUG", x); check_sprintf (" inf", "%010Re", x); check_sprintf (" inf", "%010RDe", x); mpfr_set_inf (x, -1); check_sprintf (minf_str, "%Re", x); check_sprintf (minf_str, "%RYe", x); check_sprintf (minf_uc_str, "%RE", x); check_sprintf (minf_uc_str, "%RZE", x); check_sprintf (minf_str, "%Rf", x); check_sprintf (minf_str, "%RNf", x); check_sprintf (minf_uc_str, "%RF", x); check_sprintf (minf_uc_str, "%RUF", x); check_sprintf (minf_str, "%Rg", x); check_sprintf (minf_str, "%RDg", x); check_sprintf (minf_uc_str, "%RG", x); check_sprintf (minf_uc_str, "%RYG", x); check_sprintf (" -inf", "%010Re", x); check_sprintf (" -inf", "%010RZe", x); mpfr_set_nan (x); check_sprintf (nan_str, "%Re", x); check_sprintf (nan_str, "%RNe", x); check_sprintf (nan_uc_str, "%RE", x); check_sprintf (nan_uc_str, "%RUE", x); check_sprintf (nan_str, "%Rf", x); check_sprintf (nan_str, "%RDf", x); check_sprintf (nan_uc_str, "%RF", x); check_sprintf (nan_uc_str, "%RYF", x); check_sprintf (nan_str, "%Rg", x); check_sprintf (nan_str, "%RZg", x); check_sprintf (nan_uc_str, "%RG", x); check_sprintf (nan_uc_str, "%RNG", x); check_sprintf (" nan", "%010Re", x); /* positive numbers */ mpfr_set_str (x, "18993474.61279296875", 10, MPFR_RNDN); mpfr_set_ui (z, 0, MPFR_RNDD); /* simplest case right justified */ check_sprintf (" 1.899347461279296875e+07", "%30Re", x); check_sprintf (" 2e+07", "%30.0Re", x); check_sprintf (" 18993474.612793", "%30Rf", x); check_sprintf (" 18993474.6127930", "%30.7Rf", x); check_sprintf (" 1.89935e+07", "%30Rg", x); check_sprintf (" 2e+07", "%30.0Rg", x); check_sprintf (" 18993474.61279296875", "%30.19Rg", x); check_sprintf (" 0e+00", "%30.0Re", z); check_sprintf (" 0", "%30.0Rf", z); check_sprintf (" 0.0000", "%30.4Rf", z); check_sprintf (" 0", "%30.0Rg", z); check_sprintf (" 0", "%30.4Rg", z); /* sign or space, pad with leading zeros */ check_sprintf (" 000001.899347461279296875E+07", "% 030RE", x); check_sprintf (" 0000000000000000001.89935E+07", "% 030RG", x); check_sprintf (" 0000000000000000000000002E+07", "% 030.0RE", x); check_sprintf (" 0000000000000000000000000E+00", "% 030.0RE", z); check_sprintf (" 00000000000000000000000000000", "% 030.0RF", z); /* sign + or -, left justified */ check_sprintf ("+1.899347461279296875e+07 ", "%+-30Re", x); check_sprintf ("+2e+07 ", "%+-30.0Re", x); check_sprintf ("+0e+00 ", "%+-30.0Re", z); check_sprintf ("+0 ", "%+-30.0Rf", z); /* decimal point, left justified, precision and rounding parameter */ check_vsprintf ("1.9E+07 ", "%#-10.*R*E", 1, MPFR_RNDN, x); check_vsprintf ("2.E+07 ", "%#*.*R*E", -10, 0, MPFR_RNDN, x); check_vsprintf ("2.E+07 ", "%#-10.*R*G", 0, MPFR_RNDN, x); check_vsprintf ("0.E+00 ", "%#-10.*R*E", 0, MPFR_RNDN, z); check_vsprintf ("0. ", "%#-10.*R*F", 0, MPFR_RNDN, z); check_vsprintf ("0. ", "%#-10.*R*G", 0, MPFR_RNDN, z); /* sign or space */ check_sprintf (" 1.899e+07", "% .3RNe", x); check_sprintf (" 2e+07", "% .0RNe", x); /* sign + or -, decimal point, pad with leading zeros */ check_sprintf ("+0001.8E+07", "%0+#11.1RZE", x); check_sprintf ("+00001.E+07", "%0+#11.0RZE", x); check_sprintf ("+0000.0E+00", "%0+#11.1RZE", z); check_sprintf ("+00000000.0", "%0+#11.1RZF", z); /* pad with leading zero */ check_sprintf ("0000001.899347461279296875e+07", "%030RDe", x); check_sprintf ("00000000000000000000000001e+07", "%030.0RDe", x); /* sign or space, decimal point, left justified */ check_sprintf (" 1.8E+07 ", "%- #11.1RDE", x); check_sprintf (" 1.E+07 ", "%- #11.0RDE", x); /* negative numbers */ mpfr_mul_si (x, x, -1, MPFR_RNDD); mpfr_mul_si (z, z, -1, MPFR_RNDD); /* sign + or - */ check_sprintf (" -1.8e+07", "%+10.1RUe", x); check_sprintf (" -1e+07", "%+10.0RUe", x); check_sprintf (" -0e+00", "%+10.0RUe", z); check_sprintf (" -0", "%+10.0RUf", z); /* neighborhood of 1 */ mpfr_set_str (x, "0.99993896484375", 10, MPFR_RNDN); check_sprintf ("9.9993896484375E-01 ", "%-20RE", x); check_sprintf ("9.9993896484375E-01 ", "%-20.RE", x); check_sprintf ("1E+00 ", "%-20.0RE", x); check_sprintf ("1.0E+00 ", "%-20.1RE", x); check_sprintf ("1.00E+00 ", "%-20.2RE", x); check_sprintf ("9.999E-01 ", "%-20.3RE", x); check_sprintf ("9.9994E-01 ", "%-20.4RE", x); check_sprintf ("0.999939 ", "%-20RF", x); check_sprintf ("0.999939 ", "%-20.RF", x); check_sprintf ("1 ", "%-20.0RF", x); check_sprintf ("1.0 ", "%-20.1RF", x); check_sprintf ("1.00 ", "%-20.2RF", x); check_sprintf ("1.000 ", "%-20.3RF", x); check_sprintf ("0.9999 ", "%-20.4RF", x); check_sprintf ("0.999939 ", "%-#20RF", x); check_sprintf ("0.999939 ", "%-#20.RF", x); check_sprintf ("1. ", "%-#20.0RF", x); check_sprintf ("1.0 ", "%-#20.1RF", x); check_sprintf ("1.00 ", "%-#20.2RF", x); check_sprintf ("1.000 ", "%-#20.3RF", x); check_sprintf ("0.9999 ", "%-#20.4RF", x); check_sprintf ("1 ", "%-20.0RG", x); check_sprintf ("1 ", "%-20.1RG", x); check_sprintf ("1 ", "%-20.2RG", x); check_sprintf ("1 ", "%-20.3RG", x); check_sprintf ("0.9999 ", "%-20.4RG", x); check_sprintf ("0.999939 ", "%-#20RG", x); check_sprintf ("0.999939 ", "%-#20.RG", x); check_sprintf ("1. ", "%-#20.0RG", x); check_sprintf ("1. ", "%-#20.1RG", x); check_sprintf ("1.0 ", "%-#20.2RG", x); check_sprintf ("1.00 ", "%-#20.3RG", x); check_sprintf ("0.9999 ", "%-#20.4RG", x); /* multiple of 10 */ mpfr_set_str (x, "1e17", 10, MPFR_RNDN); check_sprintf ("1e+17", "%Re", x); check_sprintf ("1.000e+17", "%.3Re", x); check_sprintf ("100000000000000000", "%.0Rf", x); check_sprintf ("100000000000000000.0", "%.1Rf", x); check_sprintf ("100000000000000000.000000", "%'Rf", x); check_sprintf ("100000000000000000.0", "%'.1Rf", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); /* x=1e-17 */ check_sprintf ("1e-17", "%Re", x); check_sprintf ("0.000000", "%Rf", x); check_sprintf ("1e-17", "%Rg", x); check_sprintf ("0.0", "%.1RDf", x); check_sprintf ("0.0", "%.1RZf", x); check_sprintf ("0.1", "%.1RUf", x); check_sprintf ("0.1", "%.1RYf", x); check_sprintf ("0", "%.0RDf", x); check_sprintf ("0", "%.0RZf", x); check_sprintf ("1", "%.0RUf", x); check_sprintf ("1", "%.0RYf", x); /* multiple of 10 with 'g' style */ mpfr_set_str (x, "10", 10, MPFR_RNDN); check_sprintf ("10", "%Rg", x); check_sprintf ("1e+01", "%.0Rg", x); check_sprintf ("1e+01", "%.1Rg", x); check_sprintf ("10", "%.2Rg", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); check_sprintf ("0.1", "%Rg", x); check_sprintf ("0.1", "%.0Rg", x); check_sprintf ("0.1", "%.1Rg", x); mpfr_set_str (x, "1000", 10, MPFR_RNDN); check_sprintf ("1000", "%Rg", x); check_sprintf ("1e+03", "%.0Rg", x); check_sprintf ("1e+03", "%.3Rg", x); check_sprintf ("1000", "%.4Rg", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); check_sprintf ("0.001", "%Rg", x); check_sprintf ("0.001", "%.0Rg", x); check_sprintf ("0.001", "%.1Rg", x); mpfr_set_str (x, "100000", 10, MPFR_RNDN); check_sprintf ("100000", "%Rg", x); check_sprintf ("1e+05", "%.0Rg", x); check_sprintf ("1e+05", "%.5Rg", x); check_sprintf ("100000", "%.6Rg", x); mpfr_ui_div (x, 1, x, MPFR_RNDN); check_sprintf ("1e-05", "%Rg", x); check_sprintf ("1e-05", "%.0Rg", x); check_sprintf ("1e-05", "%.1Rg", x); /* check rounding mode */ mpfr_set_str (x, "0.0076", 10, MPFR_RNDN); check_sprintf ("0.007", "%.3RDF", x); check_sprintf ("0.007", "%.3RZF", x); check_sprintf ("0.008", "%.3RF", x); check_sprintf ("0.008", "%.3RUF", x); check_sprintf ("0.008", "%.3RYF", x); check_vsprintf ("0.008", "%.3R*F", MPFR_RNDA, x); /* check limit between %f-style and %g-style */ mpfr_set_str (x, "0.0000999", 10, MPFR_RNDN); check_sprintf ("0.0001", "%.0Rg", x); check_sprintf ("9e-05", "%.0RDg", x); check_sprintf ("0.0001", "%.1Rg", x); check_sprintf ("0.0001", "%.2Rg", x); check_sprintf ("9.99e-05", "%.3Rg", x); /* trailing zeros */ mpfr_set_si_2exp (x, -1, -15, MPFR_RNDN); /* x=-2^-15 */ check_sprintf ("-3.0517578125e-05", "%.30Rg", x); check_sprintf ("-3.051757812500000000000000000000e-05", "%.30Re", x); check_sprintf ("-3.05175781250000000000000000000e-05", "%#.30Rg", x); check_sprintf ("-0.000030517578125000000000000000", "%.30Rf", x); /* bug 20081023 */ check_sprintf ("-3.0517578125e-05", "%.30Rg", x); mpfr_set_str (x, "1.9999", 10, MPFR_RNDN); check_sprintf ("1.999900 ", "%-#10.7RG", x); check_sprintf ("1.9999 ", "%-10.7RG", x); mpfr_set_ui (x, 1, MPFR_RNDN); check_sprintf ("1.", "%#.1Rg", x); check_sprintf ("1. ", "%-#5.1Rg", x); check_sprintf (" 1.0", "%#5.2Rg", x); check_sprintf ("1.00000000000000000000000000000", "%#.30Rg", x); check_sprintf ("1", "%.30Rg", x); mpfr_set_ui (x, 0, MPFR_RNDN); check_sprintf ("0.", "%#.1Rg", x); check_sprintf ("0. ", "%-#5.1Rg", x); check_sprintf (" 0.0", "%#5.2Rg", x); check_sprintf ("0.00000000000000000000000000000", "%#.30Rg", x); check_sprintf ("0", "%.30Rg", x); /* following tests with precision 53 bits */ mpfr_set_prec (x, 53); /* Exponent zero has a plus sign */ mpfr_set_str (x, "-9.95645044213728791504536275169812142849e-01", 10, MPFR_RNDN); check_sprintf ("-1.0e+00", "%- #0.1Re", x); /* Decimal point and no figure after it with '#' flag and 'G' style */ mpfr_set_str (x, "-9.90597761233942053494e-01", 10, MPFR_RNDN); check_sprintf ("-1.", "%- #0.1RG", x); /* precision zero */ mpfr_set_d (x, 9.5, MPFR_RNDN); check_sprintf ("9", "%.0RDf", x); check_sprintf ("10", "%.0RUf", x); mpfr_set_d (x, 19.5, MPFR_RNDN); check_sprintf ("19", "%.0RDf", x); check_sprintf ("20", "%.0RUf", x); mpfr_set_d (x, 99.5, MPFR_RNDN); check_sprintf ("99", "%.0RDf", x); check_sprintf ("100", "%.0RUf", x); mpfr_set_d (x, -9.5, MPFR_RNDN); check_sprintf ("-10", "%.0RDf", x); check_sprintf ("-10", "%.0RYf", x); check_sprintf ("-10", "%.0Rf", x); check_sprintf ("-1e+01", "%.0Re", x); check_sprintf ("-1e+01", "%.0Rg", x); mpfr_set_ui_2exp (x, 1, -1, MPFR_RNDN); check_sprintf ("0", "%.0Rf", x); check_sprintf ("5e-01", "%.0Re", x); check_sprintf ("0.5", "%.0Rg", x); mpfr_set_ui_2exp (x, 3, -1, MPFR_RNDN); check_sprintf ("2", "%.0Rf", x); mpfr_set_ui_2exp (x, 5, -1, MPFR_RNDN); check_sprintf ("2", "%.0Rf", x); mpfr_set_ui (x, 0x1f, MPFR_RNDN); check_sprintf ("0x1p+5", "%.0Ra", x); mpfr_set_ui (x, 3, MPFR_RNDN); check_sprintf ("1p+2", "%.0Rb", x); /* round to next ten power with %f but not with %g */ mpfr_set_str (x, "-6.64464380544039223686e-02", 10, MPFR_RNDN); check_sprintf ("-0.1", "%.1Rf", x); check_sprintf ("-0.0", "%.1RZf", x); check_sprintf ("-0.07", "%.1Rg", x); check_sprintf ("-0.06", "%.1RZg", x); /* round to next ten power and do not remove trailing zeros */ mpfr_set_str (x, "9.98429393291486722006e-02", 10, MPFR_RNDN); check_sprintf ("0.1", "%#.1Rg", x); check_sprintf ("0.10", "%#.2Rg", x); check_sprintf ("0.099", "%#.2RZg", x); /* Halfway cases */ mpfr_set_str (x, "1.5", 10, MPFR_RNDN); check_sprintf ("2e+00", "%.0Re", x); mpfr_set_str (x, "2.5", 10, MPFR_RNDN); check_sprintf ("2e+00", "%.0Re", x); mpfr_set_str (x, "9.5", 10, MPFR_RNDN); check_sprintf ("1e+01", "%.0Re", x); mpfr_set_str (x, "1.25", 10, MPFR_RNDN); check_sprintf ("1.2e+00", "%.1Re", x); mpfr_set_str (x, "1.75", 10, MPFR_RNDN); check_sprintf ("1.8e+00", "%.1Re", x); mpfr_set_str (x, "-0.5", 10, MPFR_RNDN); check_sprintf ("-0", "%.0Rf", x); mpfr_set_str (x, "1.25", 10, MPFR_RNDN); check_sprintf ("1.2", "%.1Rf", x); mpfr_set_str (x, "1.75", 10, MPFR_RNDN); check_sprintf ("1.8", "%.1Rf", x); mpfr_set_str (x, "1.5", 10, MPFR_RNDN); check_sprintf ("2", "%.1Rg", x); mpfr_set_str (x, "2.5", 10, MPFR_RNDN); check_sprintf ("2", "%.1Rg", x); mpfr_set_str (x, "9.25", 10, MPFR_RNDN); check_sprintf ("9.2", "%.2Rg", x); mpfr_set_str (x, "9.75", 10, MPFR_RNDN); check_sprintf ("9.8", "%.2Rg", x); /* assertion failure in r6320 */ mpfr_set_str (x, "-9.996", 10, MPFR_RNDN); check_sprintf ("-10.0", "%.1Rf", x); mpfr_clears (x, z, (mpfr_ptr) 0); return 0; } static int hexadecimal (void) { mpfr_t x, z; mpfr_inits2 (64, x, z, (mpfr_ptr) 0); /* special */ mpfr_set_inf (x, 1); check_sprintf (pinf_str, "%Ra", x); check_sprintf (pinf_str, "%RUa", x); check_sprintf (pinf_str, "%RDa", x); check_sprintf (pinf_uc_str, "%RA", x); check_sprintf (pinf_uc_str, "%RYA", x); check_sprintf (pinf_uc_str, "%RZA", x); check_sprintf (pinf_uc_str, "%RNA", x); mpfr_set_inf (x, -1); check_sprintf (minf_str, "%Ra", x); check_sprintf (minf_str, "%RYa", x); check_sprintf (minf_str, "%RZa", x); check_sprintf (minf_str, "%RNa", x); check_sprintf (minf_uc_str, "%RA", x); check_sprintf (minf_uc_str, "%RUA", x); check_sprintf (minf_uc_str, "%RDA", x); mpfr_set_nan (x); check_sprintf (nan_str, "%Ra", x); check_sprintf (nan_uc_str, "%RA", x); /* regular numbers */ mpfr_set_str (x, "FEDCBA9.87654321", 16, MPFR_RNDN); mpfr_set_ui (z, 0, MPFR_RNDZ); /* simplest case right justified */ check_sprintf (" 0xf.edcba987654321p+24", "%25Ra", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RUa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RDa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RYa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RZa", x); check_sprintf (" 0xf.edcba987654321p+24", "%25RNa", x); check_sprintf (" 0x1p+28", "%25.0Ra", x); check_sprintf (" 0x0p+0", "%25.0Ra", z); /* sign or space, pad with leading zeros */ check_sprintf (" 0X00F.EDCBA987654321P+24", "% 025RA", x); check_sprintf (" 0X000000000000000001P+28", "% 025.0RA", x); check_sprintf (" 0X0000000000000000000P+0", "% 025.0RA", z); /* sign + or -, left justified */ check_sprintf ("+0xf.edcba987654321p+24 ", "%+-25Ra", x); check_sprintf ("+0x1p+28 ", "%+-25.0Ra", x); check_sprintf ("+0x0p+0 ", "%+-25.0Ra", z); /* decimal point, left justified, precision and rounding parameter */ check_vsprintf ("0XF.FP+24 ", "%#-10.*R*A", 1, MPFR_RNDN, x); check_vsprintf ("0X1.P+28 ", "%#-10.*R*A", 0, MPFR_RNDN, x); check_vsprintf ("0X0.P+0 ", "%#-10.*R*A", 0, MPFR_RNDN, z); /* sign or space */ check_sprintf (" 0xf.eddp+24", "% .3RNa", x); check_sprintf (" 0x1p+28", "% .0RNa", x); /* sign + or -, decimal point, pad with leading zeros */ check_sprintf ("+0X0F.EP+24", "%0+#11.1RZA", x); check_sprintf ("+0X00F.P+24", "%0+#11.0RZA", x); check_sprintf ("+0X000.0P+0", "%0+#11.1RZA", z); /* pad with leading zero */ check_sprintf ("0x0000f.edcba987654321p+24", "%026RDa", x); check_sprintf ("0x0000000000000000000fp+24", "%026.0RDa", x); /* sign or space, decimal point, left justified */ check_sprintf (" 0XF.EP+24 " , "%- #11.1RDA", x); check_sprintf (" 0XF.P+24 " , "%- #11.0RDA", x); mpfr_mul_si (x, x, -1, MPFR_RNDD); mpfr_mul_si (z, z, -1, MPFR_RNDD); /* sign + or - */ check_sprintf ("-0xf.ep+24", "%+10.1RUa", x); check_sprintf (" -0xfp+24", "%+10.0RUa", x); check_sprintf (" -0x0p+0", "%+10.0RUa", z); /* rounding bit is zero */ mpfr_set_str (x, "0xF.7", 16, MPFR_RNDN); check_sprintf ("0XFP+0", "%.0RNA", x); /* tie case in round to nearest mode */ mpfr_set_str (x, "0x0.8800000000000000p+3", 16, MPFR_RNDN); check_sprintf ("0x9.p-1", "%#.0RNa", x); mpfr_set_str (x, "-0x0.9800000000000000p+3", 16, MPFR_RNDN); check_sprintf ("-0xap-1", "%.0RNa", x); /* trailing zeros in fractional part */ check_sprintf ("-0X4.C0000000000000000000P+0", "%.20RNA", x); /* rounding bit is one and the first non zero bit is far away */ mpfr_set_prec (x, 1024); mpfr_set_ui_2exp (x, 29, -1, MPFR_RNDN); mpfr_nextabove (x); check_sprintf ("0XFP+0", "%.0RNA", x); /* with more than one limb */ mpfr_set_prec (x, 300); mpfr_set_str (x, "0xf.ffffffffffffffffffffffffffffffffffffffffffffffffffff" "fffffffffffffffff", 16, MPFR_RNDN); check_sprintf ("0x1p+4 [300]", "%.0RNa [300]", x); check_sprintf ("0xfp+0 [300]", "%.0RZa [300]", x); check_sprintf ("0x1p+4 [300]", "%.0RYa [300]", x); check_sprintf ("0xfp+0 [300]", "%.0RDa [300]", x); check_sprintf ("0x1p+4 [300]", "%.0RUa [300]", x); check_sprintf ("0x1.0000000000000000000000000000000000000000p+4", "%.40RNa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0", "%.40RZa", x); check_sprintf ("0x1.0000000000000000000000000000000000000000p+4", "%.40RYa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0", "%.40RDa", x); check_sprintf ("0x1.0000000000000000000000000000000000000000p+4", "%.40RUa", x); mpfr_set_str (x, "0xf.7fffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffff", 16, MPFR_RNDN); check_sprintf ("0XFP+0", "%.0RNA", x); check_sprintf ("0XFP+0", "%.0RZA", x); check_sprintf ("0X1P+4", "%.0RYA", x); check_sprintf ("0XFP+0", "%.0RDA", x); check_sprintf ("0X1P+4", "%.0RUA", x); check_sprintf ("0XF.8P+0", "%.1RNA", x); check_sprintf ("0XF.7P+0", "%.1RZA", x); check_sprintf ("0XF.8P+0", "%.1RYA", x); check_sprintf ("0XF.7P+0", "%.1RDA", x); check_sprintf ("0XF.8P+0", "%.1RUA", x); /* do not round up to the next power of the base */ mpfr_set_str (x, "0xf.fffffffffffffffffffffffffffffffffffffeffffffffffffff" "ffffffffffffffffff", 16, MPFR_RNDN); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0", "%.40RNa", x); check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0", "%.40RZa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0", "%.40RYa", x); check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0", "%.40RDa", x); check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0", "%.40RUa", x); mpfr_clears (x, z, (mpfr_ptr) 0); return 0; } static int binary (void) { mpfr_t x; mpfr_t z; mpfr_inits2 (64, x, z, (mpfr_ptr) 0); /* special */ mpfr_set_inf (x, 1); check_sprintf (pinf_str, "%Rb", x); mpfr_set_inf (x, -1); check_sprintf (minf_str, "%Rb", x); mpfr_set_nan (x); check_sprintf (nan_str, "%Rb", x); /* regular numbers */ mpfr_set_str (x, "1110010101.1001101", 2, MPFR_RNDN); mpfr_set_ui (z, 0, MPFR_RNDN); /* simplest case: right justified */ check_sprintf (" 1.1100101011001101p+9", "%25Rb", x); check_sprintf (" 0p+0", "%25Rb", z); /* sign or space, pad with leading zeros */ check_sprintf (" 0001.1100101011001101p+9", "% 025Rb", x); check_sprintf (" 000000000000000000000p+0", "% 025Rb", z); /* sign + or -, left justified */ check_sprintf ("+1.1100101011001101p+9 ", "%+-25Rb", x); check_sprintf ("+0p+0 ", "%+-25Rb", z); /* sign or space */ check_sprintf (" 1.110p+9", "% .3RNb", x); check_sprintf (" 1.1101p+9", "% .4RNb", x); check_sprintf (" 0.0000p+0", "% .4RNb", z); /* sign + or -, decimal point, pad with leading zeros */ check_sprintf ("+00001.1p+9", "%0+#11.1RZb", x); check_sprintf ("+0001.0p+10", "%0+#11.1RNb", x); check_sprintf ("+000000.p+0", "%0+#11.0RNb", z); /* pad with leading zero */ check_sprintf ("00001.1100101011001101p+9", "%025RDb", x); /* sign or space, decimal point (unused), left justified */ check_sprintf (" 1.1p+9 ", "%- #11.1RDb", x); check_sprintf (" 1.p+9 ", "%- #11.0RDb", x); check_sprintf (" 1.p+10 ", "%- #11.0RUb", x); check_sprintf (" 1.p+9 ", "%- #11.0RZb", x); check_sprintf (" 1.p+10 ", "%- #11.0RYb", x); check_sprintf (" 1.p+10 ", "%- #11.0RNb", x); mpfr_mul_si (x, x, -1, MPFR_RNDD); mpfr_mul_si (z, z, -1, MPFR_RNDD); /* sign + or - */ check_sprintf (" -1.1p+9", "%+10.1RUb", x); check_sprintf (" -0.0p+0", "%+10.1RUb", z); /* precision 0 */ check_sprintf ("-1p+10", "%.0RNb", x); check_sprintf ("-1p+10", "%.0RDb", x); check_sprintf ("-1p+9", "%.0RUb", x); check_sprintf ("-1p+9", "%.0RZb", x); check_sprintf ("-1p+10", "%.0RYb", x); /* round to next base power */ check_sprintf ("-1.0p+10", "%.1RNb", x); check_sprintf ("-1.0p+10", "%.1RDb", x); check_sprintf ("-1.0p+10", "%.1RYb", x); /* do not round to next base power */ check_sprintf ("-1.1p+9", "%.1RUb", x); check_sprintf ("-1.1p+9", "%.1RZb", x); /* rounding bit is zero */ check_sprintf ("-1.11p+9", "%.2RNb", x); /* tie case in round to nearest mode */ check_sprintf ("-1.1100101011001101p+9", "%.16RNb", x); /* trailing zeros in fractional part */ check_sprintf ("-1.110010101100110100000000000000p+9", "%.30RNb", x); mpfr_clears (x, z, (mpfr_ptr) 0); return 0; } static int mixed (void) { int n1; int n2; int i = 121; #ifndef NPRINTF_L long double d = 1. / 31.; #endif mpf_t mpf; mpq_t mpq; mpz_t mpz; mpfr_t x; mpfr_rnd_t rnd; mpf_init (mpf); mpf_set_ui (mpf, 40); mpf_div_ui (mpf, mpf, 31); /* mpf = 40.0 / 31.0 */ mpq_init (mpq); mpq_set_ui (mpq, 123456, 4567890); mpz_init (mpz); mpz_fib_ui (mpz, 64); mpfr_init (x); mpfr_set_str (x, "-12345678.875", 10, MPFR_RNDN); rnd = MPFR_RNDD; check_vsprintf ("121%", "%i%%", i); check_vsprintf ("121% -1.2345678875E+07", "%i%% %RNE", i, x); check_vsprintf ("121, -12345679", "%i, %.0Rf", i, x); check_vsprintf ("10610209857723, -1.2345678875e+07", "%Zi, %R*e", mpz, rnd, x); check_vsprintf ("-12345678.9, 121", "%.1Rf, %i", x, i); check_vsprintf ("-12345678, 1e240/45b352", "%.0R*f, %Qx", MPFR_RNDZ, x, mpq); n1 = check_vsprintf ("121, -12345678.875000000000, 1.290323", "%i, %.*Rf, %Ff%n", i, 12, x, mpf, &n2); if (n1 != n2) { printf ("error in number of characters written by mpfr_vsprintf\n"); printf ("expected: %d\n", n2); printf (" got: %d\n", n1); exit (1); } #ifndef NPRINTF_L check_vsprintf ("00000010610209857723, -1.2345678875e+07, 0.032258", "%.*Zi, %R*e, %Lf", 20, mpz, rnd, x, d); #endif mpf_clear (mpf); mpq_clear (mpq); mpz_clear (mpz); mpfr_clear (x); return 0; } #if MPFR_LCONV_DPTS /* Check with locale "da_DK". On most platforms, decimal point is ',' and thousands separator is '.'; the test is not performed if this is not the case or if the locale doesn't exist. */ static int locale_da_DK (void) { mpfr_prec_t p = 128; mpfr_t x; if (setlocale (LC_ALL, "da_DK") == 0 || localeconv()->decimal_point[0] != ',' || localeconv()->thousands_sep[0] != '.') return 0; mpfr_init2 (x, p); /* positive numbers */ mpfr_set_str (x, "18993474.61279296875", 10, MPFR_RNDN); /* simplest case right justified with thousands separator */ check_sprintf (" 1,899347461279296875e+07", "%'30Re", x); check_sprintf (" 1,89935e+07", "%'30Rg", x); check_sprintf (" 18.993.474,61279296875", "%'30.19Rg", x); check_sprintf (" 18.993.474,612793", "%'30Rf", x); /* sign or space, pad, thousands separator with leading zeros */ check_sprintf (" 000001,899347461279296875E+07", "%' 030RE", x); check_sprintf (" 0000000000000000001,89935E+07", "%' 030RG", x); check_sprintf (" 000000018.993.474,61279296875", "%' 030.19RG", x); check_sprintf (" 00000000000018.993.474,612793", "%' 030RF", x); mpfr_set_ui (x, 50, MPFR_RNDN); mpfr_exp10 (x, x, MPFR_RNDN); check_sprintf ("100000000000000000000000000000000000000000000000000", "%.0Rf", x); check_sprintf ("100.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000,", "%'#.0Rf", x); check_sprintf ("100.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000,0000", "%'.4Rf", x); mpfr_clear (x); return 0; } #endif /* MPFR_LCONV_DPTS */ /* check concordance between mpfr_asprintf result with a regular mpfr float and with a regular double float */ static int random_double (void) { mpfr_t x; /* random regular mpfr float */ double y; /* regular double float (equal to x) */ char flag[] = { '-', '+', ' ', '#', '0', /* no ambiguity: first zeros are flag zero*/ '\'' }; /* no 'a': mpfr and glibc do not have the same semantic */ char specifier[] = { 'e', 'f', 'g', 'E', 'f', /* SUSv2 doesn't accept %F, but %F and %f are the same for regular numbers */ 'G', }; int spec; /* random index in specifier[] */ int prec; /* random value for precision field */ /* in the format string for mpfr_t variable, the maximum length is reached by something like "%-+ #0'.*Rf", that is 12 characters. */ #define FMT_MPFR_SIZE 12 char fmt_mpfr[FMT_MPFR_SIZE]; char *ptr_mpfr; /* in the format string for double variable, the maximum length is reached by something like "%-+ #0'.*f", that is 11 characters. */ #define FMT_SIZE 11 char fmt[FMT_SIZE]; char *ptr; int xi; char *xs; int yi; char *ys; int i, j, jmax; mpfr_init2 (x, MPFR_LDBL_MANT_DIG); for (i = 0; i < 1000; ++i) { /* 1. random double */ do { y = DBL_RAND (); } #ifdef HAVE_DENORMS while (0); #else while (ABS(y) < DBL_MIN); #endif if (randlimb () % 2 == 0) y = -y; mpfr_set_d (x, y, MPFR_RNDN); if (y != mpfr_get_d (x, MPFR_RNDN)) /* conversion error: skip this one */ continue; /* 2. build random format strings fmt_mpfr and fmt */ ptr_mpfr = fmt_mpfr; ptr = fmt; *ptr_mpfr++ = *ptr++ = '%'; /* random specifier 'e', 'f', 'g', 'E', 'F', or 'G' */ spec = (int) (randlimb() % 6); /* random flags, but no ' flag with %e */ jmax = (spec == 0 || spec == 3) ? 5 : 6; for (j = 0; j < jmax; j++) { if (randlimb() % 3 == 0) *ptr_mpfr++ = *ptr++ = flag[j]; } *ptr_mpfr++ = *ptr++ = '.'; *ptr_mpfr++ = *ptr++ = '*'; *ptr_mpfr++ = 'R'; *ptr_mpfr++ = *ptr++ = specifier[spec]; *ptr_mpfr = *ptr = '\0'; MPFR_ASSERTN (ptr - fmt < FMT_SIZE); MPFR_ASSERTN (ptr_mpfr - fmt_mpfr < FMT_MPFR_SIZE); /* advantage small precision */ if (randlimb() % 2 == 0) prec = (int) (randlimb() % 10); else prec = (int) (randlimb() % prec_max_printf); /* 3. calls and checks */ /* the double float case is handled by the libc asprintf through gmp_asprintf */ xi = mpfr_asprintf (&xs, fmt_mpfr, prec, x); yi = mpfr_asprintf (&ys, fmt, prec, y); /* test if XS and YS differ, beware that ISO C99 doesn't specify the sign of a zero exponent (the C99 rationale says: "The sign of a zero exponent in %e format is unspecified. The committee knows of different implementations and choose not to require implementations to document their behaviour in this case (by making this be implementation defined behaviour). Most implementations use a "+" sign, e.g., 1.2e+00; but there is at least one implementation that uses the sign of the unlimited precision result, e.g., the 0.987 would be 9.87e-01, so could end up as 1e-00 after rounding to one digit of precision."), while mpfr always uses '+' */ if (xi != yi || ((strcmp (xs, ys) != 0) && (spec == 1 || spec == 4 || ((strstr (xs, "e+00") == NULL || strstr (ys, "e-00") == NULL) && (strstr (xs, "E+00") == NULL || strstr (ys, "E-00") == NULL))))) { mpfr_printf ("Error in mpfr_asprintf(\"%s\", %d, %Re)\n", fmt_mpfr, prec, x); printf ("expected: %s\n", ys); printf (" got: %s\n", xs); printf ("xi=%d yi=%d spec=%d\n", xi, yi, spec); exit (1); } mpfr_free_str (xs); mpfr_free_str (ys); } mpfr_clear (x); return 0; } static void bug20080610 (void) { /* bug on icc found on June 10, 2008 */ /* this is not a bug but a different implementation choice: ISO C99 doesn't specify the sign of a zero exponent (see note in random_double above). */ mpfr_t x; double y; int xi; char *xs; int yi; char *ys; mpfr_init2 (x, MPFR_LDBL_MANT_DIG); y = -9.95645044213728791504536275169812142849e-01; mpfr_set_d (x, y, MPFR_RNDN); xi = mpfr_asprintf (&xs, "%- #0.*Re", 1, x); yi = mpfr_asprintf (&ys, "%- #0.*e", 1, y); if (xi != yi || strcmp (xs, ys) != 0) { printf ("Error in bug20080610\n"); printf ("expected: %s\n", ys); printf (" got: %s\n", xs); printf ("xi=%d yi=%d\n", xi, yi); exit (1); } mpfr_free_str (xs); mpfr_free_str (ys); mpfr_clear (x); } static void bug20081214 (void) { /* problem with glibc 2.3.6, December 14, 2008: the system asprintf outputs "-1.0" instead of "-1.". */ mpfr_t x; double y; int xi; char *xs; int yi; char *ys; mpfr_init2 (x, MPFR_LDBL_MANT_DIG); y = -9.90597761233942053494e-01; mpfr_set_d (x, y, MPFR_RNDN); xi = mpfr_asprintf (&xs, "%- #0.*RG", 1, x); yi = mpfr_asprintf (&ys, "%- #0.*G", 1, y); if (xi != yi || strcmp (xs, ys) != 0) { mpfr_printf ("Error in bug20081214\n" "mpfr_asprintf(\"%- #0.*Re\", 1, %Re)\n", x); printf ("expected: %s\n", ys); printf (" got: %s\n", xs); printf ("xi=%d yi=%d\n", xi, yi); exit (1); } mpfr_free_str (xs); mpfr_free_str (ys); mpfr_clear (x); } static void bug20111102 (void) { mpfr_t t; char s[100]; mpfr_init2 (t, 84); mpfr_set_str (t, "999.99999999999999999999", 10, MPFR_RNDN); mpfr_sprintf (s, "%.20RNg", t); if (strcmp (s, "1000") != 0) { printf ("Error in bug20111102, expected 1000, got %s\n", s); exit (1); } mpfr_clear (t); } /* In particular, the following test makes sure that the rounding * for %Ra and %Rb is not done on the MPFR number itself (as it * would overflow). Note: it has been reported on comp.std.c that * some C libraries behave differently on %a, but this is a bug. */ static void check_emax_aux (mpfr_exp_t e) { mpfr_t x; char *s1, s2[256]; int i; mpfr_exp_t emax; MPFR_ASSERTN (e <= LONG_MAX); emax = mpfr_get_emax (); set_emax (e); mpfr_init2 (x, 16); mpfr_set_inf (x, 1); mpfr_nextbelow (x); i = mpfr_asprintf (&s1, "%Ra %.2Ra", x, x); MPFR_ASSERTN (i > 0); mpfr_snprintf (s2, 256, "0x7.fff8p+%ld 0x8.00p+%ld", e-3, e-3); if (strcmp (s1, s2) != 0) { printf ("Error in check_emax_aux for emax = "); if (e > LONG_MAX) printf ("(>LONG_MAX)\n"); else printf ("%ld\n", (long) e); printf ("Expected %s\n", s2); printf ("Got %s\n", s1); exit (1); } mpfr_free_str (s1); i = mpfr_asprintf (&s1, "%Rb %.2Rb", x, x); MPFR_ASSERTN (i > 0); mpfr_snprintf (s2, 256, "1.111111111111111p+%ld 1.00p+%ld", e-1, e); if (strcmp (s1, s2) != 0) { printf ("Error in check_emax_aux for emax = "); if (e > LONG_MAX) printf ("(>LONG_MAX)\n"); else printf ("%ld\n", (long) e); printf ("Expected %s\n", s2); printf ("Got %s\n", s1); exit (1); } mpfr_free_str (s1); mpfr_clear (x); set_emax (emax); } static void check_emax (void) { check_emax_aux (15); check_emax_aux (MPFR_EMAX_MAX); } static void check_emin_aux (mpfr_exp_t e) { mpfr_t x; char *s1, s2[256]; int i; mpfr_exp_t emin; mpz_t ee; MPFR_ASSERTN (e >= LONG_MIN); emin = mpfr_get_emin (); set_emin (e); mpfr_init2 (x, 16); mpz_init (ee); mpfr_setmin (x, e); mpz_set_si (ee, e); mpz_sub_ui (ee, ee, 1); i = mpfr_asprintf (&s1, "%Ra", x); MPFR_ASSERTN (i > 0); gmp_snprintf (s2, 256, "0x1p%Zd", ee); if (strcmp (s1, s2) != 0) { printf ("Error in check_emin_aux for emin = %ld\n", (long) e); printf ("Expected %s\n", s2); printf ("Got %s\n", s1); exit (1); } mpfr_free_str (s1); i = mpfr_asprintf (&s1, "%Rb", x); MPFR_ASSERTN (i > 0); gmp_snprintf (s2, 256, "1p%Zd", ee); if (strcmp (s1, s2) != 0) { printf ("Error in check_emin_aux for emin = %ld\n", (long) e); printf ("Expected %s\n", s2); printf ("Got %s\n", s1); exit (1); } mpfr_free_str (s1); mpfr_clear (x); mpz_clear (ee); set_emin (emin); } static void check_emin (void) { check_emin_aux (-15); check_emin_aux (mpfr_get_emin ()); check_emin_aux (MPFR_EMIN_MIN); } int main (int argc, char **argv) { char *locale; tests_start_mpfr (); #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) /* currently, we just check with 'C' locale */ locale = setlocale (LC_ALL, "C"); #endif bug20111102 (); native_types (); hexadecimal (); binary (); decimal (); mixed (); check_emax (); check_emin (); #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) #if MPFR_LCONV_DPTS locale_da_DK (); /* Avoid a warning by doing the setlocale outside of this #if */ #endif setlocale (LC_ALL, locale); #endif if (getenv ("MPFR_CHECK_LIBC_PRINTF")) { /* check against libc */ random_double (); bug20081214 (); bug20080610 (); } tests_end_mpfr (); return 0; } #else /* MPFR_VERSION */ int main (void) { printf ("Warning! Test disabled for this MPFR version.\n"); return 0; } #endif /* MPFR_VERSION */ #else /* HAVE_STDARG */ int main (void) { /* We have nothing to test. */ return 77; } #endif /* HAVE_STDARG */