/*===========================================================================
  Copyright (C) 1995,2005 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT      (c)  1992,2005  European Southern Observatory
.TYPE           Program
.NAME           computer.c
.LANGUAGE       C
.AUTHOR         F.Ochsenbein, IPG/ESO
.CATEGORY       Computer-dependant constants
.COMMENTS       This module generates a suitable computer.h file
                using some simple tests.
.ENVIRONMENT    UNIX 
.VERSION 0.0    19-Oct-1988 : Creation , FO
.VERSION 0.1    18-Aug-1989 : Correct SWAPLONG for PCs, PJG
.VERSION 0.2    09-Jan-1990 : Check IEEE by dividing NaN by itself (FO)
.VERSION 0.3    18-Jan-1991 : DEC reverses the order for IEEE double !!!
.VERSION 0.4    30-Jan-1991 : Double byteswap and NULL, PJG
.VERSION 0.4    12-Feb-1991 : Change VAX NULL to -Inf, PJG
.VERSION 0.5    07-Mar-1991 : Output to file computer.h by default. CG
.VERSION 0.6    11-Sep-1991 : Continuing the test in the interrupt routine. CG.
.VERSION 0.7    21-Sep-1992 : Add Null definitions for tables, PJG.
.VERSION 0.7    28-Mar-1993 : Use definitions in values.h if exists. CG.
.VERSION 0.8    28-Oct-1994 : Use POSIX definitions if exists. CG.

 001016 KB	1) use casts to cleanup code
		2) assign the pe*, pf* pointers AFTER their target values
		   have been declared
		3) including <math.h> gave problems on INtel-Linux ...

 050405		last modif

------------------------------------------------------------*/
/*
 * Define _POSIX_SOURCE to indicate
 * that this is a POSIX program
 */
#define _POSIX_SOURCE 1

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

#ifndef NO_FLOAT_H
#include <float.h>
#endif

#ifndef NO_LIMITS_H
#include <limits.h>
#endif

#ifndef NO_VALUES_H
#ifdef Cygwin
#include <mingw/values.h>
#else
#include <values.h> 
#endif
#endif

#ifndef DEBUG
#define DEBUG 	0	/* Switch to 1 to get hexa patterns */
#endif

#include <stdint.h>

double ldexp();

static char c[80];	/* ... Must be aligned ... */
static int ieee;
static int junk;

static char          *com0 = "/*";
static char          *com1 = "*/";
static unsigned char byte;

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

#ifdef __STDC__
static int bit_count(unsigned long u) 
#else
static int bit_count(u)        /* Count number of bits set to 1 */
        unsigned long u;
#endif
{
        int i;

  for (i=0; u; u >>= 1)
        i += u & 1L;
  return(i);
}

#ifdef __STDC__
static void on_fpe(int sig)
#else
static void on_fpe(sig)            /* If Floating point fault, assume IEEE... */
int sig;
#endif
{
#ifndef vms
    struct sigaction act, oact;

    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_handler = on_fpe;
    sigaction(SIGFPE,&act,&oact);
#else
    signal(SIGFPE, on_fpe);
#endif

    if (ieee != 1) {	/* Return if already ieee */
	ieee = 1;
	contin();
	exit(0);
        }
}

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

double 	df, f, f1, f2;

float 	e, e1, e2;

unsigned int 	*pf1, *pe1;
unsigned int 	*pf2, *pe2;
unsigned int 	usgm, uexp, uman, u;
int 	n, l2e, l2f, nb[3], bitsperbyte;
long int 	dxb;


