/*
 *  Classified Tydeman Consulting Proprietary
 *  Copyright (C) 2006, 2011 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
 *
 ***********************************************************************
 *  FILE: tdfp2int.c
 *
 *  Assertion being tested:
 *
 * C99 + Decimal FP:
 *  Floating to integer conversion
 *    If the integral part of the floating value exceeds the range
 *    of the integer type, then the ''invalid'' floating-point exception
 *    shall be raised and the resulting value is unspecified.
 *    [was:  max int type with same sign.]
 *
 * from WG14 (C standards committee) paper: 
 *   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1312.pdf
 *
 *  This test is for C99 with IEEE-754 decimal floating-point (DFP) support.
 *  Test conversions from decimal floating-point types to integer types.
 *  Test with powers of 2 (since integers are binary).
 *  For numbers in range, checks for correct value and no exceptions.
 *  For numbers too big, checks for FE_INVALID exception [and value -- no more].
 *  Also, check that no exceptions are cleared with a 2nd conversion.
 *
 * If you need to disable trapping of floating-point exceptions,
 * you might try one of the next two ways:
 *  #define FPU_DISABLE_TRAPS (void)feholdexcept( &current_fenv );
 *  #define FPU_DISABLE_TRAPS (void)fedisabletrap(FE_TRAP_ALL);
 * in tdfp2int.h.  You will also need to define NEED_TRAPS_DISABLED.
 *
 * Results of running this test on various compilers:
 * (as reported by several users of this test; your results may vary)
 *
 * Failures    Hardware      Operating system   Compiler, version, and options
 *      0 HP Integrity       HP-UX 11i V3       HP c99, A.06.23, +decfp
 * >= 192 Intel x86_64       Linux Debian       gcc 4.5.0, glibc ?; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 192 Intel x86_64       Linux Debian 4.0   gcc 4.4.1, glibc ?; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 192 Intel x86_64       Linux Fedora 10    Intel C/C++ icc 11.1 w/ no options
 * >= 201 IBM PowerPC        Linux Debian       gcc 4.3.3, glibc ?; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 201 Intel Pent 4 IA-32 Linux Fedora 10    Intel C/C++ icc 11.1 w/ no options
 * >= 201 Intel Pent 4 IA-32 Linux Fedora 10    Intel C/C++ icc 11.1; -fp-model strict
 * >= 228 Intel x86_64       Linux Fedora 15    gcc 4.6.0, glibc ?; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Core2 Duo    Linux Fedora 14    gcc 4.5.1-4, glibc 2.12.90-15; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Core2 Duo    Linux Fedora 15    gcc 4.6.1-9, glibc 2.14.1-5; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Core2 Duo    Linux Fedora 16    gcc 4.6.2-1, glibc 2.14.90-21; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Pent 4 IA-32 Linux Fedora 10    gcc 4.3.2-7, glibc 2.9-3; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Pent 4 IA-32 Linux Fedora 11    gcc 4.4.0-4, glibc 2.10.1-2; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Pent 4 IA-32 Linux Fedora 11    gcc 4.4.1-2, glibc 2.10.1-5; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * >= 237 Intel Pent 4 IA-32 Linux Fedora 14    gcc 4.5.1-4, glibc 2.12.90-15; -D__STDC_DEC_FP__ -std=gnu99 -frounding-math
 * ?????? Intel Pent 4 IA-32 Linux Fedora 10    Intel C/C++ icc 11.1; -std=c99 => _Decimal32 is unknown
 * ?????? Intel Pent 4 IA-32 Linux Fedora 10    Intel C/C++ icc 11.1; -strict-ansi => _Decimal32 is unknown
 * ?????? Intel x86_64       Linux Debian 4.0   Intel C/C++ icc 11.0 20081105; internal error compilation aborted
 *
 * ?????? IBM System z10     z/OS v1r9 ?????    IBM XL C 9 [to be done]
 * ?????? IBM Power 6        AIX 5L ?????       IBM XL C 9 [to be done]
 * ?????? IBM Power 6        Linux ?????        IBM XL C 9 [to be done]
 * ?????? SilMinds           Linux ?????        gcc ??? [to be done]
 *
 * I wish to acknowledge the following people for taking the time and effort
 * to run this test and sending me their results:
 *   Vincent Lefevre
 *
 * MODIFICATION HISTORY:
 *
 * 2006/03/02 - Create (from tflt2int).
 * 2006/03/19 - Update DEBUG section.
 * 2006/03/19 - Indent #if's.
 * 2006/03/30 - Rename WANT DEC FP macro.
 * 2006/08/19 - Add static to function definitions; const to parm.
 * 2006/09/18 - Make sure RAISE_ALL raises some flags.
 * 2007/11/21 - Add const as per PC-Lint 8.
 * 2008/06/26 - Remove test of converted value when invalid is raised.
 * 2008/06/26 - Only test when 'f' is exact power of 2.
 * 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/01/30 - Add FIX_DFP_FLAGS.
 * 2009/01/31 - Add uses of FIX_*_RANDOM_INVALID.
 * 2009/07/01 - Update DEBUG section.
 * 2009/09/15 - Reorganize code for systems not defining __STDC_DEC_FP__.
 *
 ***********************************************************************/

