/*
 *  Classified Tydeman Consulting Proprietary
 *  Copyright (C) 1996, 2012 Tydeman Consulting.  All rights reserved.
 *
 *  Fred J. Tydeman	tydeman@tybor.com
 *
 * Any person is hereby authorized to copy, use, and distribute, this
 * one sample test, subject to the following conditions:
 *
 *      1.  the software may not be redistributed for a fee except as
 *          reasonable to cover media costs;
 *      2.  any copy of the software must include this notice, as well as
 *          any other embedded copyright notices; and
 *      3.  any distribution of this software or derivative works thereof
 *          must comply with all applicable U.S. export control laws.
 *
 * Floating-Point C Extensions (FPCE) have been added to C99 (the
 * revision of the C language finished in late 1999).  If you are
 * interested in other sample tests of the FPCE Test Suite, which
 * tests the floating-point and numerics capabilities of C/C++
 * compilers and libraries, please see the FTP site:
 *      ftp://ftp.tybor.com
 *     user ID: anonymous
 *    password: your email address
 *
 *****************************************************************
 *
 * Does the C/C++ compiler/library correctly round a number printed
 * via %f?
 *
 * This is a test of rounding of %f via sprintf, using %e as the basis
 * to determine the expected result.
 *
 * These functions test sprintf() to see if it correctly converts from
 * internal (binary) to external (decimal) representation of floating-
 * point numbers.  This tests compliance to the former Standard C,
 * also known as C89 (ANSI), C90 (ISO), or C95 (amendment one), C99
 * (or C9X as it was being done) and of the current Standard C, also
 * known as C11 (or C1x as it was being done).
 *
 * Assertion being tested: ISO/ANSI 9899-1990:
 *
 * 7.9.6.1 The fprintf function: Under 'f' and under 'e,E':
 *
 * "The value is rounded to the appropriate number of digits."
 *
 * And, under Environmental limit (in the same section):
 *
 * "The minimum value for the maximum number of characters produced by
 * any single conversion shall be 509."  C99 raised this to 4095.
 *
 * Value->Rounded      Format   Values tested -> Rounded
 *  .20    .2          %.0f     1.1   ... 9.4     1.    ... 9.
 *  .25    .2 or .3    %.1f     .11   ... .94     0.1   ... 0.9
 *  .30    .3          %.2f     .011  ... .094    0.01  ... 0.09
 *  .35    .3 or .4    %.3f     .0011 ... .0094   0.001 ... 0.009
 *
 *
 * Hints on using this test:
 *
 * 1)   Compile as is.  The only known compile time failure is incorrect
 *      support for array initializers.  If that is the cause, change the
 *      #if 1 to #if 0 in the function stdc_failures().  If there is another
 *      compile time failure, please send the results to Tydeman to see if
 *      a workaround can be found.
 *
 * 2)   Run as is.  Please feedback these results to tydeman@tybor.com
 *
 *      On a 33 Mhz Intel 80486DX, this test takes between 30 and 80 seconds
 *      (depends upon compiler). I have been told that another system took
 *      5 minutes (but it also had no failures).
 *
 * 3)   If there are runtime failures and you want to find out why:
 *
 *  a)  Try defining USE_Le (just after these comments) and running
 *      to see if using %Le in place of %e gives fewer failures (This
 *      bypass will only work if long double has more precision than double
 *      and %Le prints more correct digits than %e). If using %Le in place
 *      of %e gives fewer failures, then %e is most likely rounding to fewer
 *      than the user specified number of digits. This matters for numbers
 *      such as: 4.5e-13, 5.5e-17, 5.5e-18, 1.5e-34, 1.5e-37, 3.5e-39 which
 *      are very close to X.4999...9YYY (or X.5000...0YYY) and are being
 *      incorrectly rounded to exact midpoint X.5000...  This test program
 *      computes the expected %f result from the %e result.  If the %e result
 *      is wrong, then the expected %f computed may be wrong and a correct %f
 *      result from printf() may be reported as an error.  Note:  The only
 *      numbers that should print as X.5000... from %e are X.5eNN, where X
 *      is any integer, including 0, and NN is either 0 or -1; for NN = -2,
 *      -3, -4, ..., the values are not exactly X.5eNN when converted from
 *      binary to decimal.
 *
 *      A specific example of this is these two numbers:
 *
 *      Decimal -> IEEE-754 double -> 17 digit decimal  plus more
 *      3.5e-4  = 3F36F0068DB8BAC7 = 3.4999999999999999 6443816874247545e-4
 *      8.5e-9  = 3E4240ECA6A943FE = 8.5000000000000000 1240564454548648e-9
 *
 *      If %e conversion code rounds the decimal string to 17 digits
 *      (instead of the requested 99), then this program sees 3.50...0e-4
 *      and 8.50...0e-9 which are taken to be exact midpoints.
 *
 *      If you wish to not print the x.50...0e-nn failures, then define
 *      SUPPRESS_MIDPOINT (just after these comments).
 *
 *  b)  Try changing the value of MIN_WIDTH (just after these comments)
 *      to a smaller value.  If that gives fewer failures, then %f is not
 *      printing all the digits being asked for (Some compilers limit the
 *      number of digits that are printed to less than 509 (4095 in C99);
 *      such as 32, 42, or 64, three values seen so far).
 *
 *
 * Results of running this test on various compilers:
 * (as reported by several users of this test; your mileage may vary)
 *
 * Failures    Hardware      Operating system   Compiler, version, and options
 *      0 ARM + FPU             RiscOS             Norcroft ARM v4.69 C [no options]
 *      0 ARM + SWFP            RiscOS             Norcroft ARM v4.69 C [no options]
 *      0 Apple Mac PPC 603e    Tenon MachTen      gcc 2.7.2.1
 *      0 Apple Mac PPC G4      Mac OS X 10.3.7    Gnu gcc 3.3 (build 1495)
 *      0 Apple Mac PPC G4      Mac OS X 10.3.7    IBM XL C 6.0 + Gnu gcc 3.3
 *      0 DEC Alpha             Windows NT 4.0 SP4 Visual C++ 5.0
 *      0 HP Integrity          HP-UX 11i V3       HP c99, A.06.23, +decfp
 *      0 Intel 80486/66        Windows 95         IBM Visual Age C/C++ V3.5
 *      0 Intel 80486/66        Windows 95         Microsoft C/C++ Visual 4.2
 *      0 Intel Core i5-64      Linux Fedora 14    Portable C Compiler pcc 0.9.9 2010/11/19 (x86_64)
 *      0 Intel Core i5-64      Linux Fedora 14    Portable C Compiler pcc 0.9.9 2011/02/03 (x86_64)
 *      0 Intel Core i5-64      Linux Fedora 15    Gnu gcc 4.6.0-9 (2011/05/30) + glibc-2.14-3 (x86_64)
 *      0 Intel Core2 Duo       Linux Fedora 14    Gnu gcc 4.5.1-4 + glibc 2.12.90-15; -std=gnu99 -frounding-math
 *      0 Intel Core2 Duo       Linux Fedora 15    Gnu gcc 4.6.1-9 + glibc 2.14-5; -std=gnu99 -frounding-math
 *      0 Intel Core2 Duo       Linux Fedora 16    Gnu gcc 4.6.2-1 + glibc 2.14.90-21; -std=gnu99 -frounding-math
 *      0 Intel Core2 Duo       Linux Fedora 16    clang 2.9-6 + glibc-2.14.90-24
 *      0 Intel Core2 Duo       Linux Fedora 16    pcc 1.0.0-2 (2011/12/16) + glibc-2.14.90-24
 *      0 Intel Core2 Duo       OS/2 eCS 2.0       Open Watcom C/C++ v1.8
 *      0 Intel Core2 Duo       OS/2 eCS 2.0       Open Watcom C/C++ v1.9
 *      0 Intel PPro 150MHz     Solaris 2.5.1      gcc v2.7.2, -O -ffloat-store
 *      0 Intel PPro 150MHz     Solaris 2.5.1      sun cc PC3.0.1 21 Jan 1995, -O -fsimple
 *      0 Intel Pentium         Linux 2.0.23       Gnu gcc 2.6.3
 *      0 Intel Pentium         OS/2 Warp          Gnu gcc 2.7.2.1 + emx 0.9c + fix02
 *      0 Intel Pentium         OS/2 Warp          IBM Visual Age C++ 3.0
 *      0 Intel Pentium 4       Linux Fedora  6    gcc 4.1.2-13.fc6 + glibc 2.5-18.fc6
 *      0 Intel Pentium 4       Linux Fedora 10    gcc 4.3.2-7, glibc 2.9-3; -std=gnu99 -frounding-math
 *      0 Intel Pentium 4       Linux Fedora 11    gcc 4.4.0-4, glibc 2.10.1-2; -std=gnu99 -frounding-math
 *      0 Intel Pentium 4       Linux Fedora 11    gcc 4.4.1-2, glibc 2.10.1-5; -std=gnu99 -frounding-math
 *      0 Intel Pentium 4       Linux Fedora 14    gcc 4.5.1-4 + glibc 2.12.90-15; -std=gnu99 -frounding-math
 *      0 Intel Pentium 4       OS/2 eCS 1.1       Gnu gcc 2.8.1 + emx 0.9d w/ TEST_RND_UP_DECADE
 *      0 Intel Pentium 4       OS/2 eCS 1.1       Open Watcom C/C++ v1.5 w/ TEST_RND_UP_DECADE
 *      0 Intel Pentium 4       SuSE Linux 9.1     gcc 3.3.3-41 + glibc 2.3.3-97
 *      0 Intel Pentium 4       Windows XP         Metrowerks CodeWarrior Pro 8.3
 *      0 Intel Pentium 4       Windows XP         Metrowerks CodeWarrior Pro 9.2
 *      0 Intel Pentium 4       Windows XP         Microsoft C/C++ V 12.00 aka Visual 6.0
 *      0 Intel Pentium 4       Windows XP         Microsoft C/C++ V 14.00 aka Visual Studio 8
 *      0 Intel Pentium 4 IA-32 Linux Fedora 10    Intel C/C++ icc 11.1 -std=c99 -strict-ansi -fp-model strict -O0
 *      0 Intel Pentium III     RedHat Linux 8     Comeau C/C++ 4.3.0.1 + glibc 2.2.93
 *      0 Intel Pentium III     RedHat Linux 8     Gnu gcc 3.2 + glibc 2.2.93
 *      0 Intel Pentium III     RedHat Linux 8     Intel C/C++ v7 + glibc 2.2.93
 *      0 Intel Pentium MMX 200 Linux 2.0.30       /usr/bin/cc
 *      0 Intel Pentium MMX 200 Linux 2.0.30       /usr/bin/g++
 *      0 Intel Pentium MMX 200 Linux 2.0.30       /usr/bin/gcc
 *      0 Intel Pentium/90      Windows NT 4.0     IBM Visual Age C/C++ V3.5
 *      0 Intel Pentium/90      Windows NT 4.0     Microsoft C/C++ Visual 4.2
 *      0 Intel PentiumPro      OS/2 4 Merlin      Gnu gcc 2.8.1 + emx 0.9d
 *      0 Intel PentiumPro      OS/2 4 Merlin      Metrowerks CodeWarrior Pro 4
 *      0 Intel PentiumPro      OS/2 4 Merlin      Metrowerks CodeWarrior Pro 5
 *      0 Intel PentiumPro      Windows NT V4.0    Microsoft C++ Visual 4.2
 *      0 Intel PentiumPro/200  Windows NT 4.0     Intel C/C++ V2.4 -Op -Za -Od
 *      0 Intel PentiumPro/350  Windows NT 4.0 SP3 Microsoft C/C++ V 12.00 aka Visual 6.0
 *      0 Intel x86             Solaris 2.6        cc (Workshop 4.2)
 *      0 Intel x86             Solaris 7          cc (Workshop 5.0)
 *      0 Intel x86             Windows NT 4.0 SP4 Visual C++ 5.0
 *      0 Intel x86             Windows NT 4.0 SP4 Visual C++ 6.0 SP2
 *      0 Meiko CS2             Meiko/SunOS 5.3    Gnu gcc 2.6.3
 *      0 Meiko CS2             Meiko/SunOS 5.3    KAI KCC 3.0g
 *      0 Meiko CS2             Meiko/SunOS 5.3    PGI pgcc 1.4
 *      0 Meiko CS2             Meiko/SunOS 5.3    Sun cc/CC 4.0
 *      0 Motorola M-CORE       SDS simulator      dcc (Diab Data 4.3a)
 *      0 Motorola M-CORE       SDS simulator      dcc (Diab Data 4.3b)
 *      0 StrongARM+FPE 1.07M   RiscBSD 1.2        gcc 2.7.2.1
 *      0 Sun 4m sparc          Sun OS 5.4         Gnu gcc 2.7.0
 *      0 Sun 4m sparc          Sun OS 5.4         Sun C 4.0
 *      0 Sun 4m sparc          Sun OS 5.4         cc (C 4.0)
 *      0 Sun 4m sparc          Sun OS 5.5.1       cc (C 4.0)
 *      0 Sun SPARC 20/512      Solaris 2.6        /opt/SUNWspro/bin/CC
 *      0 Sun SPARC 20/512      Solaris 2.6        /opt/SUNWspro/bin/c89
 *      0 Sun SPARC 20/512      Solaris 2.6        /opt/SUNWspro/bin/cc
 *      0 Sun SPARC 20/512      Solaris 2.6        /usr/local/bin/g++
 *      0 Sun SPARC 20/512      Solaris 2.6        /usr/local/bin/gcc
 *      0 Sun SPARC 20/512      Solaris 2.6        /usr/local/bin/lcc -A -A
 *      0 Sun SparcStation4     Solaris 2.5.1      gcc v2.7.2, -O -ffloat-store
 *      0 Sun SparcStation4     Solaris 2.5.1      sun cc SC4.0 18 Oct 1995 C 4.0, -O -fsimple=0
 *      0 Sun UltraSPARC        Sun Solaris 2.5    Apogee-C SPARC rel 4.0 -fast
 *      0 Sun sparc             Sun OS 5.5.1       ACE CoSy cc
 *      0 Unisys A18            MCP (SSR 44.1)     A Series C++
 *      1 Intel Pentium 4       Linux Fedora 14    Portable C Compiler pcc 0.9.9 2010/11/19
 *      1 Intel Pentium III     RedHat Linux 7     Gnu gcc 2.96 + libc 2.1.92
 *      1 Intel Pentium III     RedHat Linux 7     Intel icc 7 in C++ mode
 *      1 Sun SPARC 4/380       SunOS 4.1.3        /usr/lang/acc
 *      1 Sun SPARC 4/380       SunOS 4.1.3        /usr/local/bin/g++
 *      1 Sun SPARC 4/380       SunOS 4.1.3        /usr/local/bin/gcc
 *      1 Sun SPARC 4/380       SunOS 4.1.3        /usr/local/bin/lcc -A -A
 *      2 Sun 4m SPARC          Sun OS 4.1.4       Gnu GCC 2.6.0
 *      2 Sun 4m sparc          Sun OS 4.1.4       Gnu gcc 2.7.0
 *     25 Intel x86             DG/UX 5.4?         cc (Data General 4.20MU04?)
 *     25 Ultra Sparc           UXP/DS V20L10      fcc (Fujitsu C V12L10)
 *     86 IBM PowerPC 43P       AIX 4.1            /bin/c89
 *     86 IBM PowerPC 43P       AIX 4.1            /bin/cc
 *     86 IBM PowerPC 43P       AIX 4.1            /bin/xlC
 *     86 IBM PowerPC 43P       AIX 4.1            /usr/bin/c89
 *     86 IBM PowerPC 43P       AIX 4.1            /usr/bin/cc
 *     86 IBM PowerPC 43P       AIX 4.1            /usr/local/bin/g++
 *     86 IBM PowerPC 43P       AIX 4.1            /usr/local/bin/gcc
 *     86 IBM RS6000 7006/42T   AIX 4.2.0.0        c89 (xlC.C 3.1.3.5)
 *     86 IBM RS6000 7010/250   AIX 4.1.4.0        c89 (xlC.C 3.1.3.5)
 *    231 HP 9000 750           HP-UX A.09.05      c89 (A.09.77)
 *    231 HP 9000 777/C100      HP-UX A.09.07      c89 (A.09.73)
 *    231 HP 9000/735           HP-UX    9.07      Gnu gcc 2.7.0
 *    231 HP 9000/735           HP-UX    9.07      HP cc 9.73 -Ae
 *    231 Hitachi 3027-G32/3050 HI-UX   04.00      c89
 *    233 IBM PowerPC 43P       AIX 4.2            /bin/c89
 *    233 IBM PowerPC 43P       AIX 4.2            /bin/cc
 *    233 IBM PowerPC 43P       AIX 4.2            /bin/xlC
 *    233 IBM PowerPC 43P       AIX 4.2            /usr/bin/c89
 *    233 IBM PowerPC 43P       AIX 4.2            /usr/bin/cc
 *    233 IBM PowerPC 43P       AIX 4.2            /usr/local/bin/g++
 *    233 IBM PowerPC 43P       AIX 4.2            /usr/local/bin/gcc
 *    233 IBM RS6000 7030/3AT   AIX 4.1.5.0        c89 (xlC.C 3.1.4.0)
 *    233 Sony NWS-5000 VP      NEWS-OS 6.1.1      cc (ANSI C 3.18)
 *    281 HP 9000 735           HP-UX B.10.20      c89 (A.10.32.03)
 *    281 HP 9000/735           HP-UX 10.01        /bin/c89
 *    281 HP 9000/735           HP-UX 10.01        /usr/bin/c89
 *    281 HP 9000/735           HP-UX 10.01        /usr/local/bin/g++
 *    281 HP 9000/735           HP-UX 10.01        /usr/local/bin/gcc
 *    281 HP 9000/770           HP-UX B.10.01      Gnu gcc 2.7.0
 *    281 HP 9000/770           HP-UX B.10.01      HP cc A.10.11 + libc 76.3 -Ae
 *    281 HP 9000/819           HP-UX B.10.1       HP cc 10.30 -Ae
 *    281 HP PA-RISC 9000/770   HP-UX B.10.01      HP PA ANSI C
 *    282 HP 9000/819           HP-UX B.10.1       HP CC (V?)
 *    617 Motorola M-CORE       SDS simulator      dcc (Diab Data 4.1a)
 *    617 Motorola M-CORE       SDS simulator      dcc (Diab Data 4.2a)
 *    671 IBM S/390             OS/390 V2R5        IBM C/C++ V2R4 (MIN_WIDTH=32)
 *    766 IBM S/390             OS/390 V2R5        IBM C/C++ V2R4 (MIN_WIDTH=64)
 *  2,161 Intel Pentium 4       OS/2 eCS 1.1       Open Watcom C/C++ v1.0
 *  2,251 Intel Pentium 4       OS/2 eCS 1.1       Open Watcom C/C++ v1.0 w/ TEST_RND_UP_DECADE
 *  2,251 Intel Pentium 4       OS/2 eCS 1.1       Open Watcom C/C++ v1.3 w/ TEST_RND_UP_DECADE
 *  9,658 Intel Pentium         Linux 2.0.23       KnoSof OSPC mcc 4.1 + mce
 * 12,361 Intel 80486DX         OS/2 Warp          Gnu gcc 2.5.7 + emx 0.8h
 * 12,361 Intel 80486DX         OS/2 Warp          Gnu gcc 2.7.2 + emx 0.9b + fix05
 * 12,361 Intel Pentium 4       OS/2 eCS 1.1       Gnu gcc 2.5.7 + emx 0.8h w/ TEST_RND_UP_DECADE
 * 12,361 Intel Pentium 4       OS/2 eCS 1.1       Gnu gcc 2.7.2 + emx 0.9b + fix05 w/ TEST_RND_UP_DECADE
 * 13,391 Intel Pentium 4       OS/2 eCS 1.1       Gnu gcc 2.5.7 + emx 0.8h w/ TEST_RND_UP_DECADE ???
 * 13,391 Intel Pentium 4       OS/2 eCS 1.1       Gnu gcc 2.7.2 + emx 0.9b + fix05 w/ TEST_RND_UP_DECADE
 * 16,430 Intel Pentium 4       OS/2 eCS 1.1       Open Watcom C/C++ v1.4 w/ TEST_RND_UP_DECADE
 * 27,147 Cray T3D SC256-8-4    UNICOS MAX 1.3.0.3 CRI mpp cc 4.0.5
 * 27,148 Cray T3D SC256-8-4    UNICOS MAX 1.3.0.3 CRI mpp CC 1.0.3.4
 * 32,381 MIPS R10000           UX/4800 R13.5      NEC R13.5
 * 32,381 MIPS R4400            UX/4800 R11.5      NEC R11.5
 * 33,543 Intel 80486DX         OS/2 Warp          Gnu gcc 2.7.2.1 + emx 0.9c + fix02
 * 33,543 Intel Pentium         OS/2 Warp          Gnu gcc 2.7.2.1 + emx 0.9c
 * 33,543 Intel Pentium 4       OS/2 eCS 1.1       Gnu gcc 2.7.2.1 + emx 0.9c + fix02 w/ TEST_RND_UP_DECADE
 * 33,543 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.34
 * 33,543 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.38
 * 33,543 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.39
 * 33,543 Intel Pentium III     Windows 98         Digital Mars C/C++ V8.20
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.20 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.34 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.38 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.39 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.47 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.48 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.50 w/ TEST_RND_UP_DECADE
 * 35,331 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.51 w/ TEST_RND_UP_DECADE
 * 45,108 MC68030/MC68882       System V.3 TAU     ACE Expert C alfa-8.21
 * 50,182 Cray J90              UNICOS 9.0         CRI cc 5.0.1.0,
 * 50,183 Cray J90              UNICOS 9.0         CRI CC 2.0.1
 * 62,255 IBM RS6000 6015/DD1   AIX 4.1.2          c89 (xlC.C 3.1.1.0)
 * 62,255 IBM RS6000 7011/230   AIX 3.2.5          c89 (xlCcmp.* 2.1.3.0)
 * 62,286 Intel 80486           ISC 4.0.1          gcc 2.7.2
 * 62,286 Intel x86             DYNIX/ptx V4.4.4   cc (Sequent V4.4.4)
 * 62,287 Mips R4400+R4000      SGI Irix64 6.2     cc (C 6.2)
 * 62,287 SGI O2 R10000-SC      IRIX 6.3           /bin/CC
 * 62,287 SGI O2 R10000-SC      IRIX 6.3           /usr/bin/CC
 * 62,287 SGI O2 R10000-SC      IRIX 6.3           /usr/local/bin/g++
 * 62,287 SGI O2 R10000-SC      IRIX 6.3           /usr/local/bin/gcc
 * 62,287 SGI Origin/200-4      IRIX 6.4           /bin/CC
 * 62,287 SGI Origin/200-4      IRIX 6.4           /bin/c89
 * 62,287 SGI Origin/200-4      IRIX 6.4           /bin/cc
 * 62,287 SGI Origin/200-4      IRIX 6.4           /usr/bin/CC
 * 62,287 SGI Origin/200-4      IRIX 6.4           /usr/bin/c89
 * 62,287 SGI Origin/200-4      IRIX 6.4           /usr/bin/cc
 * 62,287 SGI Origin/200-4      IRIX 6.4           /usr/local/bin/g++
 * 62,287 SGI Origin/200-4      IRIX 6.4           /usr/local/bin/gcc
 * 62,288 SGI O2 R10000-SC      IRIX 6.3           /bin/c89
 * 62,288 SGI O2 R10000-SC      IRIX 6.3           /bin/cc
 * 62,288 SGI O2 R10000-SC      IRIX 6.3           /usr/bin/c89
 * 62,288 SGI O2 R10000-SC      IRIX 6.3           /usr/bin/cc
 * 62,291 DEC Alpha             OSF/1  3.2         Gnu gcc 2.7.2.1
 * 62,291 DEC Alpha             OSF/1  3.2         cc + sprintf 4.2.11.2
 * 62,291 DEC Alpha 2100-5/250  OSF/1 3.2          /bin/cxx -x cxx
 * 62,291 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/local/bin/g++
 * 62,291 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/local/bin/gcc
 * 62,291 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/local/bin/lcc -A -A
 * 62,291 DEC Alpha 250 4/266   OSF/1 V4.0         cc (DEC C V5.2-023)
 * 62,291 DEC Alpha 4000/610    OSF/1 V3.2C        cc
 * 62,291 DECstation 5000/200   ULTRIX 4.3         /usr/local/bin/lcc -A -A
 * 62,291 Intel x86             NCR 3.01.01        NCR cc 3.02
 * 62,291 Mips IP22             SGI Irix   5.2     Gnu gcc 2.7.2.f.1
 * 62,291 Mips IP22             SGI Irix   5.2     cc
 * 62,291 Mips R4400+R4010      SGI Irix   5.3     cc (C 3.19)
 * 62,291 SGI Challenge L       IRIX 5.3           /bin/CC
 * 62,291 SGI Challenge L       IRIX 5.3           /usr/bin/CC
 * 62,291 SGI Challenge L       IRIX 5.3           /usr/local/bin/g++
 * 62,291 SGI Challenge L       IRIX 5.3           /usr/local/bin/gcc
 * 62,291 SGI Challenge L       IRIX 5.3           /usr/local/bin/lcc -A -A
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /bin/c89
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /bin/cc
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/bin/c89
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/bin/cc
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/ccs/bin/c89
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/ccs/bin/cc
 * 62,292 DEC Alpha 2100-5/250  OSF/1 3.2          /usr/ucb/cc
 * 62,292 DEC Alpha 4100 5/600  Digital Unix V4.0D cc (DEC C V5.6-079)
 * 62,292 DECstation 5000/200   ULTRIX 4.3         /usr/local/bin/g++
 * 62,292 DECstation 5000/200   ULTRIX 4.3         /usr/local/bin/gcc
 * 62,292 SGI Challenge L       IRIX 5.3           /bin/cc
 * 62,292 SGI Challenge L       IRIX 5.3           /usr/bin/cc
 * 62,581 Cray YMP              UNICOS 9.0         CRI cc 4.0.4.1 -D_CRAYIEEE -D_LD64
 * 63,126 Cray YMP              UNICOS 9.0         CRI CC 2.0.0.3 -D_CRAYIEEE -D_LD64
 * 66,287 Intel Pentium 4       Windows XP         Digital Mars C/C++ V8.19 w/ TEST_RND_UP_DECADE
 * 66,718 Intel x86             NCR 3.02           NCR cc 3.03
 * 66,718 Intel x86?            SCO UnixWare 7.1   cc 3.2
 * 67,485 Intel 80486/66        Windows 95         Borland C/C++ V5.01
 * 67,485 Intel Pentium/90      Windows NT 4.0     Borland C/C++ V5.01
 * 67,488 Intel 80486DX         PC DOS             Borland C/C++ 4.00 in C mode
 * 67,488 Intel 80486DX         PC DOS             Borland Turbo C 2.01
 * 67,488 Intel 80486DX         Windows 3.1        Borland C/C++ 4.00 in C++ mode
 * 67,488 Intel Pentium         PC DOS             Borland Turbo C 2.01
 * 67,488 Intel Pentium 4       PC DOS             Borland C/C++ 4.00 in C mode w/ TEST_RND_UP_DECADE
 * 67,488 Intel Pentium 4       PC DOS             Borland C/C++ 4.00 in C++ mode w/ TEST_RND_UP_DECADE
 * 67,488 Intel Pentium 4       PC DOS             Borland Turbo C 2.01 w/ TEST_RND_UP_DECADE
 * 67,488 Intel Pentium Pro     Windows NT 4.0 SP3 Borland C/C++ V5.01 (16-bit C mode)
 * 67,788 Intel Pentium III     Windows 98         Digital Mars C/C++ V8.19
 * 70,005 Intel 80486/66        Windows 95         Symantec C/C++ V7.01
 * 70,005 Intel 80486DX         PC DOS             Symantec C/C++ 7.0r1x in C mode
 * 70,005 Intel 80486DX         PC DOS             Symantec C/C++ 7.0r1x in C++ mode
 * 70,005 Intel Pentium 4       PC DOS             Symantec C/C++ 7.0r1x in C mode w/ TEST_RND_UP_DECADE
 * 70,005 Intel Pentium III     Windows 98         Digital Mars C/C++ V8.16
 * 70,005 Intel Pentium/90      Windows NT 4.0     Symantec C/C++ V7.01
 * 71,279 NeXT Turbostation     Mach 3.3           /bin/cc
 * 71,279 NeXT Turbostation     Mach 3.3           /usr/local/bin/g++
 * 71,279 NeXT Turbostation     Mach 3.3           /usr/local/bin/gcc
 * 72,821 Intel Pentium 4       Windows XP         LCC 2002/02/10 w/ TEST_RND_UP_DECADE
 * 72,821 Intel Pentium 4       Windows XP         LCC 2004/07/27 w/ TEST_RND_UP_DECADE
 * 72,828 Intel Pentium III     Windows 98         LCC 2002/02/10
 * 72,828 Intel Pentium III     Windows 98         LCC 2003/01/12
 * 73,214 DEC Alpha             OpenVMS 7.1        DEC C V5.7 (G float format)
 * 73,214 DEC Alpha             OpenVMS 7.1        DEC C V5.7 (IEEE float format)
 * 73,793 Intel Pentium 4       Windows XP         LCC 2008/07/24 w/ TEST_RND_UP_DECADE -ansic
 * 75,179 Intel Pentium 4       Windows XP         LCC 2006/04/10 w/ TEST_RND_UP_DECADE
 * 77,817 NeXT Turbostation     Mach 3.3           /usr/local/bin/lcc -A -A
 * 77,817 Sun 4m sparc          Sun OS 4.1.4       Sun acc 3.0.1
 *112,761 Cray YMP              UNICOS 9.0         CRI cc 4.0.4.1
 *113,274 Cray YMP              UNICOS 9.0         CRI CC 2.0.0.3
 *??????? DECstation 5000/200   ULTRIX 4.3         /bin/cc [would not compile]
 *??????? DECstation 5000/200   ULTRIX 4.3         /usr/bin/cc [would not compile]
 *??????? HP 9000/735           HP-UX 10.01        /bin/CC [would not compile]
 *??????? HP 9000/735           HP-UX 10.01        /bin/cc [would not compile]
 *??????? HP 9000/735           HP-UX 10.01        /usr/bin/CC [would not compile]
 *??????? HP 9000/735           HP-UX 10.01        /usr/bin/cc [would not compile]
 *??????? HP 9000/735           HP-UX 10.01        /usr/ccs/bin/cc [would not compile]
 *??????? Intel Pentium III     RedHat Linux 7     Intel icc 7 [would not compile]
 *??????? SGI O2 R10000-SC      IRIX 6.3           /usr/local/bin/lcc -A -A [would not link]
 *??????? SGI Origin/200-4      IRIX 6.4           /usr/local/bin/lcc -A -A [garbage output]
 *??????? Sun SPARC 20/512      Solaris 2.6        /usr/ucb/cc [would not compile]
 *??????? Sun SPARC 4/380       SunOS 4.1.3        /bin/cc [missing float.h]
 *??????? Sun SPARC 4/380       SunOS 4.1.3        /usr/bin/cc [missing float.h]
 *??????? Sun SPARC 4/380       SunOS 4.1.3        /usr/lang/CC [would not compile]
 *??????? Sun SPARC 4/380       SunOS 4.1.3        /usr/ucb/cc [missing float.h]
 *coredmp IBM S/390             OS/390 V2R5        IBM C/C++ V2R4 (runtime core dump)
 *coredmp Intel 80486/66        Windows 95         Watcom v10.5 (runtime core dump)
 *coredmp Intel Pentium/90      Windows NT 4.0     Watcom v10.5 (runtime core dump)
 *
 * I wish to acknowledge the following people for taking the time and effort
 * to run this test and sending me their results:
 *      Nelson H. F. Beebe, Center for Scientific Computing, University of Utah
 *      L. Busby
 *      Rex Jaeschke, consultant
 *      Derek Jones
 *      Larry Jones
 *      H. G. McIlvried, III
 *      David S. Schwab
 *      Linda Stanberry
 *      Jonathan Ziebell
 *
 * MODIFICATION HISTORY:
 *
 * 1996/11/10 - Add tests for more kinds of "rounding" styles.
 * 1996/11/11 - Add bypass for underflow trap being enabled.
 * 1996/11/15 - Add bypass for -DBL_MIN_10_EXP being "same" as --308.
 * 1996/11/15 - Add test/bypass for missing EXIT_SUCCESS, EXIT_FAILURE.
 * 1996/11/15 - Add test/bypass for sprintf() returning a pointer.
 * 1996/11/22 - Add test for -DBL_MIN_10_EXP being "same" as --308.
 * 1996/12/06 - Fix bug of large exponent ranges => print more than MIN_WIDTH.
 * 1996/12/06 - Add test/bypass for "aggregate initializers not implemented".
 * 1997/01/10 - Add use of %Le to help find failures via USE_Le.
 * 1997/01/15 - Reduce nesting level of statements to be less than 15.
 * 1997/01/22 - Replace many 0s with 0...0 in %e error message.
 * 1997/01/23 - Allow ability to not print x.50...0e-nn failures.
 * 1997/01/26 - LCL_* -> LMS_* (reserved by POSIX.2).
 * 1997/03/18 - Allow for DBL_EPSILON to be non-constant for static init.
 * 1998/07/07 - Add many more system's results.
 * 1999/04/16 - Add in full formula for E_WIDTH (as a comment).
 * 1999/08/11 - Add \n to make PP error message more readable; add more results.
 * 2000/03/01 - Make classification explicit in each file.
 * 2000/03/01 - Remove confidential so can post to public ftp site.
 * 2000/07/23 - Add "using namespace std;" for C++ usage.
 * 2002/01/18 - Add ability to tailor via external file (TAILOR).
 * 2003/02/22 - Add FIX_IMPLICIT_FLUSH.
 * 2003/02/22 - Redo order of messages at end of run.
 * 2004/07/30 - Update DEBUG section.
 * 2004/09/01 - Fix code for rnd_ceil and 9.4 becoming 10.
 * 2004/09/01 - Add TEST_RND_UP_DECADE.
 * 2004/09/02 - Add test of %#.0f being same as %#.*f (with * being 0).
 * 2006/07/23 - Mods due to Lint 8.
 * 2006/07/23 - Update DEBUG section.
 * 2006/07/23 - Indent #if's.
 * 2007/11/21 - Mods due to Lint 8.
 * 2008/07/14 - Shorten marco symbols to less than 32 chars.
 * 2008/11/29 - Suppress info messages if RETVAL defined (part of test suite).
 * 2009/07/01 - Update DEBUG section.
 * 2012/01/23 - Add C11 (which replaced C99 in December 2011).
 *
 ***********************************************************************/

