Hi, While getting JikesRVM and IcedTea to build and run, I've found two problems with our Double/VMDouble implementation:
* parseDouble can't handle hex strings (PR32701)
* toString doesn't seem to handle some NaNs. This stopped JikesRVM building
with JamVM.
The attached patch contains a fix for the second of these that makes JamVM
build JikesRVM.
I'm not sure how correct it is, just that it works.
It also contains an attempt at the first, but I have to admit to completely
missing something
here, because what I have isn't working. I'm trying to handle hex strings by
inverting what
toHexString does, but I seem to be out on both the mantissa and exponent a bit.
I don't
think it yet handles all cases either. Help would be much appreciated :)
Changelog:
2007-07-15 Andrew John Hughes <[EMAIL PROTECTED]>
* native/jni/java-lang/java_lang_VMDouble.c:
(java_lang_VMDouble_toString): Do NaN check in C
instead of Java via !=.
(java_lang_VMDouble_natParseDouble): Renamed from
java_lang_VMDouble_parseDouble.
* vm/reference/java/lang/VMDouble.java:
(parseDouble(String)): Implement hex strings in Java,
and call natParseDouble otherwise.
(natParseDouble(String)): New native method.
--
Andrew :-)
Escape the Java Trap with GNU Classpath!
http://www.gnu.org/philosophy/java-trap.html
public class gcj extends Freedom implements Java { ... }
Index: include/java_lang_VMDouble.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/java_lang_VMDouble.h,v
retrieving revision 1.3
diff -u -3 -p -u -r1.3 java_lang_VMDouble.h
--- include/java_lang_VMDouble.h 16 Apr 2005 09:19:54 -0000 1.3
+++ include/java_lang_VMDouble.h 15 Jul 2007 21:29:42 -0000
@@ -15,7 +15,7 @@ JNIEXPORT jlong JNICALL Java_java_lang_V
JNIEXPORT jdouble JNICALL Java_java_lang_VMDouble_longBitsToDouble (JNIEnv *env, jclass, jlong);
JNIEXPORT jstring JNICALL Java_java_lang_VMDouble_toString (JNIEnv *env, jclass, jdouble, jboolean);
JNIEXPORT void JNICALL Java_java_lang_VMDouble_initIDs (JNIEnv *env, jclass);
-JNIEXPORT jdouble JNICALL Java_java_lang_VMDouble_parseDouble (JNIEnv *env, jclass, jstring);
+JNIEXPORT jdouble JNICALL Java_java_lang_VMDouble_natParseDouble (JNIEnv *env, jclass, jstring);
#ifdef __cplusplus
}
Index: native/jni/java-lang/java_lang_VMDouble.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/java-lang/java_lang_VMDouble.c,v
retrieving revision 1.17
diff -u -3 -p -u -r1.17 java_lang_VMDouble.c
--- native/jni/java-lang/java_lang_VMDouble.c 5 Apr 2007 12:41:34 -0000 1.17
+++ native/jni/java-lang/java_lang_VMDouble.c 15 Jul 2007 21:29:52 -0000
@@ -404,7 +404,7 @@ Java_java_lang_VMDouble_toString
jint least_necessary_precision = 2;
jboolean parsed_value_unequal;
- if ((*env)->CallStaticBooleanMethod (env, clsDouble, isNaNID, value))
+ if (value != value)
return (*env)->NewStringUTF (env, "NaN");
if (value == POSITIVE_INFINITY)
@@ -455,7 +455,7 @@ Java_java_lang_VMDouble_toString
* Signature: (Ljava/lang/String;)D
*/
JNIEXPORT jdouble JNICALL
-Java_java_lang_VMDouble_parseDouble
+Java_java_lang_VMDouble_natParseDouble
(JNIEnv * env, jclass cls __attribute__ ((__unused__)), jstring str)
{
jboolean isCopy;
Index: vm/reference/java/lang/VMDouble.java
===================================================================
RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMDouble.java,v
retrieving revision 1.3
diff -u -3 -p -u -r1.3 VMDouble.java
--- vm/reference/java/lang/VMDouble.java 2 Jul 2005 20:33:08 -0000 1.3
+++ vm/reference/java/lang/VMDouble.java 15 Jul 2007 21:29:52 -0000
@@ -127,5 +127,62 @@ final class VMDouble
*/
public static native void initIDs();
- public static native double parseDouble(String str);
+ /**
+ * Parse a double in string form. Hex strings are handled in Java,
+ * while decimal strings are passed to native code.
+ */
+ public static double parseDouble(String str)
+ {
+ int hexSign = str.indexOf("0x");
+ if (hexSign == -1)
+ hexSign = str.indexOf("0X");
+ if (hexSign != -1)
+ {
+ int sign = str.charAt(0) == '-' ? -1 : 1;
+ int point = str.indexOf(".");
+ int bei = str.indexOf("p");
+ if (bei == -1)
+ bei = str.indexOf("P");
+ if (bei == -1)
+ throw new NumberFormatException("No binary exponent indicator " +
+ "in hexadecimal floating point " +
+ "literal");
+ int end = str.length();
+ char endChar = str.charAt(end - 1);
+ if (endChar == 'f' || endChar == 'F' ||
+ endChar == 'd' || endChar == 'D')
+ --end;
+ boolean denormal = str.charAt(hexSign + 2) == '0';
+ final int mantissaBits = 52;
+ final int exponentBits = 11;
+ System.out.println("Decoding 0x" + str.substring(str.indexOf(".")+1,bei));
+ long mantissa = Long.decode("0x"+str.substring(str.indexOf('.')+1,bei));
+ if (str.charAt(bei+1) == '+')
+ ++bei;
+ System.out.println("Decoding " + str.substring(bei+1,end));
+ long exponent = Long.decode(str.substring(bei+1,end));
+ if (denormal && mantissa == 0)
+ {
+ // Do nothing for zero
+ }
+ else
+ {
+ if (denormal)
+ --exponent;
+ exponent += (1 << (exponentBits - 1)) - 1;
+ }
+ long value = mantissa | (exponent << mantissaBits);
+ System.out.println("Sign: " + sign);
+ System.out.println("Mantissa: " + mantissa);
+ System.out.println("Exponent: " + exponent);
+ System.out.println("Value: " + value);
+ throw new NumberFormatException("Hexadecimal floating point parsing "+
+ "not implemented!");
+ }
+ else
+ return natParseDouble(str);
+ }
+
+ public static native double natParseDouble(String str);
+
}
signature.asc
Description: Digital signature
