Mail Archives: djgpp-workers/2009/09/14/18:26:45
Am Montag, 14. September 2009 schrieb Eli Zaretskii:
[snip]
> Do you have a test that actually trips it? If so, how about adding it
> to tests/libc/ansi/math?
>
Below is a test progran that will trigger the bug.
If y is positive finite and x is positive infinity then the result of atan2(y, x)
must be +0.0 but atan2 returns errno=1 and NaN as result. The explanaition has
already be given in the previuos post. If y is negative finite and x is negative
infinite the result must be -PI, but again errno=1 and result set to NaN.
Here is the original (offending) code snippet:
aby:
movl 8(%esp), %eax /* inf or NaN */ <== loads mantissa high part of double y.
testl $0x000FFFFF, %eax
jne badarg /* y = NaN */
movl 4(%esp), %eax <== loads mantissa low part of double y.
testl %eax, %eax
jnz badarg
movl 16(%esp), %eax
andl $0x7FF00000,%eax
cmpl $0x7FF00000,%eax
jne argok /* x is finite */
jmp badarg
abx:
movl 16(%esp), %eax /* inf or NaN */ <== loads mantissa high part of double x.
testl $0x000FFFFF, %eax
jnz badarg
movl 4(%esp), %eax <== loads mantissa low part of double y instead of double x.
testl %eax, %eax
jnz badarg
movl 8(%esp), %eax
andl $0x7FF00000,%eax
cmpl $0x7FF00000,%eax
jne argok /* y is finite */
A quick inspection of the marked lines show that the test ist broken and will
never work properly. Every time the 32 bits at 4(%esp) are different from zero
the value of x will be interpreted as NaN and this is simply wrong. With this
code there is no way to identify x as infinite because the low part of the x-
mantissa is never evaluated.
Regards,
Juan M. Guerrero
2009-09-14 Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
Diffs against djgpp CVS head of 2009-08-16.
* src/libc/ansi/math/atan2.S: Check mantissa of y and not mantissa of x.
diff -aprNU5 djgpp.orig/src/libc/ansi/math/atan2.S djgpp/src/libc/ansi/math/atan2.S
--- djgpp.orig/src/libc/ansi/math/atan2.S 1999-08-04 19:58:20 +0000
+++ djgpp/src/libc/ansi/math/atan2.S 2009-09-15 00:16:18 +0000
@@ -45,12 +45,12 @@ aby:
jmp badarg
abx:
movl 16(%esp), %eax /* inf or NaN */
testl $0x000FFFFF, %eax
- jnz badarg
- movl 4(%esp), %eax
+ jne badarg /* x = NaN */
+ movl 12(%esp), %eax
testl %eax, %eax
jnz badarg
movl 8(%esp), %eax
andl $0x7FF00000,%eax
diff -aprNU5 djgpp.orig/tests/libc/ansi/math/elefunt/atan2.c djgpp/tests/libc/ansi/math/elefunt/atan2.c
--- djgpp.orig/tests/libc/ansi/math/elefunt/atan2.c 1970-01-01 00:00:00 +0000
+++ djgpp/tests/libc/ansi/math/elefunt/atan2.c 2009-09-15 00:12:56 +0000
@@ -0,0 +1,48 @@
+#include <libc/ieee.h>
+#include <stdio.h>
+#include <errno.h>
+#include <math.h>
+
+
+int main(void)
+{
+ _double_union_t x, y;
+ double result;
+
+ y.d = M_PI;
+ x.dt.sign = 0;
+ x.dt.exponent = 0x07FF;
+ x.dt.mantissah = 0x000000000;
+ x.dt.mantissal = 0x000000000; /* +Infinity. */
+
+ /*
+ * Compute atan of the quotient of a positive finite number with pos. infinite.
+ * The result must be +0.0
+ */
+ errno = 0;
+ result = atan2(y.d, x.d);
+ if (errno)
+ printf("errno=%d\ny=%f x=%f: result=%f result must be +0.0\n", errno, y.d, x.d, result);
+ else if (result == +0.0)
+ printf("test passed.\n");
+ else
+ printf("test failed.\n");
+
+
+ /*
+ * Compute atan of the quotient of a negative finite number with pos. infinite.
+ * The result must be -0.0
+ */
+ errno = 0;
+ y.dt.sign = 1;
+ x.dt.sign = 1;
+ result = atan2(y.d, x.d);
+ if (errno)
+ printf("errno=%d\ny=%f x=%f: result=%f result must be -0.0\n", errno, y.d, x.d, result);
+ else if (result == -M_PI)
+ printf("test passed.\n");
+ else
+ printf("test failed.\n");
+
+ return 0;
+}
diff -aprNU5 djgpp.orig/tests/libc/ansi/math/elefunt/makefile djgpp/tests/libc/ansi/math/elefunt/makefile
--- djgpp.orig/tests/libc/ansi/math/elefunt/makefile 2003-04-20 14:10:34 +0000
+++ djgpp/tests/libc/ansi/math/elefunt/makefile 2009-09-15 00:16:18 +0000
@@ -98,11 +98,12 @@ TARGETS = \
tpower.$(LOG) \
tsin.$(LOG) \
tsinh.$(LOG) \
tsqrt.$(LOG) \
ttan.$(LOG) \
- ttanh.$(LOG)
+ ttanh.$(LOG) \
+ atan2.$(LOG)
# $(EXECUTABLES) = $(TARGETS:/s/.$(LOG)/$(EXE))
all :: $(TARGETS)
@rem.com
@@ -120,11 +121,11 @@ summary:
egrep "^1|ESTIMATED LOSS" *$(LOG)
clean:
$(RM) *.o *.obj *.bak *.exe
$(RM) talog tasin tatan texp tpower tsin tsinh
- $(RM) tsqrt ttan ttanh tmacha
+ $(RM) tsqrt ttan ttanh tmacha atan2
realclean : clean # delete log files, too
$(RM) *.djl *.bcl *.tcl
ifdef BORLAND
tmacha$(EXE): tmacha.$(OE) $(OBJS)
@@ -180,10 +181,12 @@ tsqrt$(EXE): msqrt.$(OE) tsqrt.$(OE) $(O
$(LD) $(LDFLAGS) $(OUT) $@ $^ $(LIBS)
ttan$(EXE): mtan.$(OE) ttan.$(OE) $(OBJS)
$(LD) $(LDFLAGS) $(OUT) $@ $^ $(LIBS)
ttanh$(EXE): mtanh.$(OE) ttanh.$(OE) $(OBJS)
$(LD) $(LDFLAGS) $(OUT) $@ $^ $(LIBS)
+tatan2$(EXE): atan2.$(OE)
+ $(LD) $(LDFLAGS) $(OUT) $@ $^ $(LIBS)
endif
# dependencies found by gcc -MM *.c
tpower.$(OE) : tpower.c elefunt.h
@@ -195,10 +198,11 @@ tsinh.$(OE) : tsinh.c elefunt.h
tsqrt.$(OE) : tsqrt.c elefunt.h
ttan.$(OE) : ttan.c elefunt.h
ttanh.$(OE) : ttanh.c elefunt.h
tmacha.$(OE) : tmacha.c elefunt.h
atan.$(OE) : atan.c
+atan2.$(OE) : atan2.c
exp.$(OE) : exp.c
ipow.$(OE) : ipow.c elefunt.h
ldexp.$(OE) : ldexp.c
tsmach.$(OE) : tsmach.c elefunt.h
malog.$(OE) : malog.c elefunt.h
- Raw text -