classpath
[Top][All Lists]
Advanced

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

floats ??????


From: Giannis Georgalis
Subject: floats ??????
Date: 14 Sep 2002 20:55:53 +0300
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50

Hello guys,

As I was adviced, in order to contribute to GNU classpath, I've
downloaded and built yesterday's CVS tree of GNU classpath, CVS tree
of kissme, jikes, and mauve. Some inquiries, requests and suggestions
follow;

This period I have quite a lot of spare time.
This is a very good chance for me to get familiar with GNU
classpath and contribute as much as I can! I would appreciate some
pointers and resources that will help me speed up my understanding
of classpath code.

I've successfully installed the latest GNU classpath CVS tree with
latest jikes and latest kissme CVS tree (I did that today). As I was
playing around with mauve and classpath, in order to get a general
idea of the project, I encountered a very strange behavior in the
way Java floats work ... That of-course helped me to search around
the code and have an average overall understanding of the jni. I'll
be more specific;
I've run mauve with these keys:

KEYS = !java. java.lang. !java.lang.Character. !java.lang.Class. 
!java.lang.reflect.

and the following tests FAILED (a subset):
FAIL: gnu.testlet.java.lang.Float.new_Float (number 9)
FAIL: gnu.testlet.java.lang.Math.max (number 23)
FAIL: gnu.testlet.java.lang.Math.max (number 26)
<snip>

Now, that's strange because the implementation of the java.lang.Float
is correct!!!  (and so is java.lang.Math). I'm assuming that there is
a serious problem in the representation of the java floats (jfloat).
I'm aware that jfloat is typedef'ed (C/C++) float and I'm absolutely
sure that (C/C++) floats work *fine* on my machine (I've extensively
tested them). I'll just provide one of the cases that java floats fail
to work properly (there are quite some cases, but I think the root of
evil is the same).

take as an example the code:

float a=-1.0f,b=-2.0f;
if(a > b)x
  System.out.println("correct!!");
else
  System.out.println("FAIL !!!");

It outputs "FAIL !!!", but if I substitute the line:
"float a=-1.0f,b=-2.0f;" with "double a=-1.0f,b=-2.0f;"
it outputs "correct!!".

Is this a GNU classpath problem, a jikes problem or a kissme problem ?
I made some changes to java.lang.Float, so that it passes the tests,
but the solution is a very nasty hack so it cannot be taken seriously,
as the problem resides on the nature of java primitive floats and not 
the class' implementation.

--------------------start patch-----------------------

*** Float.java.~1.25.~  Mon Feb 25 22:02:58 2002
--- Float.java  Fri Sep 13 16:00:47 2002
***************
*** 84,91 ****
  
    /**
     * All IEEE 754 values of NaN have the same value in Java.
     */
!   public static final float NaN = 0.0f / 0.0f;
  
    /**
     * The primitive type <code>float</code> is represented by this
--- 84,94 ----
  
    /**
     * All IEEE 754 values of NaN have the same value in Java.
+    * NaN value is the same with the return value of
+    * intBitsToFloat(0x7fc00000).
+    * @see intBitsToFloat(int bits)
     */