/*
 * Start of user tailorable section.  You can either edit this file,
 * or, do a series of #define's in the file tbin2dec.h to use those values.
 */

#ifdef   TAILOR			/* A way to tailor via external file */
  #include "tbin2dec.h"		/* A place to define CUT_OFF, E_WIDTH, ... */
#endif

#ifdef DEBUG	/* local override of FIXes to force errors to show */
  #ifdef DEBUG2	/* Kills some compilers */
    #undef  FIX_NAMESPACE_STD
  #endif
#endif

#ifndef   CUT_OFF
  #define CUT_OFF 5uL		/* Maximum number of %f error messages to
				   print */
#endif
#ifndef   E_WIDTH
  #define E_WIDTH 99		/* At least DBL_DIG * 2.5 */
#endif
#ifndef   MIN_WIDTH
  #define MIN_WIDTH 509		/* Minimum field width for C90 is 509;
				   for C99 is 4095 */
#endif

/*
 * Pick one of the next two.  #undef for Std C, #define for debug.
 */
#ifdef TRY_LE
  #define USE_Le		/* Use %Le in place of %e for more digits */
#else
  #undef  USE_Le		/* Assume %e is accurate and correct */
#endif

/*
 * Pick one of the next two.
 */
#ifdef NO_MIDS
  #define SUPPRESS_MIDPOINT	/* Do NOT print x.50...0e-nn failures */
