Fix ilogb exception and errno (bug 6794)

[BZ #6794]
Following Joseph comments about bug 6794, here is a proposed fix. It turned out
to be a large fix mainly because I had to move some file along to follow libm
files/names conventions.

Basically I have added wrappers (w_ilogb.c, w_ilogbf.c, w_ilogbl.c) that now calls
the symbol '__ieee754_ilogb'. The wrappers checks for '__ieee754_ilogb' output and
set the errno and raise exceptions as expected.

The '__ieee754_ilogb' is implemented in sysdeps. I have moved the 's_ilogb[f|l]' files
to e_ilogb[f|l] and renamed the '__ilogb[f|l]' to '__ieee754_ilogb[f|l]'.

I also found out a bug in i386 and x86-64 assembly coded ilogb implementation where
it raises a FE_DIVBYZERO when argument is '0.0'. I corrected this issue as well.

Finally I added the errno and FE_INVALID tests for 0.0, NaN and +-InF argument. Tested
on i386, x86-64, ppc32 and ppc64.
This commit is contained in:
Adhemerval Zanella 2012-04-11 16:30:13 -03:00 committed by Andreas Jaeger
parent 0396e69dbe
commit 76da726532
17 changed files with 223 additions and 41 deletions

View File

@ -1,3 +1,34 @@
2012-04-17 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
[BZ #6794]
* math/Makefile: Add e_ilogb and w_ilogb, remove s_logb.
* math/libm-test.inc: Add ilogb errno and exception tests.
* math/w_ilogb.c: New file: ilogb wrapper.
* math/w_ilogbf.c: New file: ilogbf wrapper.
* math/w_ilogbl.c: New file: ilogbl wrapper.
* sysdeps/generic/math_private.h: Add __ieee754_ilogb[l|f] prototypes.
* sysdeps/i386/fpu/s_ilogb.S: Moved to ...
* sysdeps/i386/fpu/e_ilogb.S: ... here. Also fixed a FE_DIVBYZERO
exception being thrown with 0.0 as argument.
* sysdeps/i386/fpu/s_ilogbf.S: Moved to ...
* sysdeps/i386/fpu/e_ilogbf.S: ... here. Also fixed a FE_DIVBYZERO
exception being thrown with 0.0 as argument.
* sysdeps/i386/fpu/s_ilogbl.S: Moved to ...
* sysdeps/i386/fpu/e_ilogbl.S: ... here. Also fixed a FE_DIVBYZERO
exception being thrown with 0.0 as argument.
* sysdeps/x86_64/fpu/s_ilogbl.S: Moved to ...
* sysdeps/x86_64/fpu/e_ilogbl.S: ... here. Also fixed a FE_DIVBYZERO
exception being thrown with 0.0 as argument.
* sysdeps/ieee754/dbl-64/s_ilogb.c: Moved to ...
* sysdeps/ieee754/dbl-64/e_ilogb.c: ... here.
* sysdeps/ieee754/flt-32/e_ilogbf.c: Moved to ...
* sysdeps/ieee754/flt-32/e_ilogbf.c: ... here.
* sysdeps/ieee754/ldbl-128ibm/s_ilogbl.c: Moved to ...
* sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c: ... here.
* sysdeps/ieee754/ldbl-opt/s_ilogb.c: Moved to ...
* sysdeps/ieee754/ldbl-opt/w_ilogb.c: ... here.
* sysdeps/ieee754/ldbl-opt/w_ilogbl.c: New file: ilogbl wrapper.
2012-04-17 Petr Baudis <pasky@ucw.cz>
* include/sys/uio.h: Change __vector to __iovec to avoid clash

20
NEWS
View File

@ -12,16 +12,16 @@ Version 2.16
174, 350, 369, 411, 706, 2074, 2541, 2547, 2548, 2551, 2552, 2553, 2554,
2562, 2563, 2565, 2566, 2576, 2636, 2678, 3335, 3768, 3866, 3868, 3976,
3992, 4026, 4108, 4596, 4822, 5077, 5461, 5805, 5993, 6471, 6486, 6578,
6649, 6730, 6770, 6884, 6890, 6894, 6895, 6907, 6911, 9739, 9902, 10110,
10135, 10140, 10153, 10210, 10254, 10346, 10545, 10716, 11174, 11322,
11365, 11451, 11494, 11521, 11959, 12047, 12340, 13058, 13525, 13526,
13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547, 13551, 13552,
13553, 13555, 13559, 13566, 13583, 13592, 13618, 13637, 13656, 13658,
13673, 13691, 13695, 13704, 13705, 13706, 13726, 13738, 13760, 13761,
13786, 13792, 13806, 13824, 13840, 13841, 13844, 13846, 13851, 13852,
13854, 13871, 13872, 13873, 13879, 13883, 13892, 13895, 13908, 13910,
13911, 13912, 13913, 13915, 13916, 13917, 13918, 13919, 13920, 13921,
13926, 13928, 13938, 13963, 13967, 13973
6649, 6730, 6770, 6794, 6884, 6890, 6894, 6895, 6907, 6911, 9739, 9902,
10110, 10135, 10140, 10153, 10210, 10254, 10346, 10545, 10716, 11174,
11322, 11365, 11451, 11494, 11521, 11959, 12047, 12340, 13058, 13525,
13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547, 13551,
13552, 13553, 13555, 13559, 13566, 13583, 13592, 13618, 13637, 13656,
13658, 13673, 13691, 13695, 13704, 13705, 13706, 13726, 13738, 13760,
13761, 13786, 13792, 13806, 13824, 13840, 13841, 13844, 13846, 13851,
13852, 13854, 13871, 13872, 13873, 13879, 13883, 13892, 13895, 13908,
13910, 13911, 13912, 13913, 13915, 13916, 13917, 13918, 13919, 13920,
13921, 13926, 13928, 13938, 13963, 13967, 13973
* ISO C11 support:

View File

@ -42,14 +42,16 @@ libm-support = k_standard s_lib_version s_matherr s_signgam \
libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod \
e_hypot e_j0 e_j1 e_jn e_lgamma_r e_log e_log10 e_pow \
e_rem_pio2 e_remainder e_scalb e_sinh e_sqrt e_gamma_r \
e_ilogb \
k_cos k_rem_pio2 k_sin k_tan s_asinh s_atan s_cbrt \
s_ceil s_cos s_erf s_expm1 s_fabs \
s_floor s_ilogb s_log1p s_logb \
s_floor s_log1p s_logb \
s_nextafter s_nexttoward s_rint s_scalbln \
s_significand s_sin s_tan s_tanh w_acos w_acosh w_asin \
w_atan2 w_atanh w_cosh w_drem w_exp w_exp2 w_exp10 w_fmod \
w_tgamma w_hypot w_j0 w_j1 w_jn w_lgamma w_lgamma_r \
w_log w_log10 w_pow w_remainder w_scalb w_sinh w_sqrt \
w_ilogb \
s_fpclassify s_fmax s_fmin s_fdim s_nan s_trunc \
s_remquo e_log2 e_exp2 s_round s_nearbyint s_sincos \
conj cimag creal cabs carg s_cexp s_csinh s_ccosh s_clog \

View File

@ -3802,13 +3802,22 @@ ilogb_test (void)
TEST_f_i (ilogb, 1024, 10);
TEST_f_i (ilogb, -2000, 10);
/* XXX We have a problem here: the standard does not tell us whether
exceptions are allowed/required. ignore them for now. */
TEST_f_i (ilogb, 0.0, FP_ILOGB0, EXCEPTIONS_OK);
TEST_f_i (ilogb, nan_value, FP_ILOGBNAN, EXCEPTIONS_OK);
TEST_f_i (ilogb, plus_infty, INT_MAX, EXCEPTIONS_OK);
TEST_f_i (ilogb, minus_infty, INT_MAX, EXCEPTIONS_OK);
/* ilogb (0.0) == FP_ILOGB0 plus invalid exception */
errno = 0;
TEST_f_i (ilogb, 0.0, FP_ILOGB0, INVALID_EXCEPTION);
check_int ("errno for ilogb(0.0) unchanged", errno, EDOM, 0, 0, 0);
/* ilogb (NaN) == FP_ILOGBNAN plus invalid exception */
errno = 0;
TEST_f_i (ilogb, nan_value, FP_ILOGBNAN, INVALID_EXCEPTION);
check_int ("errno for ilogb(NaN) unchanged", errno, EDOM, 0, 0, 0);
/* ilogb (inf) == INT_MAX plus invalid exception */
errno = 0;
TEST_f_i (ilogb, plus_infty, INT_MAX, INVALID_EXCEPTION);
check_int ("errno for ilogb(Inf) unchanged", errno, EDOM, 0, 0, 0);
/* ilogb (-inf) == INT_MAX plus invalid exception */
errno = 0;
TEST_f_i (ilogb, minus_infty, INT_MAX, INVALID_EXCEPTION);
check_int ("errno for ilogb(-Inf) unchanged", errno, EDOM, 0, 0, 0);
END (ilogb);
}

42
math/w_ilogb.c Normal file
View File

@ -0,0 +1,42 @@
/* Copyright (C) 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Adhemerval Zanella <azanella@linux.vnet.ibm.com>, 2011.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <errno.h>
#include <math_private.h>
/* wrapper ilogb */
int
__ilogb (double x)
{
int r = __ieee754_ilogb (x);
if (__builtin_expect (r == FP_ILOGB0, 0)
|| __builtin_expect (r == FP_ILOGBNAN, 0)
|| __builtin_expect (r == INT_MAX, 0))
{
__set_errno (EDOM);
feraiseexcept (FE_INVALID);
}
return r;
}
weak_alias (__ilogb, ilogb)
#ifdef NO_LONG_DOUBLE
strong_alias (__ilogb, __ilogbl)
weak_alias (__ilogb, ilogbl)
#endif

38
math/w_ilogbf.c Normal file
View File

@ -0,0 +1,38 @@
/* Copyright (C) 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Adhemerval Zanella <azanella@linux.vnet.ibm.com>, 2011.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <errno.h>
#include <math_private.h>
/* wrapper ilogbf */
int
__ilogbf (float x)
{
int r = __ieee754_ilogbf (x);
if (__builtin_expect (r == FP_ILOGB0, 0)
|| __builtin_expect (r == FP_ILOGBNAN, 0)
|| __builtin_expect (r == INT_MAX, 0))
{
__set_errno (EDOM);
feraiseexcept (FE_INVALID);
}
return r;
}
weak_alias (__ilogbf, ilogbf)

37
math/w_ilogbl.c Normal file
View File

@ -0,0 +1,37 @@
/* Copyright (C) 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Adhemerval Zanella <azanella@linux.vnet.ibm.com>, 2011.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <errno.h>
#include <math_private.h>
/* wrapper ilogbl */
int
__ilogbl (long double x)
{
int r = __ieee754_ilogbl (x);
if (__builtin_expect (r == FP_ILOGB0, 0)
|| __builtin_expect (r == FP_ILOGBNAN, 0)
|| __builtin_expect (r == INT_MAX, 0))
{
__set_errno (EDOM);
feraiseexcept (FE_INVALID);
}
return r;
}
weak_alias (__ilogbl, ilogbl)

View File

@ -213,6 +213,7 @@ extern double __ieee754_yn (int,double);
extern double __ieee754_remainder (double,double);
extern int32_t __ieee754_rem_pio2 (double,double*);
extern double __ieee754_scalb (double,double);
extern int __ieee754_ilogb (double);
/* fdlibm kernel function */
extern double __kernel_standard (double,double,int);
@ -260,6 +261,7 @@ extern float __ieee754_ynf (int,float);
extern float __ieee754_remainderf (float,float);
extern int32_t __ieee754_rem_pio2f (float,float*);
extern float __ieee754_scalbf (float,float);
extern int __ieee754_ilogbf (float);
/* float versions of fdlibm kernel functions */
@ -305,6 +307,7 @@ extern long double __ieee754_ynl (int,long double);
extern long double __ieee754_remainderl (long double,long double);
extern int __ieee754_rem_pio2l (long double,long double*);
extern long double __ieee754_scalbl (long double,long double);
extern int __ieee754_ilogbl (long double);
/* long double versions of fdlibm kernel functions */
extern long double __kernel_sinl (long double,long double,int);

View File

@ -7,7 +7,7 @@
RCSID("$NetBSD: s_ilogb.S,v 1.5 1995/10/12 15:53:09 jtc Exp $")
ENTRY(__ilogb)
ENTRY(__ieee754_ilogb)
fldl 4(%esp)
/* I added the following ugly construct because ilogb(+-Inf) is
required to return INT_MAX in ISO C99.
@ -18,6 +18,8 @@ ENTRY(__ilogb)
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
cmpb $0x40, %dh
je 2f /* Is +-0, jump. */
fxtract
pushl %eax
@ -34,5 +36,8 @@ ENTRY(__ilogb)
1: fstp %st
movl $0x7fffffff, %eax
ret
END (__ilogb)
weak_alias (__ilogb, ilogb)
2: fstp %st
movl $0x80000000, %eax /* FP_ILOGB0 */
ret
END (__ieee754_ilogb)
weak_alias (__ieee754_ilogb, __ilogb_finite)

View File

@ -7,7 +7,7 @@
RCSID("$NetBSD: s_ilogbf.S,v 1.4 1995/10/22 20:32:43 pk Exp $")
ENTRY(__ilogbf)
ENTRY(__ieee754_ilogbf)
flds 4(%esp)
/* I added the following ugly construct because ilogb(+-Inf) is
required to return INT_MAX in ISO C99.
@ -18,6 +18,8 @@ ENTRY(__ilogbf)
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
cmpb $0x40, %dh
je 2f /* Is +-0, jump. */
fxtract
pushl %eax
@ -34,5 +36,8 @@ ENTRY(__ilogbf)
1: fstp %st
movl $0x7fffffff, %eax
ret
END (__ilogbf)
weak_alias (__ilogbf, ilogbf)
2: fstp %st
movl $0x80000000, %eax /* FP_ILOGB0 */
ret
END (__ieee754_ilogbf)
weak_alias (__ieee754_ilogbf, __ilogbf_finite)

View File

@ -8,7 +8,7 @@
RCSID("$NetBSD: $")
ENTRY(__ilogbl)
ENTRY(__ieee754_ilogbl)
fldt 4(%esp)
/* I added the following ugly construct because ilogb(+-Inf) is
required to return INT_MAX in ISO C99.
@ -19,6 +19,8 @@ ENTRY(__ilogbl)
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
cmpb $0x40, %dh
je 2f /* Is +-0, jump. */
fxtract
pushl %eax
@ -35,5 +37,8 @@ ENTRY(__ilogbl)
1: fstp %st
movl $0x7fffffff, %eax
ret
END (__ilogbl)
weak_alias (__ilogbl, ilogbl)
2: fstp %st
movl $0x80000000, %eax /* FP_ILOGB0 */
ret
END (__ieee754_ilogbl)
weak_alias (__ieee754_ilogbl, __ilogbl_finite)

View File

@ -25,7 +25,7 @@ static char rcsid[] = "$NetBSD: s_ilogb.c,v 1.9 1995/05/10 20:47:28 jtc Exp $";
#include <math.h>
#include <math_private.h>
int __ilogb(double x)
int __ieee754_ilogb(double x)
{
int32_t hx,lx,ix;
@ -52,8 +52,4 @@ int __ilogb(double x)
}
return FP_ILOGBNAN;
}
weak_alias (__ilogb, ilogb)
#ifdef NO_LONG_DOUBLE
strong_alias (__ilogb, __ilogbl)
weak_alias (__ilogb, ilogbl)
#endif
strong_alias (__ieee754_ilogb, __ilogb_finite)

