This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[Miloslav Trmac <mitr@volny.cz>] libc/1563: sinf (), cosf () and tanf () don't work for large numbers on i386



I didn't test the patch in the appended bug report.  I just checked
that the report is valid and generated a test for glibc 2.2 (appended).

I'm appending also the results of the testsuite.  Even with double and
long double the values are wrong - but float is totally broken.

I'm not sure if we want to add these tests to the testsuite.

Andreas


testing double (without inline functions)
Failure: Test: cos (3.40282347e+38) == -0.270673140781272490007
Result:
 is:         -9.47165278361613127700e-01  -0x1.e4f2d8ecf09220000000p-1
 should be:  -2.70673140781272469901e-01  -0x1.152b56fe3ea320000000p-2
 difference:  6.76492137580340657799e-01   0x1.5a5d2d6dd14090000000p-1
 ulp       :  12186598954903570.0000
 max.ulp   :  0.0000
Maximal error of `cos'
 is      :  12186598954903570.0000 ulp
 accepted:  2.0000 ulp
Failure: Test: sin (3.40282347e+38) == 0.96267130987663771929
Result:
 is:          3.20745904831484740516e-01   0x1.48719d4e4f01d0000000p-2
 should be:   9.62671309876637737446e-01   0x1.ece341016f6ea0000000p-1
 difference:  6.41925405045153052441e-01   0x1.48aa725a47edc0000000p-1
 ulp       :  5781950029922012.0000
 max.ulp   :  0.0000
Maximal error of `sin'
 is      :  5781950029922012.0000 ulp
 accepted:  0.0000 ulp
Failure: Test: tan (3.40282347e+38) == -3.556582330622010687599
Result:
 is:         -3.38637735313000898252e-01  -0x1.5ac3d9b97180e0000000p-2
 should be:  -3.55658233062201079022e+00  -0x1.c73e16fdc6c890000000p+1
 difference:  3.21794459530900978095e+00   0x1.9be59bc6989870000000p+1
 ulp       :  7246167040166279.0000
 max.ulp   :  0.0000
Maximal error of `tan'
 is      :  7246167040166279.0000 ulp
 accepted:  0.5000 ulp

Test suite completed:
  2470 test cases plus 2262 tests for exception flags executed.
  6 errors occured.

testing float (without inline functions)
Failure: Test: cos (3.40282347e+38) == -0.270673140781272490007
Result:
 is:          3.40282346638528859812e+38   0x1.fffffe00000000000000p+127
 should be:  -2.70673125982284545898e-01  -0x1.152b5600000000000000p-2
 difference:  3.40282346638528859812e+38   0x1.fffffe00000000000000p+127
 ulp       :  inf
 max.ulp   :  0.0000
Maximal error of `cos'
 is      :  inf ulp
 accepted:  1.0000 ulp
Failure: Test: sin (3.40282347e+38) == 0.96267130987663771929
Result:
 is:          3.40282346638528859812e+38   0x1.fffffe00000000000000p+127
 should be:   9.62671339511871337891e-01   0x1.ece34200000000000000p-1
 difference:  3.40282346638528859812e+38   0x1.fffffe00000000000000p+127
 ulp       :  inf
 max.ulp   :  0.0000
Maximal error of `sin'
 is      :  inf ulp
 accepted:  0.0000 ulp
Failure: tan (3.40282347e+38) == -3.556582330622010687599: Exception "Invalid operation" set
Failure: Test: tan (3.40282347e+38) == -3.556582330622010687599
Result:
 is:          nan   nan
 should be:  -3.55658221244812011719e+00  -0x1.c73e1600000000000000p+1

Test suite completed:
  2457 test cases plus 2255 tests for exception flags executed.
  6 errors occured.

testing long double (without inline functions)
Failure: Test: cos (3.40282347e+38) == -0.270673140781272490007
Result:
 is:         -9.47165278361613146348e-01  -0xf.2796c767849115800000p-4
 should be:  -2.70673140781272490013e-01  -0x8.a95ab7f1f5192e600000p-5
 difference:  6.76492137580340656335e-01   0xa.d2e96b6e8a047e500000p-4
 ulp       :  24958154659642511306.0000
 max.ulp   :  0.0000
Maximal error of `cos'
 is      :  24958154659642511306.0000 ulp
 accepted:  529.0000 ulp