#else
  #undef  SUPPRESS_MIDPOINT	/* Do print x.50...0e-nn failures */
#endif

/*
 * If you wish to test rounding up that spans a decade boundary,
 * then define this symbol.  This is a harder test than the default
 * which does not span a decade boundary. This is not the default
 * because I have too many results before 2004/09/01 that did not
 * have this option.
 */
/* #define TEST_RND_UP_DECADE */

/*
 * End of user tailorable section.  Rest of code should not need modification.
 */

#include <stdio.h>		/* sprintf(), printf() */
#include <errno.h>		/* errno */
#include <float.h>		/* DBL_DIG, DBL_EPSILON, FLT_RADIX, ... */
#include <stdlib.h>		/* exit(), EXIT_SUCCESS, EXIT_FAILURE */

#ifdef DEBUG	/* local override of FIXes to force errors to show */
  #ifdef DEBUG3
  #endif
  #undef  FIX_IMPLICIT_FLUSH
  #define TEST_RND_UP_DECADE
#endif
#ifdef DEBUG4
  #undef  RETVAL
#endif

#ifndef FIX_NAMESPACE_STD
  #ifdef __cplusplus		/* For C++ to call C functions		*/
using namespace std;		/* Add implicit std:: to each function call */
  #endif
#endif

enum how_round {
    add_5_chop, sub_5_ceil, near_even, near_odd, rnd_floor, rnd_ceil, rnd_weird
};

