Mail Archives: djgpp/2018/02/02/13:39:13
X-Authentication-Warning: | delorie.com: mail set sender to djgpp-bounces using -f
|
X-Recipient: | djgpp AT delorie DOT com
|
Message-ID: | <5A74B159.4020603@gmx.de>
|
Date: | Fri, 02 Feb 2018 19:43:37 +0100
|
From: | "Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via djgpp AT delorie DOT com]" <djgpp AT delorie DOT com>
|
User-Agent: | Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.13) Gecko/20101206 SUSE/3.1.7 Thunderbird/3.1.7
|
MIME-Version: | 1.0
|
To: | djgpp AT delorie DOT com
|
Subject: | Re: Fixing various bugs in frexp.S
|
References: | <5A4946EB DOT 3090500 AT gmx DOT de> <p2vmp0$14s4$1 AT gioia DOT aioe DOT org> <279ab41f-d898-4bcf-b5d4-ad9bf86e7a06 AT googlegroups DOT com> <83lgh86tza DOT fsf AT gnu DOT org>
|
In-Reply-To: | <83lgh86tza.fsf@gnu.org>
|
X-Provags-ID: | V03:K0:2BKdukfhcIXJGkTwwHb6480QfdmIXXmFzaDU9Y0t5UxqtlPPhPn
|
| HGEb+IMs6nOpwSUuzyxVN2asog7W3AmVCCiFk9JYTgzOme7YbG8cfexukj3T/1xnxvv0Pia
|
| IfXKff7ERRnNccV14VNEK+syoCm82Bc3WAqWSjZt1W3rhEMBSMP6fKWTBzbBlxiokpAwvmO
|
| mY0vjx6YKo3c2yff/S6qQ==
|
X-UI-Out-Filterresults: | notjunk:1;V01:K0:/7949yHaRn4=:DKGZVCyodborNr22fyY9xF
|
| Q+ZUpEeemMcTs3uP193ggWoyKZMSgIEqv35JbkGNgNms7/0SOMi/Nsudn6S5PZgFRWAus/o3O
|
| P2y9xRkMWmTxm+Td3Po2KhuQfminkeEQkja7nC+QBlylmw2mF5osfwQ8MjXaXYgtkV5d3ZkmK
|
| Osk3UNzVpwlkIiWLmIvcft1QwLPh4gni3nsB2aYAx5ll3q2kqLQZmf3CXBvpRIzAF14AMLR5z
|
| eIZX582cYzlo5mWkmtFkipr/HMR97HXRNW7mc0RvuNMLQvhhnGEzRzx+lTPEyc1o/87X4aMmU
|
| cpo3+okzAZzEu2XB0yXhhiVDsPVHIUPoMvQm67a8vKh5VUZ3nKYkjAFNiI2RmHIdCR5SNb82e
|
| W4rNKsc0LaCmq+1s4n+pPcXTovCLnZLetdJR6H7JNsmQ1TJdrhCKlD0SUmvsTQzgJylOUlVXM
|
| xRLzy/ksSip2N0c7SzuwYmYYekymD/UrOPWXBuXH/c+O79/Q4VpGzzUGQZLMaPgU3jxUPdyZq
|
| ia+kZLRXPQKc2hMwtEvi3fhfflqtALHLx9Eu8+iYNxgid+hmhVPwInaovEo7YkNOcz3ICnMHk
|
| FuBvG/pCtbmTinmVmQJwC9R42lIUxYuIGjEshAKBREZib4fz8WDQTw75DrBQSHCGUTZdm/I/m
|
| RVioBc4dHjhtXNVTFFQsMB+VTGICaUASB2Ngz0qy9nzCzpcbOdg3t2y1ikEdHXj6PbmvLxlO9
|
| U8dn1r42RiUt1KiMY3Dq7YFMbzEe7vHenv2C3WQmM1Gw/Ub5FA9dYufimiVH8BMaAeirByTQx
|
| 1DLG804NmKJfNQNEWhKwxqPsXuPXs25usJKGMFW95K8+7MLOjY=
|
Reply-To: | djgpp AT delorie DOT com
|
Am 08.01.2018 20:17, schrieb Eli Zaretskii (eliz AT gnu DOT org) [via djgpp AT delorie DOT com]:
>> Date: Mon, 8 Jan 2018 10:27:20 -0800 (PST)
>> From: "Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via djgpp AT delorie DOT com]"<djgpp AT delorie DOT com>
>>
>>>> - for NaN and infinity arguments no sign checks are done thus the
>>>> results are always positive
>>>
>>>> All these issues are serious deviations from the ansi/posix behavior.
>>>
>>> An NaN is a NaN. It has no positive or negative value. It has no value at
>>> all. I seriously doubt ansi/posix says anything about signedness of NaNs.
>>
>> The goal is not to generate a negative NaN but to preserve the sign of the
>> imput argument. The implementation should no convert a -NaN in a +NaN IMO.
>> This way the implementation bahaves as the implementation on my linux box.
>
> I agree with Martin that the sign of a NaN is meaningless: you cannot
> detect that sign by comparing a NaN with zero, for example.
>
> Does glibc give any explanation (in its sources, for example) for
> this behavior?
I have checked that on a BSD system, frexp[f|l] always return
a positive NaN no matter what the sign of the input NaN is.
Thus I have adjusted the frexp[f|l] functions accordingly.
They will always return a positive sign for NaN.
This means that apart from libm/math/s_frexpl.c also libm/math/s_frexp.c
and libm/math/sf_frexp.c must be adjusted because these
functions have always preserved the sign of zero, infinity and
NaN. An inspection of the linux code seems to indicate that
they have also based their code on the same old SunPro math
code that has also been used by DJGPP. This means that DJGPP's
frexp[f] from libm have always preserved the sign of NaN.
libc/ansi/math/frexp.S has simple bugs. It only returns correct
values for normalized numbers and for positive zero. Also in
case of error it sets errno to EDOM and this is wrong as can be
read in any man page of frexp. Case of error means that the
imput value is ether infinity or NaN. For negative zero, +/- NaN
and +/- infinity the values are simple wrong. Below are the results
as are generated by djdev205:
IN: -0 OUT: mantissa = -0 exp = -2147483647 err = 0
IN: 0 OUT: mantissa = 0 exp = 0 err = 0
IN: -nan OUT: mantissa = -nan exp = 0 err = 1
IN: nan OUT: mantissa = -nan exp = 0 err = 1
IN: -inf OUT: mantissa = -nan exp = 0 err = 1
IN: inf OUT: mantissa = -nan exp = 0 err = 1
In other words all negative values are wrong, Inf is returned
as NaN and the negative zero has -2147483647 as exponent.
It is surprising that no one has noted this in 20 years.
If no one has really serious objections, I will commit the
patch below in a couple of days.
Regards,
Juan M. Guerrero
Index: djgpp/src/libc/ansi/math/frexp.S
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/math/frexp.S,v
retrieving revision 1.5
diff -U 5 -r1.5 frexp.S
--- djgpp/src/libc/ansi/math/frexp.S 3 Jan 2018 15:52:09 -0000 1.5
+++ djgpp/src/libc/ansi/math/frexp.S 2 Feb 2018 18:26:13 -0000
@@ -2,12 +2,10 @@
/* Copyright (C) 2017 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
pos_NaN:
.long 0x7FC00000
-neg_NaN:
- .long 0xFFC00000
pos_inf:
.long 0x7F800000
neg_inf:
.long 0xFF800000
@@ -90,17 +88,13 @@
flds pos_NaN
ret
negarg: /* arg is - inf or - NaN */
cmpl $0x80000000, %eax
- jnz negNaN
+ jnz posNaN
movl 4(%esp), %eax
testl %eax, %eax
- jnz negNaN
+ jnz posNaN
flds neg_inf
ret
-
-negNaN:
- flds neg_NaN
- ret
Index: djgpp/src/libm/math/s_frexp.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libm/math/s_frexp.c,v
retrieving revision 1.2
diff -U 5 -r1.2 s_frexp.c
--- djgpp/src/libm/math/s_frexp.c 2 Jan 2018 22:02:08 -0000 1.2
+++ djgpp/src/libm/math/s_frexp.c 2 Feb 2018 18:26:13 -0000
@@ -106,12 +106,17 @@
{
__int32_t hx, ix, lx;
EXTRACT_WORDS(hx,lx,x);
ix = 0x7fffffff&hx;
*eptr = 0;
- if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */
- if (ix<0x00100000) { /* subnormal */
+ if(((ix&0x000fffff)|lx)==0) return x; /* 0,inf */
+ if(ix>=0x7ff00000) { /* nan */
+ hx = hx&0x7fffffff;
+ SET_HIGH_WORD(x,hx);
+ return x;
+ }
+ if (ix<0x00100000) { /* subnormal */
x *= two54;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
*eptr = -54;
}
Index: djgpp/src/libm/math/s_frexpl.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libm/math/s_frexpl.c,v
retrieving revision 1.1
diff -U 5 -r1.1 s_frexpl.c
--- djgpp/src/libm/math/s_frexpl.c 2 Jan 2018 22:05:37 -0000 1.1
+++ djgpp/src/libm/math/s_frexpl.c 2 Feb 2018 18:26:13 -0000
@@ -24,14 +24,14 @@
* arg = x*2^exp.
* If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
* with *exp=0.
*/
-#define IS_INF_OR_NAN(v) ((v).ldt.exponent == 0x7FFF)
-#define IS_DENORMAL(v) ((v).ldt.exponent == 0x0000 && (((v).ldt.mantissah & 0x80000000) == 0x00000000))
-#define IS_PSEUDO_DENORMAL(v) ((v).ldt.exponent == 0x0000 && (((v).ldt.mantissah & 0x80000000) == 0x80000000))
-#define IS_ZERO(v) (((v).ldt.mantissah | (v).ldt.mantissal) == 0x00000000)
+#define IS_DENORMAL(v) (((v).ldt.exponent == 0x0000) && (((v).ldt.mantissah & 0x80000000) == 0x00000000))
+#define IS_PSEUDO_DENORMAL(v) (((v).ldt.exponent == 0x0000) && (((v).ldt.mantissah & 0x80000000) == 0x80000000))
+#define IS_INF_OR_ZERO(v) ((((v).ldt.mantissah & 0x7FFFFFFF) | (v).ldt.mantissal) == 0x00000000)
+#define IS_NAN(v) (((v).ldt.exponent == 0x7FFF) && !IS_INF_OR_ZERO(v))
#include <libc/ieee.h>
#include "fdlibm.h"
#ifdef __STDC__
@@ -49,11 +49,15 @@
#endif
{
_longdouble_union_t value;
value.ld = x;
*eptr = 0;
- if (IS_INF_OR_NAN(value) || IS_ZERO(value)) return x; /* 0,inf,nan */
+ if (IS_INF_OR_ZERO(value)) return x; /* 0 or inf */
+ if (IS_NAN(value)) { /* nan */
+ value.ldt.sign = 0;
+ return value.ld;
+ }
if (IS_DENORMAL(value)) { /* subnormal */
value.ld *= two65;
*eptr = -65;
}
else if (IS_PSEUDO_DENORMAL(value)) { /* pseudo subnormal */
Index: djgpp/src/libm/math/sf_frexp.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libm/math/sf_frexp.c,v
retrieving revision 1.1
diff -U 5 -r1.1 sf_frexp.c
--- djgpp/src/libm/math/sf_frexp.c 7 Feb 1998 14:13:20 -0000 1.1
+++ djgpp/src/libm/math/sf_frexp.c 2 Feb 2018 18:26:13 -0000
@@ -31,11 +31,16 @@
{
__int32_t hx, ix;
GET_FLOAT_WORD(hx,x);
ix = 0x7fffffff&hx;
*eptr = 0;
- if(ix>=0x7f800000||(ix==0)) return x; /* 0,inf,nan */
+ if((ix&0x007fffff)==0) return x; /* 0,inf */
+ if(ix>=0x7f800000) { /* nan */
+ hx = hx&0x7fffffff;
+ SET_HIGH_WORD(x,hx);
+ return x;
+ }
if (ix<0x00800000) { /* subnormal */
x *= two25;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
*eptr = -25;
Index: djgpp/tests/cygnus/frexpl-t.c
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/cygnus/frexpl-t.c,v
retrieving revision 1.2
diff -U 5 -r1.2 frexpl-t.c
--- djgpp/tests/cygnus/frexpl-t.c 27 Jan 2018 19:12:08 -0000 1.2
+++ djgpp/tests/cygnus/frexpl-t.c 2 Feb 2018 18:26:13 -0000
@@ -103,13 +103,13 @@
{{.ldt = {0x0U, 0x80000000U, 0x7FFFU, 0}}, {.ldt = {0x0U, 0x80000000U, 0x7FFFU, 0}}, 0}, /* Inf */
{{.ldt = {0x0U, 0x80000000U, 0x7FFFU, 1}}, {.ldt = {0x0U, 0x80000000U, 0x7FFFU, 1}}, 0}, /* -Inf */
/* NaNs. */
{{.ldt = {0x1U, 0x80000000U, 0x7FFFU, 0}}, {.ldt = {0x1U, 0x80000000U, 0x7FFFU, 0}}, 0}, /* SNaN */
- {{.ldt = {0x1U, 0x80000000U, 0x7FFFU, 1}}, {.ldt = {0x1U, 0x80000000U, 0x7FFFU, 1}}, 0}, /* -SNaN */
+ {{.ldt = {0x1U, 0x80000000U, 0x7FFFU, 1}}, {.ldt = {0x1U, 0x80000000U, 0x7FFFU, 0}}, 0}, /* -SNaN */
{{.ldt = {0x0U, 0xFFFFFFFFU, 0x7FFFU, 0}}, {.ldt = {0x0U, 0xFFFFFFFFU, 0x7FFFU, 0}}, 0}, /* QNaN */
- {{.ldt = {0x0U, 0xFFFFFFFFU, 0x7FFFU, 1}}, {.ldt = {0x0U, 0xFFFFFFFFU, 0x7FFFU, 1}}, 0}, /* -QNaN */
+ {{.ldt = {0x0U, 0xFFFFFFFFU, 0x7FFFU, 1}}, {.ldt = {0x0U, 0xFFFFFFFFU, 0x7FFFU, 0}}, 0}, /* -QNaN */
/* Number. */
{{.ldt = {0x2168C000U, 0xC90FDAA2U, 0x3FFFU + 0x0001U, 0}}, {.ldt = {0x2168C000U, 0xC90FDAA2U, 0x3FFEU, 0}}, 2}, /* PI */
{{.ldt = {0x2168C000U, 0xC90FDAA2U, 0x3FFFU + 0x0001U, 1}}, {.ldt = {0x2168C000U, 0xC90FDAA2U, 0x3FFEU, 1}}, 2}, /* -PI */
@@ -196,10 +196,11 @@
static const size_t n_tests_long_double = sizeof(tests_long_double) / sizeof(tests_long_double[0]);
#undef IS_EQUAL
#define IS_EQUAL(a, b) (((a).ldt.sign == (b).ldt.sign) && ((a).ldt.exponent == (b).ldt.exponent) && ((a).ldt.mantissah == (b).ldt.mantissah) && ((a).ldt.mantissal == (b).ldt.mantissal))
+#define IS_EQUAL_NAN(a, b) ((((a).ldt.sign == (b).ldt.sign) || ((a).ldt.sign != (b).ldt.sign))&& ((a).ldt.exponent == (b).ldt.exponent) && ((a).ldt.mantissah == (b).ldt.mantissah) && ((a).ldt.mantissal == (b).ldt.mantissal))
int frexpl_test(void)
{
unsigned int i, counter;
@@ -210,17 +211,19 @@
_longdouble_union_t mantissa;
mantissa.ld = frexpl(tests_long_double[i].value.ld, &exponent);
if (IS_EQUAL(tests_long_double[i].mantissa, mantissa) && tests_long_double[i].exponent == exponent)
counter++;
+ else if(IS_EQUAL_NAN(tests_long_double[i].mantissa, mantissa) && tests_long_double[i].exponent == exponent)
+ counter++;
else
printf("frexpl test failed: value to frexpl = %.12Lf\n"
"mantissa result = %.12Lf exponent result = %d\n"
"mantissa should be = %.12Lf exponent should be = %d\n",
tests_long_double[i].value.ld, mantissa.ld, exponent, tests_long_double[i].mantissa.ld, tests_long_double[i].exponent);
}
- result = counter < n_tests_long_double || result ? 1 : 0;
+ result = counter < n_tests_long_double ? 1 : 0;
printf("%s\n", result ? "frexpl test failed." : "frexpl test succeded.");
return result;
}
- Raw text -