i386/67469: src/lib/msun/i387/s_tan.S gives incorrect results for large inputs

David Schultz das at FreeBSD.ORG
Fri Feb 4 13:59:12 PST 2005


On Wed, Jun 02, 2004, Bruce Evans wrote:
> On Tue, 1 Jun 2004, David Schultz wrote:
> 
> > >Description:
> > src/lib/msun/i387/s_tan.S returns wildly inaccuate results when
> > its input has a large magnitude (>> 2*pi).  For example:
> >
> > input			s_tan.S				k_tan.c
> > 1.776524190754802e+269	1.773388446261095e+16		-1.367233274980565e+01
> > 1.182891728897420e+57	-1.9314539773999572e-01		1.0020569035866138e+03
> > 2.303439778835110e+202	2.8465460220132694e+00		3.5686329695133922e+00

Here is a patch to fix the problem for tan().  See caveats below...

Index: s_tan.S
===================================================================
RCS file: /cvs/src/lib/msun/i387/s_tan.S,v
retrieving revision 1.6
diff -u -r1.6 s_tan.S
--- s_tan.S	28 Aug 1999 00:06:14 -0000	1.6
+++ s_tan.S	4 Feb 2005 21:43:32 -0000
@@ -45,14 +45,21 @@
 	jnz	1f
 	fstp	%st(0)
 	ret
-1:	fldpi
-	fadd	%st(0)
-	fxch	%st(1)
-2:	fprem1
-	fstsw	%ax
-	andw	$0x400,%ax
-	jnz	2b
-	fstp	%st(1)
-	fptan
-	fstp	%st(0)
+
+/* Use the fdlibm routines for accuracy with large arguments. */
+1:	pushl   %ebp
+	movl    %esp,%ebp
+	subl    $32,%esp
+	leal	12(%esp),%eax
+	movl	%eax,8(%esp)
+	fstpl	(%esp)
+	call	__ieee754_rem_pio2
+	addl	$12,%esp
+	andl	$1,%eax			/* compute (eax & 1) ? -1 : 1 */
+	sall	%eax
+	subl	$1,%eax
+	neg	%eax
+	movl	%eax,16(%esp)
+	call	__kernel_tan
+	leave
 	ret

Unfortunately, I'm still getting the wrong answer for large values
that are *supposed* to be handled by the fptan instruction.  The
error seems to increase towards the end of the range of fptan,
(-2^63,2^63).  For instance, tan(0x1.3dea2a2c29172p+22) is only
off by the least significant 15 binary digits or so, but
tan(0x1.2c95e550f1635p+62) is off by about 5%.  Is fptan simply
inherently inaccurate, or did I screw up somewhere?  I would be
interested in results from an AMD processor.


More information about the freebsd-i386 mailing list