static unsigned long failures = 0uL;	/* Number of failures */
static unsigned long printed = 0uL;	/* Number of %f failures printed */
static unsigned long midpoint = 0uL;	/* Number of x.50...0e-nn failures */
static int       test_rc = 1;	/* Should we test return code of sprintf() */

/*lint -e774 // boolean within 'if' always evaluates to false   */
/*lint -e777 // testing float's for equality                    */
/*lint -e788 // enum constant not used with defaulted switch    */
/*lint -e801 // use of goto is deprecated			*/
/*lint -e838 // Previously assigned value to 'rc' not used	*/
/*lint -e909 // implicit conversion from int to bool            */
/*lint -e910 // implicit conversion from 0 to ptr               */
/*lint -e944 // argument for operator always evalutes to false  */
/*lint -e946 // subtract applied to pointers			*/
/*lint -e947 // subtract applied to pointers			*/
/*lint -e953 // var could be declared as const			*/
/*lint -e973 // unary operator in macro not parenthesized       */
/*==============================================================*/
/*
 * Check for non-conformance to Standard C for issues other than
 * the main purpose of this test.  These other faults were found
 * by various users of this test on their systems and had to be
 * bypassed before the real test could be run.
 */
static void
stdc_failures(void)
{

/*
 * If any of the array initializers fail at compile time,
 * change the #if 1 to #if 0
 */
#if 1
    auto char        str0[] =
    {"automatic array initializer\n"};
    static char      str1[] =
    {"static array initializer\n"};
    auto const char  str2[] =
    {"automatic const array initializer\n"};
    static const char str3[] =
    {"static const array initializer\n"};
    auto double      v0[] =
    {0.0, 1.0};
    static double    v1[] =
    {0.0, 1.0};
    auto const double v2[] =
    {0.0, 1.0};
    static const double v3[] =
    {0.0, 1.0};
#else
  #define LMS_INITIALIZERS
#endif

#ifdef LMS_INITIALIZERS
    (void) printf("FAIL: Aggregate initializers not supported\n");
    failures++;
#else
    if ((str0[0] == str2[0]) && (str1[0] == str3[0])) {
	if ((v0[0] == v2[0]) && (v1[0] == v3[0])) {
	    ;			/* use the vars */
	}
    }
#endif

#ifndef   EXIT_SUCCESS		/* Missing from vendor's stdlib.h */
  #define EXIT_SUCCESS 0
  #define LMS_MISSING_EXIT
#endif

#ifndef   EXIT_FAILURE		/* Missing from vendor's stdlib.h */
  #define EXIT_FAILURE 1
  #define LMS_MISSING_EXIT
#endif

#ifdef LMS_MISSING_EXIT
    (void) printf("FAIL: EXIT_FAILURE or EXIT_SUCCESS is missing from stdlib.h\n");
    failures++;
#endif

/*
 * This code attempts to detect if sprintf() returns an int (as per
 * Standard C), or a pointer (which is what some compilers do).
 *
 * If sprintf() returns an int as per Standard C, then the tests of the
 * integer value returned by sprintf() will be done (test_rc = 1).
 *
 * If sprintf() returns a pointer (as some compilers have it), then the
 * tests of the return code will be ignored (test_rc = 0).
 */
    {				/* local block */
    int              rc;	/* return code from sprintf() */
    char             out[99];	/* only need room for 4 */

	rc = sprintf(out, "%#.*f", 1, 0.5);	/* FUT */
	if (rc != 3) {		/* 3 is an unusual value for an address */
	    (void) printf("FAIL: sprintf() appears to return(%i) a pointer (should be an int)\n", rc);
	    failures++;
	    test_rc = 0;	/* Turn off testing of return code */
	}
    }

/*
 * This code attempts to detect if the preprocessor treats pp-tokens
 * and tokens as per Standard C.
 *
 * In the following, -Z expands into --pp, which looks like a prefix
 * decrement operator (--) applied to pp.  But, -- really is two
 * separate pp-tokens and is effectivly, - -pp, which is just the value
 * of pp.  If this bug exists, then the bypass is -(Z) or - Z
 * This bug effected usage of DBL_MIN_10_EXP later in code.
 */
    {				/* local block */
#define Z -pp
    int              pp, pp4, pp5;

	pp = 5;
	pp5 = -Z;		/* expands into --pp, but treated like - -pp */
	pp4 = --pp;
	if ((pp5 != 5) || (pp4 != 4) || (pp != 4)) {
	    (void) printf("FAIL: Preprocessor expansion is not Standard C conforming.\n");
	    (void) printf("\tpp =%i (should be 4).\n", pp);
	    (void) printf("\tpp4=%i (should be 4).\n", pp4);
	    (void) printf("\tpp5=%i (should be 5).\n", pp5);
	    failures++;
	}
#undef Z
    }
}