#define __STDC_WANT_DEC_FP__ 1		/* Tell implementation that we want Decimal FP */

/*lint -e537 // repeated include */
/*lint -e551 // var not accessed */
/*lint -e701 // Shift left of signed quantity */
/*lint -e703 // Shift left of signed quantity */
/*lint -e737 // loss of sign on promotion */
/*lint -e750 // local macro not referenced */
/*lint -e766 // header not needed */
/*lint -e792 // void cast of void expression */
/*lint -e801 // use of goto is deprecated */
/*lint -e909 // implicit conversion: if(i) */
/*lint -e912 // implicit conversion */

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

#ifdef DEBUG	/* local override of FIXes to force errors to show */
  #ifdef DEBUG2	/* Kills some compilers */
    #undef  FIX_BROKEN_PP
    #undef  FIX_DFP_FLAGS
    #undef  FIX_FP_FROM_ULLI
    #undef  FIX_NAMESPACE_STD
    #undef  FIX_SEMIBROKEN_PP
    #undef  FIX_SYM_FE_DIVBYZERO_ENUM
    #undef  FIX_SYM_FE_INEXACT_ENUM
    #undef  FIX_SYM_FE_INVALID_ENUM
    #undef  FIX_SYM_FE_OVERFLOW_ENUM
    #undef  FIX_SYM_FE_UNDERFLOW_ENUM
  #endif
#endif

#ifdef     DECFENV_H
  #include DECFENV_H	/* Might be needed */
#endif
#ifdef     FENV_H
  #include FENV_H	/* fe clear/raise/test except(), FE_ALL_EXCEPT */
#else
  #include <fenv.h>	/* fe clear/raise/test except(), FE_ALL_EXCEPT */
#endif
#ifdef     DECFLOAT_H
  #include DECFLOAT_H	/* DEC*_MAX_EXP */
#endif
#include <float.h>	/* DEC*_MAX_EXP */
#include <limits.h>	/* *_MAX */
#include <stdio.h>	/* printf() */

#ifdef DEBUG	/* local override of FIXes to force errors to show */
  #ifdef DEBUG3
    #undef  CLEAR_ALL
    #undef  LONGLONG
    #undef  NEED_TRAPS_DISABLED
    #undef  RAISE_ALL
    #undef  ULONGLONG
  #endif
  #undef  FIX_IMPLICIT_FLUSH
  #undef  FIX_INVALID_OCTAL
  #undef  FIX_PRAGMAS
  #undef  FIX_PRAGMA_FENV_ACCESS
  #undef  FIX_SCHAR_RANDOM_INVALID
  #undef  FIX_SINT_RANDOM_INVALID
  #undef  FIX_SLLONG_RANDOM_INVALID
  #undef  FIX_SLONG_RANDOM_INVALID
  #undef  FIX_SSHRT_RANDOM_INVALID
  #undef  FIX_UCHAR_RANDOM_INVALID
  #undef  FIX_UINT_RANDOM_INVALID
  #undef  FIX_ULLONG_RANDOM_INVALID
  #undef  FIX_ULONG_RANDOM_INVALID
  #undef  FIX_USHRT_RANDOM_INVALID
#endif
#ifdef DEBUG4
  #undef  RETVAL
#endif

/*
 * Tell implementation that we will be checking the floating-point status flags.
 */
#if (!defined FIX_PRAGMAS) && (!defined FIX_PRAGMA_FENV_ACCESS)
  #pragma STDC FENV_ACCESS ON
#endif

#ifndef   FP_RADIX
  #define FP_RADIX 10
#endif

/*
 * Clear all FP exception flags.
 */
#ifndef   CLEAR_ALL
  #define CLEAR_ALL (void)feclearexcept( FE_ALL_EXCEPT )
#endif

/*
 * Raise all FP exception flags.
 */
#ifndef   RAISE_ALL
  #define RAISE_ALL (void)feraiseexcept( FE_ALL_EXCEPT )