!   public static final float NaN = intBitsToFloat(0x7fc00000);
  
    /**
     * The primitive type <code>float</code> is represented by this
***************
*** 185,191 ****
     */
    public static String toString(float f)
    {
!     return Double.toString(f, true);
    }
  
    /**
--- 188,194 ----
     */
    public static String toString(float f)
    {
!     return Double.toString((double)f, true);
    }
  
    /**
***************
*** 270,276 ****
    {
      // This works since NaN != NaN is the only reflexive inequality
      // comparison which returns true.
!     return v != v;
    }
  
    /**
--- 273,282 ----
    {
      // This works since NaN != NaN is the only reflexive inequality
      // comparison which returns true.
!     // FIXME: (very nasty hack) see also Float.NaN.
!     // I've added the "|| v == NaN", which makes isNaN work correctly.
!     // I have no idea why the initial version doesn't work...
!     return (v != v) || (v == NaN);
    }
  
    /**

--------------------end patch-----------------------

Additionally in my effort to figure out what is going on, I have
altered a jni file and prevented it from calling a java method. I
think this minor change makes it more efficient. ...and it is portable
(tested on solaris sparc gcc, solaris intel gcc/cc, sunos gcc,
gnu/linux intel gcc, gnu/linux alpha gcc). If you have a different
opinion, please tell me the reason, so I can adapt to the "philosophy"
of the project.

--------------------start patch-----------------------

*** java_lang_Double.c.~1.9.~   Wed Aug 14 00:15:03 2002
--- java_lang_Double.c  Fri Sep 13 02:28:20 2002
***************
*** 47,53 ****
  
  #include "java_lang_Double.h"
  
- static jmethodID isNaNID;
  static jdouble NEGATIVE_INFINITY;
  static jdouble POSITIVE_INFINITY;
  
--- 47,52 ----
***************
*** 62,73 ****
    jfieldID negInfID;
    jfieldID posInfID;
  
!   isNaNID = (*env)->GetStaticMethodID(env, cls, "isNaN", "(D)Z");
!   if (isNaNID == NULL)
!     {
!       DBG("unable to determine method id of isNaN\n")
!       return;
!     }
    negInfID = (*env)->GetStaticFieldID(env, cls, "NEGATIVE_INFINITY", "D");
    if (negInfID == NULL)
      {
--- 61,73 ----
    jfieldID negInfID;
    jfieldID posInfID;
  
! /*   isNaNID = (*env)->GetStaticMethodID(env, cls, "isNaN", "(D)Z"); */
! /*   if (isNaNID == NULL) */
! /*     { */
! /*       DBG("unable to determine method id of isNaN\n") */
! /*       return; */
! /*     } */
! 
    negInfID = (*env)->GetStaticFieldID(env, cls, "NEGATIVE_INFINITY", "D");
    if (negInfID == NULL)
      {
***************
*** 153,178 ****
    fprintf (stderr, "java.lang.Double.toString (%g)\n", value);
  #endif
  
!   if ((*env)->CallStaticBooleanMethod(env, cls, isNaNID, value))
      return (*env)->NewStringUTF(env, "NaN");
    
    if (value == POSITIVE_INFINITY)
      return (*env)->NewStringUTF(env, "Infinity");
! 
    if (value == NEGATIVE_INFINITY)
      return (*env)->NewStringUTF(env, "-Infinity");
! 
    _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat);
! 
    value = fabs (value);
! 
    s = buffer;
    d = result;
! 
    if (sign)
      *d++ = '-';
! 
!   if (value >= 1e-3 && value < 1e7 || value == 0)
      {
        if (decpt <= 0)
        *d++ = '0';
--- 153,178 ----
    fprintf (stderr, "java.lang.Double.toString (%g)\n", value);
  #endif
  
!   if(value!=value)
      return (*env)->NewStringUTF(env, "NaN");
    
    if (value == POSITIVE_INFINITY)
      return (*env)->NewStringUTF(env, "Infinity");
!   
    if (value == NEGATIVE_INFINITY)
      return (*env)->NewStringUTF(env, "-Infinity");
!   
    _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat);
!   
    value = fabs (value);
!   
    s = buffer;
    d = result;
!   
    if (sign)
      *d++ = '-';
!   
!   if ((value >= 1e-3 && value < 1e7) || value == 0)
      {
        if (decpt <= 0)
        *d++ = '0';

--------------------end patch-----------------------

That's all I have to say for now. Please tell me what to do in order
to be most helpful to the project.

Thanks,
Giannis

-- 
Is God willing to prevent evil, but not able? Then he is not omnipotent.
Is he able, but not willing? Then he is malevolent.
Is he both able and willing? Then whence cometh evil?
Is he neither able nor willing? Then why call him God?
(Epicurus)





reply via email to

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