classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Partial Double/Float merge with libgcj


From: Tom Tromey
Subject: Re: Partial Double/Float merge with libgcj
Date: 12 Oct 2001 11:24:14 -0600

>>>>> "Mark" == Mark Wielaard <address@hidden> writes:

Mark> Maybe someone who knows a bit about float/doubles in java can
Mark> comment on these differences.

I don't know if I qualify, but ...

Mark>    public static boolean isNaN (double v)
Mark>    {
Mark> -    return (doubleToLongBits (v) == 0x7ff8000000000000L);
Mark> +    long bits = doubleToLongBits (v);
Mark> +    long e = bits & 0x7ff0000000000000L;
Mark> +    long f = bits & 0x000fffffffffffffL;
Mark> +
Mark> +    return e == 0x7ff0000000000000L && f != 0L;
Mark>    }

I think this is a remnant of when libgcj's doubleToLongBits would
return the actual raw value instead of turning all NaNs into a single
value.  Both implementations are correct, but the Classpath
implementation is more desirable.

Mark>    public static boolean isInfinite (double v)
Mark>    {
Mark> -    return (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY);
Mark> +    long bits = doubleToLongBits (v);
Mark> +    long f = bits & 0x7fffffffffffffffL;
Mark> +
Mark> +    return f == 0x7ff0000000000000L;
Mark>    }

These implementations are equivalent.

Mark> -  public static double parseDouble (String s) throws 
NumberFormatException
Mark> -  {
Mark> -    String t = s.trim ();
Mark> -      return parseDouble0 (t);
Mark> -  }
Mark> -
Mark> -  private static native double parseDouble0 (String s)
Mark> +  public native static double parseDouble (String s) 
Mark>      throws NumberFormatException;

Here the Classpath code seems a bit wasteful.  Can't the native code
do the trimming for us?  Then we avoid allocating a new String.

Mark> -  private static native void initIDs ();
Mark> +  private static void initIDs () { /* Not used in libgcj */ };

Feel free to add a native initIDs() method to libgcj.  It can just do
nothing, or maybe throw InternalError.

Mark>    public boolean equals (Object obj)
Mark>    {
Mark> -    return (obj instanceof Float && ((Float) obj).value == value);
Mark> +    if (!(obj instanceof Float))
Mark> +      return false;
Mark> +
Mark> +    Float f = (Float) obj;
Mark> +
Mark> +    return floatToIntBits (value) == floatToIntBits (f.floatValue ());
Mark>    }

Here I think the libgcj implementation is correct.
`==' on float values will decide 0.0 == -0.0.
Comparing the bits decides 0.0 != -0.0, which is required for
equals().
Similarly, `==' and equals() disagree on whether NaNs are equal.

Mark>    public static boolean isNaN (float v)
Mark>    {
Mark> -    return (floatToIntBits (v) == 0x7fc00000);
Mark> +    int bits = floatToIntBits (v);
Mark> +    int e = bits & 0x7f800000;
Mark> +    int f = bits & 0x007fffff;
Mark> +
Mark> +    return e == 0x7f800000 && f != 0;
Mark>    }

This is the same as the Double case; the Classpath implementation is
better.

Mark>    public static boolean isInfinite (float v)
Mark>    {
Mark> -    return (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY);
Mark> +    int bits = floatToIntBits (v);
Mark> +    int f = bits & 0x7fffffff;
Mark> +
Mark> +    return f == 0x7f800000;
Mark>    }

These are equivalent.

Tom



reply via email to

[Prev in Thread] Current Thread [Next in Thread]