mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 08:11:08 +00:00
Fix pow in non-default rounding modes (bug 3976).
This commit is contained in:
parent
ca811b2256
commit
b7cd39e8f8
14
ChangeLog
14
ChangeLog
@ -1,4 +1,16 @@
|
||||
2012-03-02 Joseph Myers <joseph@codesourcery.com>
|
||||
2012-03-05 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
[BZ #3976]
|
||||
* sysdeps/ieee754/dbl-64/e_pow.c: Include <fenv.h>.
|
||||
(__ieee754_pow): Save and restore rounding mode and use
|
||||
round-to-nearest for main computations.
|
||||
* math/libm-test.inc (pow_test_tonearest): New function.
|
||||
(pow_test_towardzero): Likewise.
|
||||
(pow_test_downward): Likewise.
|
||||
(pow_test_upward): Likewise.
|
||||
(main): Call the new functions.
|
||||
* sysdeps/i386/fpu/libm-test-ulps: Update.
|
||||
* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
|
||||
|
||||
[BZ #3976]
|
||||
* math/libm-test.inc (cosh_test_tonearest): New function.
|
||||
|
10
NEWS
10
NEWS
@ -9,11 +9,11 @@ Version 2.16
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
174, 350, 411, 2541, 2547, 2548, 3335, 3992, 4026, 4108, 4596, 4822, 5077,
|
||||
5461, 5805, 5993, 6884, 6907, 9739, 9902, 10110, 10135, 10140, 10210,
|
||||
11174, 11322, 11365, 11494, 12047, 13058, 13525, 13526, 13527, 13528,
|
||||
13529, 13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553, 13555,
|
||||
13559, 13583, 13618, 13637, 13695, 13704, 13706, 13738, 13786
|
||||
174, 350, 411, 2541, 2547, 2548, 3335, 3976, 3992, 4026, 4108, 4596, 4822,
|
||||
5077, 5461, 5805, 5993, 6884, 6907, 9739, 9902, 10110, 10135, 10140,
|
||||
10210, 11174, 11322, 11365, 11494, 12047, 13058, 13525, 13526, 13527,
|
||||
13528, 13529, 13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553,
|
||||
13555, 13559, 13583, 13618, 13637, 13695, 13704, 13706, 13738, 13786
|
||||
|
||||
* ISO C11 support:
|
||||
|
||||
|
@ -5318,6 +5318,111 @@ pow_test (void)
|
||||
END (pow);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pow_test_tonearest (void)
|
||||
{
|
||||
int save_round_mode;
|
||||
errno = 0;
|
||||
FUNC(pow) (0, 0);
|
||||
if (errno == ENOSYS)
|
||||
/* Function not implemented. */
|
||||
return;
|
||||
|
||||
START (pow_tonearest);
|
||||
|
||||
save_round_mode = fegetround ();
|
||||
|
||||
if (!fesetround (FE_TONEAREST))
|
||||
{
|
||||
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L);
|
||||
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L);
|
||||
}
|
||||
|
||||
fesetround (save_round_mode);
|
||||
|
||||
END (pow_tonearest);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pow_test_towardzero (void)
|
||||
{
|
||||
int save_round_mode;
|
||||
errno = 0;
|
||||
FUNC(pow) (0, 0);
|
||||
if (errno == ENOSYS)
|
||||
/* Function not implemented. */
|
||||
return;
|
||||
|
||||
START (pow_towardzero);
|
||||
|
||||
save_round_mode = fegetround ();
|
||||
|
||||
if (!fesetround (FE_TOWARDZERO))
|
||||
{
|
||||
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L);
|
||||
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L);
|
||||
}
|
||||
|
||||
fesetround (save_round_mode);
|
||||
|
||||
END (pow_towardzero);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pow_test_downward (void)
|
||||
{
|
||||
int save_round_mode;
|
||||
errno = 0;
|
||||
FUNC(pow) (0, 0);
|
||||
if (errno == ENOSYS)
|
||||
/* Function not implemented. */
|
||||
return;
|
||||
|
||||
START (pow_downward);
|
||||
|
||||
save_round_mode = fegetround ();
|
||||
|
||||
if (!fesetround (FE_DOWNWARD))
|
||||
{
|
||||
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L);
|
||||
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L);
|
||||
}
|
||||
|
||||
fesetround (save_round_mode);
|
||||
|
||||
END (pow_downward);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pow_test_upward (void)
|
||||
{
|
||||
int save_round_mode;
|
||||
errno = 0;
|
||||
FUNC(pow) (0, 0);
|
||||
if (errno == ENOSYS)
|
||||
/* Function not implemented. */
|
||||
return;
|
||||
|
||||
START (pow_upward);
|
||||
|
||||
save_round_mode = fegetround ();
|
||||
|
||||
if (!fesetround (FE_UPWARD))
|
||||
{
|
||||
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L);
|
||||
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L);
|
||||
}
|
||||
|
||||
fesetround (save_round_mode);
|
||||
|
||||
END (pow_upward);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
remainder_test (void)
|
||||
{
|
||||
@ -7218,6 +7323,10 @@ main (int argc, char **argv)
|
||||
fabs_test ();
|
||||
hypot_test ();
|
||||
pow_test ();
|
||||
pow_test_tonearest ();
|
||||
pow_test_towardzero ();
|
||||
pow_test_downward ();
|
||||
pow_test_upward ();
|
||||
sqrt_test ();
|
||||
|
||||
/* Error and gamma functions: */
|
||||
|
@ -933,6 +933,42 @@ ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# pow_downward
|
||||
Test "pow_downward (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
|
||||
double: 1
|
||||
idouble: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
Test "pow_downward (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# pow_towardzero
|
||||
Test "pow_towardzero (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
|
||||
double: 1
|
||||
idouble: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
Test "pow_towardzero (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# pow_upward
|
||||
Test "pow_upward (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
Test "pow_upward (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
|
||||
double: 1
|
||||
idouble: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# sin_downward
|
||||
Test "sin_downward (1) == 0.8414709848078965066525023216302989996226":
|
||||
ildouble: 1
|
||||
@ -1838,6 +1874,30 @@ ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "pow_downward":
|
||||
double: 1
|
||||
float: 1
|
||||
idouble: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "pow_towardzero":
|
||||
double: 1
|
||||
float: 1
|
||||
idouble: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "pow_upward":
|
||||
double: 1
|
||||
float: 1
|
||||
idouble: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "sin_downward":
|
||||
double: 1
|
||||
float: 1
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* IBM Accurate Mathematical Library
|
||||
* written by International Business Machines Corp.
|
||||
* Copyright (C) 2001, 2002, 2004, 2011 Free Software Foundation
|
||||
* Copyright (C) 2001-2012 Free Software Foundation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
@ -41,6 +41,7 @@
|
||||
#include "MathLib.h"
|
||||
#include "upow.tbl"
|
||||
#include "math_private.h"
|
||||
#include <fenv.h>
|
||||
|
||||
#ifndef SECTION
|
||||
# define SECTION
|
||||
@ -84,6 +85,11 @@ __ieee754_pow(double x, double y) {
|
||||
(u.i[HIGH_HALF]==0 && u.i[LOW_HALF]!=0)) &&
|
||||
/* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */
|
||||
(v.i[HIGH_HALF]&0x7fffffff) < 0x4ff00000) { /* if y<-1 or y>1 */
|
||||
fenv_t env;
|
||||
double retval;
|
||||
|
||||
libc_feholdexcept_setround (&env, FE_TONEAREST);
|
||||
|
||||
z = log1(x,&aa,&error); /* x^y =e^(y log (X)) */
|
||||
t = y*134217729.0;
|
||||
y1 = t - (t-y);
|
||||
@ -97,7 +103,10 @@ __ieee754_pow(double x, double y) {
|
||||
a2 = (a-a1)+aa;
|
||||
error = error*ABS(y);
|
||||
t = __exp1(a1,a2,1.9e16*error); /* return -10 or 0 if wasn't computed exactly */
|
||||
return (t>0)?t:power1(x,y);
|
||||
retval = (t>0)?t:power1(x,y);
|
||||
|
||||
libc_feupdateenv (&env);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (x == 0) {
|
||||
|
@ -976,6 +976,36 @@ Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
|
||||
# pow_downward
|
||||
Test "pow_downward (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
Test "pow_downward (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# pow_towardzero
|
||||
Test "pow_towardzero (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
Test "pow_towardzero (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# pow_upward
|
||||
Test "pow_upward (1.0625, 1.125) == 1.070582293028761362162622578677070098674":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
Test "pow_upward (1.5, 1.03125) == 1.519127098714743184071644334163037684948":
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
# sin_downward
|
||||
Test "sin_downward (1) == 0.8414709848078965066525023216302989996226":
|
||||
ildouble: 1
|
||||
@ -1834,6 +1864,24 @@ Function: "log1p":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
|
||||
Function: "pow_downward":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "pow_towardzero":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "pow_upward":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
ildouble: 1
|
||||
ldouble: 1
|
||||
|
||||
Function: "sin_downward":
|
||||
float: 1
|
||||
ifloat: 1
|
||||
|
Loading…
Reference in New Issue
Block a user