The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Index: src/kernel/none/mp.c
===================================================================
RCS file: /home/cvs/pari/src/kernel/none/mp.c,v
retrieving revision 1.33.2.3
diff -u -r1.33.2.3 mp.c
--- ./src/kernel/none/mp.c	29 Jan 2002 13:46:23 -0000	1.33.2.3
+++ ./src/kernel/none/mp.c	10 Oct 2005 09:45:44 -0000
@@ -2314,9 +2314,22 @@
 
   if (x==0) { z[1]=evalexpo(-308); z[2]=0; return z; }
   fi.f = x;
-  e = evalexpo(((fi.i & (HIGHBIT-1)) >> mant_len) - exp_mid);
-  z[1] = e | evalsigne(x<0? -1: 1);
-  z[2] = (fi.i << expo_len) | HIGHBIT;
+  {
+    const ulong a = fi.i;
+    ulong A;
+    e = ((a & (HIGHBIT-1)) >> mant_len) - exp_mid;
+    if (e == exp_mid+1) err(talker, "NaN or Infinity in dbltor");
+    A = a << expo_len;
+    if (e == -exp_mid)
+    { /* unnormalized values */
+      int sh = bfffo(A);
+      e -= sh-1;
+      z[2] = A << sh;
+    }
+    else
+      z[2] = HIGHBIT | A;
+    z[1] = evalexpo(e) | evalsigne(x<0? -1: 1);
+  }
   return z;
 }
 
@@ -2370,10 +2383,35 @@
   {
     const ulong a = fi.i[INDEX0];
     const ulong b = fi.i[INDEX1];
-    e = evalexpo(((a & (HIGHBIT-1)) >> shift) - exp_mid);
-    z[1] = e | evalsigne(x<0? -1: 1);
-    z[3] = b << expo_len;
-    z[2] = HIGHBIT | b >> (BITS_IN_LONG-expo_len) | (a << expo_len);
+    ulong A, B;
+    e = ((a & (HIGHBIT-1)) >> shift) - exp_mid;
+    if (e == exp_mid+1) err(talker, "NaN or Infinity in dbltor");
+    A = b >> (BITS_IN_LONG-expo_len) | (a << expo_len);
+    B = b << expo_len;
+    if (e == -exp_mid)
+    { /* unnormalized values */
+      int sh;
+      if (A)
+      {
+        sh = bfffo(A);
+        e -= sh-1;
+        z[2] = (A << sh) | (B >> (32-sh));
+        z[3] = B << sh;
+      }
+      else 
+      {
+        sh = bfffo(B); /* B != 0 */
+        e -= sh-1 + 32;
+        z[2] = B << sh;
+        z[3] = 0;
+      }
+    }
+    else
+    {
+      z[3] = B;
+      z[2] = HIGHBIT | A;
+    }
+    z[1] = evalexpo(e) | evalsigne(x<0? -1: 1);
   }
   return z;
 }