/*================================================================*/
/*
 * Find value of Unit in Last Place of argument.
 * lower_power <= x < upper_power, eg, radix**j <= x < radix**(j+1)
 * ulp in   upward direction = epsilon * lower_power
 * ulp in downward direction = epsilon * lower_power / radix if x is
 * exactly a power of radix, else, same as ulp in upward direction.
 */
static double
ulp(double x, const int dir)
{
    static double    lower_power = 1.0;
    static double    upper_power = (double) FLT_RADIX;
    static double    last_ulp = -1.0 /* really want DBL_EPSILON */;
    double           max_power = DBL_MAX / (double) FLT_RADIX;
    double           one_less = 1.0 - DBL_EPSILON / (double) FLT_RADIX;
    const double     one_over = 1.0 / (double) FLT_RADIX;
    const double     radix = (double) FLT_RADIX;

    if (last_ulp < 0.0){	/* In case DBL_EPSILON is not a constant */
    	last_ulp = DBL_EPSILON;
    }
    if (x != x) {
	return x;		/* Not-a-Number */
    }
    if (x < 0.0) {
	x = -x;
    }
    if ((x < lower_power) || (upper_power <= x)) {
	if (x == 0.0) {
	    return 0.0;		/* 0.0 */
	}
	if (DBL_MAX < x) {
	    return x;		/* Infinity */
	}
	if (x < DBL_MIN) {	/* denormal numbers */
	    upper_power = DBL_MIN;
	    last_ulp = upper_power * DBL_EPSILON;
	    lower_power = 0.0;	/* in case dir < 0 */
	} else if (max_power < x) {	/* in top 'binade' */
	    lower_power = max_power / one_less;
	    upper_power = lower_power;	/* lie to prevent overflow */
	    last_ulp = lower_power * DBL_EPSILON;
	} else {
	    if (x < lower_power) {
		do {
		    lower_power *= one_over;
		} while (x < lower_power);
		upper_power = lower_power * radix;
		last_ulp = lower_power * DBL_EPSILON;
	    } else if (upper_power <= x) {
		do {
		    upper_power *= radix;
		} while (upper_power <= x);
		lower_power = upper_power * one_over;
		last_ulp = lower_power * DBL_EPSILON;
	    } else {
		(void) printf("Should not happen in ulp()\n");
	    }
	}
    }
    if ((dir < 0) && (x == lower_power)) {	/* power of radix */
	return last_ulp * one_over;
    } else {
	return last_ulp;
    }
}