main(argc,argv)
int argc;
char **argv;
{

double  dval1, dval2;

int  i;


#ifndef vms
  struct sigaction act, oact;
	/* Setup pointer to float */
#endif

  if (argc > 1) freopen(argv[1],"w",stdout);
  else 		freopen("computer.h","w",stdout);

  
        /* Generate Header */

  printf("%s+++++++++++++++++++++++++++++\n", com0);
  puts(".TYPE \t\tHeader");
  puts(".NAME \t\tcomputer.h");
  puts(".LANGUAGE \tC");
  puts(".AUTHOR\t\tESO -- IPG");
  puts(".CATEGORY\tComputer-dependant constants");
  puts(".COMMENTS \tThis module includes constants depending on the computer:");
  puts("\t\tnumber of bits per char,");
  puts("\t\tbyte swapping, description of floating-point numbers. ");
  puts("\t\tLimits also provided for each type of atomic data.");
  puts("\t\tNULL numbers are also defined via isNULL (test) and");
  puts("\t\ttoNULL");
  puts("\t\t********* Generated by computer.c program **************");
  puts(".ENVIRON\tUNIX and VAX/VMS");
  puts(".VERSION \t1.1\t18-Jan-1991 (check Floating Pattern)");
  puts(".VERSION \t2.1\t25-Mar-1994 (using values.h if exists)");
  puts(".VERSION \t3.1\t28-Oct-1994 (POSIX definitions if exists)");
  printf("-----------------------%s\n\n", com1);

  puts("#ifndef COMPUTER_H");
  puts("#define COMPUTER_H\n");

  puts("/*");
  puts(" * Define _POSIX_SOURCE to indicate");
  puts(" * that this is a POSIX program");
  puts(" */");
  puts("#ifndef _POSIX_SOURCE");
  puts("#define _POSIX_SOURCE 1");
  puts("#endif\n");

#ifndef NO_FLOAT_H
  puts("#include <float.h>");
#endif
#ifndef NO_LIMITS_H
  puts("#include <limits.h>");
#endif
#ifndef NO_VALUES_H
#ifdef Cygwin
  puts("#include <mingw/values.h>");
#else
  puts("#include <values.h>"); 
#endif

#endif


        /* Check first the number of bits per byte */

  for (byte=1, bitsperbyte=0; byte; bitsperbyte++) {
  	i = byte << 1;
	byte = i;
  }
#ifndef BITSPERBYTE
  puts("\n#undef BITSPERBYTE");
  printf("#define BITSPERBYTE\t%d\n", bitsperbyte);
#endif

#ifndef BITS
  puts("#define BITS(type)\t(BITSPERBYTE*((int)sizeof(type)))\n");
#endif

  puts("#define ONES_COMP\t1");
  puts("#define TWOS_COMP\t2\n");
  puts("#define IEEEFLOAT\t0");
  puts("#define VAXFLOAT\t1");
  puts("#define VAXGFLOAT\t2");
  puts("#define HPFLOAT\t\t3\n");

        /* Check 1 or 2's Complement    */

  i = -1;
  if (i&1)      /* 2's Complement       */
        printf("#define INTFMT\t\t2\t%s 2's Complement Integers\t%s\n\n", 
		com0,com1);
  else  printf("#define INTFMT\t\t1\t%s 1's Complement Integers\t%s\n\n", 
		com0,com1);


  puts("#define MAXIO1\t\t(512*90)\n\n");
                                /* Maximum allowed for single i/o */

#if DEBUG
	e1 = f1 =  1.e0;
	e2 = f2 = -1.e0;
  	pf1 = (unsigned int *)&f1;
  	pf2 = (unsigned int *)&f2;
  	pe1 = (unsigned int *)&e1;
  	pe2 = (unsigned int *)&e2;
	printf("%s Hexa pattern of -1.e0 (float)%08X", com0,*pe2),
	 printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1);
	printf("%s Hexa pattern of  1.e0 (float)%08X", com0,*pe1),
	 printf(" (double)%08X %08X\t%s\n",pf1[0],pf1[1], com1);
	e2 = f2 =  2.e0; 
	printf("%s Hexa pattern of  2.e0 (float)%08X", com0,*pe2),
	 printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1);
	e2 = f2 =  .5e0;
	printf("%s Hexa pattern of  .5e0 (float)%08X", com0,*pe2),
	 printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1);
	e2 = f2 = .25e0;
	printf("%s Hexa pattern of .25e0 (float)%08X", com0,*pe2),
	 printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1);
	e2 = f2 =.125e0;
	printf("%s Hexa pattern of.125e0 (float)%08X", com0,*pe2),
	 printf(" (double)%08X %08X\t%s\n",pf2[0],pf2[1], com1);
