[Top][All Lists]
[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