/*================================================================*/
/*
 * Determine how this system rounds.  Known rounding methods are:
 * 0) Add 0.5 and truncate fraction.  X.5 is always rounded up.
 * 1) Add 0.4999... and truncate fraction; or subtract 0.5 and ceil.
 *    It is the same as 1) except X.5 is always rounded down.
 * 2) Round to nearest even.  It is the same as 1) except if the number
 *    is exactly on the 0.5 boundry.  Then the number is rounded so that
 *    the result is an even number.  That way 0.5, 2.5, 4.5, 6.5, and 8.5
 *    round down and 1.5, 3.5, 5.5, 7.5, and 9.5 round up.
 * 3) Round to nearest odd.  It is the same as 1) except if the number
 *    is exactly on the 0.5 boundry.  Then the number is rounded so that
 *    the result is an odd number.  That way 0.5, 2.5, 4.5, 6.5, and 8.5
 *    round up and 1.5, 3.5, 5.5, 7.5, and 9.5 round down.
 * 4) floor, or round down towards -infinity.
 * 5) ceil, or round up towards +infinity.
 *
 * If sprintf() returns a pointer (instead of the expected int), then
 * sprintf() will return a random integer and the tests of the count
 * will be bypassed.
 */

#define ONE_DIGIT( buffer, val ) \
    errno = 0;\
    rc = sprintf( buffer, "%#.0f", val );\
    e = errno;\
    if (0 != e) {\
	(void) printf("errno is %d, expected 0 in line %d\n", e, (int) __LINE__);\
    }\
    if (test_rc && (2 != rc)) {\
	(void) printf("count is %d, expected 2 in line %d\n", rc, (int) __LINE__);\
	(void) printf(" buf  is %s\n", buffer);\
    }

static enum how_round
find_round(void)
{
    double           v15 = 3. / 2.;
    double           v25 = 5. / 2.;
    double           v35 = 3.25;
    double           v45 = 4.75;
    int              e;
    int              rc;
    enum how_round   rounds = rnd_weird;	/* will be set before return */
    char             buf1[9];
    char             buf2[9];
    char             buf3[9];
    char             buf4[9];
    char             bufa[9];
    char             bufb[9];
    char             bufc[9];
    char             bufd[9];

    if( 3. != (v15+v15) ){
      (void) printf("FAIL: 3./2. not exactly 1.5, results suspect\n");
      failures++;
    }
    if( 5. != (v25+v25) ){
      (void) printf("FAIL: 5./2. not exactly 2.5, results suspect\n");
      failures++;
    }

    ONE_DIGIT(buf1, v15);	/* 1.50 --> 1. or 2. */
    ONE_DIGIT(buf2, v25);	/* 2.50 --> 2. or 3. */
    ONE_DIGIT(buf3, v35);	/* 3.25 --> 3. or 4. */
    ONE_DIGIT(buf4, v45);	/* 4.75 --> 4. or 5. */
#ifdef DEBUG
    (void) printf("Values used to determine rounding are:\n");
    (void) printf("  1.5 --> %s, 2.5 --> %s, 3.25 --> %s, 4.75 --> %s\n",
		  buf1, buf2, buf3, buf4);
#endif
    /*
     * Now that we have the raw data, determine how round.
     */
    if (('3' == buf3[0]) && ('5' == buf4[0])) {		/* rounds */
	if (('2' == buf1[0]) && ('3' == buf2[0])) {
	    rounds = add_5_chop;
	} else if (('2' == buf1[0]) && ('2' == buf2[0])) {
	    rounds = near_even;
	} else if (('1' == buf1[0]) && ('3' == buf2[0])) {
	    rounds = near_odd;
	} else if (('1' == buf1[0]) && ('2' == buf2[0])) {
	    rounds = sub_5_ceil;
	} else {
	    (void) printf("FAIL: Cannot determine how system rounds.\n");
	    (void) printf("1.5 --> %s, 2.5 --> %s, 3.25 --> %s, 4.75 --> %s\n",
			  buf1, buf2, buf3, buf4);
	}
    } else {			/* floor or ceil */
	if (('1' == buf1[0]) && ('2' == buf2[0])
		&& ('3' == buf3[0]) && ('4' == buf4[0])) {	/* floor */
	    rounds = rnd_floor;
	} else if (('2' == buf1[0]) && ('3' == buf2[0])
		   && ('4' == buf3[0]) && ('5' == buf4[0])) {	/* ceil */
	    rounds = rnd_ceil;
	} else {
	    (void) printf("FAIL: Cannot determine how system rounds.\n");
	    (void) printf("1.5 --> %s, 2.5 --> %s, 3.25 --> %s, 4.75 --> %s\n",
			  buf1, buf2, buf3, buf4);
	}
    }
    (void) sprintf( bufa, "%#.*f", 0, v15);
    (void) sprintf( bufb, "%#.*f", 0, v25);
    (void) sprintf( bufc, "%#.*f", 0, v35);
    (void) sprintf( bufd, "%#.*f", 0, v45);
    if( (buf1[0] != bufa[0]) ||  (buf2[0] != bufb[0])
     || (buf3[0] != bufc[0]) ||  (buf4[0] != bufd[0]) ){
      failures++;
      (void) printf("FAIL: %%#.0f not equal to %%#.*f\n");
      (void) printf("  buf1=%s, bufa=%s\n", buf1, bufa);
      (void) printf("  buf2=%s, bufb=%s\n", buf2, bufb);
      (void) printf("  buf3=%s, bufc=%s\n", buf3, bufc);
      (void) printf("  buf4=%s, bufd=%s\n", buf4, bufd);
    }
    return rounds;
}