Failure: Test: sin (3.40282347e+38) == 0.96267130987663771929
Result:
 is:          3.20745904831484767079e-01   0xa.438cea72780ebd400000p-5
 should be:   9.62671309876637719286e-01   0xf.671a080b7b74eb100000p-4
 difference:  6.41925405045152952207e-01   0xa.455392d23f6d8c700000p-4
 ulp       :  11841433661280278727.0000
 max.ulp   :  0.0000
Maximal error of `sin'
 is      :  11841433661280278727.0000 ulp
 accepted:  627.0000 ulp
Failure: Test: tan (3.40282347e+38) == -3.556582330622010687599
Result:
 is:         -3.38637735313000895433e-01  -0xa.d61ecdcb8c06f9800000p-5
 should be:  -3.55658233062201068766e+00  -0xe.39f0b7ee364462700000p-2
 difference:  3.21794459530900979222e+00   0xc.df2cde34c4c383400000p-2
 ulp       :  14840150098260539444.0000
 max.ulp   :  0.0000
Maximal error of `tan'
 is      :  14840150098260539444.0000 ulp
 accepted:  1401.0000 ulp

Test suite completed:
  2266 test cases plus 2079 tests for exception flags executed.
  6 errors occured.

2000-01-31  Andreas Jaeger  <aj@suse.de>

	* math/libm-test.inc (tan_test): New test for FLOAT_MAX.
	(sin_test): Likewise.
	(cos_test): Likewise.
 
============================================================
Index: math/libm-test.inc
--- math/libm-test.inc	1999/10/31 17:02:25	1.10
+++ math/libm-test.inc	2000/01/31 19:41:24
@@ -1,6 +1,6 @@
-/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
+   Contributed by Andreas Jaeger <aj@suse.de>, 1997.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -1761,6 +1761,7 @@
   TEST_f_f (cos, M_PI_2l, 0);
 
   TEST_f_f (cos, 0.7, 0.7648421872844884262L);
+  TEST_f_f (cos, 3.40282347e+38, -0.270673140781272490007L);
 
   END (cos);
 }
@@ -3546,7 +3547,7 @@
   TEST_f_f (sin, M_PI_2l, 1);
   TEST_f_f (sin, -M_PI_2l, -1);
   TEST_f_f (sin, 0.7, 0.64421768723769105367L);
-
+  TEST_f_f (sin, 3.40282347e+38, 0.96267130987663771929L);
   END (sin);
 
 }
@@ -3632,6 +3633,7 @@
 
   TEST_f_f (tan, M_PI_4l, 1);
   TEST_f_f (tan, 0.7, 0.84228838046307944813L);
+  TEST_f_f (tan, 3.40282347e+38, -3.556582330622010687599L);
 
   END (tan);
 }





>Number:         1563
>Category:       libc
>Synopsis:       sinf (), cosf () and tanf () don't work for large numbers on i386
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    libc-gnats
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Sat Jan 29 17:40:03 EST 2000
>Last-Modified:
>Originator:     Miloslav Trmac
>Organization:
 none
>Release:        libc-2.1.2
>Environment:
Host type: i386-redhat-linux-gnu
System: Linux linux.elcomed.cz 2.2.12-20 #1 Mon Sep 27 10:25:54 EDT 1999 i586 unknown
Architecture: i586

Addons: crypt glibc-compat linuxthreads
Build CFLAGS: -O3 -Wall -Winline -Wstrict-prototypes -Wwrite-strings -g
Build CC: egcs
Compiler version: egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
Kernel headers: 2.2.12-20
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio

>Description:
	The sinf (), cosf () and tanf () functions, as defined in