#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

#ifndef   Flt_10_7
  #define Flt_10_7 _Decimal32
#endif

#ifndef   Flt_10_16
  #define Flt_10_16 _Decimal64
#endif

#ifndef   Flt_10_34
  #define Flt_10_34 _Decimal128
#endif

#define LD Flt_10_34, DEC128_MAX_EXP
#define  D Flt_10_16,  DEC64_MAX_EXP
#define  F Flt_10_7 ,  DEC32_MAX_EXP

#ifdef ULLONG_MAX
  #ifdef ULONGLONG
    #define ULL ULONGLONG, "%#llx", ULLONG_MAX, ULLONG_MIN
  #else
    #define ULL unsigned long long, "%#llx", ULLONG_MAX, ULLONG_MIN
  #endif
#endif
#ifdef LLONG_MAX
  #ifdef LONGLONG
    #define SLL   signed LONGLONG, "%#llx",  LLONG_MAX,  LLONG_MIN
  #else
    #define SLL   signed long long, "%#llx",  LLONG_MAX,  LLONG_MIN
  #endif
#endif
#define  UL unsigned      long,  "%#lx",  ULONG_MAX,  ULONG_MIN
#define  SL   signed      long,  "%#lx",   LONG_MAX,   LONG_MIN
#define  UI unsigned       int,   "%#x",   UINT_MAX,   UINT_MIN
#define  SI   signed       int,   "%#x",    INT_MAX,    INT_MIN
#define  US unsigned     short,  "%#hx",  USHRT_MAX,  USHRT_MIN
#define  SS   signed     short,  "%#hx",   SHRT_MAX,   SHRT_MIN
#define  UC unsigned      char,   "%#x",  UCHAR_MAX,  UCHAR_MIN
#define  SC   signed      char,   "%#x",  SCHAR_MAX,  SCHAR_MIN

#define STR(s) # s
#define STN(n) tst_ ## n

/*
 * 'Type generic' function done via macro.
 * f = 2**j and is the value to convert.
 * First, test for expected flags being raised; for both plus and minus.
 * Second, test for any flags being cleared; for both plus and minus.
 * Note:  For sign-magnitude and 1s complement, type_MIN == -type_MAX,
 * and is 1 less than a power of 2.
 * While for 2s complement, type_MIN == -type_MAX-1, and is a power of 2.
 * minint is used to detect this one special case.
 */
#define DEF_TSTS(N,PRT,I_TYPE,FMT,I_MAX,I_MIN,F_TYPE,F_MAX_EXP)\
static void STN(N)(F_TYPE const fmaxint){\
  F_TYPE f = (F_TYPE)1.0;\
  I_TYPE i1,i2,i3,i4;\
  I_TYPE imax = (I_TYPE)I_MAX;\
  unsigned long j;\
  unsigned long const max_exp = log10radix * (unsigned long)F_MAX_EXP;\
  int flags;\
  int lcl_failed=0;\
  int minint = (int)((I_MIN) != -(I_MAX));\
  if(PRT)(void)printf("Testing conversion from " STR(F_TYPE) " to " STR(I_TYPE) "\n");\
  for(j=0uL; (j<max_exp) && (f<=fmaxint); j++){\
    CLEAR_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i1 = f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( imax ){\
      if( flags ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected no flags, got: %#x\n", j, (unsigned)flags);\
      }\
      if( i1 != (((I_TYPE)1)<<j) ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected power of 2, got: " FMT "\n", j, i1);\
      }\
    }else{\
      if( !((FE_INVALID) & flags) ){\
	lcl_failed++;\
	(void)printf("+f: j=%lu, expected FE_INVALID, got: %#x\n", j, (unsigned)flags);\
      }\
      if( (~(FE_INVALID)) & flags ){\
	lcl_failed++;\
	(void)printf("+f: j=%lu, expected just FE_INVALID, got: %#x\n", j, (unsigned)flags);\
      }\
      if( 0 && (i1 != I_MAX) ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected max integer, got: " FMT "\n", j, i1);\
      }\
    }\
    CLEAR_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i2 = -f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( imax || minint ){\
      if(!imax)minint = 0;\
      if( flags ){\
	lcl_failed++;\
        (void)printf("-f: j=%lu, expected no flags, got: %#x\n", j, (unsigned)flags);\
      }\
      if( i2 != -(((I_TYPE)1)<<j) ){\
	lcl_failed++;\
        (void)printf("-f: j=%lu, expected power of 2, got: " FMT "\n", j, i2);\
      }\
    }else{\
      if( !((FE_INVALID) & flags) ){\
	lcl_failed++;\
	(void)printf("-f: j=%lu, expected FE_INVALID, got: %#x\n", j, (unsigned)flags);\
      }\
      if( (~(FE_INVALID)) & flags ){\
	lcl_failed++;\
	(void)printf("-f: j=%lu, expected just FE_INVALID, got: %#x\n", j, (unsigned)flags);\
      }\
      if( 0 && (i2 != I_MIN) ){\
	lcl_failed++;\
        (void)printf("-f: j=%lu, expected min integer, got: " FMT "\n", j, i2);\
      }\
    }\
    RAISE_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i3 = f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( allflags != flags ){\
      lcl_failed++;\
      (void)printf("+f: j=%lu, expected all flags, got: %#x\n", j, (unsigned)flags);\
    }\
    if( i3 != i1 ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected i1 == i3, got: " FMT ", " FMT "\n", j, i1, i3);\
    }\
    RAISE_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i4 = -f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( allflags != flags ){\
      lcl_failed++;\
      (void)printf("-f: j=%lu, expected all flags, got: %#x\n", j, (unsigned)flags);\
    }\
    if( i4 != i2 ){\
	lcl_failed++;\
        (void)printf("-f: j=%lu, expected i2 == i4, got: " FMT ", " FMT "\n", j, i2, i4);\
    }\
    f += f;		/* next larger power of 2 */\
			/*lint -e915 -e704 -e702 */\
    imax >>= 1;		/* next smaller power of 2 */\
			/*lint +e915 +e704 +e702 */\
    if(9<=lcl_failed){\
      if(!PRT)(void)printf("Testing conversion from " STR(F_TYPE) " to " STR(I_TYPE) "\n");\
      (void)printf("Too many failures\n");\
      break;\
    }\
  }\
  failed += lcl_failed;\
}

