Floating point remainder in Kaffe
Patrick Tullmann
tullmann at cs.utah.edu
Wed Sep 30 10:33:42 PDT 1998
Kaffe's floating point remainder operator is implemented incorrectly.
The problem is that the wrong floating point remainder function is
being used. Kaffe tries to use the remainder() function if that's
available when, in this case, it should be using the fmod() function.
According to the JLS (S15.16.3) Java's floating point remainder (using
the '%' operator) is *different from* the java.lang.Math.IEEEremainder()
function. The operator is based on truncating division while the
function is based on rounding division. You might think that this
won't add up to much, but 8.0 % 3.0 results in -1.0 with rounding
division versus 2.0 with truncating division.
In Kaffe, remainder() is called to implement both the remainder
operator and the IEEEremainder function. Actually, remainder() is
defined as fmod() if remainder() doesn't exist, or drem() if fmod()
isn't available. ... Assuming you've got all that straight, it gets
more complicated ... On FreeBSD, fmod() uses truncating division,
while remainder() and drem() use rounding division.
I think config-math.h should define two remainder functions:
javaRemainder() and IEEERemainder(). javaRemainder() should invoke
fmod() and IEEERemainder should invoke remainder() (or drem()). Then,
the functions java_lang_Math_IEEERemainder(), soft_freml(),
soft_frem(), and the rem_double() macro in intrp/icode.h need to be
updated to call the correct remainder function. The rem_double() and
rem_float() functions in jit/icode.c will have to be changed to not
take advantage of the builtin IEEEremainder support (right?
HAVE_rem_double and HAVE_rem_float are no longer useful?)
The attached diff makes these changes. I did not deprectate
HAVE_rem_float or HAVE_rem_double, but I think that will need to be
done.
-Pat
Index: ChangeLog
===================================================================
RCS file: /home/cvspublic/kaffe/ChangeLog,v
retrieving revision 1.138
diff -u -b -r1.138 ChangeLog
--- ChangeLog 1998/09/26 09:50:24 1.138
+++ ChangeLog 1998/09/30 17:29:11
@@ -1,3 +1,17 @@
+Tue Sep 29 15:10:07 1998 Patrick Tullmann <tullmann at cs.utah.edu>
+ * configure.in: add fmodf to the list of checked functions (needed
+ for change to config/config-math.h
+ * config/config-math.h: add javaRemainder and IEEERemainder functions.
+ Get rid of remainder, use IEEERemainder and javaRemainder instead.
+ * libraries/clib/native/Math.c: have
+ java_lang_Math_IEEEremainder() call IEEERemainder().
+ * kaffe/kaffe/kaffevm/soft.c, kaffe/kaffe/kaffevm/intrp/icode.h:
+ Use javaRemainder() instead of remainder().
+ * kaffe/kaffe/kaffevm/jit/icode.c: don't use IEEE remainder
+ opcodes in the JIT for remainder operations, always use the soft
+ calls. The Java '%' operator is not the same as the IEEE spec.
+ (I think HAVE_rem_double and HAVE_rem_float are useless now.)
+
Fri Sep 25 11:58:18 1998 Maxim Kizub <max at immsp.kiev.ua>
* libraries/javalib/java/util/Hashtable.java: fix
Index: configure.in
===================================================================
RCS file: /home/cvspublic/kaffe/configure.in,v
retrieving revision 1.27
diff -u -b -r1.27 configure.in
--- configure.in 1998/09/29 09:29:32 1.27
+++ configure.in 1998/09/29 21:13:25
@@ -527,7 +527,7 @@
AC_CHECK_FUNCS(memcpy memmove)
AC_CHECK_FUNCS(mkdir)
AC_CHECK_FUNCS(getcwd getwd gettimeofday ftime time uname getuid)
-AC_CHECK_FUNCS(remainder remainderf fmod drem rint floor ceil finite isinf isnan strtod strdup)
+AC_CHECK_FUNCS(remainder remainderf fmod fmodf drem rint floor ceil finite isinf isnan strtod strdup)
AC_CHECK_FUNCS(strerror hstrerror)
AC_CHECK_FUNCS(fcntl ioctl)
AC_CHECK_FUNCS(alarm setitimer)
Index: config/config-math.h
===================================================================
RCS file: /home/cvspublic/kaffe/config/config-math.h,v
retrieving revision 1.1.1.1
diff -u -b -r1.1.1.1 config-math.h
--- config-math.h 1998/03/31 19:10:52 1.1.1.1
+++ config-math.h 1998/09/29 21:13:25
@@ -14,16 +14,40 @@
#include <math.h>
#include <limits.h>
+/*
+ * Java defines two sorts of floating-point remainder operations, one
+ * IEEE 754 remainder (for java.lang.IEEEremainder()) and a
+ * different version for the % operator.
+ */
+
+/* IEEE 754 remainder for doubles */
#if defined(HAVE_REMAINDER)
-#elif defined(HAVE_FMOD)
-#define remainder fmod
+#define IEEERemainder(a, b) remainder(a, b)
#elif defined(HAVE_DREM)
-#define remainder drem
+#define IEEERemainder(a, b) drem(a, b)
#else
-#error "Need some form of remainder"
+#error "Kaffe requires a truncating-division-based floating-point remainder operation"
#endif
-#if !defined(HAVE_REMAINDERF)
-#define remainderf(a, b) (float)remainder((double)a, (double)b)
+
+/* IEEE 754 remainder for floats */
+#if defined(HAVE_REMAINDERF)
+#define IEEERemainderf(a, b) remainderf(a, b)
+#else
+#define IEEERemainderf(a, b) ((float)IEEERemainder((double)a, (double)b))
+#endif
+
+/* Java remainder for doubles */
+#if defined(HAVE_FMOD)
+#define javaRemainder(a, b) fmod(a, b)
+#else
+#error "Kaffe requires a truncating-division-based floating-point remainder operation"
+#endif
+
+/* Java remainder for floats */
+#if defined(HAVE_FMODF)
+#define javaRemainderf(a, b) fmodf(a, b)
+#else
+#define javaRemainderf(a, b) ((float)javaRemainder((double)a, (double)b))
#endif
#if !defined(HAVE_FLOOR)
Index: libraries/clib/native/Math.c
===================================================================
RCS file: /home/cvspublic/kaffe/libraries/clib/native/Math.c,v
retrieving revision 1.1.1.1
diff -u -b -r1.1.1.1 Math.c
--- Math.c 1998/03/31 19:10:54 1.1.1.1
+++ Math.c 1998/09/29 21:13:25
@@ -72,7 +72,7 @@
double
java_lang_Math_IEEEremainder(double v1, double v2)
{
- return (remainder(v1, v2));
+ return (IEEERemainder(v1, v2));
}
double
Index: kaffe/kaffevm/soft.c
===================================================================
RCS file: /home/cvspublic/kaffe/kaffe/kaffevm/soft.c,v
retrieving revision 1.6
diff -u -b -r1.6 soft.c
--- soft.c 1998/08/26 21:30:17 1.6
+++ soft.c 1998/09/29 21:13:25
@@ -619,13 +619,13 @@
jfloat
soft_frem(jfloat v1, jfloat v2)
{
- return (remainderf(v1, v2));
+ return (javaRemainderf(v1, v2));
}
jdouble
soft_freml(jdouble v1, jdouble v2)
{
- return (remainder(v1, v2));
+ return (javaRemainder(v1, v2));
}
jlong
Index: kaffe/kaffevm/intrp/icode.h
===================================================================
RCS file: /home/cvspublic/kaffe/kaffe/kaffevm/intrp/icode.h,v
retrieving revision 1.4
diff -u -b -r1.4 icode.h
--- icode.h 1998/08/21 02:40:22 1.4
+++ icode.h 1998/09/29 21:13:25
@@ -250,8 +250,8 @@
#define mul_double(t, f1, f2) (t)[0].v.tdouble = (f1)[0].v.tdouble * (f2)[0].v.tdouble
#define div_float(t, f1, f2) (t)[0].v.tfloat = (f1)[0].v.tfloat / (f2)[0].v.tfloat
#define div_double(t, f1, f2) (t)[0].v.tdouble = (f1)[0].v.tdouble / (f2)[0].v.tdouble
-#define rem_float(t, f1, f2) (t)[0].v.tfloat = remainderf((f1)[0].v.tfloat, (f2)[0].v.tfloat)
-#define rem_double(t, f1, f2) (t)[0].v.tdouble = remainder((f1)[0].v.tdouble, (f2)[0].v.tdouble)
+#define rem_float(t, f1, f2) (t)[0].v.tfloat = javaRemainderf((f1)[0].v.tfloat, (f2)[0].v.tfloat)
+#define rem_double(t, f1, f2) (t)[0].v.tdouble = javaRemainder((f1)[0].v.tdouble, (f2)[0].v.tdouble)
#define neg_float(t, f) (t)[0].v.tfloat = -(f)[0].v.tfloat
#define neg_double(t, f) (t)[0].v.tdouble = -(f)[0].v.tdouble
Index: kaffe/kaffevm/jit/icode.c
===================================================================
RCS file: /home/cvspublic/kaffe/kaffe/kaffevm/jit/icode.c,v
retrieving revision 1.3
diff -u -b -r1.3 icode.c
--- icode.c 1998/08/26 21:44:17 1.3
+++ icode.c 1998/09/29 21:13:26
@@ -1015,9 +1015,6 @@
rem_float(SlotInfo* dst, SlotInfo* src, SlotInfo* src2)
{
used_ieee_division = true;
-#if defined(HAVE_rem_float)
- slot_slot_slot(dst, src, src2, HAVE_rem_float, Tcomplex);
-#else
end_sub_block();
pusharg_float(src2, 1);
pusharg_float(src, 0);
@@ -1025,16 +1022,12 @@
popargs();
end_sub_block();
return_float(dst);
-#endif
}
void
rem_double(SlotInfo* dst, SlotInfo* src, SlotInfo* src2)
{
used_ieee_division = true;
-#if defined(HAVE_rem_double)
- lslot_lslot_lslot(dst, src, src2, HAVE_rem_double, Tcomplex);
-#else
end_sub_block();
pusharg_double(src2, pusharg_long_idx_inc);
pusharg_double(src, 0);
@@ -1042,7 +1035,6 @@
popargs();
end_sub_block();
return_double(dst);
-#endif
}
void
More information about the kaffe
mailing list