sysdeps/libm_i387, don't reduce their arguments to range -2**63, 2**63, as
needed by the FPU. Contrary to the comments in the files, float can hold
numbers in range -2**128, 2**128, and thus the argument reduction is needed.
>How-To-Repeat:
-------------------------------------------------------
#include <float.h>
#include <math.h>
#include <stdio.h>

int main (void)
{
  printf ("%f: sin = %f, cos = %f, tan = %f\n", FLT_MAX, sinf (FLT_MAX),
          cosf (FLT_MAX), tanf (FLT_MAX));
  return 0;
}
--------------------------------------------------------
>Fix:
--------------------------------------------------------
diff -u glibc-2.1.2/sysdeps/libm-i387/s_cosf.S libm-i387/s_cosf.S
--- glibc-2.1.2/sysdeps/libm-i387/s_cosf.S	Mon Dec 30 02:46:58 1996
+++ libm-i387/s_cosf.S	Sat Jan 29 23:25:43 2000
@@ -1,15 +1,30 @@
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
+ *
+ * Adapted for `float' by Miloslav Trmac <mitr@volny.cz>.
  */
 
 #include <machine/asm.h>
 
-RCSID("$NetBSD: s_cosf.S,v 1.3 1995/05/08 23:55:16 jtc Exp $")
+RCSID("$NetBSD: $")
 
-/* A float's domain isn't large enough to require argument reduction. */
 ENTRY(__cosf)
 	flds	4(%esp)
+	fcos
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	1f
+	ret
+	.align ALIGNARG(4)
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	2b
+	fstp	%st(1)
 	fcos
 	ret
 END (__cosf)
diff -u glibc-2.1.2/sysdeps/libm-i387/s_sinf.S libm-i387/s_sinf.S
--- glibc-2.1.2/sysdeps/libm-i387/s_sinf.S	Mon Dec 30 02:47:16 1996
+++ libm-i387/s_sinf.S	Sat Jan 29 23:27:09 2000
@@ -1,15 +1,30 @@
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
+ *
+ * Adapted for `float' by Miloslav Trmac <mitr@volny.cz>.
  */
 
 #include <machine/asm.h>
 
-RCSID("$NetBSD: s_sinf.S,v 1.3 1995/05/09 00:27:53 jtc Exp $")
+RCSID("$NetBSD: $")
 
-/* A float's domain isn't large enough to require argument reduction. */
 ENTRY(__sinf)
 	flds	4(%esp)
+	fsin
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	1f
+	ret
+	.align ALIGNARG(4)
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	2b
+	fstp	%st(1)
 	fsin
 	ret
 END (__sinf)
diff -u glibc-2.1.2/sysdeps/libm-i387/s_tanf.S libm-i387/s_tanf.S
--- glibc-2.1.2/sysdeps/libm-i387/s_tanf.S	Mon Dec 30 02:47:18 1996
+++ libm-i387/s_tanf.S	Sat Jan 29 23:28:13 2000
@@ -1,15 +1,30 @@
 /*
  * Written by J.T. Conklin <jtc@netbsd.org>.
  * Public domain.
+ *
+ * Adapted for `float' by Miloslav Trmac <mitr@volny.cz>.
  */
 
 #include <machine/asm.h>
 
-RCSID("$NetBSD: s_tanf.S,v 1.3 1995/05/09 00:31:09 jtc Exp $")
+RCSID("$NetBSD: $")
 
-/* A float's domain isn't large enough to require argument reduction. */
 ENTRY(__tanf)
 	flds	4(%esp)
+	fptan
+	fnstsw	%ax
+	testl	$0x400,%eax
+	jnz	1f
+	fstp	%st(0)
+	ret
+1:	fldpi
+	fadd	%st(0)
+	fxch	%st(1)
+2:	fprem1
+	fstsw	%ax
+	testl	$0x400,%eax
+	jnz	2b
+	fstp	%st(1)
 	fptan
 	fstp	%st(0)
 	ret
--------------------------------------------------------
>Audit-Trail:
>Unformatted:




-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.rhein-neckar.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]