/*
 * Same tests as above, but for unsigned types.
 */
#define DEF_TSTU(N,PRT,I_TYPE,FMT,I_MAX,I_MIN,F_TYPE,F_MAX_EXP)\
static void STN(N)(F_TYPE const fmaxint){\
  F_TYPE f = (F_TYPE)1.0;\
  I_TYPE i1,i2,i3,i4;\
  I_TYPE imax = (I_TYPE)I_MAX;\
  unsigned long j;\
  unsigned long const max_exp = log10radix * (unsigned long)F_MAX_EXP;\
  int flags;\
  int lcl_failed=0;\
  if(PRT)(void)printf("Testing conversion from " STR(F_TYPE) " to " STR(I_TYPE) "\n");\
  for(j=0uL; (j<max_exp) &&  (f<=fmaxint); j++){\
    CLEAR_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i1 = f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( imax ){\
      if( flags ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected no flags, got: %#x\n", j, (unsigned)flags);\
      }\
      if( i1 != (((I_TYPE)1)<<j) ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected power of 2, got: " FMT "\n", j, i1);\
      }\
    }else{\
      if( !((FE_INVALID) & flags) ){\
	lcl_failed++;\
	(void)printf("+f: j=%lu, expected FE_INVALID, got: %#x\n", j, (unsigned)flags);\
      }\
      if( (~(FE_INVALID)) & flags ){\
	lcl_failed++;\
	(void)printf("+f: j=%lu, expected just FE_INVALID, got: %#x\n", j, (unsigned)flags);\
      }\
      if( 0 && (i1 != I_MAX) ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected max integer, got: " FMT "\n", j, i1);\
      }\
    }\
    CLEAR_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i2 = -f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( !((FE_INVALID) & flags) ){\
      lcl_failed++;\
      (void)printf("-f: j=%lu, expected FE_INVALID, got: %#x; i2 is " FMT "\n", j, (unsigned)flags, i2);\
    }\
    if( (~(FE_INVALID)) & flags ){\
      lcl_failed++;\
      (void)printf("-f: j=%lu, expected just FE_INVALID, got: %#x; i2 is " FMT "\n", j, (unsigned)flags, i2);\
    }\
    if( 0 && (i2 != 0u) ){\
      lcl_failed++;\
      (void)printf("-f: j=%lu, expected 0, got: " FMT "\n", j, i2);\
    }\
    RAISE_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i3 = f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( allflags != flags ){\
      lcl_failed++;\
      (void)printf("+f: j=%lu, expected all flags, got: %#x\n", j, (unsigned)flags);\
    }\
    if( i3 != i1 ){\
	lcl_failed++;\
        (void)printf("+f: j=%lu, expected i1 == i3, got: " FMT ", " FMT "\n", j, i1, i3);\
    }\
    RAISE_ALL;\
		/*lint -e524 -e732 -e915 -e919 */\
    i4 = -f;	/* conversion we are testing */\
		/*lint +e524 +e732 +e915 +e919  */\
    flags = fetestexcept( FE_ALL_EXCEPT );\
    if( allflags != flags ){\
      lcl_failed++;\
      (void)printf("-f: j=%lu, expected all flags, got: %#x\n", j, (unsigned)flags);\
    }\
    if( i4 != i2 ){\
	lcl_failed++;\
        (void)printf("-f: j=%lu, expected i2 == i4, got: " FMT ", " FMT "\n", j, i2, i4);\
    }\
    f += f;		/* next larger power of 2 */\
			/*lint -e915 -e704 -e702 */\
    imax >>= 1;		/* next smaller power of 2 */\
			/*lint +e915 +e704 +e702 */\
    if(9<=lcl_failed){\
      if(!PRT)(void)printf("Testing conversion from " STR(F_TYPE) " to " STR(I_TYPE) "\n");\
      (void)printf("Too many failures\n");\
      break;\
    }\
  }\
  failed += lcl_failed;\
}

static unsigned long log10radix;
static unsigned int failed = 0u;

/*
 * Suppose a CPU has two or more FPUs (such as a x86 with a x87 and MMX),
 * each with its own set of floating-point exception flags.  Then, it is
 * possible that FE_INVALID might have a bit for each FPU.  If, invalid is
 * raised on this FPU and, flags = fetestexcept(FE_ALL_EXCEPT);
 * returns the exceptions for just the FPU where this program is running,
 * then flags == FE_INVALID will be false, even though just invalid is raised.
 * So, need to form a mask of all the flags for just this FPU.
 */
static int allflags;	/* flags raised after RAISE_ALL; */

#if 1 /* was #ifdef __STDC_DEC_FP__	// Need support for decimal FP */

static Flt_10_34 maxint_ld;	/* max int in FP format */
static Flt_10_16 maxint_d;
static Flt_10_7  maxint_f;

  #if (!defined FIX_BROKEN_PP)	/* many pre-processors die on these macros */
/*
 * Used to convert 4 arguments (which contain embedded ',' chars)
 * into 8 arguments.
 */
    #ifdef RETVAL			/* Running as part of test suite */
      #define P 0
    #else				/* Running standalone */
      #define P 1
    #endif
    #if (!defined FIX_SEMIBROKEN_PP)	/* many pre-processors die on these macros */
      #define DEF_TESTU(N,I,F) DEF_TSTU(N,P,I,F)
      #define DEF_TESTS(N,I,F) DEF_TSTS(N,P,I,F)
    #else				/* a workaround for some compilers */
      #define DEF_TESTU(N,I,F) DEF_TEST_UI((N,P,I,F))
      #define DEF_TEST_UI(args) DEF_TSTU args
      #define DEF_TESTS(N,I,F) DEF_TEST_SI((N,P,I,F))
      #define DEF_TEST_SI(args) DEF_TSTS args
    #endif

    #if (defined ULLONG_MAX) && (!defined FIX_FP_FROM_ULLI) && (!defined FIX_ULLONG_RANDOM_INVALID)
DEF_TESTU(00,ULL,LD)
    #endif
    #if (defined LLONG_MAX) && (!defined FIX_SLLONG_RANDOM_INVALID)
DEF_TESTS(01,SLL,LD)
    #endif
    #if (!defined FIX_ULONG_RANDOM_INVALID)
DEF_TESTU(02, UL,LD)
    #endif
    #if (!defined FIX_SLONG_RANDOM_INVALID)
DEF_TESTS(03, SL,LD)
    #endif
    #if (!defined FIX_UINT_RANDOM_INVALID)
DEF_TESTU(04, UI,LD)
    #endif
    #if (!defined FIX_SINT_RANDOM_INVALID)
DEF_TESTS(05, SI,LD)
    #endif
    #if (!defined FIX_USHRT_RANDOM_INVALID)
DEF_TESTU(06, US,LD)
    #endif
    #if (!defined FIX_SSHRT_RANDOM_INVALID)
DEF_TESTS(07, SS,LD)
    #endif
    #ifdef FIX_INVALID_OCTAL
      #if (!defined FIX_UCHAR_RANDOM_INVALID)
DEF_TESTU(108, UC,LD)
      #endif
      #if (!defined FIX_SCHAR_RANDOM_INVALID)
DEF_TESTS(109, SC,LD)
      #endif
    #else
      #if (!defined FIX_UCHAR_RANDOM_INVALID)
DEF_TESTU(08, UC,LD)
      #endif
      #if (!defined FIX_SCHAR_RANDOM_INVALID)
DEF_TESTS(09, SC,LD)
      #endif
    #endif

    #if (defined ULLONG_MAX) && (!defined FIX_FP_FROM_ULLI) && (!defined FIX_ULLONG_RANDOM_INVALID)
DEF_TESTU(10,ULL, D)
    #endif
    #if (defined LLONG_MAX) && (!defined FIX_SLLONG_RANDOM_INVALID)
DEF_TESTS(11,SLL, D)
    #endif
    #if (!defined FIX_ULONG_RANDOM_INVALID)
DEF_TESTU(12, UL, D)
    #endif
    #if (!defined FIX_SLONG_RANDOM_INVALID)
DEF_TESTS(13, SL, D)
    #endif
    #if (!defined FIX_UINT_RANDOM_INVALID)
DEF_TESTU(14, UI, D)
    #endif
    #if (!defined FIX_SINT_RANDOM_INVALID)
DEF_TESTS(15, SI, D)
    #endif
    #if (!defined FIX_USHRT_RANDOM_INVALID)
DEF_TESTU(16, US, D)
    #endif
    #if (!defined FIX_SSHRT_RANDOM_INVALID)
DEF_TESTS(17, SS, D)
    #endif
    #if (!defined FIX_UCHAR_RANDOM_INVALID)
DEF_TESTU(18, UC, D)
    #endif
    #if (!defined FIX_SCHAR_RANDOM_INVALID)
DEF_TESTS(19, SC, D)
    #endif

    #if (defined ULLONG_MAX) && (!defined FIX_FP_FROM_ULLI) && (!defined FIX_ULLONG_RANDOM_INVALID)
DEF_TESTU(20,ULL, F)
    #endif
    #if (defined LLONG_MAX) && (!defined FIX_SLLONG_RANDOM_INVALID)
DEF_TESTS(21,SLL, F)
    #endif
    #if (!defined FIX_ULONG_RANDOM_INVALID)
DEF_TESTU(22, UL, F)
    #endif
    #if (!defined FIX_SLONG_RANDOM_INVALID)
DEF_TESTS(23, SL, F)
    #endif
    #if (!defined FIX_UINT_RANDOM_INVALID)
DEF_TESTU(24, UI, F)
    #endif
    #if (!defined FIX_SINT_RANDOM_INVALID)
DEF_TESTS(25, SI, F)
    #endif
    #if (!defined FIX_USHRT_RANDOM_INVALID)
DEF_TESTU(26, US, F)
    #endif
    #if (!defined FIX_SSHRT_RANDOM_INVALID)
DEF_TESTS(27, SS, F)
    #endif
    #if (!defined FIX_UCHAR_RANDOM_INVALID)
DEF_TESTU(28, UC, F)
    #endif
    #if (!defined FIX_SCHAR_RANDOM_INVALID)
DEF_TESTS(29, SC, F)
    #endif

  #endif /* FIX_BROKEN_PP */

#endif /* __STDC_DEC_FP__ // Need support for decimal FP */

/*================================================================*/

int main(void){

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

#ifndef RETVAL
  (void)printf("This program tests conversions from decimal floating-point types to integer types.\n");
  (void)printf("It tests positive powers of 2.0, e.g., f = 2.0**j\n");
  (void)printf("It tests both i = +f; and i = -f;\n");
  (void)printf("For numbers that are representable, it checks expected value and no exceptions.\n");
  (void)printf("For numbers that are NOT representable, it checks for FE_INVALID exception.\n");
#endif

#ifndef __STDC_IEC_559__
  (void)printf("This implementation does not claim conformance to IEC-60559 or IEEE-754\n");
  (void)printf("Checks of the floating-point exception flags may be meaningless.\n");
#endif

#if (!defined __STDC_DEC_FP__)
  (void)printf("This implementation does not claim to support Decimal FP.\n");
  (void)printf("Checks of the floating-point exception flags may be meaningless.\n");
#endif

  switch (FP_RADIX){
  case 10:
    log10radix = 1uL;
    break;
  case 100:
    log10radix = 2uL;
    break;
  case 1000:
    log10radix = 3uL;
    break;
  case 10000:
    log10radix = 4uL;
    break;
  default:
    failed++;
    (void)printf("Failed.  Unsupported FP_RADIX value: %i\n", (int)FP_RADIX);
    goto death;
  }

#if (defined NEED_TRAPS_DISABLED)
  #ifndef RETVAL
  failed++;
  (void)printf("Failed due to traps enabled.\n");
  #endif
  { fenv_t current_fenv;
    FPU_DISABLE_TRAPS
  }
#endif

#if (!defined FIX_DFP_FLAGS)
  RAISE_ALL;
  allflags = fetestexcept( FE_ALL_EXCEPT );	/* get flags for this FPU */
  if( 0 == allflags ){
    failed++;
    (void)printf("Failed due to RAISE_ALL or fetestexcept doing no flags.\n");
  }else if( 0 == (allflags & (FE_INVALID)) ){
    failed++;
    (void)printf("Failed due to RAISE_ALL or fetestexcept not doing FE_INVALID.\n");
  }
#endif

#if (defined FIX_BROKEN_PP)
  #ifndef RETVAL
  failed++;
  (void)printf("Failed due to broken PreProcessor.\n");
  #endif

#elif (defined FIX_DFP_FLAGS)
  #ifndef RETVAL
  failed++;
  (void)printf("Failed due to broken Decimal FP flags.\n");
  #endif

#else

  #if (defined FIX_SEMIBROKEN_PP)
    #ifndef RETVAL
  failed++;
  (void)printf("Failed due to semibroken PreProcessor.\n");
    #endif
  #endif

  /*
   * Compute largest integer in FP formats.
   */
  {
    int j;

    maxint_ld = (Flt_10_34)0.;
    for(j=1; j<=DEC128_MANT_DIG; j++){
      maxint_ld *= (Flt_10_34)FP_RADIX;
      maxint_ld += (Flt_10_34)(FP_RADIX-1);
    }/* j */

    maxint_d = (Flt_10_16)0.;
    for(j=1; j<=DEC64_MANT_DIG; j++){
      maxint_d *= (Flt_10_16)FP_RADIX;
      maxint_d += (Flt_10_16)(FP_RADIX-1);
    }/* j */

    maxint_f = (Flt_10_7)0.;
    for(j=1; j<=DEC32_MANT_DIG; j++){
      maxint_f *= (Flt_10_7)FP_RADIX;
      maxint_f += (Flt_10_7)(FP_RADIX-1);
    }/* j */
  }

  /*
   * Tests from long double
   */
  #if (defined ULLONG_MAX) && (!defined FIX_FP_FROM_ULLI) && (!defined FIX_ULLONG_RANDOM_INVALID)
  tst_00(maxint_ld);
  #endif
  #if (defined LLONG_MAX) && (!defined FIX_SLLONG_RANDOM_INVALID)
  tst_01(maxint_ld);
  #endif
  #if (!defined FIX_ULONG_RANDOM_INVALID)
  tst_02(maxint_ld);
  #endif
  #if (!defined FIX_SLONG_RANDOM_INVALID)
  tst_03(maxint_ld);
  #endif
  #if (!defined FIX_UINT_RANDOM_INVALID)
  tst_04(maxint_ld);
  #endif
  #if (!defined FIX_SINT_RANDOM_INVALID)
  tst_05(maxint_ld);
  #endif
  #if (!defined FIX_USHRT_RANDOM_INVALID)
  tst_06(maxint_ld);
  #endif
  #if (!defined FIX_SSHRT_RANDOM_INVALID)
  tst_07(maxint_ld);
  #endif
  #ifdef FIX_INVALID_OCTAL
    #if (!defined FIX_UCHAR_RANDOM_INVALID)
  tst_108(maxint_ld);
    #endif
    #if (!defined FIX_SCHAR_RANDOM_INVALID)
  tst_109(maxint_ld);
    #endif
  #else
    #if (!defined FIX_UCHAR_RANDOM_INVALID)
  tst_08(maxint_ld);
    #endif
    #if (!defined FIX_SCHAR_RANDOM_INVALID)
  tst_09(maxint_ld);
    #endif
  #endif

  /*
   * Tests from double
   */
  #if (defined ULLONG_MAX) && (!defined FIX_FP_FROM_ULLI) && (!defined FIX_ULLONG_RANDOM_INVALID)
  tst_10(maxint_d);
  #endif
  #if (defined LLONG_MAX) && (!defined FIX_SLLONG_RANDOM_INVALID)
  tst_11(maxint_d);
  #endif
  #if (!defined FIX_ULONG_RANDOM_INVALID)
  tst_12(maxint_d);
  #endif
  #if (!defined FIX_SLONG_RANDOM_INVALID)
  tst_13(maxint_d);
  #endif
  #if (!defined FIX_UINT_RANDOM_INVALID)
  tst_14(maxint_d);
  #endif
  #if (!defined FIX_SINT_RANDOM_INVALID)
  tst_15(maxint_d);
  #endif
  #if (!defined FIX_USHRT_RANDOM_INVALID)
  tst_16(maxint_d);
  #endif
  #if (!defined FIX_SSHRT_RANDOM_INVALID)
  tst_17(maxint_d);
  #endif
  #if (!defined FIX_UCHAR_RANDOM_INVALID)
  tst_18(maxint_d);
  #endif
  #if (!defined FIX_SCHAR_RANDOM_INVALID)
  tst_19(maxint_d);
  #endif

  /*
   * Tests from float
   */
  #if (defined ULLONG_MAX) && (!defined FIX_FP_FROM_ULLI) && (!defined FIX_ULLONG_RANDOM_INVALID)
  tst_20(maxint_f);
  #endif
  #if (defined LLONG_MAX) && (!defined FIX_SLLONG_RANDOM_INVALID)
  tst_21(maxint_f);
  #endif
  #if (!defined FIX_ULONG_RANDOM_INVALID)
  tst_22(maxint_f);
  #endif
  #if (!defined FIX_SLONG_RANDOM_INVALID)
  tst_23(maxint_f);
  #endif
  #if (!defined FIX_UINT_RANDOM_INVALID)
  tst_24(maxint_f);
  #endif
  #if (!defined FIX_SINT_RANDOM_INVALID)
  tst_25(maxint_f);
  #endif
  #if (!defined FIX_USHRT_RANDOM_INVALID)
  tst_26(maxint_f);
  #endif
  #if (!defined FIX_SSHRT_RANDOM_INVALID)
  tst_27(maxint_f);
  #endif
  #if (!defined FIX_UCHAR_RANDOM_INVALID)
  tst_28(maxint_f);
  #endif
  #if (!defined FIX_SCHAR_RANDOM_INVALID)
  tst_29(maxint_f);
  #endif

  if(failed){
    (void)printf("To help you figure out which flags were raised:\n");
  #if (defined FE_INVALID) || (defined FIX_SYM_FE_INVALID_ENUM)
    (void)printf(" FE_INVALID   = %#x", (unsigned)FE_INVALID );
    if( allflags != FE_ALL_EXCEPT )
      (void)printf(",\tmasked = %#x", (unsigned)FE_INVALID & allflags);
    (void)printf("\n");
  #endif
  #if (defined FE_DIVBYZERO) || (defined FIX_SYM_FE_DIVBYZERO_ENUM)
    (void)printf(" FE_DIVBYZERO = %#x", (unsigned)FE_DIVBYZERO);
    if( allflags != FE_ALL_EXCEPT )
      (void)printf(",\tmasked = %#x", (unsigned)FE_DIVBYZERO & allflags);
    (void)printf("\n");
  #endif
  #if (defined FE_OVERFLOW) || (defined FIX_SYM_FE_OVERFLOW_ENUM)
    (void)printf(" FE_OVERFLOW  = %#x", (unsigned)FE_OVERFLOW );
    if( allflags != FE_ALL_EXCEPT )
      (void)printf(",\tmasked = %#x", (unsigned)FE_OVERFLOW & allflags);
    (void)printf("\n");
  #endif
  #if (defined FE_UNDERFLOW) || (defined FIX_SYM_FE_UNDERFLOW_ENUM)
    (void)printf(" FE_UNDERFLOW = %#x", (unsigned)FE_UNDERFLOW);
    if( allflags != FE_ALL_EXCEPT )
      (void)printf(",\tmasked = %#x", (unsigned)FE_UNDERFLOW & allflags);
    (void)printf("\n");
  #endif
  #if (defined FE_INEXACT) || (defined FIX_SYM_FE_INEXACT_ENUM)
    (void)printf(" FE_INEXACT   = %#x", (unsigned)FE_INEXACT  );
    if( allflags != FE_ALL_EXCEPT )
      (void)printf(",\tmasked = %#x", (unsigned)FE_INEXACT & allflags);
    (void)printf("\n");
  #endif
  }

#endif /* FIX_BROKEN_PP */

death:;

  if(failed){
    (void)printf("Test Failed with at least %u failures\n", failed);
  }else{
    (void)printf("Test ( Pass ) {} \n");
  }

#ifdef FIX_IMPLICIT_FLUSH
  (void)fflush(stdout);		/* need explicit flush */
#endif
#if (defined RETVAL) && (defined STANDALONE_TEST)
  return RETVAL;		/* Being run as part of test suite */
#else
  return 0;
#endif
}