/*================================================================*/
/*
 * Compute the expected digit for %f by using %e.  Assumes %e is good.
 * %e will produce one of these forms:  d.edd or d.ddddedd
 */
static char
compute_digit(double val, char ebuf[], const enum how_round rounds, int *half_way)
{
    char             dig_want = (char) '?';

    if (ebuf && half_way) {
#ifdef USE_Le
	(void) sprintf(ebuf, "%#.*Le", E_WIDTH, (long double) val);
#else
	(void) sprintf(ebuf, "%#.*e", E_WIDTH, val);	/* Prefered */
#endif

	*half_way = 0;		/* assume not X.5000...0e-NN */
	if (('e' == ebuf[2])	/* X.e-NN */
		||(rounds == rnd_floor)) {	/* floor */
	    dig_want = ebuf[0];
	} else if ((rounds == rnd_ceil)		/* ceil; may be bigger than '9' */
		   ||('5' < ebuf[2])) {		/* big digits */
	    dig_want = (char) (ebuf[0] + 1);	/* round up */
	} else if (ebuf[2] < '5') {	/* little digits */
	    dig_want = ebuf[0];	/* round down */
	} else {		/* '5' == ebuf[2] */
	    if (rounds == add_5_chop) {
		dig_want = (char) (ebuf[0] + 1);	/* round up */
	    } else {		/* X.5000...digit or X.5000...0e-NN */
    int              fjt = 3;	/* index of first non-zero after 5 */
		while ('0' == ebuf[fjt]) {
		    fjt++;
		}
		if ('e' == ebuf[fjt]) {
		    *half_way = 1;	/* X.5000...0e-NN */
		    switch (rounds) {
		    case sub_5_ceil:
			dig_want = (char) (ebuf[0]);	/* round down */
			break;
		    case near_even:
			switch (ebuf[0]) {	/* round to even */
			case '1':
			case '3':
			case '5':
			case '7':
			case '9':
			    dig_want = (char) (ebuf[0] + 1);
			    break;
			case '0':
			case '2':
			case '4':
			case '6':
			case '8':
			    dig_want = ebuf[0];
			    break;
			default:
			    (void) printf("Should not happen in line %d\n",
					  (int) __LINE__);
			}	/* switch */
			break;
		    case near_odd:
			switch (ebuf[0]) {	/* round to odd */
			case '1':
			case '3':
			case '5':
			case '7':
			case '9':
			    dig_want = ebuf[0];
			    break;
			case '0':
			case '2':
			case '4':
			case '6':
			case '8':
			    dig_want = (char) (ebuf[0] + 1);
			    break;
			default:
			    (void) printf("Should not happen in line %d\n",
					  (int) __LINE__);
			}	/* switch */
			break;
		    default:
			(void) printf("Should not happen in line %d\n",
				      (int) __LINE__);
		    }		/* switch */
		} else {	/* X.5000... non-zero-digit digits e-xxx =>
				   round up */
		    dig_want = (char) (ebuf[0] + 1);
		}
	    }
	}
    }
    return dig_want;
}

/*================================================================*/
/*
 * Replace many 0s with "..." to end up with: x.xxx0...0e-xx
 */
static void
efmt_zeros(char ebuf[])
{
    char            *p;		/* walks thru array */
    char            *q;		/* points to 1st 0 of a string of 0s */
    if (ebuf) {
	q = 0;
	for (p = ebuf; (*p) && ('e' != *p); p++) {
	    if ('0' == *p) {
		if (0 == q) {
		    q = p;	/* 1st 0 after non-0 */
		}
	    } else {
		q = 0;		/* indicate non-0 */
	    }
	}
	if (0 != q) {		/* string of 0s before the 'e' */
	    if (5 < (p - q)) {	/* have enough 0s to remove */
		*(q + 1) = (char) '.';
		*(q + 2) = (char) '.';
		*(q + 3) = (char) '.';
		q += 5;
		for (;;) {	/* copy e-xx part, including nul */
		    *q = *p;
		    if (!(*p)) {
			break;	/* just copied the trailing nul */
		    }
		    q++;
		    p++;
		}
	    }
	}
    }
}

/*================================================================*/
/*
 * Replace many 0s with "..." to end up with: 0.0...0x (... is nn 0s)
 */
static void
ffmt_zeros(char out[])
{
    const char      *p;		/* walks thru array */
    char            *q;		/* points to 1st 0 of a string of 0s */
    int              removed;	/* # of 0s removed */

    if (out && (out[2] == '0')) {
	q = out + 2;		/* 1st zero after '.' */
	for (p = q; ('0' == *p); p++) {
	    ;			/* find 1st non-0 (may be nul) */
	}
	removed = (p - q) - 2;
	if (5 < (p - q)) {	/* have enough 0s to remove */
	    *(q + 1) = (char) '.';
	    *(q + 2) = (char) '.';
	    *(q + 3) = (char) '.';
	    q += 5;
	    for (;;) {		/* copy last part, including nul */
		*q = *p;
		if (!(*p)) {
		    break;	/* just copied the trailing nul */
		}
		q++;
		p++;
	    }
	    (void) sprintf(q, " (... is %i 0s)", removed);
	}
    }
}

/*================================================================*/
/*
 * Test sprintf to see if it is consistent on rounding and meets ISO C.
 */
