diff -Naurd mpfr-3.1.3-a/PATCHES mpfr-3.1.3-b/PATCHES
--- mpfr-3.1.3-a/PATCHES	2015-07-17 08:54:48.592799981 +0000
+++ mpfr-3.1.3-b/PATCHES	2015-07-17 08:54:48.616811495 +0000
@@ -0,0 +1 @@
+muldiv-2exp-underflow
diff -Naurd mpfr-3.1.3-a/VERSION mpfr-3.1.3-b/VERSION
--- mpfr-3.1.3-a/VERSION	2015-07-02 10:50:08.126574142 +0000
+++ mpfr-3.1.3-b/VERSION	2015-07-17 08:54:48.616811495 +0000
@@ -1 +1 @@
-3.1.3-p2
+3.1.3-p3
diff -Naurd mpfr-3.1.3-a/src/div_2si.c mpfr-3.1.3-b/src/div_2si.c
--- mpfr-3.1.3-a/src/div_2si.c	2015-07-02 10:50:08.106573933 +0000
+++ mpfr-3.1.3-b/src/div_2si.c	2015-07-17 08:54:48.608807656 +0000
@@ -45,7 +45,8 @@
           if (rnd_mode == MPFR_RNDN &&
               (__gmpfr_emin > MPFR_EMAX_MAX - (n - 1) ||
                exp < __gmpfr_emin + (n - 1) ||
-               (inexact >= 0 && mpfr_powerof2_raw (y))))
+               ((MPFR_IS_NEG (y) ? inexact <= 0 : inexact >= 0) &&
+                mpfr_powerof2_raw (y))))
             rnd_mode = MPFR_RNDZ;
           return mpfr_underflow (y, rnd_mode, MPFR_SIGN(y));
         }
diff -Naurd mpfr-3.1.3-a/src/div_2ui.c mpfr-3.1.3-b/src/div_2ui.c
--- mpfr-3.1.3-a/src/div_2ui.c	2015-07-02 10:50:08.106573933 +0000
+++ mpfr-3.1.3-b/src/div_2ui.c	2015-07-17 08:54:48.608807656 +0000
@@ -44,7 +44,9 @@
       if (MPFR_UNLIKELY (n >= diffexp))  /* exp - n <= emin - 1 */
         {
           if (rnd_mode == MPFR_RNDN &&
-              (n > diffexp || (inexact >= 0 && mpfr_powerof2_raw (y))))
+              (n > diffexp ||
+               ((MPFR_IS_NEG (y) ? inexact <= 0 : inexact >= 0) &&
+                mpfr_powerof2_raw (y))))
             rnd_mode = MPFR_RNDZ;
           return mpfr_underflow (y, rnd_mode, MPFR_SIGN (y));
         }
diff -Naurd mpfr-3.1.3-a/src/mpfr.h mpfr-3.1.3-b/src/mpfr.h
--- mpfr-3.1.3-a/src/mpfr.h	2015-07-02 10:50:08.126574142 +0000
+++ mpfr-3.1.3-b/src/mpfr.h	2015-07-17 08:54:48.616811495 +0000
@@ -27,7 +27,7 @@
 #define MPFR_VERSION_MAJOR 3
 #define MPFR_VERSION_MINOR 1
 #define MPFR_VERSION_PATCHLEVEL 3
-#define MPFR_VERSION_STRING "3.1.3-p2"
+#define MPFR_VERSION_STRING "3.1.3-p3"
 
 /* Macros dealing with MPFR VERSION */
 #define MPFR_VERSION_NUM(a,b,c) (((a) << 16L) | ((b) << 8) | (c))
diff -Naurd mpfr-3.1.3-a/src/mul_2si.c mpfr-3.1.3-b/src/mul_2si.c
--- mpfr-3.1.3-a/src/mul_2si.c	2015-07-02 10:50:08.106573933 +0000
+++ mpfr-3.1.3-b/src/mul_2si.c	2015-07-17 08:54:48.608807656 +0000
@@ -48,7 +48,8 @@
           if (rnd_mode == MPFR_RNDN &&
               (__gmpfr_emin > MPFR_EMAX_MAX + (n + 1) ||
                exp < __gmpfr_emin - (n + 1) ||
-               (inexact >= 0 && mpfr_powerof2_raw (y))))
+               ((MPFR_IS_NEG (y) ? inexact <= 0 : inexact >= 0) &&
+                mpfr_powerof2_raw (y))))
             rnd_mode = MPFR_RNDZ;
           return mpfr_underflow (y, rnd_mode, MPFR_SIGN(y));
         }
