Submitted By:            Matt Burgess <matthew_at_linuxfromscratch_dot_org>
Date:                    2011-12-22
Initial Package Version: 3.1.0
Upstream Status:         Already in upstream patch repo
Origin:                  Upstream
Description:             This patch contains patches for several bugs in MPFR,
                         the main one being a rounding related error with the
                         mpfr_*printf functions.

diff -Naur mpfr-3.1.0.orig/PATCHES mpfr-3.1.0/PATCHES
--- mpfr-3.1.0.orig/PATCHES	2011-10-03 08:17:15.000000000 +0000
+++ mpfr-3.1.0/PATCHES	2011-12-22 11:08:42.188819413 +0000
@@ -0,0 +1,4 @@
+gmp41compat
+vasprintf
+lib-search-path
+mpfr_unlikely
diff -Naur mpfr-3.1.0.orig/VERSION mpfr-3.1.0/VERSION
--- mpfr-3.1.0.orig/VERSION	2011-10-03 08:17:15.000000000 +0000
+++ mpfr-3.1.0/VERSION	2011-11-28 12:22:52.000000000 +0000
@@ -1 +1 @@
-3.1.0
+3.1.0-p4
diff -Naur mpfr-3.1.0.orig/doc/mpfr.info mpfr-3.1.0/doc/mpfr.info
--- mpfr-3.1.0.orig/doc/mpfr.info	2011-10-03 09:43:04.000000000 +0000
+++ mpfr-3.1.0/doc/mpfr.info	2011-11-28 12:22:52.000000000 +0000
@@ -2994,11 +2994,12 @@
 
    * `mpfr_urandom' and `mpfr_urandomb' changed in MPFR 3.1.  Their
      behavior no longer depends on the platform (assuming this is also
-     true for GMP's random generator).  As a consequence, the returned
-     values can be different between MPFR 3.1 and previous MPFR
-     versions.  Note: as the reproducibility of these functions was not
-     specified before MPFR 3.1, the MPFR 3.1 behavior is _not_ regarded
-     as backward incompatible with previous versions.
+     true for GMP's random generator, which is not the case between GMP
+     4.1 and 4.2 if `gmp_randinit_default' is used).  As a consequence,
+     the returned values can be different between MPFR 3.1 and previous
+     MPFR versions.  Note: as the reproducibility of these functions
+     was not specified before MPFR 3.1, the MPFR 3.1 behavior is _not_
+     regarded as backward incompatible with previous versions.
 
 
 
@@ -4239,13 +4240,13 @@
 Node: Type and Macro Changes129308
 Node: Added Functions132029
 Node: Changed Functions134972
-Node: Removed Functions139167
-Node: Other Changes139579
-Node: Contributors141108
-Node: References143574
-Node: GNU Free Documentation License145315
-Node: Concept Index167758
-Node: Function and Type Index173677
+Node: Removed Functions139253
+Node: Other Changes139665
+Node: Contributors141194
+Node: References143660
+Node: GNU Free Documentation License145401
+Node: Concept Index167844
+Node: Function and Type Index173763
 
 End Tag Table
 
diff -Naur mpfr-3.1.0.orig/doc/mpfr.texi mpfr-3.1.0/doc/mpfr.texi
--- mpfr-3.1.0.orig/doc/mpfr.texi	2011-10-03 08:17:14.000000000 +0000
+++ mpfr-3.1.0/doc/mpfr.texi	2011-11-28 12:22:52.000000000 +0000
@@ -3466,8 +3466,9 @@
 a lack of specification.
 
 @item @code{mpfr_urandom} and @code{mpfr_urandomb} changed in MPFR 3.1.
-Their behavior no longer depends on the platform (assuming this is also
-true for GMP's random generator).  As a consequence, the returned values
+Their behavior no longer depends on the platform (assuming this is also true
+for GMP's random generator, which is not the case between GMP 4.1 and 4.2 if
+@code{gmp_randinit_default} is used).  As a consequence, the returned values
 can be different between MPFR 3.1 and previous MPFR versions.
 Note: as the reproducibility of these functions was not specified
 before MPFR 3.1, the MPFR 3.1 behavior is @emph{not} regarded as
diff -Naur mpfr-3.1.0.orig/src/mpfr-impl.h mpfr-3.1.0/src/mpfr-impl.h
--- mpfr-3.1.0.orig/src/mpfr-impl.h	2011-10-03 08:17:09.000000000 +0000
+++ mpfr-3.1.0/src/mpfr-impl.h	2011-10-05 21:39:57.000000000 +0000
@@ -988,10 +988,11 @@
  ******************************************************/
 
 /* Theses macros help the compiler to determine if a test is
- * likely or unlikely. */
+   likely or unlikely. The !! is necessary in case x is larger
+   than a long. */
 #if __MPFR_GNUC(3,0) || __MPFR_ICC(8,1,0)
 # define MPFR_LIKELY(x) (__builtin_expect(!!(x),1))
-# define MPFR_UNLIKELY(x) (__builtin_expect((x),0))
+# define MPFR_UNLIKELY(x) (__builtin_expect(!!(x),0))
 #else
 # define MPFR_LIKELY(x) (x)
 # define MPFR_UNLIKELY(x) (x)
diff -Naur mpfr-3.1.0.orig/src/mpfr.h mpfr-3.1.0/src/mpfr.h
--- mpfr-3.1.0.orig/src/mpfr.h	2011-10-03 08:17:09.000000000 +0000
+++ mpfr-3.1.0/src/mpfr.h	2011-11-28 12:22:52.000000000 +0000
@@ -27,7 +27,7 @@
 #define MPFR_VERSION_MAJOR 3
 #define MPFR_VERSION_MINOR 1
 #define MPFR_VERSION_PATCHLEVEL 0
-#define MPFR_VERSION_STRING "3.1.0"
+#define MPFR_VERSION_STRING "3.1.0-p4"
 
 /* Macros dealing with MPFR VERSION */
 #define MPFR_VERSION_NUM(a,b,c) (((a) << 16L) | ((b) << 8) | (c))
diff -Naur mpfr-3.1.0.orig/src/vasprintf.c mpfr-3.1.0/src/vasprintf.c
--- mpfr-3.1.0.orig/src/vasprintf.c	2011-10-03 08:17:09.000000000 +0000
+++ mpfr-3.1.0/src/vasprintf.c	2011-11-03 15:15:11.000000000 +0000
@@ -1178,7 +1178,7 @@
   mpfr_exp_t exp;
   char * str;
   const int spec_g = (spec.spec == 'g' || spec.spec == 'G');
-  const int keep_trailing_zeros = spec_g && spec.alt;
+  const int keep_trailing_zeros = !spec_g || spec.alt;
 
   /* WARNING: an empty precision field is forbidden (it means precision = 6
      and it should have been changed to 6 before the function call) */
@@ -1356,7 +1356,7 @@
   else
     /* 1 <= |p| */
     {
-      size_t nsd;  /* Number of significant digits */
+      size_t str_len;
 
       /* Determine the position of the most significant decimal digit. */
       exp = floor_log10 (p);
@@ -1365,12 +1365,10 @@
         /* P is too large to print all its integral part digits */
         return -1;
 
-      np->ip_size = exp + 1;
-
-      nsd = spec.prec + np->ip_size;
       if (dec_info == NULL)
-        {
-          str = mpfr_get_str (NULL, &exp, 10, nsd, p, spec.rnd_mode);
+        { /* this case occurs with mpfr_printf ("%.0RUf", x) with x=9.5 */
+          str =
+            mpfr_get_str (NULL, &exp, 10, spec.prec+exp+1, p, spec.rnd_mode);
           register_string (np->sl, str);
         }
       else
@@ -1379,81 +1377,60 @@
           str = dec_info->str;
         }
       np->ip_ptr = MPFR_IS_NEG (p) ? ++str : str; /* skip sign */
+      str_len = strlen (str);
+
+      /* integral part */
+      if (exp > str_len)
+        /* mpfr_get_str gives no trailing zero when p is rounded up to the next
+           power of 10 (p integer, so no fractional part) */
+        {
+          np->ip_trailing_zeros = exp - str_len;
+          np->ip_size = str_len;
+        }
+      else
+        np->ip_size = exp;
 
       if (spec.group)
         /* thousands separator in integral part */
         np->thousands_sep = MPFR_THOUSANDS_SEPARATOR;
 
-      if (nsd == 0 || (spec_g && !spec.alt))
-        /* compute how much non-zero digits in integral and fractional
-           parts */
+      /* fractional part */
+      str += np->ip_size;
+      str_len -= np->ip_size;
+      if (!keep_trailing_zeros)
+        /* remove trailing zeros, if any */
         {
-          size_t str_len;
-          str_len = strlen (str); /* note: the sign has been skipped */
-
-          if (exp > str_len)
-            /* mpfr_get_str doesn't give the trailing zeros when p is a
-               multiple of 10 (p integer, so no fractional part) */
+          char *ptr = str + str_len - 1; /* pointer to the last digit of
+                                            str */
+          while ((*ptr == '0') && (str_len != 0))
             {
-              np->ip_trailing_zeros = exp - str_len;
-              np->ip_size = str_len;
-              if (spec.alt)
-                np->point = MPFR_DECIMAL_POINT;
-            }
-          else
-            /* str may contain some digits which are in fractional part */
-            {
-              char *ptr;
-
-              ptr = str + str_len - 1; /* points to the end of str */
-              str_len -= np->ip_size;  /* number of digits in fractional
-                                          part */
-
-              if (!keep_trailing_zeros)
-                /* remove trailing zeros, if any */
-                {
-                  while ((*ptr == '0') && (str_len != 0))
-                    {
-                      --ptr;
-                      --str_len;
-                    }
-                }
-
-              if (str_len > INT_MAX)
-                /* too many digits in fractional part */
-                return -1;
-
-              if (str_len != 0)
-                /* some digits in fractional part */
-                {
-                  np->point = MPFR_DECIMAL_POINT;
-                  np->fp_ptr = str + np->ip_size;
-                  np->fp_size = str_len;
-                }
+              --ptr;
+              --str_len;
             }
         }
-      else
-        /* spec.prec digits in fractional part */
-        {
-          if (np->ip_size == exp - 1)
-            /* the absolute value of the number has been rounded up to a power
-               of ten.
-               Insert an additional zero in integral part and put the rest of
-               them in fractional part. */
-            np->ip_trailing_zeros = 1;
 
-          if (spec.prec != 0)
-            {
-              MPFR_ASSERTD (np->ip_size + np->ip_trailing_zeros == exp);
-              MPFR_ASSERTD (np->ip_size + spec.prec == nsd);
+      if (str_len > 0)
+        /* some nonzero digits in fractional part */
+        {
+          if (str_len > INT_MAX)
+            /* too many digits in fractional part */
+            return -1;
+
+          np->point = MPFR_DECIMAL_POINT;
+          np->fp_ptr = str;
+          np->fp_size = str_len;
+        }
 
-              np->point = MPFR_DECIMAL_POINT;
-              np->fp_ptr = str + np->ip_size;
-              np->fp_size = spec.prec;
-            }
-          else if (spec.alt)
-            np->point = MPFR_DECIMAL_POINT;
+      if (keep_trailing_zeros && str_len < spec.prec)
+        /* add missing trailing zeros */
+        {
+          np->point = MPFR_DECIMAL_POINT;
+          np->fp_trailing_zeros = spec.prec - np->fp_size;
         }
+
+      if (spec.alt)
+        /* add decimal point even if no digits follow it */
+        np->point = MPFR_DECIMAL_POINT;
     }
 
   return 0;
diff -Naur mpfr-3.1.0.orig/src/version.c mpfr-3.1.0/src/version.c
--- mpfr-3.1.0.orig/src/version.c	2011-10-03 08:17:09.000000000 +0000
+++ mpfr-3.1.0/src/version.c	2011-11-28 12:22:52.000000000 +0000
@@ -25,5 +25,5 @@
 const char *
 mpfr_get_version (void)
 {
-  return "3.1.0";
+  return "3.1.0-p4";
 }
diff -Naur mpfr-3.1.0.orig/tests/Makefile.am mpfr-3.1.0/tests/Makefile.am
--- mpfr-3.1.0.orig/tests/Makefile.am	2011-10-03 08:17:14.000000000 +0000
+++ mpfr-3.1.0/tests/Makefile.am	2011-10-03 08:17:14.000000000 +0000
@@ -65,8 +65,24 @@
 TESTS = $(check_PROGRAMS)
 TESTS_ENVIRONMENT = MPFR_QUIET=1 $(VALGRIND)
 
-# Option to prevent libtool from generating wrapper scripts for the tests.
+# The -no-install option prevents libtool from generating wrapper scripts
+# for the tests.
 # This is useful to easily run the test scripts under valgrind or gdb.
 # See discussion http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/28033
 # http://article.gmane.org/gmane.comp.lib.gnulib.bugs/28140 in particular.
-AM_LDFLAGS = -no-install
+#
+# The -L$(top_builddir)/src/.libs option is necessary for some platforms,
+# such as HP-UX, when --with-gmp or --with-gmp-lib is used and an old MPFR
+# library is already installed in the corresponding lib directory: its
+# purpose is to make sure that the local .libs comes first in the library
+# search path (otherwise the tests are linked against the old MPFR library
+# by the LINK command -- see the generated Makefile). See:
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00042.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00043.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00044.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00066.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00065.html
+# and
+#   http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9728
+#
+AM_LDFLAGS = -no-install -L$(top_builddir)/src/.libs
diff -Naur mpfr-3.1.0.orig/tests/Makefile.in mpfr-3.1.0/tests/Makefile.in
--- mpfr-3.1.0.orig/tests/Makefile.in	2011-10-03 08:17:35.000000000 +0000
+++ mpfr-3.1.0/tests/Makefile.in	2011-10-03 08:17:35.000000000 +0000
@@ -1124,11 +1124,27 @@
 TESTS = $(check_PROGRAMS)
 TESTS_ENVIRONMENT = MPFR_QUIET=1 $(VALGRIND)
 
-# Option to prevent libtool from generating wrapper scripts for the tests.
+# The -no-install option prevents libtool from generating wrapper scripts
+# for the tests.
 # This is useful to easily run the test scripts under valgrind or gdb.
 # See discussion http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/28033
 # http://article.gmane.org/gmane.comp.lib.gnulib.bugs/28140 in particular.
-AM_LDFLAGS = -no-install
+#
+# The -L$(top_builddir)/src/.libs option is necessary for some platforms,
+# such as HP-UX, when --with-gmp or --with-gmp-lib is used and an old MPFR
+# library is already installed in the corresponding lib directory: its
+# purpose is to make sure that the local .libs comes first in the library
+# search path (otherwise the tests are linked against the old MPFR library
+# by the LINK command -- see the generated Makefile). See:
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00042.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00043.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00044.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00066.html
+#   http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00065.html
+# and
+#   http://debbugs.gnu.org/cgi/bugreport.cgi?bug=9728
+#
+AM_LDFLAGS = -no-install -L$(top_builddir)/src/.libs
 all: all-am
 
 .SUFFIXES:
diff -Naur mpfr-3.1.0.orig/tests/trandom.c mpfr-3.1.0/tests/trandom.c
--- mpfr-3.1.0.orig/tests/trandom.c	2011-10-03 08:17:14.000000000 +0000
+++ mpfr-3.1.0/tests/trandom.c	2011-11-28 12:22:52.000000000 +0000
@@ -114,21 +114,29 @@
   mpfr_t x;
   gmp_randstate_t s;
 
+#if __MPFR_GMP(4,2,0)
+# define C1 "0.895943"
+# define C2 "0.848824"
+#else
+# define C1 "0.479652"
+# define C2 "0.648529"
+#endif
+
   gmp_randinit_default (s);
   gmp_randseed_ui (s, 42);
   mpfr_init2 (x, 17);
   mpfr_urandomb (x, s);
-  if (mpfr_cmp_str1 (x, "0.895943") != 0)
+  if (mpfr_cmp_str1 (x, C1) != 0)
     {
-      printf ("Error in bug20100914, expected 0.895943, got ");
+      printf ("Error in bug20100914, expected " C1 ", got ");
       mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
       printf ("\n");
       exit (1);
     }
   mpfr_urandomb (x, s);
-  if (mpfr_cmp_str1 (x, "0.848824") != 0)
+  if (mpfr_cmp_str1 (x, C2) != 0)
     {
-      printf ("Error in bug20100914, expected 0.848824, got ");
+      printf ("Error in bug20100914, expected " C2 ", got ");
       mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
       printf ("\n");
       exit (1);
diff -Naur mpfr-3.1.0.orig/tests/tsprintf.c mpfr-3.1.0/tests/tsprintf.c
--- mpfr-3.1.0.orig/tests/tsprintf.c	2011-10-03 08:17:14.000000000 +0000
+++ mpfr-3.1.0/tests/tsprintf.c	2011-11-03 15:15:11.000000000 +0000
@@ -475,6 +475,18 @@
   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);
@@ -1078,6 +1090,23 @@
   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
@@ -1161,6 +1190,7 @@
   locale = setlocale (LC_ALL, "C");
 #endif
 
+  bug20111102 ();
   native_types ();
   hexadecimal ();
   binary ();
diff -Naur mpfr-3.1.0.orig/tests/turandom.c mpfr-3.1.0/tests/turandom.c
--- mpfr-3.1.0.orig/tests/turandom.c	2011-10-03 08:17:14.000000000 +0000
+++ mpfr-3.1.0/tests/turandom.c	2011-11-28 12:22:52.000000000 +0000
@@ -160,23 +160,29 @@
   mpfr_t x;
   gmp_randstate_t s;
 
+#if __MPFR_GMP(4,2,0)
+# define C1 "0.8488312"
+# define C2 "0.8156509"
+#else
+# define C1 "0.6485367"
+# define C2 "0.9362717"
+#endif
+
   gmp_randinit_default (s);
   gmp_randseed_ui (s, 42);
   mpfr_init2 (x, 17);
   mpfr_urandom (x, s, MPFR_RNDN);
-  /* the following values are obtained on a 32-bit computer, we should get
-     the same values on a 64-bit computer */
-  if (mpfr_cmp_str1 (x, "0.8488312") != 0)
+  if (mpfr_cmp_str1 (x, C1) != 0)
     {
-      printf ("Error in bug20100914, expected 0.8488312, got ");
+      printf ("Error in bug20100914, expected " C1 ", got ");
       mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
       printf ("\n");
       exit (1);
     }
   mpfr_urandom (x, s, MPFR_RNDN);
-  if (mpfr_cmp_str1 (x, "0.8156509") != 0)
+  if (mpfr_cmp_str1 (x, C2) != 0)
     {
-      printf ("Error in bug20100914, expected 0.8156509, got ");
+      printf ("Error in bug20100914, expected " C2 ", got ");
       mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
       printf ("\n");
       exit (1);
