OSDN Git Service

Fix for PR libgcj/4583:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Nov 2001 19:32:28 +0000 (19:32 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Nov 2001 19:32:28 +0000 (19:32 +0000)
* java/math/BigDecimal.java (BigDecimal(double)): Rewrote.
(BigDecimal(String)): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@47329 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/java/math/BigDecimal.java

index 29413b8..2a6cd62 100644 (file)
@@ -1,3 +1,9 @@
+2001-11-25  Tom Tromey  <tromey@redhat.com>
+
+       Fix for PR libgcj/4583:
+       * java/math/BigDecimal.java (BigDecimal(double)): Rewrote.
+       (BigDecimal(String)): Likewise.
+
 2001-11-19  Tom Tromey  <tromey@redhat.com>
 
        * verify.cc (_Jv_BytecodeVerifier::branch_prepass) [op_iinc]:
index 6fbd927..bf803a2 100644 (file)
@@ -28,7 +28,8 @@ package java.math;
 
 import java.math.BigInteger;
 
-public class BigDecimal extends Number implements Comparable {
+public class BigDecimal extends Number implements Comparable
+{
   private BigInteger intVal;
   private int scale;
   private static final long serialVersionUID = 6108874887143696463L;
@@ -63,16 +64,119 @@ public class BigDecimal extends Number implements Comparable {
 
   public BigDecimal (double num) throws NumberFormatException 
   {
-    this (Double.toString (num));
+    if (Double.isInfinite (num) || Double.isNaN (num))
+      throw new NumberFormatException ("invalid argument: " + num);
+    // Note we can't convert NUM to a String and then use the
+    // String-based constructor.  The BigDecimal documentation makes
+    // it clear that the two constructors work differently.
+
+    final int mantissaBits = 52;
+    final int exponentBits = 11;
+    final long mantMask = (1L << mantissaBits) - 1;
+    final long expMask = (1L << exponentBits) - 1;
+
+    long bits = Double.doubleToLongBits (num);
+    long mantissa = bits & mantMask;
+    long exponent = (bits >>> mantissaBits) & expMask;
+    boolean denormal = exponent == 0;
+    // Correct the exponent for the bias.
+    exponent -= denormal ? 1022 : 1023;
+    // Now correct the exponent to account for the bits to the right
+    // of the decimal.
+    exponent -= mantissaBits;
+    // Ordinary numbers have an implied leading `1' bit.
+    if (! denormal)
+      mantissa |= (1L << mantissaBits);
+
+    // Shave off factors of 10.
+    while (exponent < 0 && (mantissa & 1) == 0)
+      {
+       ++exponent;
+       mantissa >>= 1;
+      }
+
+    intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa);
+    if (exponent < 0)
+      {
+       // We have MANTISSA * 2 ^ (EXPONENT).
+       // Since (1/2)^N == 5^N * 10^-N we can easily convert this
+       // into a power of 10.
+       scale = (int) (- exponent);
+       BigInteger mult = BigInteger.valueOf (5).pow (scale);
+       intVal = intVal.multiply (mult);
+      }
+    else
+      {
+       intVal = intVal.shiftLeft ((int) exponent);
+       scale = 0;
+      }
   }
 
   public BigDecimal (String num) throws NumberFormatException 
   {
-    int point = num.indexOf('.');
-    this.intVal = new BigInteger (point == -1 ? num :
-                              num.substring (0, point) + 
-                              num.substring (point + 1));
-    scale = num.length() - (point == -1 ? num.length () : point + 1);
+    int len = num.length();
+    int start = 0, point = 0;
+    int dot = -1;
+    boolean negative = false;
+    if (num.charAt(0) == '+')
+      {
+       ++start;
+       ++point;
+      }
+    else if (num.charAt(0) == '-')
+      {
+       ++start;
+       ++point;
+       negative = true;
+      }
+
+    while (point < len)
+      {
+       char c = num.charAt (point);
+       if (c == '.')
+         {
+           if (dot >= 0)
+             throw new NumberFormatException ("multiple `.'s in number");
+           dot = point;
+         }
+       else if (c == 'e' || c == 'E')
+         break;
+       else if (Character.digit (c, 10) < 0)
+         throw new NumberFormatException ("unrecognized character: " + c);
+       ++point;
+      }
+
+    String val;
+    if (dot >= 0)
+      {
+       val = num.substring (start, dot) + num.substring (dot + 1, point);
+       scale = point - 1 - dot;
+      }
+    else
+      {
+       val = num.substring (start, point);
+       scale = 0;
+      }
+    if (val.length () == 0)
+      throw new NumberFormatException ("no digits seen");
+
+    if (negative)
+      val = "-" + val;
+    intVal = new BigInteger (val);
+
+    // Now parse exponent.
+    if (point < len)
+      {
+       int exp = Integer.parseInt (num.substring (point + 1));
+       exp -= scale;
+       if (exp > 0)
+         {
+           intVal = intVal.multiply (BigInteger.valueOf (10).pow (exp));
+           scale = 0;
+         }
+       else
+         scale = - exp;
+      }
   }
 
   public static BigDecimal valueOf (long val) 
@@ -338,7 +442,6 @@ public class BigDecimal extends Number implements Comparable {
       intVal.divide (BigInteger.valueOf (10).pow (scale));
   }
 
-\f
   public int intValue () 
   {
     return toBigInteger ().intValue ();