delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2008/04/24/09:27:28

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
X-Recipient: djgpp-workers AT delorie DOT com
X-Authenticated: #27081556
X-Provags-ID: V01U2FsdGVkX1/i0u5HgAvi/kIyvIJ8Q4cVW89h0vqsOknjR9VG+F
bdqH/Xij1Q6usS
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
To: djgpp-workers AT delorie DOT com
Subject: Re: Implementation of certain conversion specifiers in _doprnt (patch #2)
Date: Thu, 24 Apr 2008 16:28:46 +0200
User-Agent: KMail/1.9.5
MIME-Version: 1.0
Message-Id: <200804241628.47232.juan.guerrero@gmx.de>
X-Y-GMX-Trusted: 0
Reply-To: djgpp-workers AT delorie DOT com

According to C99 the NaN and Inf strings have been replaced by nan/NAN and
inf/INF.  Also isspeciall() no longer returns "Unnormal" instead of nan/NAN.
This is to become compatible with gnu glibc and to avoid to make break configure
scripts.  The corresponding existing tests have been adjusted accordingly.

Regards,
Juan M. Guerrero






2008-04-23  Juan Manuel Guerrero  <juan DOT guerrero AT gmx DOT de>
	Diffs against djgpp CVS head of 2008-04-23.


	* src/libc/ansi/stdio/doprnt.c: Use of nan/NAN and inf/INF (C99 strings)
	instead of Inf and NaN strings.  Also return nan/NAN instead of
	"Unnormal".

	* tests/cygnus/convert.c (test_nan_inf): Tests adjusted for the use
	of nan/NAN and inf/INF (C99 strings) instead of Inf and NaN strings.

	* src/docs/kb/wc204.txi: Info about the replacement of "unnormal" by
	nan/NAN added.





diff -aprNU3 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi
--- djgpp.orig/src/docs/kb/wc204.txi	2008-04-23 23:07:22 +0000
+++ djgpp/src/docs/kb/wc204.txi	2008-04-23 23:10:26 +0000
@@ -1123,3 +1123,11 @@ input string.
 @findex printf AT r{, and C99 conversion flags}
 The @code{'} conversion flag is now supported by @code{_doprnt}
 and the @code{printf} family of functions.
+
+@findex _doprnt AT r{, and return string for special numbers like @code{pseudo-nan}}
+@findex printf AT r{, and return string for special numbers like @code{pseudo-nan}}
+To increase compatibility with GNU glibc's @code{printf}, @code{printf} will
+return for the following special numbers @code{Quiet NaN},  @code{Signalling NaN},
+@code{Pseudo-Denormal}, @code{Pseudo-NaN}, @code{Pseudo-Infinity},
+@code{Pseudo-Zero} and denormalized numbers @code{nan} or @code{NAN} instead
+of @code{Unnormal}.
diff -aprNU3 djgpp.orig/src/libc/ansi/stdio/doprnt.c djgpp/src/libc/ansi/stdio/doprnt.c
--- djgpp.orig/src/libc/ansi/stdio/doprnt.c	2008-04-23 23:07:22 +0000
+++ djgpp/src/libc/ansi/stdio/doprnt.c	2008-04-23 23:10:26 +0000
@@ -44,12 +44,12 @@ static char *grouping;
 		flags&CHARINT ? (char basetype)va_arg(argp, int) : \
 		(basetype)va_arg(argp, int)
 
-#define IS_FINITE(x)  (((x).ldt.exponent < 0x7FFFU && (x).ldt.exponent > 0x0000U && (x).ldt.mantissah & 0x80000000UL)  \
-                       || ((x).ldt.exponent == 0x0000U && !((x).ldt.mantissah & 0x80000000UL)))
-
-#define IS_ZERO(x)    ((x).ldt.exponent == 0x0U && (x).ldt.mantissah == 0x0UL && (x).ldt.mantissal == 0x0UL)
-#define IS_NAN(x)     ((x).ldt.exponent == 0x7FFFU && ((x).ldt.mantissah & 0x7FFFFFFFUL || (x).ldt.mantissal))
-
+#define IS_FINITE(x)         (((x).ldt.exponent < 0x7FFFU && (x).ldt.exponent > 0x0000U && (x).ldt.mantissah & 0x80000000UL)  \
+                              || ((x).ldt.exponent == 0x0000U && !((x).ldt.mantissah & 0x80000000UL)))
+#define IS_ZERO(x)           ((x).ldt.exponent == 0x0U && (x).ldt.mantissah == 0x0UL && (x).ldt.mantissal == 0x0UL)
+#define IS_NAN(x)            ((x).ldt.exponent == 0x7FFFU && ((x).ldt.mantissah & 0x7FFFFFFFUL || (x).ldt.mantissal))
+#define IS_PSEUDO_NUMBER(x)  (((x).ldt.exponent != 0x0000U && !((x).ldt.mantissah & 0x80000000UL))   /*  Pseudo-NaN, Pseudo-Infinity and Unnormal.  */ \
+                              || ((x).ldt.exponent == 0x0000U && (x).ldt.mantissah & 0x80000000UL))  /*  Pseudo-Denormal.  */
 
 static __inline__ int todigit(char c)
 {
@@ -77,19 +77,19 @@ static __inline__ char tochar(int n)
 #define	ZEROPAD		0x0100		/* zero (as opposed to blank) pad */
 #define	HEXPREFIX	0x0200		/* add 0x or 0X prefix */
 #define	GROUPING	0x0400		/* non monetary thousands grouping */
+#define	UPPERCASE	0x0800		/* INF/NAN for [EFG] */
 
 static int cvtl(long double number, int prec, int flags, char *signp,
 	        unsigned char fmtch, char *startp, char *endp);
 static char *doprnt_roundl(long double fract, int *expv, char *start,
 			   char *end, char ch, char *signp);
-static char *exponentl(char *p, int expv, unsigned char fmtch);
+static char *exponentl(char *p, int expv, unsigned char fmtch, int flags);
 #ifdef __GO32__
-static int isspeciall(long double d, char *bufp);
+static int isspeciall(long double d, char *bufp, int flags);
 #endif
 static __inline__ char * __grouping_format(char *string_start, char *string_end, char *buffer_end, int flags);
 
 static char NULL_REP[] = "(null)";
-static char UNNORMAL_REP[] = "Unnormal";
 
 
 int
@@ -265,11 +265,12 @@ _doprnt(const char *fmt0, va_list argp, 
       base = 10;
       flags |= FINITENUMBER;
       goto number;
-    case 'e':
     case 'E':
+    case 'G':
+      flags |= UPPERCASE;
+    case 'e':
     case 'f':
     case 'g':
-    case 'G':
       flags |= FLOAT;
       if (flags & LONGDBL)
 	_ldouble = va_arg(argp, long double);
@@ -311,14 +312,12 @@ _doprnt(const char *fmt0, va_list argp, 
       }
       else
       {
-	_longdouble_union_t ip;
-
-	ip.ld = _ldouble;
+	ieee_value.ld = _ldouble;
 
-	if (ip.ldt.sign)
+	if (ieee_value.ldt.sign)
 	{
 	  neg_ldouble = 1;
-	  if (IS_ZERO(ip) || IS_NAN(ip))
+	  if (IS_ZERO(ieee_value) || IS_NAN(ieee_value) || IS_PSEUDO_NUMBER(ieee_value))
 	    softsign = '-';
 	}
 	else
@@ -410,6 +409,7 @@ _doprnt(const char *fmt0, va_list argp, 
       goto nosign;
     case 'X':
       digs = "0123456789ABCDEF";
+      flags |= UPPERCASE;
       /* FALLTHROUGH */
     case 'x':
       ARG(unsigned);
@@ -577,7 +577,7 @@ cvtl(long double number, int prec, int f
   int doingzero=0;     /* We're displaying 0.0 */
   long double integer, tmp;
 
-  if ((expcnt = isspeciall(number, startp)))
+  if ((expcnt = isspeciall(number, startp, flags)))
     return(expcnt);
 
   dotrim = expcnt = gformat = 0;
@@ -768,7 +768,7 @@ cvtl(long double number, int prec, int f
 	--t;
       ++t;
     }
-    t = exponentl(t, expcnt, fmtch);
+    t = exponentl(t, expcnt, fmtch, flags);
     break;
   case 'g':
   case 'G':
@@ -913,7 +913,7 @@ doprnt_roundl(long double fract, int *ex
 }
 
 static char *
-exponentl(char *p, int expv, unsigned char fmtch)
+exponentl(char *p, int expv, unsigned char fmtch, int flags)
 {
   char *t;
   char expbuf[MAXEXPLD];
@@ -944,41 +944,54 @@ exponentl(char *p, int expv, unsigned ch
 }
 
 static int
-isspeciall(long double d, char *bufp)
+isspeciall(long double d, char *bufp, int flags)
 {
-  typedef struct {
-    unsigned manl:32;
-    unsigned manh:32;
-    unsigned exp:15;
-    unsigned sign:1;
-  } IEEExp;
-
-  typedef union {
-    IEEExp ip;
-    long double ldouble;  /* double and long double precision arguments */
-  } ip_union;
-
-  ip_union ip;
-
-  ip.ldouble = d;
-
-
-  /* Unnormals: the MSB of mantissa is non-zero, but the exponent is
-     not zero either.  */
-  if ((ip.ip.manh & 0x80000000U) == 0 && ip.ip.exp != 0)
-  {
-    if (ip.ip.sign)
-      *bufp++ = '-';
-    strcpy(bufp, UNNORMAL_REP);
-    return strlen(bufp) + ip.ip.sign;
-  }
-  if (ip.ip.exp != 0x7fff)
-    return(0);
-  if ((ip.ip.manh & 0x7fffffff) || ip.ip.manl)
-    strcpy(bufp, "NaN");
+  /*
+   *  For intel's 80 bit floating point number identify
+   *  the following special values:
+   *
+   *  Supported Floating-Point Encodings (generated by processor as an operation result)
+   *                      exp                  integer                     fraction
+   *  Signalling NaN:   0x7FFF,                   1,      0x0000000000000001 <=, <= 0x3FFFFFFFFFFFFFFF
+   *  Quiet NaN:        0x7FFF,                   1,      0x4000000000000000 <=, <= 0x7FFFFFFFFFFFFFFF
+   *  Infinity:         0x7FFF,                   1,                           0
+   *  Pseudo-Denormal:  0x0000,                   1,      0x0000000000000001 <=, <= 0x7FFFFFFFFFFFFFFF
+   *
+   *  Unsupported Floating-Point Encodings (not generated by processor as an operation result)
+   *                            exp            integer                     fraction
+   *  Pseudo-NaN:       0x7FFF,                   0,      0x0000000000000001 <=, <= 0x7FFFFFFFFFFFFFFF
+   *  Pseudo-Infinity:  0x7FFF,                   0,                           0
+   *  Pseudo-Zero:      0x0001 <=, < 0x7FFF,      0,                           0
+   *  Unnormal:         0x0001 <=, < 0x7FFF,      0,      0x0000000000000001 <=, <= 0x7FFFFFFFFFFFFFFF
+   *
+   *  Patterns of the values according to:
+   *    Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+   *    Application Architecture.
+   *    5.1.3 "Representation of Values in Floating-Point Registers"
+   *    Table 5-2 "Floating-Point Register Encodings"
+   *    Figure 5-11 "Floating-Point Exception Fault Prioritization"
+   *
+   *  To be compatible with printf of GNU glibc Quiet NaN, signalling NaN, Pseudo-NaN,
+   *  Pseudo-Infinity, Pseudo-Zero, Pseudo-Denormal and denormalized numbers (unnormal)
+   *  will all return nan/NAN instead of "Unnormal" as used to be.
+   */
+
+  static const char INF_REP[2][4] = {"inf", "INF"};
+  static const char NAN_REP[2][4] = {"nan", "NAN"};
+  int style = (flags & UPPERCASE) ? 1 : 0;
+  _longdouble_union_t ieee_value;
+
+
+  ieee_value.ld = d;
+  if (IS_PSEUDO_NUMBER(ieee_value))  /*  Pseudo-NaN, Pseudo-Infinity, Unnormal and Pseudo-Denormal.  */
+    strcpy(bufp, NAN_REP[style]);
+  else if (ieee_value.ldt.exponent != 0x7FFFU)
+    return 0;
+  else if (ieee_value.ldt.mantissah & 0x7FFFFFFFUL || ieee_value.ldt.mantissal)  /*  Quiet NaN and signalling NaN.  */
+    strcpy(bufp, NAN_REP[style]);
   else
-    (void)strcpy(bufp, "Inf");
-  return(3);
+    strcpy(bufp, INF_REP[style]);
+  return 3;
 }
 
 static __inline__ char *
diff -aprNU3 djgpp.orig/tests/cygnus/convert.c djgpp/tests/cygnus/convert.c
--- djgpp.orig/tests/cygnus/convert.c	1999-04-04 08:13:22 +0000
+++ djgpp/tests/cygnus/convert.c	2008-04-23 23:10:26 +0000
@@ -283,16 +283,29 @@ _DEFUN_VOID(test_nan_inf)
   newfunc("nan print");
   line(1);
   sprintf(buffer,"%e", nan());
-  test_sok(buffer,"NaN");
+  test_sok(buffer,"nan");
   line(2);
   sprintf(buffer,"%e", -nan());
-  test_sok(buffer,"NaN");
+  test_sok(buffer,"nan");
   line(3);
   sprintf(buffer,"%+e", nan());
-  test_sok(buffer,"+NaN");
+  test_sok(buffer,"+nan");
   line(4);
   sprintf(buffer,"%+e", -nan());
-  test_sok(buffer,"-NaN");
+  test_sok(buffer,"-nan");
+  newfunc("NAN print");
+  line(1);
+  sprintf(buffer,"%E", nan());
+  test_sok(buffer,"NAN");
+  line(2);
+  sprintf(buffer,"%E", -nan());
+  test_sok(buffer,"NAN");
+  line(3);
+  sprintf(buffer,"%+E", nan());
+  test_sok(buffer,"+NAN");
+  line(4);
+  sprintf(buffer,"%+E", -nan());
+  test_sok(buffer,"-NAN");
   newfunc("nanf");
   line(1);
   flt_inf_nan.value = nanf();
@@ -305,16 +318,29 @@ _DEFUN_VOID(test_nan_inf)
   newfunc("nanf print");
   line(1);
   sprintf(buffer,"%f", nanf());
-  test_sok(buffer,"NaN");
+  test_sok(buffer,"nan");
   line(2);
   sprintf(buffer,"%f", -nanf());
-  test_sok(buffer,"NaN");
+  test_sok(buffer,"nan");
   line(3);
   sprintf(buffer,"%+f", nanf());
-  test_sok(buffer,"+NaN");
+  test_sok(buffer,"+nan");
   line(4);
   sprintf(buffer,"%+f", -nanf());
-  test_sok(buffer,"-NaN");
+  test_sok(buffer,"-nan");
+  newfunc("NANf print");
+  line(1);
+  sprintf(buffer,"%F", nanf());
+  test_sok(buffer,"NAN");
+  line(2);
+  sprintf(buffer,"%F", -nanf());
+  test_sok(buffer,"NAN");
+  line(3);
+  sprintf(buffer,"%+F", nanf());
+  test_sok(buffer,"+NAN");
+  line(4);
+  sprintf(buffer,"%+F", -nanf());
+  test_sok(buffer,"-NAN");
   newfunc("infinity");
   line(1);
   inf_nan.value = infinity();
@@ -327,16 +353,29 @@ _DEFUN_VOID(test_nan_inf)
   newfunc("infinity print");
   line(1);
   sprintf(buffer,"%e", infinity());
-  test_sok(buffer,"Inf");
+  test_sok(buffer,"inf");
   line(2);
   sprintf(buffer,"%e", -infinity());
-  test_sok(buffer,"-Inf");
+  test_sok(buffer,"-inf");
   line(3);
   sprintf(buffer,"%+e", infinity());
-  test_sok(buffer,"+Inf");
+  test_sok(buffer,"+inf");
   line(4);
   sprintf(buffer,"%+e", -infinity());
-  test_sok(buffer,"-Inf");
+  test_sok(buffer,"-inf");
+  newfunc("INFINITY print");
+  line(1);
+  sprintf(buffer,"%E", infinity());
+  test_sok(buffer,"INF");
+  line(2);
+  sprintf(buffer,"%E", -infinity());
+  test_sok(buffer,"-INF");
+  line(3);
+  sprintf(buffer,"%+E", infinity());
+  test_sok(buffer,"+INF");
+  line(4);
+  sprintf(buffer,"%+E", -infinity());
+  test_sok(buffer,"-INF");
   newfunc("infinityf");
   line(1);
   flt_inf_nan.value = infinityf();
@@ -349,16 +388,29 @@ _DEFUN_VOID(test_nan_inf)
   newfunc("infinityf print");
   line(1);
   sprintf(buffer,"%f", infinityf());
-  test_sok(buffer,"Inf");
+  test_sok(buffer,"inf");
   line(2);
   sprintf(buffer,"%f", -infinityf());
-  test_sok(buffer,"-Inf");
+  test_sok(buffer,"-inf");
   line(3);
   sprintf(buffer,"%+f", infinityf());
-  test_sok(buffer,"+Inf");
+  test_sok(buffer,"+inf");
   line(4);
   sprintf(buffer,"%+f", -infinityf());
-  test_sok(buffer,"-Inf");
+  test_sok(buffer,"-inf");
+  newfunc("INFINITYf print");
+  line(1);
+  sprintf(buffer,"%F", infinityf());
+  test_sok(buffer,"INF");
+  line(2);
+  sprintf(buffer,"%F", -infinityf());
+  test_sok(buffer,"-INF");
+  line(3);
+  sprintf(buffer,"%+F", infinityf());
+  test_sok(buffer,"+INF");
+  line(4);
+  sprintf(buffer,"%+F", -infinityf());
+  test_sok(buffer,"-INF");
 #ifdef __DJGPP__
   _fpreset();
 #endif

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019