#endif

        /* Check Swapping       */

  i = ('1'<<bitsperbyte) | '2';
  *(int16_t *)c = i, c[2] = 0;
  printf("\n#define SWAPSHORT\t%s\n", c);

  i = ('1'<<bitsperbyte) | '2';
  i = (i<<bitsperbyte) | '3';
  i = (i<<bitsperbyte) | '4';
  *(int32_t *)c = i, c[4] = 0;
  printf("#define SWAPINT\t\t%s\n", c);

	/* Find out Dynamic range of Floating-Point */
	/* Note: VAX/VMS approximates (1+2**-24) to (1+2**-23) when 
	   converting from Single to Double precision. That's why
	   there is a second test e1 == e2
	*/
  e = 1.0;
  dval1 = (double) 1.e0;
  dval2 = (double) 2.e0;


  for (l2e = -32; l2e; l2e++) {
	e1 = 1.0 + (float) ldexp(dval1, l2e);
	e2 = 1.0 + (float) ldexp(dval2, l2e);
	if (e1 != e && e1 != e2) break;
      }
  f = 1.0;
  for (l2f = -99; l2f ; l2f++ ) {
	f1 = 1.0 + ldexp(dval1, l2f);
	f2 = 1.0 + ldexp(dval2, l2f);
	if (f1 != f && f1 != f2) break;
      }
#if DEBUG
  printf("%s(float)  l2e=%d\tHexa pattern=%08X, %08X %s\n", 
	com0,l2e,*pe1,*pe2,com1);
  printf("%s(double) l2f=%d\tHexa pattern=%08X %08X, %08X %08X %s\n", 
	com0,l2f,pf1[0],pf1[1],pf2[0],pf2[1],com1);
#endif

  for (i=4, e1 = 1.0; i > 1; l2e += bitsperbyte, i--) {
	e1 += i*ldexp(1., l2e);
#if DEBUG
	printf("%s(float)  i=%ld l2e=%d\tHexa pattern=%08X\t%s\n", 
		com0,i,l2e,*pe1,com1);
#endif
  }
  for (i=8, f1 = 1.0; i > 1; l2f += bitsperbyte, i--) {
	f1 += i*ldexp(1., l2f); 
#if DEBUG
	printf("%s(double) i=%ld l2f=%d\tHexa pattern=%08X %08X\t%s\n", 
		com0,i,l2f,pf1[0],pf1[1],com1);
#endif
  }

  n = sizeof(float);
  *(float *)c = e1, c[n] = 0; 
  for (i=0; i < n; i++)
	if (c[i] >= 1 && c[i] <= n) c[i] += '0';
	else if ((c[i] & 0xf) == 2) c[i] = '2';
	else c[i] = '1';
  printf("#define SWAPFLOAT\t%s\n", c);

  n = sizeof(double);
  *(double *)c = f1, c[n] = 0; 
  for (i=0; i < n; i++)
	if (c[i] >= 1 && c[i] <= n) c[i] += '0';
	else if ((c[i] & 0xf) == 2) c[i] = '2';
	else c[i] = '1';
  printf("#define SWAPDOUBLE\t%s\n\n", c);

        /* Find Integer min / max */

#ifndef NO_LIMITS_H
  puts("#undef  MINCHAR");
  puts("#define MINCHAR\t\tCHAR_MIN");
  puts("#undef  MINSHORT");
  puts("#define MINSHORT\tSHRT_MIN");
  puts("#undef  MININT");
  puts("#define MININT\t\tINT_MIN");
  puts("#undef  MINLONG");
  puts("#define MINLONG\t\tLONG_MIN");
  puts("#undef  MAXCHAR");
  puts("#define MAXCHAR\t\tCHAR_MAX");
  puts("#undef  MAXSHORT");
  puts("#define MAXSHORT\tSHRT_MAX");
  puts("#undef  MAXINT");
  puts("#define MAXINT\t\tINT_MAX");
  puts("#undef  MAXLONG");
  puts("#define MAXLONG\t\tLONG_MAX");
  puts("#undef  MAXUCHAR");
  puts("#define MAXUCHAR\tUCHAR_MAX");
  puts("#undef  MAXUSHORT");
  puts("#define MAXUSHORT\tUSHRT_MAX");
  puts("#undef  MAXUINT");
  puts("#define MAXUINT\t\tUINT_MAX");
  puts("#undef  MAXULONG");
  puts("#define MAXULONG\tULONG_MAX\n");
#else
  puts("#define MINCHAR\t\t((char) (1  << (BITS(char) - 1)))");
# ifndef MINSHORT
  puts("#define MINSHORT\t((short)(1  << (BITS(short) - 1)))");
# endif
# ifndef MININT
  puts("#define MININT\t\t((unsigned int)1 << (BITS(int) - 1))");
