delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2007/10/19/16:38:22

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/WPO8HzWPWoKId8N+X1Bphbe+AiEJxY0amErsw0J
4Jj1IlPFxhxxN0
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
To: djgpp-workers AT delorie DOT com
Subject: Implementation of the %a conversion specifier and the grouping format for doprnt
Date: Fri, 19 Oct 2007 22:11:12 +0200
User-Agent: KMail/1.9.5
MIME-Version: 1.0
Message-Id: <200710192211.12891.juan.guerrero@gmx.de>
X-Y-GMX-Trusted: 0
Reply-To: djgpp-workers AT delorie DOT com

The goal of this patch is to implement the grouping functionality and
the %[a|A] hex conversion specifier in _doprnt().  Also the %F conversion
specifier has been added as a synonym for %f as specified by C99.
If the conversion specifiers %a, %e, %f or %g are used then "inf" or "nan"
strings will be used.  For %A, %E, %F or %G "INF" or "NAN" will be used
as C99 says.



If the printf output is compared with the linux printf output there will be
three differences:

1) djgpp's doprnt promots all double to long double.  This seems not to be the
case with gnu libc printf function.  This will have the consequence that the
representation of doubles will not be the same.  I do not have the time to become
familiar with gnu libc code to understand what they do and how to change djgpp's
doprnt() accordingly.  Anyway the issue here is to be standard conforming and
not to imitate the gnu libc behaviour.
The representation (printing) of long doubles coding normalized finite numbers
by this %a implementation is the same as by the gnu libc implementation.

2) The representation (printing) of long doubles coding denormalized finite numbers
by this %a implementation diferes from the gnu libc implementation.
Example:  Given the following denormalized number (long double):
  mantissah = 0x00000000U
  mantissal = 0x12345678U
  exponent  = 0x0000 (biased)
with base 2 and smallest valid exponent = -16382 (decimal).
The standard says that if the power is 2 then the mantissa representation shall
be exact.  This is always possible because the mantissa is 64 bit long which can
always divided in an integral number of nibbles (hex digits).
The gnu libc printf function will print:
  0x0.000000012345678p-16385
with the conversion specifier: %La.  That looks bizaar from a mathematical point of view
IMHO but it is standard conforming because it is an exact representation of the mantissa.
If the same number is printed with %.6La then the output looks like:
  0x0.000000p-16385
In the best case this looks bizaar, in the worst case it looks confusing.
My implementation works as follows:
a) Renormalisation of the mantissa.
   The standard tells that the hex representation of the mantissa of a *normalized* finite
   number shall look like:
     0xh.hhhh
   where the integer part of the mantissa shall by one single hex digit *different* from zero.
   By right shifting of the mantissa of a *denormalized* finite number, it is always possible
   to "renormalize" the mantissa.  Of cuorse, the value of the number will not change because
   the exponent is adjusted accordingly to compensate for the mantissa shifting.
   This will make that representation of the above mantissa will look like:
     0x1.234567800000000 p-(3 + 4 * 7 + 4)  (mantissa only)
   Because the binary coded long double mantissa has an explicit binary digit in the integer
   part, always three more binary digits from the mantissa must be shifted before the radix
   point to get a single hex digit in the integer part.  Also all nibbles that are zero must
   be shifted from the fraction part into the integer part.  Then one nibble different from
   zero must be shifted in the integer part. In the above example this means:
   3 + 7 * 4 + 4 in the exponent.
b) All formating information (precison and rounding to even, etc.) is applied to this new,
   renormalized mantissa.  If no precision is given, the standard says that trailing zeros in
   the fraction part may be omitted.  In this case the above mantissa will become:
     0x1.2345678 p-(3 + 4 * 7 + 4)
   For the above example the result to be printed with %La will look like:
     0x1.2345678p-(16417 = 16382 + 3 + 4 * 7 + 4)
   The result of printing with %.6La will look lke:
     0x1.234568p-16417  (rounding to even)
   The representation is exact (within the limits of the rounding) and IMHO it looks more
   rational than 0x0.000000p-16385.
   It should be noticed that if the same number is printed in decimal representation it looks
   like:
    0.000000 for %Lf
   and
    1.11332e-4942 for %.6Lg
   From a mathematical point of view, both representations make sense.  Either the number is so
   small that it is represented by zero or it is represented by a small value different from
   zero.  In this case both mantissa and exponent should be different from zero.
In other words, the difference in behaviour when printing subnormal finite numbers between gnu
libc implementation and this one is not a bug but it is fully intentional.

3) The difference I will report here has not been introduced by me.  I simple reporting it because
I have noticed it. There is a difference in printing this number:
  mantissah = 0x00000000U
  mantissal = 0x00000000U
  exponent  = 0x7FFFU (biased)
djgpp's doprnt() outputs "Unnormal". gnu libc outputs: 0x0p+16381.  The decimal representation that
gnu libc produces looks even worser.  Looking at "intel 64 and IA-32 Architectures Software Developer's
Manual. Vol 1" (253665.pdf) shows that the above does not encode any valid number.  The version gnu
libc is 2.3.X (opensuse 10.2).  I do not know if this is a bug of gnu libc and I do not have the time
to investigate this further.

To test the %a conversion specifier I have added a new test file (printf3.c) to tests/libc/ansi/stdio/.
The makefile has been modified accordingly.  Also tests/cygnus/convert.c has been modified to
reflect the use of the C99 nan|NAN and inf|INF strings instead of the old ones.


Because djgpp offers no locale at all (except C/posix), the grouping format functionally can only
be test if variables like decimal_point, thousands_sep and grouping are explicitly hardcoded in
doprnt().  To test the new formating function I have taken the locale values from de_DE of my linux
machine.  Of course, after verifying that it works as I expected that testing code has been removed.


The changelog below is a very crude resume of the things I have changed.
As usual, comments, objections, suggestions are welcome.


Regards,
Juan M. Guerrero






2007-10-18  Juan Manuell Guerrero  <juan DOT guerrero AT gmx DOT de>

	* src/libc/ansi/stdio/doprnt.c: Use nan and inf with %a, %e, %f or %g.
	Use NAN and INF with %A, %E, %F or %G.
	(_doprnt): %F conversion specifier added.
	(isspeciall): Replace the union ip_union to access long doubles with
	the one defined in libc/ieee.h.
	(cvtl): Implement %a and %A conversion specifier.
	(__grouping_format): New function.  Formats the integer portion of the
	result of a decimal conversion (%i, %d, %u, %f, %F, %g and %G) using
	the non-monetary thousends' grouping character.


2007-10-18  Juan Manuell Guerrero  <juan DOT guerrero AT gmx DOT de>

	* tests/libc/ansi/stdio/printf3.c: New file.  Implements tests
	for %a and %A conversion specifier.
	* tests/libc/ansi/stdio/makefile: Entry for printf3.c added.


2007-10-18  Juan Manuell Guerrero  <juan DOT guerrero AT gmx DOT de>

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


2007-10-18  Juan Manuell Guerrero  <juan DOT guerrero AT gmx DOT de>

	* src/docs/kb/wc204.txi: Info about grouping conversion qualifier and
	%a, %A and %F convertion specifiers for doprnt.c and printf family of
	functions added.


2007-10-18  Juan Manuell Guerrero  <juan DOT guerrero AT gmx DOT de>

	* src/libc/ansi/stdio/printf.txh: Info for %a and %A conversion
	specifier added.  %F conversion specifier added.



