This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
[Miloslav Trmac <mitr@volny.cz>] libc/1563: sinf (), cosf () and tanf () don't work for large numbers on i386
- To: libc-alpha Mailinglist <libc-alpha at sourceware dot cygnus dot com>
- Subject: [Miloslav Trmac <mitr@volny.cz>] libc/1563: sinf (), cosf () and tanf () don't work for large numbers on i386
- From: Andreas Jaeger <aj at suse dot de>
- Date: 31 Jan 2000 20:49:22 +0100
- Cc: Miloslav Trmac <mitr at volny dot cz>
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);
}
- To: bugs at gnu dot org
- Subject: libc/1563: sinf (), cosf () and tanf () don't work for large numbers on i386
- From: Miloslav Trmac <mitr at volny dot cz>
- Date: Sat, 29 Jan 2000 23:36:52 +0100
- Delivery-date: Sun, 30 Jan 2000 04:36:44 +0100
- Envelope-to: aj@localhost
- Resent-Cc: gnats-admin at gnu dot org
- Resent-Reply-To: bugs@gnu.org, Miloslav Trmac <mitr@volny.cz>
- Xref: gromit.rhein-neckar.de mail.gnats-libc-bugs:4602
>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