public inbox for newlib-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jeff Johnston <jjohnstn@sourceware.org>
To: newlib-cvs@sourceware.org
Subject: [newlib-cygwin] stdlib: Make strtod/strtof set ERANGE consistently for underflow.
Date: Wed,  7 Jul 2021 17:22:10 +0000 (GMT)	[thread overview]
Message-ID: <20210707172210.34E843854807@sourceware.org> (raw)

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=fb01286fab9b370c86323f84a46285cfbebfe4ff

commit fb01286fab9b370c86323f84a46285cfbebfe4ff
Author: Keith Packard <keithp@keithp.com>
Date:   Tue Jun 22 10:26:26 2021 -0700

    stdlib: Make strtod/strtof set ERANGE consistently for underflow.
    
    The C standard says that errno may acquire the value ERANGE if the
    result from strtod underflows. According to IEEE 754, underflow occurs
    whenever the value cannot be represented in normalized form.
    
    Newlib is inconsistent in this, setting errno to ERANGE only if the
    value underflows to zero, but not for denorm values, and never for hex
    format floats.
    
    This patch attempts to consistently set errno to ERANGE for all
    'underflow' conditions, which is to say all values which are not
    exactly zero and which cannot be represented in normalized form.
    
    This matches glibc behavior, as well as the Linux, Mac OS X, OpenBSD,
    FreeBSD and SunOS strtod man pages.
    
    Signed-off-by: Keith Packard <keithp@keithp.com>

Diff:
---
 newlib/libc/stdlib/strtod.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c
index 8bb75ef0a..019416ca7 100644
--- a/newlib/libc/stdlib/strtod.c
+++ b/newlib/libc/stdlib/strtod.c
@@ -326,6 +326,11 @@ _strtod_l (struct _reent *ptr, const char *__restrict s00, char **__restrict se,
 					Bfree(ptr,bb);
 					}
 				ULtod(rv.i, bits, exp, i);
+#ifndef NO_ERRNO
+                                /* try to avoid the bug of testing an 8087 register value */
+                                if ((dword0(rv)&Exp_mask) == 0)
+                                    errno = ERANGE;
+#endif
 			  }}
 			goto ret;
 		  }
@@ -1238,7 +1243,7 @@ _strtod_l (struct _reent *ptr, const char *__restrict s00, char **__restrict se,
 		dval(rv) *= dval(rv0);
 #ifndef NO_ERRNO
 		/* try to avoid the bug of testing an 8087 register value */
-		if (dword0(rv) == 0 && dword1(rv) == 0)
+		if ((dword0(rv) & Exp_mask) == 0)
 			ptr->_errno = ERANGE;
 #endif
 		}
@@ -1298,6 +1303,28 @@ strtof_l (const char *__restrict s00, char **__restrict se, locale_t loc)
   return retval;
 }
 
+/*
+ * These two functions are not quite correct as they return true for
+ * zero, however they are 'good enough' for the test in strtof below
+ * as we only need to know whether the double test is false when
+ * the float test is true.
+ */
+static inline int
+isdenorm(double d)
+{
+    U u;
+    dval(u) = d;
+    return (dword0(u) & Exp_mask) == 0;
+}
+
+static inline int
+isdenormf(float f)
+{
+    union { float f; __uint32_t i; } u;
+    u.f = f;
+    return (u.i & 0x7f800000) == 0;
+}
+
 float
 strtof (const char *__restrict s00,
 	char **__restrict se)
@@ -1307,7 +1334,7 @@ strtof (const char *__restrict s00,
     return signbit (val) ? -nanf ("") : nanf ("");
   float retval = (float) val;
 #ifndef NO_ERRNO
-  if (isinf (retval) && !isinf (val))
+  if ((isinf (retval) && !isinf (val)) || (isdenormf(retval) && !isdenorm(val)))
     _REENT->_errno = ERANGE;
 #endif
   return retval;


                 reply	other threads:[~2021-07-07 17:22 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210707172210.34E843854807@sourceware.org \
    --to=jjohnstn@sourceware.org \
    --cc=newlib-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).