int
main(void)
{
    double           ten2dig;	/* positive powers of 10 */
    double           scale_up;	/* to prevent underflow doing ulps */
    double           scale_down;/* to prevent underflow doing ulps */
    double           val;	/* value[] / ten2dig */
    double           value[18];	/* basic value to print */
    int              max_exp;	/* min of MAX_10_EXP, -MIN_10_EXP */
    int              dig;	/* number of digits testing */
    int              pt;	/* have a decimal point? */
    int              e;
    int              rc;	/* return code got from function */
    int              rc_want;	/* return code want from function */
    int              e_wid;
    int              j;		/* loop index */
    int              kk;	/* ulps above or below loop index */
    int              half_way;	/* is it X.5000...0eNN */
    int              where;	/* index into out where check */
    enum how_round   rounds;
    char             dig_want;	/* expected digit from  %f */
    char             out[MIN_WIDTH + 30];	/* room for (... is nnn 0s) */
    char             ebuf[E_WIDTH + 12];	/* at least DBL_DIG*2.5 + 12 */

#ifndef TAILOR
    (void)printf("Info:  'TAILOR' not defined => NOT using any bug workarounds.\n");
#endif

    /*
     * At least one compiler does not allow initialization of arrays, so
     * do it the long way at runtime.
     */
#ifdef TEST_RND_UP_DECADE
  #ifndef RETVAL
    (void)printf("Testing with TEST_RND_UP_DECADE\n");
  #endif
    value[0] = 9.5;		/* will round up to next decade */
#else
    value[0] = 9.4;		/* should stay in same decade */
#endif
    value[1] = 9.0;
    value[2] = 8.5;
    value[3] = 8.0;
    value[4] = 7.5;
    value[5] = 7.0;
    value[6] = 6.5;
    value[7] = 6.0;
    value[8] = 5.5;
    value[9] = 5.0;
    value[10] = 4.5;
    value[11] = 4.0;
    value[12] = 3.5;
    value[13] = 3.0;
    value[14] = 2.5;
    value[15] = 2.0;
    value[16] = 1.5;
    value[17] = 1.1;

    /*
     * This is the formula for the minimum number of digits to use
     * to represent an internal double number in decimal.  But, it
     * is not used since it involves the math library (which makes
     * running this harder; some people do not know how to link in
     * a math library).  Also, the accuracy of the math library can
     * be very bad.  Could also use DECIMAL_DIG of C99.
     *
     * e_wid = (int)ceil(1.0+log10((double)FLT_RADIX)*(double)DBL_MANT_DIG);
     */
    e_wid = (5 * (int) DBL_DIG) / 2;	/* Using enough precision? */
    if (E_WIDTH < e_wid) {
	(void) printf("Increase E_WIDTH to at least %i\n", e_wid);
    }
    stdc_failures();		/* See if any misc. Standard C problems */

    /*
     * Compute small values to test from X.Y / large value.  Therefore,
     * to prevent both overflow of the large value and underflow of the
     * small value, we need to limit the powers of 10 that we will use.
     */
    max_exp = -(DBL_MIN_10_EXP);	/* ()'s are in case macro is -xxx */
    if ((DBL_MAX_10_EXP) < max_exp) {	/* min of two ranges */
	max_exp = DBL_MAX_10_EXP;
    }
    /*
     * For machines with very large exponent ranges for double, we need to
     * limit the decades that we check so that we do not try to print more
     * than MIN_WIDTH characters (all that is required by Standard C).
     */
    if ((MIN_WIDTH - 2) < max_exp) {
	max_exp = MIN_WIDTH - 2;	/* leave room for leading "0." */
    }
    rounds = find_round();	/* find rounding style */
    if( rnd_weird == rounds ){
      failures++;
      goto give_up;
    }

    scale_down = DBL_EPSILON / (double) FLT_RADIX;	/* should be exact */
    scale_up = 1.0 / scale_down;	/* power of base so that ulp of small
					   will not underflow */

    ten2dig = 1.0;		/* 10 ** 0 */
    pt = 0;			/* no decimal point so far */
    for (dig = 0; dig <= max_exp; dig++) {	/* 0...MIN(DBL_*_10_EXP) */
	for (j = 0; j < (int) (sizeof (value) / sizeof (value[0])); j++) {

	    val = value[j] / ten2dig;	/* x / 10**(dig) */
	    val *= scale_up;
	    for (kk = 1; kk <= 7; kk++) {
		val = val + ulp(val, 1);	/* val = nextafter(val,MAX) */
	    }
	    val *= scale_down;

	    for (kk = 7; -7 < kk; kk--) {	/* 7 ulps above to 7 ulps
						   below */

		if (val == 0.0) {	/* underflowed */
		    (void) printf("FAIL: Underflow: One of DBL_*_10_EXP is wrong\n");
		    failures++;
		    goto give_up;
		}
		/*
		 * Find expected digit.  It will be greater than '9'
		 * if rounding is rnd_ceil and value is greater than 9.
		 * dig val    => ceil  others
		 *  0  9.4    => 10.   9.
		 *  1  0.94   => 1.0   0.9
		 *  2  0.094  => 0.10  0.09
		 *  3  0.0094 => 0.010 0.009
		 */
		dig_want = compute_digit(val, ebuf, rounds, &half_way);
		where = dig + pt;
		rc_want = dig + 2;
		if('9' < dig_want){	/* due to '9'+1 */
		  dig_want = (char)'1';	/* as if 9+1 became 10 */
		  if(dig < 2){
		    where = 0;
		  }else{
		    where--;		/* carry left one digit */
		  }
		  if(!dig) rc_want++;	/* one extra digit for 10. */
		}
		out[where] = (char) '?';	/* init known value */

		/*
		 * Now test the Function Under Test (FUT).
		 */
		errno = 0;
		rc = sprintf(out, "%#.*f", dig, val);	/* FUT */
		e = errno;

		if ((test_rc && (rc != rc_want)) || e
			|| (out[where] != dig_want)) {
		    failures++;
		    if (half_way) {
			midpoint++;
		    }
		    if ((printed < CUT_OFF)
#ifdef SUPPRESS_MIDPOINT	/* Do NOT print x.50...0e-nn failures */
			    && (!half_way)
#endif
		      ) {
			printed++;
			(void) printf("FAIL: dig=%i, errno=%i, rc=%i, kk=%i\n",
				      dig, e, rc, kk);
#ifdef DEBUG
			(void) printf(", %%a=>%a\n", val);
#endif
			efmt_zeros(ebuf);	/* many 0s to ... */
			(void) printf(", %%e=>%s\n", ebuf);
			ffmt_zeros(out);	/* many 0s to ... */
			(void) printf(", %%f=>%s\n", out);
			if (e) {
			    (void) printf(", errno should be 0");
			}
			if (test_rc && (rc != rc_want)) {
			    (void) printf(", rc should be %i", rc_want);
			}
			if (half_way) {
			    if (kk < 0) {
				(void) printf(", %%e should be X.4999...9Y...e-NN");
			    } else if (0 < kk) {
				(void) printf(", %%e should be X.5000...0Y...e-NN");
			    } else {
				(void) printf(", %%e should not be X.5000...0e-NN");
			    }
			}
			if (out[where] != dig_want) {
			    (void) printf(", %%f[%i] should be %c (based upon %%e)",
					  where, dig_want);
			}
			(void) printf("\n");
		    }
		}
		val *= scale_up;
		val = val - ulp(val, -1);	/* val = nextafter(val, 0.0); */
		val *= scale_down;

	    }			/* kk loop */
	}			/* j loop */
	if (dig == max_exp) {
	    break;		/* next would overflow */
	} else {
    double      last_pow = ten2dig;	/* so can detect overflow */
	    ten2dig *= 10.0;	/* another power of 10 */
	    if (ten2dig <= last_pow) {	/* overflowed */
		(void) printf("FAIL: Overflow: One of DBL_*_10_EXP is wrong\n");
		failures++;
		goto give_up;
	    }
	}
	pt = 1;			/* have a leading decimal point */
    }				/* dig loop */

    /*
     * Make sure can print out fields up to MIN_WIDTH (at least 509 digits)
     * %#.507f outputs 509 chars.  There is a leading "0." and then the 507
     * digits after the decimal point as per the precision.  C99 raised the
     * 509 to 4095.
     */

    for (dig = max_exp; dig <= (MIN_WIDTH - 2); dig++) {
	out[dig + 1] = (char) '?';	/* so can see if changed to '0' */

	errno = 0;
	rc = sprintf(out, "%#.*f", dig, 0.0);	/* FUT */
	e = errno;

	if ((test_rc && (rc != (dig + 2))) || e || (out[dig + 1] != '0')) {
	    failures++;
	    if (printed < CUT_OFF) {
		printed++;
		(void) printf("FAIL: dig=%i, errno=%i, rc=%i\n",
			      dig, e, rc);
		ffmt_zeros(out);	/* many 0s to ... */
		(void) printf(", %%f=>%s\n", out);
		if (e) {
		    (void) printf(", errno should be 0");
		}
		if (test_rc && (rc != (dig + 2))) {
		    (void) printf(", rc should be %i", dig + 2);
		}
		if (out[dig + 1] != '0') {
		    (void) printf(", out[%i] should be %c", dig + 1, '0');
		}
		(void) printf("\n");
	    }
	}
    }				/* dig loop */

  give_up:

#ifdef RETVAL
    if (failures)
#endif
    {
      (void) printf("Rounding is ");
      switch (rounds) {
      case add_5_chop:
	(void) printf("add 0.5 and truncate.");
	break;
      case sub_5_ceil:
	(void) printf("add 0.4999... and truncate; or sub 0.5 and ceil.");
	break;
      case near_even:
	(void) printf("round to nearest, even.");
	break;
      case near_odd:
	(void) printf("round to nearest, odd.");
	break;
      case rnd_floor:
	(void) printf("truncate or floor.");
	break;
      case rnd_ceil:
	(void) printf("upwards or ceil.");
	break;
      case rnd_weird:
      default:
	(void) printf("unknown.  Should not happen.");
	break;
      }
      (void) printf("\n");
    }

    if (midpoint) {
	(void) printf("%lu failure(s) were due to %%e producing x.50...0e-nn\n",
		      midpoint);
    }
    if (printed >= CUT_OFF) {
        (void) printf("WARNING:  Not all %lu failures were printed.\n",
		      failures);
    }

#ifndef RETVAL
    (void) printf("MIN_WIDTH=%i.\n", MIN_WIDTH);
#endif
    if (failures) {
        (void) printf("Test Failed with %lu failure(s).\n", failures);
	rc = EXIT_FAILURE;
    }else{
        (void) printf("Test ( Pass ) {} \n");
	rc = EXIT_SUCCESS;
    }
#ifdef FIX_IMPLICIT_FLUSH
    (void)fflush(stdout);	/* need explicit flush */
#endif
#if (defined RETVAL) && (defined STANDALONE_TEST)
    rc = RETVAL;		/* Being run as part of test suite */
#endif

    return rc;
}

