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


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(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
diff -u -b -r1.1.1.1 config-math.h
--- config-math.h	1998/03/31 19:10:52
+++ 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)
-#error "Need some form of remainder"
+#error "Kaffe requires a truncating-division-based floating-point remainder operation"
-#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)
+#define IEEERemainderf(a, b) ((float)IEEERemainder((double)a, (double)b))
+/* Java remainder for doubles */
+#if defined(HAVE_FMOD)
+#define javaRemainder(a, b) fmod(a, b)
+#error "Kaffe requires a truncating-division-based floating-point remainder operation"
+/* Java remainder for floats */
+#if defined(HAVE_FMODF)
+#define javaRemainderf(a, b) fmodf(a, b)
+#define javaRemainderf(a, b) ((float)javaRemainder((double)a, (double)b))
 #if !defined(HAVE_FLOOR)
Index: libraries/clib/native/Math.c
RCS file: /home/cvspublic/kaffe/libraries/clib/native/Math.c,v
retrieving revision
diff -u -b -r1.1.1.1 Math.c
--- Math.c	1998/03/31 19:10:54
+++ Math.c	1998/09/29 21:13:25
@@ -72,7 +72,7 @@
 java_lang_Math_IEEEremainder(double v1, double v2)
-	return (remainder(v1, v2));
+	return (IEEERemainder(v1, v2));
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 @@
 soft_frem(jfloat v1, jfloat v2)
-	return (remainderf(v1, v2));
+	return (javaRemainderf(v1, v2));
 soft_freml(jdouble v1, jdouble v2)
-	return (remainder(v1, v2));
+	return (javaRemainder(v1, v2));
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);
 	pusharg_float(src2, 1);
 	pusharg_float(src, 0);
@@ -1025,16 +1022,12 @@
 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);
 	pusharg_double(src2, pusharg_long_idx_inc);
 	pusharg_double(src, 0);
@@ -1042,7 +1035,6 @@

More information about the kaffe mailing list