diff -aprNU3 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi
--- djgpp.orig/src/docs/kb/wc204.txi	2005-05-11 20:06:08 +0000
+++ djgpp/src/docs/kb/wc204.txi	2007-10-02 18:32:24 +0000
@@ -1094,3 +1094,15 @@ formats for @code{"%x"} and @code{"%X"} 
 
 @pindex djasm AT r{, cr4 register}
 @code{djasm} recognises the fourth control register, @code{cr4}.
+
+@findex _doprnt AT r{, and C99 conversion specifiers}
+@findex printf AT r{, and C99 conversion specifiers}
+The @code{a}, @code{A} and @code{F} conversion specifiers
+are now supported by @code{_doprnt} and the @code{printf}
+family of functions.
+
+@findex _doprnt AT r{, and C99 conversion qualifiers}
+@findex printf AT r{, and C99 conversion qualifiers}
+The @code{'} conversion qualifier is now supported by @code{_doprnt}
+and the @code{printf} family of functions.
+
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	2005-03-17 19:00:40 +0000
+++ djgpp/src/libc/ansi/stdio/doprnt.c	2007-10-19 11:12:00 +0000
@@ -1,3 +1,4 @@
+/* Copyright (C) 2007 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
@@ -12,14 +13,17 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <locale.h>
-#include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <math.h>
+#include <limits.h>
 #include <libc/file.h>
 #include <libc/local.h>
 #include <libc/ieee.h>
 
-static char decimal = '.';
+static char decimal_point;
+static char thousands_sep;
+static char *grouping;
 
 /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
 #define	MAXEXP		308
@@ -34,12 +38,22 @@ static char decimal = '.';
 
 #define	PUTC(ch)	(void) putc(ch, fp)
 
-#define ARG(basetype) _ulonglong = \
-		flags&LONGDBL ? va_arg(argp, long long basetype) : \
-		flags&LONGINT ? va_arg(argp, long basetype) : \
-		flags&SHORTINT ? (short basetype)va_arg(argp, int) : \
-		flags&CHARINT ? (char basetype)va_arg(argp, int) : \
-		(basetype)va_arg(argp, int)
+#define ARG(basetype) _ulonglong =                                      \
+                flags & LONGDBL  ? va_arg(argp, long long basetype) :   \
+                flags & LONGINT  ? va_arg(argp, long basetype) :        \
+                flags & SHORTINT ? (short basetype)va_arg(argp, int) :  \
+                flags & CHARINT  ? (char basetype)va_arg(argp, int) :   \
+                (basetype)va_arg(argp, int)
+
+#define CONVERT(type, value, base, string, case)               \
+  do {                                                         \
+    const char *digit = (case) ? UPPER_DIGITS : LOWER_DIGITS;  \
+    register type _value = (type)(value);                      \
+                                                               \
+    do {                                                       \
+      *--(string) = digit[(_value) % (base)];                  \
+    } while ((_value) /= (base));                              \
+  } while (0)
 
 static int nan_p = 0;
 
@@ -58,14 +72,18 @@ static __inline__ char tochar(int n)
 
 /* have to deal with the negative buffer count kludge */
 
-#define	LONGINT		0x01		/* long integer */
-#define	LONGDBL		0x02		/* long double */
-#define	SHORTINT	0x04		/* short integer */
-#define	CHARINT		0x08		/* char */
-#define	ALT		0x10		/* alternate form */
-#define	LADJUST		0x20		/* left adjustment */
-#define	ZEROPAD		0x40		/* zero (as opposed to blank) pad */
-#define	HEXPREFIX	0x80		/* add 0x or 0X prefix */
+#define	LONGINT		0x001		/* long integer */
+#define	LONGDBL		0x002		/* long double */
+#define	SHORTINT	0x004		/* short integer */
+#define	CHARINT		0x008		/* char */
+#define	FLOAT		0x010		/* %f, %F, %g or %G decimal conversions */
+#define	ALT		0x020		/* alternate form */
+#define	LADJUST		0x040		/* left adjustment */
+#define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */
+#define	HEXPREFIX	0x100		/* add 0x or 0X prefix */
+#define	UPPERCASE	0x200		/* INF/NAN for [AEFG] */
+#define	GROUPING	0x400		/* non monetary thousands grouping */
+#define	FINITENUMBER	0x800		/* not set if NAN, INF or Unnormal */
 
 static int cvtl(long double number, int prec, int flags, char *signp,
 	        unsigned char fmtch, char *startp, char *endp);
@@ -73,11 +91,17 @@ static char *doprnt_roundl(long double f
 			   char *end, char ch, char *signp);
 static char *exponentl(char *p, int expv, unsigned char fmtch);
 #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";
+static const char UNNORMAL_REP[] = "Unnormal";
+static const char LOWER_DIGITS[] = "0123456789abcdef";
+static const char UPPER_DIGITS[] = "0123456789ABCDEF";
+static const char INF_REP[2][4] = {"inf", "INF"};  /* inf for [aefg] and INF for [AEFG] */
+static const char NAN_REP[2][4] = {"nan", "NAN"};  /* nan for [aefg] and NAN for [AEFG] */
 
 int
 _doprnt(const char *fmt0, va_list argp, FILE *fp)
@@ -88,24 +112,26 @@ _doprnt(const char *fmt0, va_list argp, 
   int n;			/* random handy integer */
   char *t;			/* buffer pointer */
   long double _ldouble;		/* double and long double precision arguments
-				   %L.[eEfgG] */
+				   %L.[aAeEfFgG] */
   unsigned long long _ulonglong=0; /* integer arguments %[diouxX] */
   int base;			/* base for [diouxX] conversion */
   int dprec;			/* decimal precision in [diouxX] */
   int fieldsz;			/* field size expanded by sign, etc */
   int flags;			/* flags as above */
-  int fpprec;			/* `extra' floating precision in [eEfgG] */
+  int fpprec;			/* `extra' floating precision in [eEfFgG] */
   int prec;			/* precision from format (%.3d), or -1 */
   int realsz;			/* field size expanded by decimal precision */
   int size;			/* size of converted field or string */
   int width;			/* width from format (%8d), or 0 */
   char sign;			/* sign prefix (' ', '+', '-', or \0) */
   char softsign;		/* temporary negative sign for floats */
-  const char *digs;		/* digits for [diouxX] conversion */
-  char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */
+  char buf[BUF];		/* space for %c, %[diouxX], %[aAeEfFgG] */
   int neg_ldouble = 0;		/* non-zero if _ldouble is negative */
+  struct lconv *locale_info;    /* current locale information */
+
 
-  decimal = localeconv()->decimal_point[0];
+  locale_info = localeconv();
+  decimal_point = locale_info->decimal_point[0];
 
   if (fp->_flag & _IORW)
   {
@@ -116,9 +142,10 @@ _doprnt(const char *fmt0, va_list argp, 
     return (EOF);
 
   fmt = fmt0;
-  digs = "0123456789abcdef";
   for (cnt = 0;; ++fmt)
   {
+    _longdouble_union_t ldvalue;
+
     while ((ch = *fmt) && ch != '%')
     {
       PUTC (ch);
@@ -127,12 +154,24 @@ _doprnt(const char *fmt0, va_list argp, 
     }
     if (!ch)
       return cnt;
+    base = 0;
     flags = 0; dprec = 0; fpprec = 0; width = 0;
     prec = -1;
     sign = '\0';
   rflag:
     switch (*++fmt)
     {
+    case '\'':
+       /*
+        *  If the locale is C or POSIX
+        *  this is defacto a NOP because
+        *  neither thousands_sep nor grouping
+        *  are set.
+        */
+       flags |= GROUPING;
+       thousands_sep = locale_info->thousands_sep[0];
+       grouping = locale_info->grouping;
+       goto rflag;
     case ' ':
       /*
        * ``If the space and + flags both appear, the space
@@ -195,7 +234,7 @@ _doprnt(const char *fmt0, va_list argp, 
       flags |= LONGDBL;
       goto rflag;
     case 'h':
-      if (flags&SHORTINT) {
+      if (flags & SHORTINT) {
 	/* C99 */
 	/* for 'hh' - char */
 	flags |= CHARINT;
@@ -205,7 +244,7 @@ _doprnt(const char *fmt0, va_list argp, 
       }
       goto rflag;
     case 'l':
-      if (flags&LONGINT)
+      if (flags & LONGINT)
 	flags |= LONGDBL; /* for 'll' - long long */
       else
 	flags |= LONGINT;
@@ -236,30 +275,52 @@ _doprnt(const char *fmt0, va_list argp, 
 	sign = '-';
       }
       base = 10;
+      flags |= FINITENUMBER;
       goto number;
-    case 'e':
+    case 'A':
     case 'E':
+    case 'F':
+    case 'G':
+      flags |= UPPERCASE;
+    case 'a':
+    case 'e':
     case 'f':
     case 'g':
-    case 'G':
+      flags |= FLOAT;
+      if (*fmt == 'A' || *fmt == 'a')
+        flags |= HEXPREFIX;
       if (flags & LONGDBL)
 	_ldouble = va_arg(argp, long double);
       else
 	_ldouble = (long double)va_arg(argp, double);
+
+      ldvalue.ld = _ldouble;
+      if (ldvalue.ldt.exponent != 0x7FFF)
+        flags |= FINITENUMBER;
+
       /*
        * don't do unrealistic precision; just pad it with
        * zeroes later, so buffer size stays rational.
        */
       if (prec > MAXFRACT)
       {
-	if (*fmt != 'g' && (*fmt != 'G' || (flags&ALT)))
+	if (*fmt != 'g' && (*fmt != 'G' || (flags & ALT)))
 	  fpprec = prec - MAXFRACT;
 	prec = MAXFRACT;
       }
       else if (prec == -1)
       {
-	if (flags&LONGINT)
+	if (flags & LONGINT)
 	  prec = DEFLPREC;
+	else if (flags & HEXPREFIX)
+          /*
+           *  C99 imposes that precision must be sufficient
+           *  for an exact representation of the mantissa.
+           *  If no explicit precision is given, the required
+           *  precision for exact representation will be
+           *  determinated in the convertion function itself.
+           */
+	  prec = -1;
 	else
 	  prec = DEFPREC;
       }
@@ -275,11 +336,7 @@ _doprnt(const char *fmt0, va_list argp, 
       }
       else
       {
-	_longdouble_union_t ip;
-
-	ip.ld = _ldouble;
-
-	if (ip.ldt.sign)
+	if (ldvalue.ldt.sign)
 	  neg_ldouble = 1;
 	else
 	  neg_ldouble = 0;
@@ -288,9 +345,9 @@ _doprnt(const char *fmt0, va_list argp, 
       /*
        * cvt may have to round up past the "start" of the
        * buffer, i.e. ``intf("%.2f", (double)9.999);'';
-       * if the first char isn't NULL, it did.
+       * if the first char isn't NUL, it did.
        */
-      *buf = NULL;
+      *buf = 0;
       size = cvtl(_ldouble, prec, flags, &softsign, *fmt, buf,
 		  buf + sizeof(buf));
       /*
@@ -303,6 +360,7 @@ _doprnt(const char *fmt0, va_list argp, 
 	sign = '-';
       nan_p = 0;
       t = *buf ? buf : buf + 1;
+      base = flags & HEXPREFIX ? 16 : 10;
       goto pforw;
     case 'n':
       if (flags & LONGDBL)
@@ -366,9 +424,10 @@ _doprnt(const char *fmt0, va_list argp, 
     case 'u':
       ARG(unsigned);
       base = 10;
+      flags |= FINITENUMBER;
       goto nosign;
     case 'X':
-      digs = "0123456789ABCDEF";
+      flags |= UPPERCASE;
       /* FALLTHROUGH */
     case 'x':
       ARG(unsigned);
@@ -399,31 +458,32 @@ _doprnt(const char *fmt0, va_list argp, 
       if (_ulonglong != 0 || prec != 0)
       {
         /* conversion is done separately since operations
-	  with long long are much slower */
-#define CONVERT(type) \
-	{ \
-	  register type _n = (type)_ulonglong; \
-	  do { \
-	    *--t = digs[_n % base]; \
-	    _n /= base; \
-	  } while (_n); \
-	}
-	if (flags&LONGDBL)
-	  CONVERT(unsigned long long) /* no ; */
-	else
-	  CONVERT(unsigned long) /* no ; */
-#undef CONVERT
+           with long long are much slower */
+        if (flags & LONGDBL)
+          CONVERT(unsigned long long, _ulonglong, base, t, flags & UPPERCASE);
+        else
+          CONVERT(unsigned long, _ulonglong, base, t, flags & UPPERCASE);
+
         if (flags & ALT && base == 8 && *t != '0')
           *--t = '0';		/* octal leading 0 */
       }
 
-      digs = "0123456789abcdef";
       size = buf + BUF - t;
 
     pforw:
+      if (flags & FINITENUMBER && flags & GROUPING && base == 10 && thousands_sep && *grouping != CHAR_MAX)
+      {
+        register char *p;
+
+        for (p = buf; *t; *p++ = *t++)
+          ;  /*  The function expects the string to be formated at the beginning of the buffer.  */
+        t = __grouping_format(buf, p, buf + BUF, flags);
+        size = buf + BUF - t;
+      }
+
       /*
        * All reasonable formats wind up here.  At this point,
-       * `t' points to a string which (if not flags&LADJUST)
+       * `t' points to a string which (if not flags & LADJUST)
        * should be padded out to `width' places.  If
        * flags&ZEROPAD, it should first be prefixed by any
        * sign or other prefix; otherwise, it should be blank
@@ -443,23 +503,23 @@ _doprnt(const char *fmt0, va_list argp, 
       realsz = dprec > fieldsz ? dprec : fieldsz;
       if (sign)
 	realsz++;
-      if (flags & HEXPREFIX)
+      if (flags & HEXPREFIX && flags & FINITENUMBER)
 	realsz += 2;
 
       /* right-adjusting blank padding */
-      if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
+      if ((flags & (LADJUST | ZEROPAD)) == 0 && width)
 	for (n = realsz; n < width; n++)
 	  PUTC(' ');
       /* prefix */
       if (sign)
 	PUTC(sign);
-      if (flags & HEXPREFIX)
+      if (flags & HEXPREFIX && flags & FINITENUMBER)
       {
 	PUTC('0');
-	PUTC((char)*fmt);
+	PUTC((*fmt == 'A') ? 'X' : (*fmt == 'a') ? 'x' : (char)*fmt);
       }
       /* right-adjusting zero padding */
-      if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+      if ((flags & (LADJUST | ZEROPAD)) == ZEROPAD)
 	for (n = realsz; n < width; n++)
 	  PUTC('0');
       /* leading zeroes from decimal precision */
@@ -525,9 +585,197 @@ 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);
 
+  if (fmtch == 'a' || fmtch == 'A')
+  {
+    /*
+     *  We are dealing with intel's extended double format.
+     *  The 64-bit mantissa explicitly contains the leading integer binary digit.
+     *  C99 standard defines hex float format as: 0xh.hhhp+d
+     *  where h is a hex digit, d is a decimal digit and p represents base 2.
+     *  The 64 bit of the mantissa can be subdivided into 16 nibbles,
+     *  so exact hex representation of the binary coded mantissa is
+     *  possible.  To get a single hex digit in the integer part of
+     *  the mantissa the period must be shifted by three places
+     *  to the right if the number is a normalized finite one.
+     *  If it is a denormalized finite number, then it may become necessary
+     *  to shift the period by ont to fifteen places.  Accordingly the exponent
+     *  must be adjusted.
+     */
+#undef  FALSE
+#define FALSE                           0
+#undef  TRUE
+#define TRUE                            1
+#define CHAR_SIZE                       8
+#define HEX_DIGIT_SIZE                  4
+#define IEEE754_LONG_DOUBLE_BIAS        0x3fff
+
+
+    long_double_t ip = *(long_double_t *)(void *)&number;
+    char *fraction_part;
+    int left_shifts, precision_given, positive_exponent, exponent = ip.exponent;
+    unsigned long long int mantissa = (unsigned long long int) ip.mantissah << 32 | ip.mantissal;
+
+    p = endp;
+    t = startp;
+    precision_given = (prec != -1) ? TRUE : FALSE;
+
+    /*
+     *  Compute the amount of left shifts necessary
+     *  to have one single hex digit (nibble) in the
+     *  integer part of the mantissa.  For normalized
+     *  finite numbers these are 3.  For denormalized
+     *  finte numbers these will range from 1 to 15.
+     *  Accordingly to this value the exponent will be
+     *  adjusted.
+     */
+    left_shifts = 0;  /*  No shifts for 0.0  */
+    if (mantissa)
+    {
+      unsigned long long int m = mantissa;
+
+      for (; (mantissa & 0x8000000000000000ULL) == 0; left_shifts++)
+        mantissa <<= 1;
+      if (left_shifts)  /*  Denormalized finite.  */
+      {
+        if (precision_given == FALSE)
+          mantissa = m;
+
+        if (left_shifts < (int)(sizeof(mantissa) * CHAR_SIZE - HEX_DIGIT_SIZE))
+        {
+          /*
+           *  For an exact representation of the mantissa
+           *  there must be a integral number of nibbles
+           *  (hex digit) in the fraction part of the mantissa.
+           *  A fraction part of a nibble will be shifted
+           *  into the integer part of the mantissa.
+           *  The converted mantisssa will look like:
+           *    0xh.hhhh
+           *  and the exponent will be adjusted accordingly.
+           */
+          unsigned int bin_digits, digits = (sizeof(mantissa) * CHAR_SIZE - 1 - left_shifts) % HEX_DIGIT_SIZE;  /*  Number of digits that do not build a nibble in the fraction part.  */
+
+          /*
+           *  Shift the period to the left
+           *  until no fraction of a nibble remains
+           *  in the fraction part of the mantissa.
+           */
+          for (bin_digits = 0; bin_digits < digits; bin_digits++)
+            left_shifts++;
+
+          /*
+           *  If no binary digits are shifted into the integer part,
+           *  then the nibble of the integer part must be filled with zeros.
+           */
+          if (precision_given == TRUE && bin_digits == 0)
+            mantissa >>= (HEX_DIGIT_SIZE - 1);
+        }
+        else
+          left_shifts = sizeof(mantissa) * CHAR_SIZE - 1;
+      }
+      else              /*  Normalized finite.  */
+        left_shifts = HEX_DIGIT_SIZE - 1;
+    }
+
+    /*
+     *  Mantissa.
+     *  The mantissa representation shall be exact
+     *  except that trailing zeros may be omitted.
+     */
+    if (precision_given == TRUE)
+    {
+      unsigned int fraction_hex_digits = sizeof(mantissa) * CHAR_SIZE / HEX_DIGIT_SIZE - 1;  /*  Number of hex digits (nibbles) in the fraction part.  */
+
+      if (prec < (int)fraction_hex_digits)
+      {
+        /*
+         *  If requested precision is less than the size of
+         *  the mantissa's fraction do rounding to even.
+         */
+#define MUST_ROUND_TO_EVEN(value)  ((((value) & 0x0fULL) == 0x08ULL) && ((((value) & 0xf0ULL) >> HEX_DIGIT_SIZE) % 2))
+        unsigned int n = fraction_hex_digits - prec - 1;  /*  One nibble more than precision.  */
+
+        mantissa >>= n * HEX_DIGIT_SIZE;  /*  The least significant nibble will determinate the rounding.  */
+        if (((mantissa & 0x0fULL) > 0x08ULL) || MUST_ROUND_TO_EVEN(mantissa))
+          mantissa += 0x10ULL;            /*  Round up.  */
+        mantissa >>= HEX_DIGIT_SIZE;      /*  Discard least significant nibble used for rounding.  */
+
+        n = fraction_hex_digits - n;
+        if ((mantissa >> (n * HEX_DIGIT_SIZE)) & 0x01ULL)  /*  Carry ?  */
+        {
+          /*
+           *  The rounding has produced a 2 hex digit long integer part
+           *  of the mantissa, so the mantissa must be shifted to the right
+           *  by one hex digit and the exponent adjusted accordingly.
+           */
+          mantissa >>= HEX_DIGIT_SIZE;
+          left_shifts -= HEX_DIGIT_SIZE;
+        }
+#undef MUST_ROUND_TO_EVEN
+      }
+    }
+
+    CONVERT(unsigned long long int, mantissa, 16, p, fmtch == 'A');
+    *t++ = *p++;
+    *t++ = decimal_point;
+
+    fraction_part = t;
+    for (; p < endp; *t++ = *p++)
+      ;
+    if (precision_given == FALSE)
+    {
+      /*
+       *  C99 imposes that, if the precision is omitted,
+       *  the precision must be sufficient for an exact
+       *  representation of the mantissa except that the
+       *  trailing zeros may be omitted.
+       */
+      while (*--t == '0')
+        ;  /*  Discart trailing zeros. */
+      t++;  /*  Points to first free place.  */
+    }
+    else
+      while (t - fraction_part < prec && t < endp)
+        *t++ = '0';  /*  Pad with zeros to the right.  At the end of the loop points to first free place.  */
+    if (t[-1] == decimal_point && !(flags & ALT))
+      t--;  /*  Do not output a decimal point.  */
+
+    /*
+     *  Exponent.
+     */
+    if (exponent == 0)
+    {
+      if (mantissa)     /*  Denormalized finite number.  */
+        exponent = 1 - IEEE754_LONG_DOUBLE_BIAS;
+    }
+    else                /*  Normalized finite number.  */
+      exponent -= IEEE754_LONG_DOUBLE_BIAS;
+    exponent -= left_shifts;
+    if (exponent < 0)
+    {
+      exponent = -exponent;
+      positive_exponent = FALSE;
+    }
+    else
+      positive_exponent = TRUE;
+
+    CONVERT(int, exponent, 10, p, flags & UPPERCASE);
+    *--p = (positive_exponent) ? '+' : '-';
+    *--p = (flags & UPPERCASE) ? 'P' : 'p';
+    for (; p < endp; *t++ = *p++)
+      ;
+
+    return t - startp;
+
+#undef IEEE754_LONG_DOUBLE_BIAS
+#undef HEX_DIGIT_SIZE
+#undef CHAR_SIZE
+#undef FALSE
+#undef TRUE
+  }
+
   dotrim = expcnt = gformat = 0;
   /* fract = modfl(number, &integer); */
   integer = number;
@@ -572,11 +820,12 @@ cvtl(long double number, int prec, int f
   number = integer;
   fract = modfl(number, &integer);
   /* If integer is zero then we need to look at where the sig figs are */
-  if (integer<1) {
-        /* If fract is zero the zero before the decimal point is a sig fig */
-        if (fract==0.0) doingzero=1;
-        /* If fract is non-zero all sig figs are in fractional part */
-        else doextradps=1;
+  if (integer < 1)
+  {
+    /* If fract is zero the zero before the decimal point is a sig fig */
+    if (fract == 0.0) doingzero = 1;
+    /* If fract is non-zero all sig figs are in fractional part */
+    else doextradps = 1;
   }
   /*
    * get integer portion of number; put into the end of the buffer.
@@ -595,6 +844,7 @@ cvtl(long double number, int prec, int f
   switch(fmtch)
   {
   case 'f':
+  case 'F':
     /* reverse integer into beginning of buffer */
     if (expcnt)
       for (; ++p < endp; *t++ = *p);
@@ -604,8 +854,8 @@ cvtl(long double number, int prec, int f
      * if precision required or alternate flag set, add in a
      * decimal point.
      */
-    if (prec || flags&ALT)
-      *t++ = decimal;
+    if (prec || flags & ALT)
+      *t++ = decimal_point;
     /* if requires more precision and some fraction left */
     if (fract)
     {
@@ -626,8 +876,8 @@ cvtl(long double number, int prec, int f
     if (expcnt)
     {
       *t++ = *++p;
-      if (prec || flags&ALT)
-	*t++ = decimal;
+      if (prec || flags & ALT)
+	*t++ = decimal_point;
       /* if requires more precision and some integer left */
       for (; prec && ++p < endp; --prec)
 	*t++ = *p;
@@ -683,14 +933,14 @@ cvtl(long double number, int prec, int f
 	  break;
       }
       *t++ = tochar((int)tmp);
-      if (prec || flags&ALT)
-	*t++ = decimal;
+      if (prec || flags & ALT)
+	*t++ = decimal_point;
     }
     else
     {
       *t++ = '0';
-      if (prec || flags&ALT)
-	*t++ = decimal;
+      if (prec || flags & ALT)
+	*t++ = decimal_point;
     }
     /* if requires more precision and some fraction left */
     if (fract)
@@ -708,10 +958,10 @@ cvtl(long double number, int prec, int f
     for (; prec--; *t++ = '0');
 
     /* unless alternate flag, trim any g/G format trailing 0's */
-    if (gformat && !(flags&ALT))
+    if (gformat && !(flags & ALT))
     {
       while (t > startp && *--t == '0');
-      if (*t == decimal)
+      if (*t == decimal_point)
 	--t;
       ++t;
     }
@@ -760,10 +1010,10 @@ cvtl(long double number, int prec, int f
      * if precision required or alternate flag set, add in a
      * decimal point.  If no digits yet, add in leading 0.
      */
-    if (prec || flags&ALT)
+    if (prec || flags & ALT)
     {
       dotrim = 1;
-      *t++ = decimal;
+      *t++ = decimal_point;
     }
     else
       dotrim = 0;
@@ -775,8 +1025,9 @@ cvtl(long double number, int prec, int f
       /* If we're not adding 0s
        * or we are but they're sig figs:
        * decrement the precision */
-      if ((doextradps!=1) || ((int)tmp!=0)) {
-        doextradps=0;
+      if ((doextradps != 1) || ((int)tmp != 0))
+      {
+        doextradps = 0;
         prec--;
       }
     }
@@ -784,12 +1035,12 @@ cvtl(long double number, int prec, int f
       startp = doprnt_roundl(fract, (int *)NULL, startp, t - 1,
 			     (char)0, signp);
     /* alternate format, adds 0's for precision, else trim 0's */
-    if (flags&ALT)
+    if (flags & ALT)
       for (; prec--; *t++ = '0');
     else if (dotrim)
     {
       while (t > startp && *--t == '0');
-      if (*t != decimal)
+      if (*t != decimal_point)
 	++t;
     }
   }
@@ -807,7 +1058,7 @@ doprnt_roundl(long double fract, int *ex
     if (fract == 0.5L)
     {
       char *e = end;
-      if (*e == decimal)
+      if (*e == decimal_point)
 	e--;
       if (*e == '0' || *e == '2' || *e == '4'
 	  || *e == '6' || *e == '8')
@@ -824,7 +1075,7 @@ doprnt_roundl(long double fract, int *ex
   if (tmp > 4)
     for (;; --end)
     {
-      if (*end == decimal)
+      if (*end == decimal_point)
 	--end;
       if (++*end <= '9')
 	break;
@@ -848,7 +1099,7 @@ doprnt_roundl(long double fract, int *ex
   else if (*signp == '-')
     for (;; --end)
     {
-      if (*end == decimal)
+      if (*end == decimal_point)
 	--end;
       if (*end != '0')
 	break;
@@ -890,44 +1141,84 @@ 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;
+  _longdouble_union_t ldvalue;
+  int style = (flags & UPPERCASE) ? 1 : 0;
 
-  ip.ldouble = d;
+  ldvalue.ld = d;
 
   nan_p = 0;  /* don't assume the static is 0 (emacs) */
 
   /* 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 ((ldvalue.ldt.mantissah & 0x80000000U) == 0 && ldvalue.ldt.exponent != 0)
   {
-    if (ip.ip.sign)
+    if (ldvalue.ldt.sign)
       *bufp++ = '-';
     strcpy(bufp, UNNORMAL_REP);
-    return strlen(bufp) + ip.ip.sign;
+    return strlen(bufp) + ldvalue.ldt.sign;
   }
-  if (ip.ip.exp != 0x7fff)
+  if (ldvalue.ldt.exponent != 0x7fff)
     return(0);
-  if ((ip.ip.manh & 0x7fffffff) || ip.ip.manl)
+  if ((ldvalue.ldt.mantissah & 0x7fffffff) || ldvalue.ldt.mantissal)
   {
-    strcpy(bufp, "NaN");
-    nan_p = ip.ip.sign ? -1 : 1; /* kludge: we don't need the sign, it's
-				    not nice, but it should work */
+    strcpy(bufp, NAN_REP[style]);
+    nan_p = ldvalue.ldt.sign ? -1 : 1; /* kludge: we don't need the sign, it's
+                                          not nice, but it should work */
   }
   else
-    (void)strcpy(bufp, "Inf");
+    (void)strcpy(bufp, INF_REP[style]);
   return(3);
 }
+
+static __inline__ char *
+__grouping_format(char *string_start, char *string_end, char *buffer_end, int flags)
+{
+  /*
+   *  Format the string representing the integer portion of a decimal
+   *  conversion using non-mometary thousands' grouping characters.
+   *  It is assumed that STRING_START points at the beginning and 
+   *  STRING_END points to the end of the string to be formatted.
+   *  BUFFER_END points to the end of the buffer that will store
+   *  the formated string.
+   */
+
+  ptrdiff_t grouping_size;
+  register char *pos, *src, *dst;
+
+
+  src = string_end;
+  dst = buffer_end;
+
+  /*
+   *  The fractional portion of the result of a decimal conversion
+   *  (%f, %F, %g or %G) is left unaltered.
+   */
+  if (flags & FLOAT)
+    for (; *src != decimal_point; *--dst = *--src)
+      ;  /*  Copy fractional portion to the end of the buffer.  */
+
+  pos = dst;
+  grouping_size = (ptrdiff_t)*grouping;
+  if (grouping_size == (ptrdiff_t)CHAR_MAX)
+    for (; src > string_start; *--dst = *--src)
+      ;  /*  Group the remainder digits together.  */
+  else
+    for (; src > string_start; *--dst = *--src)
+      if (pos - dst == grouping_size)
+      {
+        *--dst = thousands_sep;
+        pos = dst;
+        if (grouping_size)
+        {
+          grouping++;
+          if (*grouping == (ptrdiff_t)CHAR_MAX)
+            grouping_size = 0;  /*  Group the remainder digits together.  */
+          else if (*grouping)
+            grouping_size = (ptrdiff_t)*grouping;  /*  Get next size of group of digits to be formatted.  */
+        }
+      }
+
+  return (*dst == thousands_sep) ? dst + 1 : dst;  /*  Remove leading thousands separator character.  */
+}
diff -aprNU3 djgpp.orig/src/libc/ansi/stdio/printf.txh djgpp/src/libc/ansi/stdio/printf.txh
--- djgpp.orig/src/libc/ansi/stdio/printf.txh	2003-01-29 12:28:44 +0000
+++ djgpp/src/libc/ansi/stdio/printf.txh	2007-10-02 18:30:08 +0000
@@ -101,6 +101,17 @@ The conversion type specifier:
 
 @table @code
 
+@item a
+@itemx A
+
+A floating point number (float or double) printed in the style
+@code{"[-]0xh.hhhhp[+|-]d"}, where @code{h} represents a hexadecimal
+digit, @code{d} represents a decimal digit and @code{p} stands for the
+base 2.  For long double, use @code{"La"} or @code{"LA"}.  The case of
+the exponent, the case of the letters @code{"abcdef"} and the case of
+@code{"x"} matches the specifier case.  The representation always has
+an exponent.
+
 @item c
 
 A single character.
@@ -122,6 +133,7 @@ A floating point number (float or double
 case.  The representation always has an exponent.
 
 @item f
+@item F
 
 A floating point number (float or double).  For long double, use
 @code{"Lf"}.  The representation never has an exponent.
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	2007-10-02 18:01:40 +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
diff -aprNU3 djgpp.orig/tests/libc/ansi/stdio/makefile djgpp/tests/libc/ansi/stdio/makefile
--- djgpp.orig/tests/libc/ansi/stdio/makefile	2003-11-23 21:14:48 +0000
+++ djgpp/tests/libc/ansi/stdio/makefile	2007-10-01 18:59:14 +0000
@@ -16,6 +16,7 @@ SRC += hello.c
 SRC += mktemp.c
 SRC += printf.c
 SRC += printf2.c
+SRC += printf3.c
 SRC += sscanf.c
 SRC += sscanf2.c
 SRC += sscanf3.c
diff -aprNU3 djgpp.orig/tests/libc/ansi/stdio/printf3.c djgpp/tests/libc/ansi/stdio/printf3.c
--- djgpp.orig/tests/libc/ansi/stdio/printf3.c	1970-01-01 00:00:00 +0000
+++ djgpp/tests/libc/ansi/stdio/printf3.c	2007-10-19 12:31:40 +0000
@@ -0,0 +1,475 @@
+/*
+ * printf3.c
+ * Test cases for %a and %A conversion specifiers new to the ANSI C99 standard.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libc/ieee.h>
+
+#define LOWER_CASE 0
+#define UPPER_CASE 1
+
+static const char *to_be_printed[30][2] = {
+  /*
+   *  Long double test.
+   *  Normalized Finite.
+   */
+  {"0xf.123456789abcdefp+0", "-0XF.123456789ABCDEFP+0"},  /*  0: No precision given. Exact mantissa representation requested.  */
+  {"0xf.123456789ab0000p+0", "-0XF.123456789AB0000P+0"},  /*  1: No precision given. Exact mantissa representation requested. Trailing zeros will be omitted.  */
+  {"0xf.000000000000000p+0", "-0XF.000000000000000P+0"},  /*  2: No precision given. Exact mantissa representation requested. Trailing zeros will be omitted.  */
+  {"0xf.123456789fp+0",      "-0XF.123456789FP+0"},       /*  3: 9 precision digits. Rounding to even.  */
+  {"0xf.1234567891p+0",      "-0XF.1234567891P+0"},       /*  4: 9 precision digits. Rounding to even.  */
+  {"0xf.1234567898p+0",      "-0XF.1234567898P+0"},       /*  5: 9 precision digits. Rounding to even.  */
+  {"0xf.123456788p+0",       "-0XF.123456788P+0"},        /*  6: 8 precision digits. Rounding to even.  */
+  {"0xf.f00000000000000p+0", "-0XF.F00000000000000P+0"},  /*  7: 0 precision digits. Rounding to even.  */
+  {"0xf.100000000000000p+0", "-0XF.100000000000000P+0"},  /*  8: 0 precision digits. Rounding to even.  */
+  {"0x8.fedcba987654321p+0", "-0X8.FEDCBA987654321P+0"},  /*  9: 0 precision digits. Alternate flag given.  */
+  {"0xf.123456789abcdefp+0", "-0XF.123456789ABCDEFP+0"},  /* 10: 6 precision digits and 20 digits of field width.  */
+  {"0xf.123456789abcdefp+0", "-0XF.123456789ABCDEFP+0"},  /* 11: 6 precision digits and 20 digits of field width and zero padding.  */
+  {"0xf.123456789abcdefp+0", "-0XF.123456789ABCDEFP+0"},  /* 12: 6 precision digits and 20 digits of field width and zero padding and a sign.  */
+  {"0xf.123456789abcdefp+0", "-0XF.123456789ABCDEFP+0"},  /* 13: 30 precision digits and 40 digits of field width and zero padding and a sign.  */
+
+  /*
+   *  Long double test.
+   *  Denormalized Finite.
+   *
+   *  Long doubles as defined by intel's fpu.
+   *  bias: 0x3fff
+   *  Smallest licit exponent: -(bias - 1) = -16382
+   *  Radix is 2.
+   *  Mantissa of 64 bits with explicit integer bit.  Makes possible exact hex representation of mantissa.
+   *  Shifting binary point by 3 places to the right allows to represent the integer part of the mantissa
+   *  with one single hex digit. 
+   */
+  {"0x7.fffffffffffffffp-(16382 + 3)",  "-0X7.FFFFFFFFFFFFFFFP-(16382 + 3)"},  /* 14: No precision given. Exact mantissa representation requested.  */
+  {"0x0.123456789abcdefp-(16382 + 3)",  "-0X0.123456789ABCDEFP-(16382 + 3)"},  /* 15: No precision given. Exact mantissa representation requested.  */
+  {"0x0.800000000000000p-(16382 + 3)",  "-0X0.800000000000000P-(16382 + 3)"},  /* 16: No precision given. Exact mantissa representation requested. Trailing zeros will be omitted.  */
+  {"0x0.000000012345678p-(16382 + 3)",  "-0X0.000000012345678P-(16382 + 3)"},  /* 17: 3 precision digits. Rounding to even.  */
+  {"0x0.000000012345678p-(16382 + 3)",  "-0X0.000000012345678P-(16382 + 3)"},  /* 18: 12 precision digits. Rounding to even. Padding with 0.  */
+  {"0x0.0000000f1000000p-(16382 + 3)",  "-0X0.0000000F1000000P-(16382 + 3)"},  /* 19: 0 precision digits. Rounding to even.  */
+  {"0x0.0000000ff000000p-(16382 + 3)",  "-0X0.0000000FF000000P-(16382 + 3)"},  /* 20: 0 precision digits. Rounding to even.  */
+  {"0x0.000000080000000p-(16382 + 3)",  "-0X0.000000080000000P-(16382 + 3)"},  /* 21: 0 precision digits. Alternate flag given.  */
+  {"0x0.000000012345678p-(16382 + 3)",  "-0X0.000000012345678P-(16382 + 3)"},  /* 22: 6 precision digits and 20 digits of field width.  */
+  {"0x0.000000012345678p-(16382 + 3)",  "-0X0.000000012345678P-(16382 + 3)"},  /* 23: 6 precision digits and 20 digits of field width and zero padding.  */
+  {"+0x0.000000012345678p-(16382 + 3)", "-0X0.000000012345678P-(16382 + 3)"},  /* 24: 6 precision digits and 20 digits of field width and zero padding and a sign.  */
+  {"+0x0.123456789abcdefp-(16382 + 3)", "-0X0.123456789ABCDEFP-(16382 + 3)"},  /* 25: 30 precision digits and 50 digits of field width and zero padding and a sign.  */
+
+  /*
+   *  Long double test.
+   *  Zero, INF, NAN and Unnormal.
+   */
+  {"0x0.0p+0",      "-0X0.0P+0"},     /* 26: No precision given. Exact mantissa representation requested.  */
+  {"infinity",      "-INFINITY"},     /* 27: No precision given. Exact mantissa representation requested.  */
+  {"not a number",  "NOT A NUMBER"},  /* 28: No precision given. Exact mantissa representation requested.  */
+  {"Unnormal",      "-Unnormal"}      /* 29: No precision given. Exact mantissa representation requested.  */
+};
+
+static const char *should_looks_like[30][2] = {
+  /*
+   *  Long double test.
+   *  Normalized Finite.
+   */
+  {"0xf.123456789abcdefp+0", "-0XF.123456789ABCDEFP+0"},  /*  0: No precision given. Exact mantissa representation requested.  */
+  {"0xf.123456789abp+0",     "-0XF.123456789ABP+0"},      /*  1: No precision given. Exact mantissa representation requested. Trailing zeros will be omitted.  */
+  {"0xfp+0",                 "-0XFP+0"},                  /*  2: No precision given. Exact mantissa representation requested. Trailing zeros will be omitted.  */
+  {"0xf.12345678ap+0",       "-0XF.12345678AP+0"},        /*  3: 9 precision digits. Rounding to even.  */
+  {"0xf.123456789p+0",       "-0XF.123456789P+0"},        /*  4: 9 precision digits. Rounding to even.  */
+  {"0xf.12345678ap+0",       "-0XF.12345678AP+0"},        /*  5: 9 precision digits. Rounding to even.  */
+  {"0xf.12345678p+0",        "-0XF.12345678P+0"},         /*  6: 8 precision digits. Rounding to even.  */
+  {"0x1p+4",                 "-0X1P+4"},                  /*  7: 0 precision digits. Rounding to even.  */
+  {"0xfp+0",                 "-0XFP+0"},                  /*  8: 0 precision digits. Rounding to even.  */
+  {"0x9.p+0",                "-0X9.P+0"},                 /*  9: 0 precision digits. Alternate flag given.  */
+  {"       0xf.123456p+0",   "      -0XF.123456P+0"},     /* 10: 6 precision digits and 20 digits of field width.  */
+  {"0x0000000f.123456p+0",   "-0X000000F.123456P+0"},     /* 11: 6 precision digits and 20 digits of field width and zero padding.  */
+  {"+0x000000f.123456p+0",   "-0X000000F.123456P+0"},     /* 12: 6 precision digits and 20 digits of field width and zero padding and a sign.  */
+  {"+0x00f.123456789abcdef000000000000000p+0",
+   "-0X00F.123456789ABCDEF000000000000000P+0"},           /* 13: 30 precision digits and 40 digits of field width and zero padding and a sign.  */
+
+  /*
+   *  Long double test.
+   *  Denormalized Finite.
+   */
+  {"0x7.fffffffffffffffp-16385",  "-0X7.FFFFFFFFFFFFFFFP-16385"},  /* 14: No precision given. Exact mantissa representation requested.  */
+  {"0x1.23456789abcdefp-16389",   "-0X1.23456789ABCDEFP-16389"},   /* 15: No precision given. Exact mantissa representation requested.  */
+  {"0x8p-16389",                  "-0X8P-16389"},                  /* 16: No precision given. Exact mantissa representation requested. Trailing zeros will be omitted.  */
+  {"0x1.234p-16417",              "-0X1.234P-16417"},              /* 17: 3 precision digits. Rounding to even.  */
+  {"0x1.234567800000p-16417",     "-0X1.234567800000P-16417"},     /* 18: 12 precision digits. Rounding to even. Padding with 0.  */
+  {"0xfp-16417",                  "-0XFP-16417"},                  /* 19: 0 precision digits. Rounding to even.  */
+  {"0x1p-16413",                  "-0X1P-16413"},                  /* 20: 0 precision digits. Rounding to even.  */
+  {"0x8.p-16417",                 "-0X8.P-16417"},                 /* 21: 0 precision digits. Alternate flag given.  */
+  {"   0x1.234568p-16417",   "  -0X1.234568P-16417"},              /* 22: 6 precision digits and 20 digits of field width.  */
+  {"0x0001.234568p-16417",   "-0X001.234568P-16417"},              /* 23: 6 precision digits and 20 digits of field width and zero padding.  */
+  {"+0x001.234568p-16417",   "-0X001.234568P-16417"},              /* 24: 6 precision digits and 20 digits of field width and zero padding and a sign.  */
+  {"+0x000000001.23456789abcdef0000000000000000p-16389",
+   "-0X000000001.23456789ABCDEF0000000000000000P-16389"},          /* 25: 30 precision digits and 50 digits of field width and zero padding and a sign.  */
+
+  /*
+   *  Long double test.
+   *  Zero, INF, NAN and Unnormal.
+   */
+  {"0x0p+0",    "-0X0P+0"},    /* 26: No precision given. Exact mantissa representation requested.  */
+  {"inf",       "-INF"},       /* 27: No precision given. Exact mantissa representation requested.  */
+  {"nan",       "NAN"},        /* 28: No precision given. Exact mantissa representation requested.  */
+  {"Unnormal",  "-Unnormal"},  /* 29: No precision given. Exact mantissa representation requested.  */
+};
+
+static long_double_t number[] = {
+/*   mantissal    mantissah    exp             sgn  */
+  {0x89ABCDEFU, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /*  0: 0xF.123456789ABCDEFp+0  */
+  {0x89AB0000U, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /*  1: 0xF.123456700000000p+0  */
+  {0x00000000U, 0xF0000000U, 0x3FFFU + 0x03U, 0x0U},  /*  2: 0xF.000000000000000p+0  */
+  {0x89F00000U, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /*  3: 0xF.123456789Fp+0  */
+  {0x89100000U, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /*  4: 0xF.1234567891p+0  */
+  {0x89800000U, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /*  5: 0xF.1234567898p+0  */
+  {0x88000000U, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /*  6: 0xF.123456788p+0  */
+  {0x00000000U, 0xFF000000U, 0x3FFFU + 0x03U, 0x0U},  /*  7: 0xF.F00000000000000p+0  */
+  {0x00000000U, 0xF1000000U, 0x3FFFU + 0x03U, 0x0U},  /*  8: 0xF.F00000000000000p+0  */
+  {0x87654321U, 0x8FEDCBA9U, 0x3FFFU + 0x03U, 0x0U},  /*  9: 0x8.FEDCBA987654321p+0  */
+  {0x89ABCDEFU, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /* 10: 0xF.123456789ABCDEFp+0  */
+  {0x89ABCDEFU, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /* 11: 0xF.123456789ABCDEFp+0  */
+  {0x89ABCDEFU, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /* 12: 0xF.123456789ABCDEFp+0  */
+  {0x89ABCDEFU, 0xF1234567U, 0x3FFFU + 0x03U, 0x0U},  /* 13: 0xF.123456789ABCDEFp+0  */
+
+  {0xFFFFFFFFU, 0x7FFFFFFFU, 0x0000U,         0x0U},  /* 14: 0x7.FFFFFFFFFFFFFFFp-16385  */
+  {0x89ABCDEFU, 0x01234567U, 0x0000U,         0x0U},  /* 15: 0x0.123456789ABCDEFp-16385  */
+  {0x00000000U, 0x08000000U, 0x0000U,         0x0U},  /* 16: 0x0.800000000000000p-16385  */
+  {0x12345678U, 0x00000000U, 0x0000U,         0x0U},  /* 17: 0x0.000000012345678p-16385  */
+  {0x12345678U, 0x00000000U, 0x0000U,         0x0U},  /* 18: 0x0.000000012345678p-16385  */
+  {0xF1000000U, 0x00000000U, 0x0000U,         0x0U},  /* 19: 0x0.0000000F1000000p-16385  */
+  {0xFF000000U, 0x00000000U, 0x0000U,         0x0U},  /* 20: 0x0.0000000FF000000p-16385  */
+  {0x80000000U, 0x00000000U, 0x0000U,         0x0U},  /* 21: 0x0.000000080000000p-16385  */
+  {0x12345678U, 0x00000000U, 0x0000U,         0x0U},  /* 22: 0x0.000000012345678p-16385  */
+  {0x12345678U, 0x00000000U, 0x0000U,         0x0U},  /* 23: 0x0.000000012345678p-16385  */
+  {0x12345678U, 0x00000000U, 0x0000U,         0x0U},  /* 24: 0x0.000000012345678p-16385  */
+  {0x89ABCDEFU, 0x01234567U, 0x0000U,         0x0U},  /* 25: 0x0.123456789ABCDEFp-16385  */
+
+  {0x00000000U, 0x00000000U, 0x0000U,         0x0U},  /* 26: 0x0.000000000000000p+0  */
+  {0x00000000U, 0x80000000U, 0x7FFFU,         0x0U},  /* 27: INFINITY  */
+  {0x00000000U, 0xC0000000U, 0x7FFFU,         0x0U},  /* 28: NAN  */
+  {0x00000000U, 0x00000000U, 0x7FFFU,         0x0U},  /* 29: Unnormal  */
+};
+
+
+
+int
+main (void)
+{
+  _longdouble_union_t value;
+  unsigned int i = 0;
+
+  printf("Testing normalized finite numbers.\n");
+  printf("Printing value without specifying a precison.  Mantissa representation shall be exact.\n");
+  printf("Test: %u\n", i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value without specifying a precison.\nMantissa representation shall be exact.\nTrailing zeros will always be omitted.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 9 digits of precison.  Rounding to even.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.9La: %.9La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.9LA: %.9LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.9La: %.9La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.9LA: %.9LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.9La: %.9La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.9LA: %.9LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 8 digits of precison.  Rounding to even.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.8La: %.8La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.8LA: %.8LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 0 digits of precison.  Rounding to even.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0La: %.0La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0LA: %.0LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0La: %.0La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0LA: %.0LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 0 digits of precison and alternate flag given.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:       %s\n"
+         "value printed with %%#.0La: %#.0La\n"
+         "should be:                 %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:       %s\n"
+         "value printed with %%#.0LA: %#.0LA\n"
+         "should be:                 %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 6 digits of precison and field width of 20 digits.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:        %s\n"
+         "value printed with %%20.6La: %20.6La\n"
+         "should be:                  %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:       %s\n"
+         "value printed with %%20.6LA: %20.6LA\n"
+         "should be:                  %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 6 digits of precison and field width of 20 digits and zero padding.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:         %s\n"
+         "value printed with %%020.6La: %020.6La\n"
+         "should be:                   %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:         %s\n"
+         "value printed with %%020.6LA: %020.6LA\n"
+         "should be:                   %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 6 digits of precison and field width of 20 digits and zero padding and a sign.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:           %s\n"
+         "value printed with %%+020.6La: %+020.6La\n"
+         "should be:                    %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:          %s\n"
+         "value printed with %%+020.6LA: %+020.6LA\n"
+         "should be:                    %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 30 digits of precison and field width of 40 digits and zero padding and a sign.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:            %s\n"
+         "value printed with %%+040.30La: %+040.30La\n"
+         "should be:                     %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:           %s\n"
+         "value printed with %%+040.30LA: %+040.30LA\n"
+         "should be:                     %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+
+
+  printf("\n\nTesting denormalized finite numbers.  Smallest exponent: -16382.\nTo get a single nibble in the integer part of the mantissa\nthe exponent must be incremented by 3.\n");
+  printf("Printing value without specifying a precison.  Mantissa representation shall be exact.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value without specifying a precison.  Mantissa representation shall be exact.\nTrailing zeros will always be omitted.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 3 digits of precison.  Rounding to even.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.3La: %.3La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.3LA: %.3LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 12 digits of precison.  Rounding to even.\nPadding with 0 if precision is greater than number of significant digits in the mantissa.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:       %s\n"
+         "value printed with %%.12La: %.12La\n"
+         "should be:                 %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:       %s\n"
+         "value printed with %%.12LA: %.12LA\n"
+         "should be:                 %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 0 digits of precison.  Rounding to even.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0La: %.0La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0LA: %.0LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0La: %.0La\n"
+         "should be:                %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:      %s\n"
+         "value printed with %%.0LA: %.0LA\n"
+         "should be:                %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 0 digits of precison and alternate flag given.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:       %s\n"
+         "value printed with %%#.0La: %#.0La\n"
+         "should be:                 %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:       %s\n"
+         "value printed with %%#.0LA: %#.0LA\n"
+         "should be:                 %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 6 digits of precison and field width of 20 digits.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:        %s\n"
+         "value printed with %%20.6La: %20.6La\n"
+         "should be:                  %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:       %s\n"
+         "value printed with %%20.6LA: %20.6LA\n"
+         "should be:                  %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 6 digits of precison and field width of 20 digits and zero padding.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:         %s\n"
+         "value printed with %%020.6La: %020.6La\n"
+         "should be:                   %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:         %s\n"
+         "value printed with %%020.6LA: %020.6LA\n"
+         "should be:                   %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 6 digits of precison and field width of 20 digits and zero padding and a sign.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:          %s\n"
+         "value printed with %%+020.6La: %+020.6La\n"
+         "should be:                    %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:          %s\n"
+         "value printed with %%+020.6LA: %+020.6LA\n"
+         "should be:                    %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  printf("\nPrinting value with 30 digits of precison and field width of 50 digits and zero padding and a sign.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:           %s\n"
+         "value printed with %%+050.30La: %+050.30La\n"
+         "should be:                     %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:           %s\n"
+         "value printed with %%+050.30LA: %+050.30LA\n"
+         "should be:                     %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+
+
+  printf("\n\nTesting 0.0, NAN, INF and Unnormal.\n");
+  printf("Printing value without specifying a precison.\n");
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], value.ld, should_looks_like[i][UPPER_CASE]);
+
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], value.ld, should_looks_like[i][UPPER_CASE]);
+  printf("Test: %u\n", ++i);
+  value.ldt = number[i];
+  printf("value to be printed:    %s\n"
+         "value printed with %%La: %La\n"
+         "should be:              %s\n\n", to_be_printed[i][LOWER_CASE], value.ld, should_looks_like[i][LOWER_CASE]);
+  printf("value to be printed:    %s\n"
+         "value printed with %%LA: %LA\n"
+         "should be:              %s\n\n", to_be_printed[i][UPPER_CASE], -value.ld, should_looks_like[i][UPPER_CASE]);
+
+
+  return(EXIT_SUCCESS);
+}

- Raw text -


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