Re: Partial Double/Float merge with libgcj

2001-10-23 Thread Chris Gray

Tom Tromey wrote:

> > "Chris" == Chris Gray <[EMAIL PROTECTED]> writes:
>
> Chris> An interesting twist on this: jikes seems to have its own idea
> Chris> of the correct bit-pattern for NaN (0xffc0 instead of
> Chris> 0x7fc).  This shouldn't matter if all NaN's are
> Chris> canonicalized to the same value.
>
> My understanding is that floatToIntBits is required to return
> 0x7fc0 for any NaN, and that Float.NaN must be the same as
> Float.intBitsToFloat(0x7fc0).
>
> This doesn't necessarily imply that there is a Jikes bug though.

No.  It just means that Float.floatToRawIntBits(Float.NaN) returns
0xffc0 when you might naively have expected 0x7fc0.

>
> It depends on exactly when Jikes uses that particular value.
> Float.floatToRawIntBits can return other NaN values, and presumably
> the VM could use them as well.  For instace libgcj uses whatever
> the underlying hardware decides, and only does the canonicalization
> when the real bit pattern might be seen by Java.
>
> Tom
>
> ___
> Classpath mailing list
> [EMAIL PROTECTED]
> http://mail.gnu.org/mailman/listinfo/classpath


___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Re: Partial Double/Float merge with libgcj

2001-10-15 Thread Tom Tromey

> "Eric" == Eric Blake <[EMAIL PROTECTED]> writes:

Eric> However, I argue that this is a faster implementation (it avoids a
Eric> native call):
Eric> 
Eric> public static boolean isNaN(double v)
Eric> {
Eric> return v != v;
Eric> }

This seems reasonable to me too.

Tom

___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Re: Partial Double/Float merge with libgcj

2001-10-15 Thread Eric Blake

Shoot, I meant to hit reply-to-all.

Eric Blake wrote:
> 
> Chris Gray wrote:
> >
> >
> > An interesting twist on this: jikes seems to have its own idea of the correct
> > bit-pattern for NaN (0xffc0 instead of 0x7fc).  This shouldn't matter
> > if all NaN's are canonicalized to the same value.
> 
> Which version of jikes? My guess is version 1.13 or sooner, as floating
> point emulation mode was made default in later versions. When doing
> floating point emulation jikes should always spit out 0x7fc0 for
> Float.NaN, but with native math, it uses whatever the CPU thinks is NaN
> (which for x86 architecture is 0xffc0).  But you are right, as long
> as Float.floatToLongBits canonicalizes NaN, there should be no problem
> with the current algorithm.
> 
> However, I argue that this is a faster implementation (it avoids a
> native call):
> 
> public static boolean isNaN(double v)
> {
>   return v != v;
> }
> 
> This works since NaN != NaN is the only reflexive inequality comparison
> which returns true.

-- 
This signature intentionally left boring.

Eric Blake [EMAIL PROTECTED]
  BYU student, free software programmer

___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Re: Partial Double/Float merge with libgcj

2001-10-15 Thread Tom Tromey

> "Chris" == Chris Gray <[EMAIL PROTECTED]> writes:

Chris> An interesting twist on this: jikes seems to have its own idea
Chris> of the correct bit-pattern for NaN (0xffc0 instead of
Chris> 0x7fc).  This shouldn't matter if all NaN's are
Chris> canonicalized to the same value.

My understanding is that floatToIntBits is required to return
0x7fc0 for any NaN, and that Float.NaN must be the same as
Float.intBitsToFloat(0x7fc0).

This doesn't necessarily imply that there is a Jikes bug though.
It depends on exactly when Jikes uses that particular value.
Float.floatToRawIntBits can return other NaN values, and presumably
the VM could use them as well.  For instace libgcj uses whatever
the underlying hardware decides, and only does the canonicalization
when the real bit pattern might be seen by Java.

Tom

___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Re: Partial Double/Float merge with libgcj

2001-10-15 Thread Chris Gray

Tom Tromey wrote:

> > "Mark" == Mark Wielaard <[EMAIL PROTECTED]> 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 ...
>

I too am not worthy ...

