Mail Archives: djgpp-workers/2008/04/24/09:27:28
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 -