# endif
# ifndef MINLONG
  puts("#define MINLONG\t\t((unsigned long)1L << (BITS(long) - 1))\n");
# endif

  puts("#define MAXCHAR\t\t((char) (~MINCHAR ))");
# ifndef MAXSHORT
  puts("#define MAXSHORT\t((short) (~MINSHORT))");
# endif
# ifndef MAXINT
  puts("#define MAXINT\t\t((int) (~MININT))");
# endif
# ifndef MAXLONG
  puts("#define MAXLONG\t\t((long) (~MINLONG))\n");
# endif

  puts("#define MAXUCHAR\t((unsigned char) (MINCHAR | MAXCHAR ))");
  puts("#define MAXUSHORT\t((unsigned short)(MINSHORT| MAXSHORT))");
  puts("#define MAXUINT\t\t((unsigned int) (MININT | MAXINT ))");
  puts("#define MAXULONG\t((unsigned long) (MINLONG | MAXLONG ))\n");
#endif /* NO_LIMITS_H */

        /* Floating-Point Format        */


	/* Floating-Point Format: determine where are bits for
	   exponent, mantissa, sign, when floating-point number
	   seen as a long int.
	*/

  e1 = 1.e0, e2 = -1.e0;
  pe1 = (unsigned int *)&e1;
  pe2 = (unsigned int *)&e2;

  usgm = (*pe1) ^ (*pe2);       /* Sign mask */
 
  e1 = 1.e0; nb[1] = bit_count(*pe1);  		/* Bit Count of 1.e0 */
  e2 = 2.e0; nb[2] = bit_count(*pe2);           /* Bit count of 2.e0 */
  uexp = *pe1 | *pe2;
  e2 = .5e0; nb[0] = bit_count(*pe2);           /* Bit count of .5e0 */
  uexp |= *pe2;
  e2 = .25e0;   uexp |= *pe2;
  e2 = .125e0;  uexp |= *pe2;
  e2 = .0625e0; uexp |= *pe2;
  n = (nb[0] < nb[1] ? nb[0] : nb[1]);
  n = (n < nb[2] ? n : nb[2]);                  /* Minimum      */
  if (n > 1)                                    /* No hidden bit */
  {     if (n == nb[0]) e1 = .5e0;
        if (n == nb[1]) e1 = 1.e0;
        if (n == nb[2]) e1 = 2.e0;
        e2 = e1 / 16.e0;
        uexp &= ~(*pe2 & *pe2);
        n = 0;
  }
  uman = ~(usgm|uexp);

        /* Check IEEE : Divide a number by itself...   */

  e1 = .1e0;  *pe1 |= uexp;	/* This gives a number in the NaN range */
  ieee = 0;   e2 = e1;

#ifndef vms
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
  act.sa_handler = on_fpe;
  sigaction(SIGFPE,&act,&oact);
#else
  signal(SIGFPE, on_fpe);
#endif

#if DEBUG
	printf("%s Edited floating-point NULL number is %e %s\n",
	       com0, e1,com1);
	printf("%s Edited floating-point NULL number is %e %s\n",
	       com0, e2,com1);
	printf("%s        Ratio is       NULL  ?     is %e %s\n\n",
	       com0,e1/e2,com1);
#endif
  e2 = e1/e2;
  if ( ieee == 1) exit(0); /* Interrrupt already arrived, so exit */
  contin();
  exit(0);
}