>
> Mark>public static boolean isNaN (double v)
> Mark>{
> Mark> -return (doubleToLongBits (v) == 0x7ff8L);
> Mark> +long bits = doubleToLongBits (v);
> Mark> +long e = bits & 0x7ff0L;
> Mark> +long f = bits & 0x000fL;
> Mark> +
> Mark> +return e == 0x7ff0L && 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.
>

An interesting twist on this: jikes seems to have its own idea of the correct
bit-pattern for NaN (0xffc0 instead of 0x7fc).  This shouldn't matter
if all NaN's are canonicalized to the same value.

Chris Gray
VM Architect, ACUNIA



___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Re: Partial Double/Float merge with libgcj

2001-10-12 Thread Tom Tromey

> "Mark" == Mark Wielaard <[EMAIL PROTECTED]> 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) == 0x7ff8L);
Mark> +long bits = doubleToLongBits (v);
Mark> +long e = bits & 0x7ff0L;
Mark> +long f = bits & 0x000fL;
Mark> +
Mark> +return e == 0x7ff0L && 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 & 0x7fffL;
Mark> +
Mark> +return f == 0x7ff0L;
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) == 0x7fc0);
Mark> +int bits = floatToIntBits (v);
Mark> +int e = bits & 0x7f80;
Mark> +int f = bits & 0x007f;
Mark> +
Mark> +return e == 0x7f80 && 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 & 0x7fff;
Mark> +
Mark> +return f == 0x7f80;
Mark>}

These are equivalent.

Tom

___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Partial Double/Float merge with libgcj

2001-10-12 Thread Mark Wielaard

Hi,

Brian Jones had merged java.lang.Double/Float a couple of months ago.
But there were still a couple of comment/indentation differences.
I reindented/reformatted and renamed a method variable here and there.
The actual code changes are minimal:

* java/lang/Double.java: Partial merge with libgcj
(serialVersionUID): new private field
(byteValue): removed, already defined in superclass Number
(shortValue): likewise
* java/lang/Float.java: Partial merge with libgcj
(serialVersionUID): new private field

There are still a few differences between the code and I did not look
at the native code at all. If my patch is accepted by the libgcj people
then the actual diff between the Classpath and libgcj version looks like
the attached diff. Maybe someone who knows a bit about float/doubles in
java can comment on these differences.

Cheers,

Mark
-- 
Stuff to read:

  What's Wrong with Copy Protection, by John Gilmore


--- java/lang/Double.java   Fri Oct 12 16:08:07 2001
+++ ../gcc-3-1/libjava/java/lang/Double.javaFri Oct 12 16:10:50 2001
@@ -248,7 +248,11 @@
*/
   public static boolean isNaN (double v)
   {
-return (doubleToLongBits (v) == 0x7ff8L);
+long bits = doubleToLongBits (v);
+long e = bits & 0x7ff0L;
+long f = bits & 0x000fL;
+
+return e == 0x7ff0L && f != 0L;
   }
 
   /**
@@ -273,7 +277,10 @@
*/
   public static boolean isInfinite (double v)
   {
-return (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY);
+long bits = doubleToLongBits (v);
+long f = bits & 0x7fffL;
+
+return f == 0x7ff0L;
   }
 
   /**
@@ -494,18 +501,12 @@
* @see #NEGATIVE_INFINITY
* @since 1.2
*/
-  public static double parseDouble (String s) throws NumberFormatException
-  {
-String t = s.trim ();
-  return parseDouble0 (t);
-  }
-
-  private static native double parseDouble0 (String s)
+  public native static double parseDouble (String s) 
 throws NumberFormatException;
 
   /**
* Initialize JNI cache.  This method is called only by the 
* static initializer when using JNI.
*/
-  private static native void initIDs ();
+  private static void initIDs () { /* Not used in libgcj */ };
 }


--- java/lang/Float.javaFri Oct 12 14:37:56 2001
+++ ../gcc-3-1/libjava/java/lang/Float.java Fri Oct 12 14:33:38 2001
@@ -221,7 +221,12 @@
*/
   public boolean equals (Object obj)
   {
-return (obj instanceof Float && ((Float) obj).value == value);
+if (!(obj instanceof Float))
+  return false;
+
+Float f = (Float) obj;
+
+return floatToIntBits (value) == floatToIntBits (f.floatValue ());
   }
 
   /**
@@ -359,7 +364,11 @@
*/
   public static boolean isNaN (float v)
   {
-return (floatToIntBits (v) == 0x7fc0);
+int bits = floatToIntBits (v);
+int e = bits & 0x7f80;
+int f = bits & 0x007f;
+
+return e == 0x7f80 && f != 0;
   }
 
   /**
@@ -384,7 +393,10 @@
*/
   public static boolean isInfinite (float v)
   {
-return (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY);
+int bits = floatToIntBits (v);
+int f = bits & 0x7fff;
+
+return f == 0x7f80;
   }
 
   /**