View File

@ -21,7 +21,7 @@ static char rcsid[] = "$NetBSD: s_ilogbf.c,v 1.4 1995/05/10 20:47:31 jtc Exp $";
#include <math.h>
#include <math_private.h>
int __ilogbf(float x)
int __ieee754_ilogbf(float x)
{
int32_t hx,ix;
@ -42,4 +42,4 @@ int __ilogbf(float x)
}
return FP_ILOGBNAN;
}
weak_alias (__ilogbf, ilogbf)
strong_alias (__ieee754_ilogbf, __ilogbf_finite)

View File

@ -29,7 +29,7 @@ static char rcsid[] = "$NetBSD: $";
#include <math_private.h>
#include <math_ldbl_opt.h>
int __ilogbl(long double x)
int __ieee754_ilogbl(long double x)
{
int64_t hx,lx;
int ix;
@ -55,4 +55,3 @@ int __ilogbl(long double x)
}
return FP_ILOGBNAN;
}
long_double_symbol (libm, __ilogbl, ilogbl);

View File

@ -1,5 +1,5 @@
#include <math_ldbl_opt.h>
#include <sysdeps/ieee754/dbl-64/s_ilogb.c>
#include <math/w_ilogb.c>
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
compat_symbol (libm, __ilogb, ilogbl, GLIBC_2_0);
#endif

View File

@ -0,0 +1,5 @@
#include <math_ldbl_opt.h>
#undef weak_alias
#define weak_alias(n,a)
#include <math/w_ilogbl.c>
long_double_symbol (libm, __ilogbl, ilogbl);

View File

@ -7,7 +7,7 @@
#include <machine/asm.h>
ENTRY(__ilogbl)
ENTRY(__ieee754_ilogbl)
fldt 8(%rsp)
/* I added the following ugly construct because ilogb(+-Inf) is
required to return INT_MAX in ISO C99.
@ -18,6 +18,8 @@ ENTRY(__ilogbl)
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
cmpb $0x40, %dh
je 2f /* Is +-Inf, jump. */
fxtract
fstp %st
@ -31,5 +33,8 @@ ENTRY(__ilogbl)
1: fstp %st
movl $0x7fffffff, %eax
ret
END (__ilogbl)
weak_alias (__ilogbl, ilogbl)
2: fstp %st
movl $0x80000000, %eax /* FP_ILOGB0 */
ret
END (__ieee754_ilogbl)
weak_alias (__ieee754_ilogbl, __ilogbl_finite)