contin()
{  


  if (ieee == 0)	ieee = (e2 != 1.e0);

#ifndef _IEEE
  printf("#define _IEEE\t\t%d\t%s NULL edited as %e %s\n", 
	ieee, com0, e1, com1);
#endif
#ifndef _HIDDENBIT
  printf("#define _HIDDENBIT\t%d\n", n);
#endif

  e1 = 1.e0; e2 = 2.e0;
  pf1 = (unsigned int *)&f1;
  pf2 = (unsigned int *)&f2;
  pe1 = (unsigned int *)&e1;
  pe2 = (unsigned int *)&e2;

#ifndef _EXPBASE
  if ((*pe1 & uman) == (*pe2 & uman))
        puts("#define _EXPBASE\t2\n");
  else  puts("#define _EXPBASE\t16\n");
#endif


#ifndef _FEXPLEN
  printf("#define _FEXPLEN\t%d\n", bit_count(uexp));
#endif
  printf("#define FMASKSGM\t0x%08X\n", usgm);
  printf("#define FMASKEXP\t0x%08X\n", uexp);
  printf("#define FMASKMAN\t0x%08X\n\n", uman);

#ifndef NO_FLOAT_H
 puts("#undef  MAXFLOAT");
 puts("#define MAXFLOAT\tFLT_MAX");
 puts("#undef  MINFLOAT");
 puts("#define MINFLOAT\tFLT_MIN");
#else
# ifndef MAXFLOAT
  if (ieee)     puts("#define MAXFLOAT\t((float)3.40282346638528860e+38)"),
                puts("#define MINFLOAT\t((float)1.40129846432481707e-45)\n");
  else
  {     *pe1 = uexp | uman;
        printf("#define MAXFLOAT\t(float)%24.17e\n", e1);
        for (u=uexp, i=0; (u&1) == 0; i++, u >>= 1);
        *pe1 = (1L) << i;
        printf("#define MINFLOAT\t(float)%24.17e\n\n", e1);
  }
# endif	/* MAXFLOAT */
#endif	/* NO_FLOAT_H */

#if DEBUG
	f1 = 1.0e0; f2 = -1.0e0;
  	pf1 = (unsigned int *)&f1;
  	pf2 = (unsigned int *)&f2;
	printf("%s\t==== Double Precision Numbers ====%s\n",com0,com1);
	printf("%s Hexa pattern of -1.e0: %08X %08X%s \n",
	       com0,*pf2, pf2[1],com1);
	printf("%s Hexa pattern of  1.e0: %08X %08X%s \n",
	       com0,*pf1, pf1[1],com1);
	f2 = 2.e0;
	printf("%s Hexa pattern of  2.e0: %08X %08X%s \n",
	       com0,*pf2, pf2[1],com1);
	f2 =  .5e0;
	printf("%s Hexa pattern of  .5e0: %08X %08X%s \n",
	       com0,*pf2, pf2[1],com1);
	f2 = .25e0;
	printf("%s Hexa pattern of .25e0: %08X %08X%s \n",
	       com0,*pf2, pf2[1],com1);
	f2 =.125e0;
	printf("%s Hexa pattern of.125e0: %08X %08X%s \n",
	       com0,*pf2,pf2[1],com1);
#endif

  f1 = 1.e0, f2 = -1.e0;
  pf1 = (unsigned int *)&f1;
  pf2 = (unsigned int *)&f2;

  dxb = (pf1[0] ? 0 : 1);
  usgm = pf1[dxb] ^ pf2[dxb];
  nb[1] = bit_count(pf1[dxb]);			/* Bit Count of 1.e0 */
  f2 = 2.e0; nb[2] = bit_count(pf2[dxb]);     	/* Bit count of 2.e0 */
  uexp = pf2[dxb] | pf2[dxb];
  f2 = .5e0; nb[0] = bit_count(pf2[dxb]);      	/* Bit count of .5e0 */
  uexp |= pf2[dxb];
  f2 = .25e0;   uexp |= pf2[dxb];
  f2 = .125e0;  uexp |= pf2[dxb];
  f2 = .0625e0; uexp |= pf2[dxb];
#ifndef _DEXPLEN
  printf("#define _DEXPLEN\t%d\n", bit_count(uexp));
#endif
  printf("#define DINTEXP\t%ld\t%s Exponent is in longword #%ld\t%s\n",
	 dxb,com0,dxb,com1);
  printf("#define DMASKSGM\t0x%08X\n", usgm);
  printf("#define DMASKEXP\t0x%08X\n", uexp);
  printf("#define DMASKMAN\t0x%08X\n\n", ~(usgm|uexp));

#ifndef NO_FLOAT_H
 puts("#undef  MAXDOUBLE");
 puts("#define MAXDOUBLE\tDBL_MAX");
 puts("#undef  MINDOUBLE");
 puts("#define MINDOUBLE\tDBL_MIN\n");
#else
# ifndef MAXDOUBLE
  if (ieee)     puts("#define MAXDOUBLE\t1.79769313486231166e+308"),
                puts("#define MINDOUBLE\t4.94065645841246544e-324\n");
  else
  {     *pf1 = uexp | uman; *(pf1+1) = ~0;
        printf("#define MAXDOUBLE\t%24.17e\n", f1);
        for (u=uexp, i=0; (u&1) == 0; i++, u >>= 1);
        *pf1 = (1L) << i; *(pf1+1) = 0;
        printf("#define MINDOUBLE\t%24.17e\n\n", f1);
  }
# endif /* MAXDOUBLE */
#endif	/* NO_FLOAT_H */
        /* Definitions of NULL's */

  printf("%s\t Definition of NULL's \t%s\n\n",com0,com1);
  puts("#define asaUINT(x)\t(unsigned int *)(&(x))");
  puts("#define asaULONG(x)\t(unsigned long *)(&(x))\n");

  puts("#define NULL1\t\t(MINCHAR)");
  puts("#define NULL2\t\t(MINSHORT)");
  puts("#define NULL4\t\t(MININT)\n");

  puts("#define isNULLSHORT(x)\t((short)(x) == MINSHORT)");
  puts("#define toNULLSHORT(x)\tx = MINSHORT\n");

  puts("#define isNULLINT(x)\t((int)(x) == MININT)");
  puts("#define toNULLINT(x)\tx = MININT\n");

  puts("#define isNULLLONG(x)\t((long)(x) == MINLONG)");
  puts("#define toNULLLONG(x)\tx = MINLONG\n");

  if (ieee)
  { 
    printf("%s\t Use -Inf as NULL for IEEE fp \t%s\n\n",com0,com1);
    e1 = -1.0; e2 = e1 + 1.0; e = e1/e2; 
    printf("#define NULLF\t\t(FMASKSGM | FMASKEXP)\n");
    printf("#define isNULLFLOAT(x)\t((*asaUINT(x) & FMASKEXP) == FMASKEXP)\n");
    printf("#define toNULLFLOAT(x)\t *asaUINT(x) = NULLF\n");

    f1 = -1.0; f2 = f1 + 1.0; f = f1/f2;
    printf("#define NULLD\t\t(DMASKSGM | DMASKEXP)\n");
    printf("#define isNULLDOUBLE(x)\t");
    printf("((*(asaUINT(x)+DINTEXP) & DMASKEXP) == DMASKEXP)\n");
    printf("#define toNULLDOUBLE(x)\t");
    printf("*(asaUINT(x)+DINTEXP) = NULLD, \\\n");
    printf("\t\t\t *(asaUINT(x)+(DINTEXP^1)) = 0\n\n");

  }
  else
  { 
    printf("#define NULLF\t\t(~FMASKSGM)\n");
    printf("#define NULLD\t\t(DMASKSGM | DMASKEXP)\n");
    puts("#define isNULLFLOAT(x)\t(*asaUINT(x) == NULLF)");
    puts("#define toNULLFLOAT(x)\t*asaUINT(x) = NULLF");

    printf("#define isNULLDOUBLE(x)\t");
    printf("((*(asaUINT(x)+DINTEXP) == NULLD) &&  \\\n");
    printf("\t\t\t (*(asaUINT(x)+(DINTEXP^1)) == 0))\n");
    printf("#define toNULLDOUBLE(x)\t");
    printf("*(asaUINT(x)+DINTEXP) = NULLD, \\\n");
    printf("\t\t\t *(asaUINT(x)+(DINTEXP^1)) = 0\n\n");
  }

#ifndef FSIGNIF
  puts("#define FSIGNIF\t\t(BITS(float)  - _FEXPLEN + _HIDDENBIT - 1)");
#endif
#ifndef DSIGNIF
  puts("#define DSIGNIF\t\t(BITS(double) - _DEXPLEN + _HIDDENBIT - 1)");
#endif
#ifndef FMAXEXP
  puts("#define FMAXEXP\t\t((1 << (_FEXPLEN - 1)) - 1 + _IEEE)");
#endif
#ifndef DMAXEXP
  puts("#define DMAXEXP\t\t((1 << (_DEXPLEN - 1)) - 1 + _IEEE)\n\n");
#endif

  if (ieee) puts("#define FLOATFMT\tIEEEFLOAT");
  else if ( (uexp == 0x7f80) || (uexp == 0x7ff0) ) {
    if ( bit_count(uexp) < 10 )
        puts("#define FLOATFMT\tVAXFLOAT");
    else
        puts("#define FLOATFMT\tVAXGFLOAT");
    }
  else {
	fputs("ERROR: Undefined floating point format\n",stderr);
	exit(1);
	}

  puts("\n#endif");
  exit(0);
}