diff -Naurd mpfr-3.1.3-a/src/version.c mpfr-3.1.3-b/src/version.c
--- mpfr-3.1.3-a/src/version.c	2015-07-02 10:50:08.126574142 +0000
+++ mpfr-3.1.3-b/src/version.c	2015-07-17 08:54:48.616811495 +0000
@@ -25,5 +25,5 @@
 const char *
 mpfr_get_version (void)
 {
-  return "3.1.3-p2";
+  return "3.1.3-p3";
 }
diff -Naurd mpfr-3.1.3-a/tests/tmul_2exp.c mpfr-3.1.3-b/tests/tmul_2exp.c
--- mpfr-3.1.3-a/tests/tmul_2exp.c	2015-07-02 10:50:08.106573933 +0000
+++ mpfr-3.1.3-b/tests/tmul_2exp.c	2015-07-17 08:54:48.608807656 +0000
@@ -50,77 +50,82 @@
 {
   mpfr_t x, y, z1, z2;
   mpfr_exp_t emin;
-  int i, k;
+  int i, k, s;
   int prec;
   int rnd;
   int div;
   int inex1, inex2;
   unsigned int flags1, flags2;
 
-  /* Test mul_2si(x, e - k), div_2si(x, k - e) and div_2ui(x, k - e)
-   * with emin = e, x = 1 + i/16, i in { -1, 0, 1 }, and k = 1 to 4,
-   * by comparing the result with the one of a simple division.
+  /* Test mul_2si(x, e - k), div_2si(x, k - e) and div_2ui(x, k - e) with
+   * emin = e, x = s * (1 + i/16), i in { -1, 0, 1 }, s in { -1, 1 }, and
+   * k = 1 to 4, by comparing the result with the one of a simple division.
    */
   emin = mpfr_get_emin ();
   set_emin (e);
   mpfr_inits2 (8, x, y, (mpfr_ptr) 0);
   for (i = 15; i <= 17; i++)
-    {
-      inex1 = mpfr_set_ui_2exp (x, i, -4, MPFR_RNDN);
-      MPFR_ASSERTN (inex1 == 0);
-      for (prec = 6; prec >= 3; prec -= 3)
-        {
-          mpfr_inits2 (prec, z1, z2, (mpfr_ptr) 0);
-          RND_LOOP (rnd)
-            for (k = 1; k <= 4; k++)
-              {
-                /* The following one is assumed to be correct. */
-                inex1 = mpfr_mul_2si (y, x, e, MPFR_RNDN);
-                MPFR_ASSERTN (inex1 == 0);
-                inex1 = mpfr_set_ui (z1, 1 << k, MPFR_RNDN);
-                MPFR_ASSERTN (inex1 == 0);
-                mpfr_clear_flags ();
-                /* Do not use mpfr_div_ui to avoid the optimization
-                   by mpfr_div_2si. */
-                inex1 = mpfr_div (z1, y, z1, (mpfr_rnd_t) rnd);
-                flags1 = __gmpfr_flags;
-
-              for (div = 0; div <= 2; div++)
+    for (s = 1; s >= -1; s -= 2)
+      {
+        inex1 = mpfr_set_si_2exp (x, s * i, -4, MPFR_RNDN);
+        MPFR_ASSERTN (inex1 == 0);
+        for (prec = 6; prec >= 3; prec -= 3)
+          {
+            mpfr_inits2 (prec, z1, z2, (mpfr_ptr) 0);
+            RND_LOOP (rnd)
+              for (k = 1; k <= 4; k++)
                 {
+                  /* The following one is assumed to be correct. */
+                  inex1 = mpfr_mul_2si (y, x, e, MPFR_RNDN);
+                  MPFR_ASSERTN (inex1 == 0);
+                  inex1 = mpfr_set_ui (z1, 1 << k, MPFR_RNDN);
+                  MPFR_ASSERTN (inex1 == 0);
                   mpfr_clear_flags ();
-                  inex2 = div == 0 ?
-                    mpfr_mul_2si (z2, x, e - k, (mpfr_rnd_t) rnd) : div == 1 ?
-                    mpfr_div_2si (z2, x, k - e, (mpfr_rnd_t) rnd) :
-                    mpfr_div_2ui (z2, x, k - e, (mpfr_rnd_t) rnd);
-                  flags2 = __gmpfr_flags;
-                  if (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
-                      mpfr_equal_p (z1, z2))
-                    continue;
-                  printf ("Error in underflow(");
-                  if (e == MPFR_EMIN_MIN)
-                    printf ("MPFR_EMIN_MIN");
-                  else if (e == emin)
-                    printf ("default emin");
-                  else if (e >= LONG_MIN)
-                    printf ("%ld", (long) e);
-                  else
-                    printf ("<LONG_MIN");
-                  printf (") with mpfr_%s,\nx = %d/16, prec = %d, k = %d, "
-                          "%s\n", div == 0 ? "mul_2si" : div == 1 ?
-                          "div_2si" : "div_2ui", i, prec, k,
-                          mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
-                  printf ("Expected ");
-                  mpfr_out_str (stdout, 16, 0, z1, MPFR_RNDN);
-                  printf (", inex = %d, flags = %u\n", SIGN (inex1), flags1);
-                  printf ("Got      ");
-                  mpfr_out_str (stdout, 16, 0, z2, MPFR_RNDN);
-                  printf (", inex = %d, flags = %u\n", SIGN (inex2), flags2);
-                  exit (1);
-                }  /* div */
-              }  /* k */
-          mpfr_clears (z1, z2, (mpfr_ptr) 0);
-        }  /* prec */
-    }  /* i */
+                  /* Do not use mpfr_div_ui to avoid the optimization
+                     by mpfr_div_2si. */
+                  inex1 = mpfr_div (z1, y, z1, (mpfr_rnd_t) rnd);
+                  flags1 = __gmpfr_flags;
+
+                  for (div = 0; div <= 2; div++)
+                    {
+                      mpfr_clear_flags ();
+                      inex2 =
+                        div == 0 ?
+                        mpfr_mul_2si (z2, x, e - k, (mpfr_rnd_t) rnd) :
+                        div == 1 ?
+                        mpfr_div_2si (z2, x, k - e, (mpfr_rnd_t) rnd) :
+                        mpfr_div_2ui (z2, x, k - e, (mpfr_rnd_t) rnd);
+                      flags2 = __gmpfr_flags;
+                      if (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
+                          mpfr_equal_p (z1, z2))
+                        continue;
+                      printf ("Error in underflow(");
+                      if (e == MPFR_EMIN_MIN)
+                        printf ("MPFR_EMIN_MIN");
+                      else if (e == emin)
+                        printf ("default emin");
+                      else if (e >= LONG_MIN)
+                        printf ("%ld", (long) e);
+                      else
+                        printf ("<LONG_MIN");
+                      printf (") with mpfr_%s,\nx = %d/16, prec = %d, k = %d,"
+                              " %s\n", div == 0 ? "mul_2si" : div == 1 ?
+                              "div_2si" : "div_2ui", s * i, prec, k,
+                              mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+                      printf ("Expected ");
+                      mpfr_out_str (stdout, 16, 0, z1, MPFR_RNDN);
+                      printf (", inex = %d, flags = %u\n",
+                              SIGN (inex1), flags1);
+                      printf ("Got      ");
+                      mpfr_out_str (stdout, 16, 0, z2, MPFR_RNDN);
+                      printf (", inex = %d, flags = %u\n",
+                              SIGN (inex2), flags2);
+                      exit (1);
+                    }  /* div */
+                }  /* k */
+            mpfr_clears (z1, z2, (mpfr_ptr) 0);
+          }  /* prec */
+      }  /* i */
   mpfr_clears (x, y, (mpfr_ptr) 0);
   set_emin (emin);
 }
