diff options
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | math/test-misc.c | 85 | ||||
-rw-r--r-- | soft-fp/extended.h | 38 | ||||
-rw-r--r-- | soft-fp/floatundidf.c | 5 | ||||
-rw-r--r-- | soft-fp/floatundisf.c | 5 | ||||
-rw-r--r-- | soft-fp/floatunsidf.c | 5 | ||||
-rw-r--r-- | soft-fp/floatunsisf.c | 5 | ||||
-rw-r--r-- | soft-fp/op-2.h | 4 | ||||
-rw-r--r-- | soft-fp/op-4.h | 4 | ||||
-rw-r--r-- | soft-fp/op-common.h | 33 |
10 files changed, 164 insertions, 60 deletions
@@ -1,5 +1,45 @@ 2007-05-03 Jakub Jelinek <jakub@redhat.com> + * soft-fp/op-common.h (FP_TRUNC): Replace raising of FP_EX_INEXACT + with setting the sticky bit. + * math/test-misc.c (main): Add more truncation tests. + +2007-04-14 Uros Bizjak <ubizjak@gmail.com> + + * soft-fp/floatunsidf.c (__floatunsidf): Use DFtype instead of + double in the function declaration. + * soft-fp/floatundidf.c (__floatundidf): Use DFtype instead of + double in the function declaration. + * soft-fp/floatunsisf.c (__floatunsisf): Use SFtype instead of + float in the function declaration. + * soft-fp/floatunsisf.c (__floatunsisf): Use SFtype instead of + float in the function declaration. + + * soft-fp/extended.h (FP_UNPACK_RAW_E): Do not increase X##_e for + denormal operands. Do not generate FP_EX_DENORM exception. + (FP_UNPACK_RAW_EP): Ditto. + (FP_UNPACK_SEMIRAW_E): Use FP_UNPACK_RAW_E instead of + undefined _FP_UNPACK_RAW_E. + (FP_UNPACK_SEMIRAW_EP): Use FP_UNPACK_RAW_EP instead of + undefined _FP_UNPACK_RAW_EP. + (FP_PACK_SEMIRAW_E): Use FP_PACK_RAW_E instead of + undefined _FP_PACK_RAW_E. + (FP_PACK_SEMIRAW_EP): Use FP_PACK_RAW_EP instead of + undefined _FP_PACK_RAW_EP. + + * op-2.h (_FP_FRAC_COPY_2_2): Define as alias to _FP_FRAC_COPY_2. + * op-4.h (_FP_FRAC_COPY_2_2): Define as alias to _FP_FRAC_COPY_4. + +2007-04-16 Uros Bizjak <ubizjak@gmail.com> + Jakub Jelinek <jakub@redhat.com> + + * soft-fp/op-common.h (FP_EXTEND): Do not abort when + _FP_EXPBIAS_##dfs == _FP_EXPBIAS_##sfs. Handle denormals for + this case. + * soft-fp/op-common.h (FP_TRUNC): Ditto. + +2007-05-03 Jakub Jelinek <jakub@redhat.com> + * math/test-misc.c (main): Add tests for rounding long double values close to smallest double denormalized value to double. diff --git a/math/test-misc.c b/math/test-misc.c index 1dc4d909bb..a1ad6885db 100644 --- a/math/test-misc.c +++ b/math/test-misc.c @@ -1236,20 +1236,83 @@ main (void) #endif #if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG >= DBL_MANT_DIG + 4 - volatile long double ld5 = nextafter (0.0, 1.0) / 16.0L; - volatile double d5; - (void) &ld5; - int i; - for (i = 0; i <= 32; i++) + int oldmode = fegetround (); + int j; + for (j = 0; j < 4; j++) { - d5 = ld5 * i; - (void) &d5; - if (d5 != (i <= 8 ? 0 : i < 24 ? 1 : 2) * nextafter (0.0, 1.0)) + int mode; + int i; + int k = 0; + const char *mstr; + switch (j) { - printf ("%La incorrectly rounded to %a\n", ld5 * i, d5); - result = 1; +#ifdef FE_TONEAREST + case 0: + mode = FE_TONEAREST; + mstr = "nearest"; + k = 8; + break; +#endif +#ifdef FE_DOWNWARD + case 1: + mode = FE_DOWNWARD; + mstr = "-inf"; + break; +#endif +#ifdef FE_UPWARD + case 2: + mode = FE_UPWARD; + mstr = "+inf"; + k = 15; + break; +#endif +#ifdef FE_TOWARDZERO + case 3: + mode = FE_TOWARDZERO; + mstr = "0"; + break; +#endif + default: + continue; + } + + volatile long double ld5 = nextafter (0.0, 1.0) / 16.0L; + volatile double d5; + (void) &ld5; + for (i = 0; i <= 32; i++) + { + if (fesetround (mode)) + { + printf ("failed to set rounding mode to %s\n", mstr); + result = 1; + break; + } + d5 = ld5 * i; + (void) &d5; + fesetround (oldmode); + if (d5 != ((j == 0 && i == 8) ? 0 : (i + k) / 16) + * nextafter (0.0, 1.0)) + { + printf ("%La incorrectly rounded to %s as %a\n", + ld5 * i, mstr, d5); + result = 1; + } } - } + } + + volatile long double ld7 = nextafterl (0.0L, 1.0L); + volatile double d7; + (void) &ld7; + fesetround (FE_UPWARD); + d7 = ld7; + (void) &d7; + fesetround (oldmode); + + if (d7 != nextafter (0.0, 1.0)) + { + printf ("%La incorrectly rounded upward to %a\n", ld7, d7); + result = 1; + } #endif return result; diff --git a/soft-fp/extended.h b/soft-fp/extended.h index 0e2a90c084..e5f16debec 100644 --- a/soft-fp/extended.h +++ b/soft-fp/extended.h @@ -94,12 +94,6 @@ union _FP_UNION_E X##_f[1] = _flo.bits.frac1; \ X##_e = _flo.bits.exp; \ X##_s = _flo.bits.sign; \ - if (!X##_e && (X##_f[1] || X##_f[0]) \ - && !(X##_f[1] & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_UNPACK_RAW_EP(X, val) \ @@ -112,12 +106,6 @@ union _FP_UNION_E X##_f[1] = _flo->bits.frac1; \ X##_e = _flo->bits.exp; \ X##_s = _flo->bits.sign; \ - if (!X##_e && (X##_f[1] || X##_f[0]) \ - && !(X##_f[1] & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_PACK_RAW_E(val, X) \ @@ -164,13 +152,13 @@ union _FP_UNION_E #define FP_UNPACK_SEMIRAW_E(X,val) \ do { \ - _FP_UNPACK_RAW_E(X,val); \ + FP_UNPACK_RAW_E(X,val); \ _FP_UNPACK_SEMIRAW(E,4,X); \ } while (0) #define FP_UNPACK_SEMIRAW_EP(X,val) \ do { \ - _FP_UNPACK_RAW_EP(X,val); \ + FP_UNPACK_RAW_EP(X,val); \ _FP_UNPACK_SEMIRAW(E,4,X); \ } while (0) @@ -189,13 +177,13 @@ union _FP_UNION_E #define FP_PACK_SEMIRAW_E(val,X) \ do { \ _FP_PACK_SEMIRAW(E,4,X); \ - _FP_PACK_RAW_E(val,X); \ + FP_PACK_RAW_E(val,X); \ } while (0) #define FP_PACK_SEMIRAW_EP(val,X) \ do { \ _FP_PACK_SEMIRAW(E,4,X); \ - _FP_PACK_RAW_EP(val,X); \ + FP_PACK_RAW_EP(val,X); \ } while (0) #define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X) @@ -299,11 +287,6 @@ union _FP_UNION_E X##_f1 = 0; \ X##_e = _flo.bits.exp; \ X##_s = _flo.bits.sign; \ - if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_UNPACK_RAW_EP(X, val) \ @@ -315,11 +298,6 @@ union _FP_UNION_E X##_f1 = 0; \ X##_e = _flo->bits.exp; \ X##_s = _flo->bits.sign; \ - if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \ - { \ - X##_e++; \ - FP_SET_EXCEPTION(FP_EX_DENORM); \ - } \ } while (0) #define FP_PACK_RAW_E(val, X) \ @@ -365,13 +343,13 @@ union _FP_UNION_E #define FP_UNPACK_SEMIRAW_E(X,val) \ do { \ - _FP_UNPACK_RAW_E(X,val); \ + FP_UNPACK_RAW_E(X,val); \ _FP_UNPACK_SEMIRAW(E,2,X); \ } while (0) #define FP_UNPACK_SEMIRAW_EP(X,val) \ do { \ - _FP_UNPACK_RAW_EP(X,val); \ + FP_UNPACK_RAW_EP(X,val); \ _FP_UNPACK_SEMIRAW(E,2,X); \ } while (0) @@ -390,13 +368,13 @@ union _FP_UNION_E #define FP_PACK_SEMIRAW_E(val,X) \ do { \ _FP_PACK_SEMIRAW(E,2,X); \ - _FP_PACK_RAW_E(val,X); \ + FP_PACK_RAW_E(val,X); \ } while (0) #define FP_PACK_SEMIRAW_EP(val,X) \ do { \ _FP_PACK_SEMIRAW(E,2,X); \ - _FP_PACK_RAW_EP(val,X); \ + FP_PACK_RAW_EP(val,X); \ } while (0) #define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X) diff --git a/soft-fp/floatundidf.c b/soft-fp/floatundidf.c index 2169a3f198..af8e4a5aef 100644 --- a/soft-fp/floatundidf.c +++ b/soft-fp/floatundidf.c @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 64bit unsigned integer to IEEE double - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "double.h" -double -__floatundidf(UDItype i) +DFtype __floatundidf(UDItype i) { FP_DECL_EX; FP_DECL_D(A); diff --git a/soft-fp/floatundisf.c b/soft-fp/floatundisf.c index 5f08764dc5..977f7dfc79 100644 --- a/soft-fp/floatundisf.c +++ b/soft-fp/floatundisf.c @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 64bit unsigned integer to IEEE single - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "single.h" -float -__floatundisf(UDItype i) +SFtype __floatundisf(UDItype i) { FP_DECL_EX; FP_DECL_S(A); diff --git a/soft-fp/floatunsidf.c b/soft-fp/floatunsidf.c index 97b488ab68..12d0f25bf0 100644 --- a/soft-fp/floatunsidf.c +++ b/soft-fp/floatunsidf.c @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 32bit unsigned integer to IEEE double - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "double.h" -double -__floatunsidf(USItype i) +DFtype __floatunsidf(USItype i) { FP_DECL_EX; FP_DECL_D(A); diff --git a/soft-fp/floatunsisf.c b/soft-fp/floatunsisf.c index 2ec16ba7b7..80c5d3d359 100644 --- a/soft-fp/floatunsisf.c +++ b/soft-fp/floatunsisf.c @@ -1,6 +1,6 @@ /* Software floating-point emulation. Convert a 32bit unsigned integer to IEEE single - Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com) and Jakub Jelinek (jj@ultra.linux.cz). @@ -32,8 +32,7 @@ #include "soft-fp.h" #include "single.h" -float -__floatunsisf(USItype i) +SFtype __floatunsisf(USItype i) { FP_DECL_EX; FP_DECL_S(A); diff --git a/soft-fp/op-2.h b/soft-fp/op-2.h index 5c9bce4c17..3a3b3aa069 100644 --- a/soft-fp/op-2.h +++ b/soft-fp/op-2.h @@ -1,6 +1,6 @@ /* Software floating-point emulation. Basic two-word fraction declaration and manipulation. - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -613,3 +613,5 @@ #define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0) #define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0)) + +#define _FP_FRAC_COPY_2_2(D,S) _FP_FRAC_COPY_2(D,S) diff --git a/soft-fp/op-4.h b/soft-fp/op-4.h index 1b90535c56..70b9fafbe5 100644 --- a/soft-fp/op-4.h +++ b/soft-fp/op-4.h @@ -1,6 +1,6 @@ /* Software floating-point emulation. Basic four-word fraction declaration and manipulation. - Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@cygnus.com), Jakub Jelinek (jj@ultra.linux.cz), @@ -684,3 +684,5 @@ do { \ D##_f[1] = S##_f1; \ D##_f[2] = D##_f[3] = 0; \ } while (0) + +#define _FP_FRAC_COPY_4_4(D,S) _FP_FRAC_COPY_4(D,S) diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index 1f58b89478..ef11b527b7 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -1153,7 +1153,8 @@ do { \ if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \ || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \ - || _FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ + || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \ + && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \ abort(); \ D##_s = S##_s; \ _FP_FRAC_COPY_##dwc##_##swc(D, S); \ @@ -1168,6 +1169,14 @@ do { \ { \ if (_FP_FRAC_ZEROP_##swc(S)) \ D##_e = 0; \ + else if (_FP_EXPBIAS_##dfs \ + < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ + - _FP_FRACBITS_##sfs)); \ + D##_e = 0; \ + } \ else \ { \ int _lz; \ @@ -1199,7 +1208,8 @@ do { \ #define FP_TRUNC(dfs,sfs,dwc,swc,D,S) \ do { \ if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \ - || _FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ + || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \ + && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \ abort(); \ D##_s = S##_s; \ if (_FP_EXP_NORMAL(sfs, swc, S)) \ @@ -1237,11 +1247,24 @@ do { \ if (S##_e == 0) \ { \ D##_e = 0; \ - _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ - if (!_FP_FRAC_ZEROP_##swc(S)) \ + if (_FP_FRAC_ZEROP_##swc(S)) \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + else \ { \ FP_SET_EXCEPTION(FP_EX_DENORM); \ - FP_SET_EXCEPTION(FP_EX_INEXACT); \ + if (_FP_EXPBIAS_##sfs \ + < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ + { \ + _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + } \ + else \ + { \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + _FP_FRAC_LOW_##dwc(D) |= 1; \ + } \ } \ } \ else \ |